1 /* 2 * Copyright (C) 2022 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 // ***************************************************************************** 39 // 40 // LC3 decoder EHIMA 41 // 42 // ***************************************************************************** 43 44 #include <stdint.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <fcntl.h> 49 #include <unistd.h> 50 51 #include "wav_util.h" 52 #include "btstack_util.h" 53 #include "btstack_debug.h" 54 55 #include "btstack_lc3.h" 56 #include "btstack_lc3_google.h" 57 58 #define MAX_NUM_CHANNELS 2 59 #define MAX_SAMPLES_PER_FRAME 480 60 61 static uint8_t write_buffer[200]; 62 static int16_t samples_buffer[MAX_SAMPLES_PER_FRAME + MAX_NUM_CHANNELS]; 63 64 static uint32_t frame_count = 0; 65 66 static void show_usage(const char * path){ 67 printf("Usage: %s input.wav output.lc3 frame_duration_ms octets_per_frame\n", path); 68 printf("- frame_duration_ms: 7.5 or 10\n"); 69 printf("- octects_per_frame: 26..155\n"); 70 printf("\n\n"); 71 } 72 73 int main (int argc, const char * argv[]){ 74 if (argc < 4){ 75 show_usage(argv[0]); 76 return -1; 77 } 78 79 uint8_t argv_pos = 1; 80 const char * wav_filename = argv[argv_pos++]; 81 const char * lc3_filename = argv[argv_pos++]; 82 83 btstack_lc3_frame_duration_t frame_duration; 84 if (strcmp(argv[argv_pos], "10") == 0){ 85 frame_duration = BTSTACK_LC3_FRAME_DURATION_10000US; 86 } else if (strcmp(argv[argv_pos], "7.5") == 0){ 87 frame_duration = BTSTACK_LC3_FRAME_DURATION_7500US; 88 } else { 89 printf("Invalid frame duration %s, must be either 7.5 or 10\n", argv[2]); 90 return -10; 91 } 92 argv_pos++; 93 94 uint16_t bytes_per_frame = atoi(argv[argv_pos++]); 95 if ((bytes_per_frame < 26) || (bytes_per_frame > 155)){ 96 printf("Octets per Frame %u out of range [26..155]\n", bytes_per_frame); 97 return -10; 98 } 99 100 int status = wav_reader_open(wav_filename); 101 if (status != 0){ 102 printf("Could not open wav file %s\n", wav_filename); 103 return -10; 104 } 105 106 // get wav config 107 uint32_t sampling_frequency_hz = wav_reader_get_sampling_rate(); 108 uint8_t num_channels = wav_reader_get_num_channels(); 109 uint16_t number_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration); 110 111 // init decoder 112 uint8_t channel; 113 btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_CHANNELS]; 114 const btstack_lc3_encoder_t * lc3_encoder; 115 for (channel = 0 ; channel < num_channels ; channel++){ 116 btstack_lc3_encoder_google_t * encoder_context = &encoder_contexts[channel]; 117 lc3_encoder = btstack_lc3_encoder_google_init_instance(encoder_context); 118 lc3_encoder->configure(encoder_context, sampling_frequency_hz, frame_duration, number_samples_per_frame); 119 } 120 121 if (number_samples_per_frame > MAX_SAMPLES_PER_FRAME) return -10; 122 123 // calc bitrate from num octets 124 uint32_t bitrate_per_channel = ((uint32_t) bytes_per_frame * 80000) / (btstack_lc3_frame_duration_in_us(frame_duration) / 100); 125 // fix bitrate for 8_1 126 if ((sampling_frequency_hz == 8000) && (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US)) { 127 bitrate_per_channel = 27734; 128 } 129 // fix bitrate for 441_1 and 441_2 130 if (sampling_frequency_hz == 44100){ 131 switch(frame_duration){ 132 case BTSTACK_LC3_FRAME_DURATION_7500US: 133 bitrate_per_channel = 95060; 134 break; 135 case BTSTACK_LC3_FRAME_DURATION_10000US: 136 bitrate_per_channel = 95500; 137 break; 138 default: 139 btstack_unreachable(); 140 break; 141 } 142 } 143 uint32_t bitrate = bitrate_per_channel * num_channels; 144 145 // create lc3 file and write header for floating point implementation 146 FILE * lc3_file = fopen(lc3_filename, "wb"); 147 if (!lc3_file) return 1; 148 149 uint16_t frame_duration_100us = (frame_duration == BTSTACK_LC3_FRAME_DURATION_10000US) ? 100 : 75; 150 151 uint8_t header[18]; 152 little_endian_store_16(header, 0, 0xcc1c); 153 little_endian_store_16(header, 2, sizeof(header)); 154 little_endian_store_16(header, 4, sampling_frequency_hz / 100); 155 little_endian_store_16(header, 6, bitrate / 100); 156 little_endian_store_16(header, 8, num_channels); 157 little_endian_store_16(header, 10, frame_duration_100us * 10); 158 little_endian_store_16(header, 12, 0); 159 little_endian_store_32(header, 14, 0); // num samples need to set later 160 fwrite(header, 1, sizeof(header), lc3_file); 161 162 // print format 163 printf("WAC file: %s\n", wav_filename); 164 printf("LC3 file: %s\n", lc3_filename); 165 printf("Samplerate: %u Hz\n", sampling_frequency_hz); 166 printf("Channels: %u\n", num_channels); 167 printf("Frame duration: %s ms\n", (frame_duration == BTSTACK_LC3_FRAME_DURATION_10000US) ? "10" : "7.5"); 168 printf("Bitrate: %u\n", bitrate); 169 printf("Samples per Frame: %u\n", number_samples_per_frame); 170 171 while (true){ 172 // process file frame by frame 173 memset(samples_buffer, 0, sizeof(samples_buffer)); 174 // read samples per frame * num channels 175 status = wav_reader_read_int16(number_samples_per_frame * num_channels, samples_buffer); 176 177 if (status != 0) break; 178 179 // write len of complete frame 180 uint8_t len[2]; 181 little_endian_store_16(len, 0, num_channels * bytes_per_frame); 182 fwrite(len, 1, sizeof(len), lc3_file); 183 184 // encode frame by frame 185 for (channel = 0; channel < num_channels ; channel++){ 186 status = lc3_encoder->encode_signed_16(&encoder_contexts[channel], &samples_buffer[channel], num_channels, write_buffer); 187 if (status != ERROR_CODE_SUCCESS){ 188 printf("Error %u\n", status); 189 break; 190 } 191 fwrite(write_buffer, 1, bytes_per_frame, lc3_file); 192 } 193 194 if (status != 0) break; 195 196 frame_count++; 197 } 198 199 uint32_t total_samples = frame_count * number_samples_per_frame; 200 printf("Total samples: %u\n", total_samples); 201 202 // rewind and store num samples 203 little_endian_store_32(header, 14, total_samples); // num samples need to set later 204 rewind(lc3_file); 205 fwrite(header, 1, sizeof(header), lc3_file); 206 fclose(lc3_file); 207 } 208