1 /* 2 * Copyright (C) 2014 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 // SBC decoder tests 41 // 42 // ***************************************************************************** 43 44 #include "btstack_config.h" 45 46 #include <stdint.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <fcntl.h> 51 #include <unistd.h> 52 #include "oi_codec_sbc.h" 53 #include "oi_assert.h" 54 55 56 static uint8_t data[10000]; 57 static OI_INT16 pcmData[1000]; 58 static OI_UINT32 pcmBytes = sizeof(pcmData); 59 60 static uint8_t buf[4]; 61 62 static OI_UINT32 decoderData[10000]; 63 static OI_CODEC_SBC_DECODER_CONTEXT context; 64 65 typedef struct { 66 OI_UINT32 bytesRead; 67 OI_UINT32 frameBytes; 68 OI_UINT32 inputBufferBytes; 69 int frame_count; 70 int enough_data; 71 const OI_BYTE *frameData; 72 } sbc_state_t; 73 static sbc_state_t state; 74 75 76 void OI_AssertFail(char* file, int line, char* reason){ 77 printf("AssertFail file %s, line %d, reason %s\n", file, line, reason); 78 } 79 80 static void show_usage(void){ 81 printf("Usage: ./sbc_decoder_test input.sbc"); 82 } 83 84 static ssize_t __read(int fd, void *buf, size_t count){ 85 ssize_t len, pos = 0; 86 87 while (count > 0) { 88 len = read(fd, buf + pos, count); 89 if (len <= 0) 90 return pos; 91 92 count -= len; 93 pos += len; 94 } 95 return pos; 96 } 97 98 void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 99 buffer[pos++] = value; 100 buffer[pos++] = value >> 8; 101 } 102 103 void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 104 buffer[pos++] = value; 105 buffer[pos++] = value >> 8; 106 buffer[pos++] = value >> 16; 107 buffer[pos++] = value >> 24; 108 } 109 110 void little_endian_fstore_16(FILE *wav_file, uint16_t value){ 111 little_endian_store_32(buf, 0, value); 112 fwrite(&buf, 1, 2, wav_file); 113 } 114 115 void little_endian_fstore_32(FILE *wav_file, uint32_t value){ 116 little_endian_store_32(buf, 0, value); 117 fwrite(&buf, 1, 4, wav_file); 118 } 119 120 121 static void write_wav_header(FILE * wav_file, OI_CODEC_SBC_DECODER_CONTEXT * decoderContext, int frame_count){ 122 unsigned int bytes_per_sample = 2; 123 int num_samples = decoderContext->common.frameInfo.nrof_blocks * decoderContext->common.frameInfo.nrof_subbands; 124 int num_channels = decoderContext->common.frameInfo.nrof_channels; 125 int sample_rate = decoderContext->common.frameInfo.frequency; 126 127 /* write RIFF header */ 128 fwrite("RIFF", 1, 4, wav_file); 129 // num_samples = blocks * subbands 130 uint32_t data_bytes = (uint32_t) (bytes_per_sample * num_samples * frame_count * num_channels); 131 little_endian_fstore_32(wav_file, data_bytes + 36); 132 fwrite("WAVE", 1, 4, wav_file); 133 134 int byte_rate = sample_rate * num_channels * bytes_per_sample; 135 int bits_per_sample = 8 * bytes_per_sample; 136 int block_align = num_channels * bits_per_sample; 137 int fmt_length = 16; 138 int fmt_format_tag = 1; // PCM 139 140 /* write fmt chunk */ 141 fwrite("fmt ", 1, 4, wav_file); 142 little_endian_fstore_32(wav_file, fmt_length); 143 little_endian_fstore_16(wav_file, fmt_format_tag); 144 little_endian_fstore_16(wav_file, num_channels); 145 little_endian_fstore_32(wav_file, sample_rate); 146 little_endian_fstore_32(wav_file, byte_rate); 147 little_endian_fstore_16(wav_file, block_align); 148 little_endian_fstore_16(wav_file, bits_per_sample); 149 150 /* write data chunk */ 151 fwrite("data", 1, 4, wav_file); 152 little_endian_fstore_32(wav_file, data_bytes); 153 } 154 155 static void write_wav_data(FILE * wav_file, OI_CODEC_SBC_DECODER_CONTEXT * decoderContext, int16_t * data){ 156 int num_samples = decoderContext->common.frameInfo.nrof_blocks * decoderContext->common.frameInfo.nrof_subbands; 157 int num_channels = decoderContext->common.frameInfo.nrof_channels; 158 int i; 159 for (i=0; i < num_samples; i++){ 160 little_endian_fstore_16(wav_file, (uint16_t)data[i]); 161 if (num_channels == 2){ 162 little_endian_fstore_16(wav_file, (uint16_t)data); 163 } 164 } 165 } 166 167 168 169 static uint8_t read_buffer[200]; 170 171 static int read_next_sbc_chunk(int fd, sbc_state_t * state){ 172 // read data into seperate buffer 173 state->bytesRead = __read(fd, data + state->frameBytes, sizeof(data) - state->frameBytes); 174 state->frameBytes += state->bytesRead; 175 state->bytesRead = state->frameBytes; 176 state->frameData = data; 177 state->enough_data = 1; 178 return state->frameBytes != 0; 179 180 // uint16_t size = __read(fd, read_buffer, sizeof(read_buffer)); 181 // return size != 0; 182 } 183 184 185 static void handle_received_sbc_data(sbc_state_t * state, uint8_t * read_buffer, int read_buffer_len){ 186 int numFreeBytes = sizeof(data) - state->frameBytes; 187 188 if (numFreeBytes >= read_buffer_len){ 189 memcpy(data + state->frameBytes, read_buffer, read_buffer_len); 190 state->bytesRead = read_buffer_len; 191 state->inputBufferBytes = 0; 192 } else { 193 memcpy(data + state->frameBytes, read_buffer, numFreeBytes); 194 state->bytesRead = numFreeBytes; 195 state->inputBufferBytes = read_buffer_len - numFreeBytes; 196 } 197 state->frameBytes += state->bytesRead; 198 state->bytesRead = state->frameBytes; 199 state->frameData = data; 200 state->enough_data = 1; 201 } 202 203 // { 204 // while (not done){ 205 // read some data (max size) using __read or even direct read 206 // handle received sbc data 207 // } 208 // } 209 210 static void init_sbc_state(sbc_state_t * state){ 211 state->frameBytes = 0; 212 state->bytesRead = 0; 213 state->frame_count = 0; 214 state->enough_data = 0; 215 state->inputBufferBytes = 0; 216 state->frameData = NULL; 217 } 218 219 int main (int argc, const char * argv[]){ 220 if (argc < 2){ 221 show_usage(); 222 return -1; 223 } 224 225 const char * sbc_filename = argv[1]; 226 const char * wav_filename = argv[2]; 227 228 229 int fd = open(sbc_filename, O_RDONLY); 230 if (fd < 0) { 231 printf("Can't open file %s", sbc_filename); 232 return -1; 233 } 234 printf("Open sbc file: %s\n", sbc_filename); 235 236 //OI_STATUS status = OI_CODEC_SBC_DecoderReset(&context, decoderData, sizeof(decoderData), 1, 1, FALSE); 237 238 OI_STATUS status = OI_CODEC_mSBC_DecoderReset(&context, decoderData, sizeof(decoderData)); 239 if (status != 0){ 240 printf("Reset decoder error %d\n", status); 241 return -1; 242 } 243 244 FILE * wav_file = fopen(wav_filename, "wb"); 245 246 init_sbc_state(&state); 247 248 while (read_next_sbc_chunk(fd, &state)){ 249 while (state.frameBytes != 0 && state.enough_data){ 250 251 status = OI_CODEC_SBC_DecodeFrame(&context, &state.frameData, &state.frameBytes, pcmData, &pcmBytes); 252 253 if (status != 0){ 254 if (status != OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA && status != OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA){ 255 OI_CODEC_SBC_DumpConfig(&(context. common.frameInfo)); 256 printf("Frame decode error %d\n", status); 257 break; 258 } 259 printf("Not enough data, read next %u bytes\n", state.bytesRead-state.frameBytes); 260 state.enough_data = 0; 261 memmove(data, data + state.bytesRead - state.frameBytes, state.frameBytes); 262 continue; 263 } 264 265 if (state.frame_count == 0){ 266 write_wav_header(wav_file, &context, 0); 267 } 268 write_wav_data(wav_file, &context, pcmData); 269 state.frame_count++; 270 } 271 272 } 273 274 rewind(wav_file); 275 write_wav_header(wav_file, &context, state.frame_count); 276 277 fclose(wav_file); 278 printf("Write %d frames to wav file: %s\n", state.frame_count, wav_filename); 279 280 close(fd); 281 } 282