188a9940aSMilanka Ringwald /* 288a9940aSMilanka Ringwald * Copyright (C) 2014 BlueKitchen GmbH 388a9940aSMilanka Ringwald * 488a9940aSMilanka Ringwald * Redistribution and use in source and binary forms, with or without 588a9940aSMilanka Ringwald * modification, are permitted provided that the following conditions 688a9940aSMilanka Ringwald * are met: 788a9940aSMilanka Ringwald * 888a9940aSMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 988a9940aSMilanka Ringwald * notice, this list of conditions and the following disclaimer. 1088a9940aSMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1188a9940aSMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 1288a9940aSMilanka Ringwald * documentation and/or other materials provided with the distribution. 1388a9940aSMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 1488a9940aSMilanka Ringwald * contributors may be used to endorse or promote products derived 1588a9940aSMilanka Ringwald * from this software without specific prior written permission. 1688a9940aSMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 1788a9940aSMilanka Ringwald * personal benefit and not for any commercial purpose or for 1888a9940aSMilanka Ringwald * monetary gain. 1988a9940aSMilanka Ringwald * 2088a9940aSMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2188a9940aSMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2288a9940aSMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2388a9940aSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 2488a9940aSMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2588a9940aSMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2688a9940aSMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2788a9940aSMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2888a9940aSMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2988a9940aSMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3088a9940aSMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3188a9940aSMilanka Ringwald * SUCH DAMAGE. 3288a9940aSMilanka Ringwald * 3388a9940aSMilanka Ringwald * Please inquire about commercial licensing options at 3488a9940aSMilanka Ringwald * [email protected] 3588a9940aSMilanka Ringwald * 3688a9940aSMilanka Ringwald */ 3788a9940aSMilanka Ringwald 3888a9940aSMilanka Ringwald // ***************************************************************************** 3988a9940aSMilanka Ringwald // 4088a9940aSMilanka Ringwald // SBC decoder tests 4188a9940aSMilanka Ringwald // 4288a9940aSMilanka Ringwald // ***************************************************************************** 4388a9940aSMilanka Ringwald 4488a9940aSMilanka Ringwald #include "btstack_config.h" 4588a9940aSMilanka Ringwald 4688a9940aSMilanka Ringwald #include <stdint.h> 4788a9940aSMilanka Ringwald #include <stdio.h> 4888a9940aSMilanka Ringwald #include <stdlib.h> 4988a9940aSMilanka Ringwald #include <string.h> 5088a9940aSMilanka Ringwald #include <fcntl.h> 5188a9940aSMilanka Ringwald #include <unistd.h> 52*1ff8adc5SMilanka Ringwald 5388a9940aSMilanka Ringwald #include "oi_assert.h" 5488a9940aSMilanka Ringwald 55aa6493c2SMilanka Ringwald #include "btstack.h" 56*1ff8adc5SMilanka Ringwald #include "sbc_decoder.h" 57aa6493c2SMilanka Ringwald 58fcb08cdbSMilanka Ringwald static uint8_t read_buffer[24]; 5988a9940aSMilanka Ringwald 60082d19a8SMilanka Ringwald typedef struct wav_writer_state { 61082d19a8SMilanka Ringwald FILE * wav_file; 62082d19a8SMilanka Ringwald int total_num_samples; 6348e0f806SMilanka Ringwald int frame_count; 64082d19a8SMilanka Ringwald } wav_writer_state_t; 65082d19a8SMilanka Ringwald 6688a9940aSMilanka Ringwald static void show_usage(void){ 67fcb08cdbSMilanka Ringwald printf("\n\nUsage: ./sbc_decoder_test input.sbc output.wav msbc|sbc\n\n"); 6888a9940aSMilanka Ringwald } 6988a9940aSMilanka Ringwald 7088a9940aSMilanka Ringwald static ssize_t __read(int fd, void *buf, size_t count){ 7188a9940aSMilanka Ringwald ssize_t len, pos = 0; 7288a9940aSMilanka Ringwald 7388a9940aSMilanka Ringwald while (count > 0) { 7488a9940aSMilanka Ringwald len = read(fd, buf + pos, count); 7588a9940aSMilanka Ringwald if (len <= 0) 7688a9940aSMilanka Ringwald return pos; 7788a9940aSMilanka Ringwald 7888a9940aSMilanka Ringwald count -= len; 7988a9940aSMilanka Ringwald pos += len; 8088a9940aSMilanka Ringwald } 8188a9940aSMilanka Ringwald return pos; 8288a9940aSMilanka Ringwald } 8388a9940aSMilanka Ringwald 8488a9940aSMilanka Ringwald void little_endian_fstore_16(FILE *wav_file, uint16_t value){ 85*1ff8adc5SMilanka Ringwald uint8_t buf[2]; 8688a9940aSMilanka Ringwald little_endian_store_32(buf, 0, value); 8788a9940aSMilanka Ringwald fwrite(&buf, 1, 2, wav_file); 8888a9940aSMilanka Ringwald } 8988a9940aSMilanka Ringwald 9088a9940aSMilanka Ringwald void little_endian_fstore_32(FILE *wav_file, uint32_t value){ 91*1ff8adc5SMilanka Ringwald uint8_t buf[4]; 9288a9940aSMilanka Ringwald little_endian_store_32(buf, 0, value); 9388a9940aSMilanka Ringwald fwrite(&buf, 1, 4, wav_file); 9488a9940aSMilanka Ringwald } 9588a9940aSMilanka Ringwald 96435e3c4eSMilanka Ringwald 97082d19a8SMilanka Ringwald static void write_wav_header(FILE * wav_file, int total_num_samples, int num_channels, int sample_rate){ 9888a9940aSMilanka Ringwald unsigned int bytes_per_sample = 2; 9988a9940aSMilanka Ringwald /* write RIFF header */ 10088a9940aSMilanka Ringwald fwrite("RIFF", 1, 4, wav_file); 10188a9940aSMilanka Ringwald // num_samples = blocks * subbands 102082d19a8SMilanka Ringwald uint32_t data_bytes = (uint32_t) (bytes_per_sample * total_num_samples * num_channels); 10388a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes + 36); 10488a9940aSMilanka Ringwald fwrite("WAVE", 1, 4, wav_file); 10588a9940aSMilanka Ringwald 10688a9940aSMilanka Ringwald int byte_rate = sample_rate * num_channels * bytes_per_sample; 10788a9940aSMilanka Ringwald int bits_per_sample = 8 * bytes_per_sample; 10888a9940aSMilanka Ringwald int block_align = num_channels * bits_per_sample; 10988a9940aSMilanka Ringwald int fmt_length = 16; 11088a9940aSMilanka Ringwald int fmt_format_tag = 1; // PCM 11188a9940aSMilanka Ringwald 11288a9940aSMilanka Ringwald /* write fmt chunk */ 11388a9940aSMilanka Ringwald fwrite("fmt ", 1, 4, wav_file); 11488a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, fmt_length); 11588a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, fmt_format_tag); 11688a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, num_channels); 11788a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, sample_rate); 11888a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, byte_rate); 11988a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, block_align); 12088a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, bits_per_sample); 12188a9940aSMilanka Ringwald 12288a9940aSMilanka Ringwald /* write data chunk */ 12388a9940aSMilanka Ringwald fwrite("data", 1, 4, wav_file); 12488a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes); 12588a9940aSMilanka Ringwald } 12688a9940aSMilanka Ringwald 127082d19a8SMilanka Ringwald static void write_wav_data(FILE * wav_file, int num_samples, int num_channels, int16_t * data){ 128fcb08cdbSMilanka Ringwald fwrite(data, num_samples, 2, wav_file); 12988a9940aSMilanka Ringwald } 13088a9940aSMilanka Ringwald 131082d19a8SMilanka Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ 132082d19a8SMilanka Ringwald wav_writer_state_t * wav_writer_state = (wav_writer_state_t*) context; 133082d19a8SMilanka Ringwald write_wav_data(wav_writer_state->wav_file, num_samples, num_channels, data); 134082d19a8SMilanka Ringwald wav_writer_state->total_num_samples+=num_samples; 13548e0f806SMilanka Ringwald wav_writer_state->frame_count++; 136082d19a8SMilanka Ringwald } 137082d19a8SMilanka Ringwald 13888a9940aSMilanka Ringwald int main (int argc, const char * argv[]){ 139fcb08cdbSMilanka Ringwald if (argc < 4){ 14088a9940aSMilanka Ringwald show_usage(); 14188a9940aSMilanka Ringwald return -1; 14288a9940aSMilanka Ringwald } 14388a9940aSMilanka Ringwald 144fcb08cdbSMilanka Ringwald sbc_mode_t mode = SBC_MODE_STANDARD; 145fcb08cdbSMilanka Ringwald 14688a9940aSMilanka Ringwald const char * sbc_filename = argv[1]; 14788a9940aSMilanka Ringwald const char * wav_filename = argv[2]; 14888a9940aSMilanka Ringwald 149fcb08cdbSMilanka Ringwald if (strncmp(argv[3], "msbc", 4) == 0 ){ 150fcb08cdbSMilanka Ringwald mode = SBC_MODE_mSBC; 151fcb08cdbSMilanka Ringwald printf("Using SBC_MODE_mSBC mode\n"); 152fcb08cdbSMilanka Ringwald } else { 153fcb08cdbSMilanka Ringwald printf("Using SBC_MODE_STANDARD mode\n"); 154fcb08cdbSMilanka Ringwald } 15588a9940aSMilanka Ringwald 15688a9940aSMilanka Ringwald int fd = open(sbc_filename, O_RDONLY); 15788a9940aSMilanka Ringwald if (fd < 0) { 15888a9940aSMilanka Ringwald printf("Can't open file %s", sbc_filename); 15988a9940aSMilanka Ringwald return -1; 16088a9940aSMilanka Ringwald } 16188a9940aSMilanka Ringwald printf("Open sbc file: %s\n", sbc_filename); 16288a9940aSMilanka Ringwald FILE * wav_file = fopen(wav_filename, "wb"); 163082d19a8SMilanka Ringwald wav_writer_state_t wav_writer_state; 164082d19a8SMilanka Ringwald wav_writer_state.wav_file = wav_file; 16548e0f806SMilanka Ringwald wav_writer_state.frame_count = 0; 16648e0f806SMilanka Ringwald wav_writer_state.total_num_samples = 0; 16748e0f806SMilanka Ringwald 16848e0f806SMilanka Ringwald sbc_decoder_state_t state; 169fcb08cdbSMilanka Ringwald sbc_decoder_init(&state, mode, &handle_pcm_data, (void*)&wav_writer_state); 170082d19a8SMilanka Ringwald write_wav_header(wav_writer_state.wav_file, 0, 0, 0); 17122d3119aSMilanka Ringwald 1727a2baf07SMilanka Ringwald while (1){ 173dc2354f3SMilanka Ringwald // get next chunk 1747a2baf07SMilanka Ringwald int bytes_read = __read(fd, read_buffer, sizeof(read_buffer)); 1757a2baf07SMilanka Ringwald if (0 >= bytes_read) break; 176dc2354f3SMilanka Ringwald // process chunk 17748e0f806SMilanka Ringwald sbc_decoder_process_data(&state, read_buffer, bytes_read); 17888a9940aSMilanka Ringwald } 17922d3119aSMilanka Ringwald 18088a9940aSMilanka Ringwald rewind(wav_file); 18148e0f806SMilanka Ringwald write_wav_header(wav_writer_state.wav_file, wav_writer_state.total_num_samples, sbc_decoder_num_channels(&state), sbc_decoder_sample_rate(&state)); 18288a9940aSMilanka Ringwald 18388a9940aSMilanka Ringwald fclose(wav_file); 18488a9940aSMilanka Ringwald close(fd); 185082d19a8SMilanka Ringwald 18648e0f806SMilanka Ringwald printf("Write %d frames to wav file: %s\n", wav_writer_state.frame_count, wav_filename); 187082d19a8SMilanka Ringwald 18888a9940aSMilanka Ringwald } 189