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