1*e40ee29aSMatthias Ringwald /* 2*e40ee29aSMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH 3*e40ee29aSMatthias Ringwald * 4*e40ee29aSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*e40ee29aSMatthias Ringwald * modification, are permitted provided that the following conditions 6*e40ee29aSMatthias Ringwald * are met: 7*e40ee29aSMatthias Ringwald * 8*e40ee29aSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*e40ee29aSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*e40ee29aSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*e40ee29aSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*e40ee29aSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*e40ee29aSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*e40ee29aSMatthias Ringwald * contributors may be used to endorse or promote products derived 15*e40ee29aSMatthias Ringwald * from this software without specific prior written permission. 16*e40ee29aSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*e40ee29aSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*e40ee29aSMatthias Ringwald * monetary gain. 19*e40ee29aSMatthias Ringwald * 20*e40ee29aSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*e40ee29aSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*e40ee29aSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*e40ee29aSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*e40ee29aSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*e40ee29aSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*e40ee29aSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*e40ee29aSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*e40ee29aSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*e40ee29aSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*e40ee29aSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*e40ee29aSMatthias Ringwald * SUCH DAMAGE. 32*e40ee29aSMatthias Ringwald * 33*e40ee29aSMatthias Ringwald * Please inquire about commercial licensing options at 34*e40ee29aSMatthias Ringwald * [email protected] 35*e40ee29aSMatthias Ringwald * 36*e40ee29aSMatthias Ringwald */ 37*e40ee29aSMatthias Ringwald 38*e40ee29aSMatthias Ringwald // ***************************************************************************** 39*e40ee29aSMatthias Ringwald // 40*e40ee29aSMatthias Ringwald // LC3 decoder Google 41*e40ee29aSMatthias Ringwald // 42*e40ee29aSMatthias Ringwald // ***************************************************************************** 43*e40ee29aSMatthias Ringwald 44*e40ee29aSMatthias Ringwald #include <stdint.h> 45*e40ee29aSMatthias Ringwald #include <stdio.h> 46*e40ee29aSMatthias Ringwald #include <stdlib.h> 47*e40ee29aSMatthias Ringwald #include <string.h> 48*e40ee29aSMatthias Ringwald #include <fcntl.h> 49*e40ee29aSMatthias Ringwald #include <unistd.h> 50*e40ee29aSMatthias Ringwald 51*e40ee29aSMatthias Ringwald #include "wav_util.h" 52*e40ee29aSMatthias Ringwald #include "btstack_util.h" 53*e40ee29aSMatthias Ringwald #include "btstack_debug.h" 54*e40ee29aSMatthias Ringwald 55*e40ee29aSMatthias Ringwald #include "btstack_lc3.h" 56*e40ee29aSMatthias Ringwald #include "btstack_lc3_google.h" 57*e40ee29aSMatthias Ringwald 58*e40ee29aSMatthias Ringwald #define MAX_NUM_CHANNELS 2 59*e40ee29aSMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480 60*e40ee29aSMatthias Ringwald 61*e40ee29aSMatthias Ringwald static uint8_t read_buffer[200]; 62*e40ee29aSMatthias Ringwald 63*e40ee29aSMatthias Ringwald static uint32_t frame_count = 0; 64*e40ee29aSMatthias Ringwald 65*e40ee29aSMatthias Ringwald static void show_usage(const char * path){ 66*e40ee29aSMatthias Ringwald printf("\n\nUsage: %s input_file.lc3 output_file.wav\n\n", path); 67*e40ee29aSMatthias Ringwald } 68*e40ee29aSMatthias Ringwald 69*e40ee29aSMatthias Ringwald static ssize_t __read(int fd, void *buf, size_t count){ 70*e40ee29aSMatthias Ringwald ssize_t len, pos = 0; 71*e40ee29aSMatthias Ringwald while (count > 0) { 72*e40ee29aSMatthias Ringwald len = read(fd, (int8_t * )buf + pos, count); 73*e40ee29aSMatthias Ringwald if (len <= 0) 74*e40ee29aSMatthias Ringwald return pos; 75*e40ee29aSMatthias Ringwald 76*e40ee29aSMatthias Ringwald count -= len; 77*e40ee29aSMatthias Ringwald pos += len; 78*e40ee29aSMatthias Ringwald } 79*e40ee29aSMatthias Ringwald return pos; 80*e40ee29aSMatthias Ringwald } 81*e40ee29aSMatthias Ringwald 82*e40ee29aSMatthias Ringwald int main (int argc, const char * argv[]){ 83*e40ee29aSMatthias Ringwald if (argc < 3){ 84*e40ee29aSMatthias Ringwald show_usage(argv[0]); 85*e40ee29aSMatthias Ringwald return -1; 86*e40ee29aSMatthias Ringwald } 87*e40ee29aSMatthias Ringwald 88*e40ee29aSMatthias Ringwald const char * lc3_filename = argv[1]; 89*e40ee29aSMatthias Ringwald const char * wav_filename = argv[2]; 90*e40ee29aSMatthias Ringwald 91*e40ee29aSMatthias Ringwald int fd = open(lc3_filename, O_RDONLY); 92*e40ee29aSMatthias Ringwald if (fd < 0) { 93*e40ee29aSMatthias Ringwald printf("Can't open file %s", lc3_filename); 94*e40ee29aSMatthias Ringwald return -1; 95*e40ee29aSMatthias Ringwald } 96*e40ee29aSMatthias Ringwald 97*e40ee29aSMatthias Ringwald // read & parse header 98*e40ee29aSMatthias Ringwald uint16_t min_header_size = 18; 99*e40ee29aSMatthias Ringwald int bytes_read = __read(fd, read_buffer, min_header_size); 100*e40ee29aSMatthias Ringwald if (bytes_read != min_header_size) return -10; 101*e40ee29aSMatthias Ringwald uint16_t file_id = little_endian_read_16(read_buffer, 0); 102*e40ee29aSMatthias Ringwald if (file_id != 0xcc1c) return -10; 103*e40ee29aSMatthias Ringwald uint16_t header_size = little_endian_read_16(read_buffer, 2); 104*e40ee29aSMatthias Ringwald if (header_size > 100) return -10; 105*e40ee29aSMatthias Ringwald uint32_t sample_rate_hz = little_endian_read_16(read_buffer, 4) * 100; 106*e40ee29aSMatthias Ringwald uint32_t bitrate = little_endian_read_16(read_buffer, 6) * 100; 107*e40ee29aSMatthias Ringwald uint8_t num_channels = little_endian_read_16(read_buffer, 8); 108*e40ee29aSMatthias Ringwald uint32_t frame_us = little_endian_read_16(read_buffer, 10) * 10; 109*e40ee29aSMatthias Ringwald // offset 12: epmode 110*e40ee29aSMatthias Ringwald // offset 14: signal_len 111*e40ee29aSMatthias Ringwald // skip addittional fields 112*e40ee29aSMatthias Ringwald if (header_size > min_header_size){ 113*e40ee29aSMatthias Ringwald __read(fd, read_buffer, header_size - min_header_size); 114*e40ee29aSMatthias Ringwald } 115*e40ee29aSMatthias Ringwald 116*e40ee29aSMatthias Ringwald if (num_channels > MAX_NUM_CHANNELS) { 117*e40ee29aSMatthias Ringwald printf("Too much channels: %u\n", num_channels); 118*e40ee29aSMatthias Ringwald return -10; 119*e40ee29aSMatthias Ringwald } 120*e40ee29aSMatthias Ringwald 121*e40ee29aSMatthias Ringwald // pick frame duration 122*e40ee29aSMatthias Ringwald btstack_lc3_frame_duration_t duration2; 123*e40ee29aSMatthias Ringwald switch (frame_us) { 124*e40ee29aSMatthias Ringwald case 7500: 125*e40ee29aSMatthias Ringwald duration2 = BTSTACK_LC3_FRAME_DURATION_7500US; 126*e40ee29aSMatthias Ringwald break; 127*e40ee29aSMatthias Ringwald case 10000: 128*e40ee29aSMatthias Ringwald duration2 = BTSTACK_LC3_FRAME_DURATION_10000US; 129*e40ee29aSMatthias Ringwald break; 130*e40ee29aSMatthias Ringwald default: 131*e40ee29aSMatthias Ringwald return -10; 132*e40ee29aSMatthias Ringwald } 133*e40ee29aSMatthias Ringwald 134*e40ee29aSMatthias Ringwald // init decoder 135*e40ee29aSMatthias Ringwald uint8_t channel; 136*e40ee29aSMatthias Ringwald btstack_lc3_decoder_google_t decoder_contexts[MAX_NUM_CHANNELS]; 137*e40ee29aSMatthias Ringwald const btstack_lc3_decoder_t * lc3_decoder; 138*e40ee29aSMatthias Ringwald for (channel = 0 ; channel < num_channels ; channel++){ 139*e40ee29aSMatthias Ringwald btstack_lc3_decoder_google_t * decoder_context = &decoder_contexts[channel]; 140*e40ee29aSMatthias Ringwald lc3_decoder = btstack_lc3_decoder_google_init_instance(decoder_context); 141*e40ee29aSMatthias Ringwald lc3_decoder->configure(decoder_context, sample_rate_hz, duration2); 142*e40ee29aSMatthias Ringwald } 143*e40ee29aSMatthias Ringwald 144*e40ee29aSMatthias Ringwald uint32_t bitrate_per_channel = bitrate / num_channels; 145*e40ee29aSMatthias Ringwald uint16_t bytes_per_frame = lc3_decoder->get_number_octets_for_bitrate(&decoder_contexts[0], bitrate_per_channel); 146*e40ee29aSMatthias Ringwald uint16_t number_samples_per_frame = lc3_decoder->get_number_samples_per_frame(&decoder_contexts[0]); 147*e40ee29aSMatthias Ringwald 148*e40ee29aSMatthias Ringwald // fix bitrate for 8_1 149*e40ee29aSMatthias Ringwald if ((sample_rate_hz == 8000) && (bitrate_per_channel == 27700)){ 150*e40ee29aSMatthias Ringwald bitrate_per_channel = 27734; 151*e40ee29aSMatthias Ringwald bitrate = bitrate_per_channel * num_channels; 152*e40ee29aSMatthias Ringwald bytes_per_frame = 26; 153*e40ee29aSMatthias Ringwald } 154*e40ee29aSMatthias Ringwald 155*e40ee29aSMatthias Ringwald // fix bitrate for 441_1 and 441_2 156*e40ee29aSMatthias Ringwald if (sample_rate_hz == 44100){ 157*e40ee29aSMatthias Ringwald if ((frame_us == 7500) && (bitrate_per_channel == 95000)) { 158*e40ee29aSMatthias Ringwald bitrate = 95060; 159*e40ee29aSMatthias Ringwald } 160*e40ee29aSMatthias Ringwald if ((frame_us == 10000) && (bitrate_per_channel == 95500)) { 161*e40ee29aSMatthias Ringwald bytes_per_frame = 130; 162*e40ee29aSMatthias Ringwald } 163*e40ee29aSMatthias Ringwald } 164*e40ee29aSMatthias Ringwald 165*e40ee29aSMatthias Ringwald if (number_samples_per_frame > MAX_SAMPLES_PER_FRAME) { 166*e40ee29aSMatthias Ringwald printf("number samples per frame %u too large\n", number_samples_per_frame); 167*e40ee29aSMatthias Ringwald return -10; 168*e40ee29aSMatthias Ringwald } 169*e40ee29aSMatthias Ringwald 170*e40ee29aSMatthias Ringwald // print format 171*e40ee29aSMatthias Ringwald printf("LC3 file: %s\n", lc3_filename); 172*e40ee29aSMatthias Ringwald printf("WAC file: %s\n", wav_filename); 173*e40ee29aSMatthias Ringwald printf("Samplerate: %u Hz\n", sample_rate_hz); 174*e40ee29aSMatthias Ringwald printf("Channels: %u\n", num_channels); 175*e40ee29aSMatthias Ringwald printf("Bitrate %u bps\n", bitrate); 176*e40ee29aSMatthias Ringwald uint16_t frame_ms = frame_us / 1000; 177*e40ee29aSMatthias Ringwald printf("Frame: %u.%u ms\n", frame_ms, frame_us - (frame_ms * 1000)); 178*e40ee29aSMatthias Ringwald 179*e40ee29aSMatthias Ringwald printf("Bytes per frame: %u\n", bytes_per_frame); 180*e40ee29aSMatthias Ringwald printf("Samples per frame: %u\n", number_samples_per_frame); 181*e40ee29aSMatthias Ringwald 182*e40ee29aSMatthias Ringwald // open wav writer 183*e40ee29aSMatthias Ringwald wav_writer_open(wav_filename, num_channels, sample_rate_hz); 184*e40ee29aSMatthias Ringwald 185*e40ee29aSMatthias Ringwald while (true){ 186*e40ee29aSMatthias Ringwald 187*e40ee29aSMatthias Ringwald bool done = false; 188*e40ee29aSMatthias Ringwald int16_t pcm[MAX_NUM_CHANNELS * MAX_SAMPLES_PER_FRAME]; 189*e40ee29aSMatthias Ringwald 190*e40ee29aSMatthias Ringwald // get len of lc3 frames 191*e40ee29aSMatthias Ringwald int bytes_read = __read(fd, read_buffer, 2); 192*e40ee29aSMatthias Ringwald if (2 != bytes_read) { 193*e40ee29aSMatthias Ringwald done = true; 194*e40ee29aSMatthias Ringwald break; 195*e40ee29aSMatthias Ringwald } 196*e40ee29aSMatthias Ringwald uint16_t total_frame_len = little_endian_read_16(read_buffer, 0); 197*e40ee29aSMatthias Ringwald if (total_frame_len != (bytes_per_frame * num_channels)){ 198*e40ee29aSMatthias Ringwald done = true; 199*e40ee29aSMatthias Ringwald break; 200*e40ee29aSMatthias Ringwald } 201*e40ee29aSMatthias Ringwald 202*e40ee29aSMatthias Ringwald for (channel = 0; channel < num_channels; channel++){ 203*e40ee29aSMatthias Ringwald 204*e40ee29aSMatthias Ringwald // get next lc3 frame (one channel) 205*e40ee29aSMatthias Ringwald int bytes_read = __read(fd, read_buffer, bytes_per_frame); 206*e40ee29aSMatthias Ringwald if (bytes_per_frame != bytes_read) { 207*e40ee29aSMatthias Ringwald done = true; 208*e40ee29aSMatthias Ringwald break; 209*e40ee29aSMatthias Ringwald } 210*e40ee29aSMatthias Ringwald 211*e40ee29aSMatthias Ringwald // process frame 212*e40ee29aSMatthias Ringwald uint8_t tmp_BEC_detect; 213*e40ee29aSMatthias Ringwald uint8_t BFI = 0; 214*e40ee29aSMatthias Ringwald 215*e40ee29aSMatthias Ringwald uint8_t status = lc3_decoder->decode_signed_16(&decoder_contexts[channel], read_buffer, bytes_per_frame, BFI, &pcm[channel * MAX_SAMPLES_PER_FRAME], 1, &tmp_BEC_detect); 216*e40ee29aSMatthias Ringwald if (status != ERROR_CODE_SUCCESS){ 217*e40ee29aSMatthias Ringwald printf("Error %u\n", status); 218*e40ee29aSMatthias Ringwald done = true; 219*e40ee29aSMatthias Ringwald break; 220*e40ee29aSMatthias Ringwald } 221*e40ee29aSMatthias Ringwald } 222*e40ee29aSMatthias Ringwald 223*e40ee29aSMatthias Ringwald if (done) break; 224*e40ee29aSMatthias Ringwald 225*e40ee29aSMatthias Ringwald uint16_t sample; 226*e40ee29aSMatthias Ringwald int16_t wav_frame[MAX_NUM_CHANNELS]; 227*e40ee29aSMatthias Ringwald for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 228*e40ee29aSMatthias Ringwald for (channel = 0; channel < num_channels; channel++) { 229*e40ee29aSMatthias Ringwald wav_frame[channel] = pcm[channel * MAX_SAMPLES_PER_FRAME + sample]; 230*e40ee29aSMatthias Ringwald } 231*e40ee29aSMatthias Ringwald wav_writer_write_int16(num_channels, wav_frame); 232*e40ee29aSMatthias Ringwald } 233*e40ee29aSMatthias Ringwald 234*e40ee29aSMatthias Ringwald frame_count++; 235*e40ee29aSMatthias Ringwald } 236*e40ee29aSMatthias Ringwald 237*e40ee29aSMatthias Ringwald wav_writer_close(); 238*e40ee29aSMatthias Ringwald close(fd); 239*e40ee29aSMatthias Ringwald 240*e40ee29aSMatthias Ringwald printf("Wrote %d frames / %u samples\n\n", frame_count, frame_count * number_samples_per_frame); 241*e40ee29aSMatthias Ringwald } 242