1*88a9940aSMilanka Ringwald /* 2*88a9940aSMilanka Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*88a9940aSMilanka Ringwald * 4*88a9940aSMilanka Ringwald * Redistribution and use in source and binary forms, with or without 5*88a9940aSMilanka Ringwald * modification, are permitted provided that the following conditions 6*88a9940aSMilanka Ringwald * are met: 7*88a9940aSMilanka Ringwald * 8*88a9940aSMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 9*88a9940aSMilanka Ringwald * notice, this list of conditions and the following disclaimer. 10*88a9940aSMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*88a9940aSMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 12*88a9940aSMilanka Ringwald * documentation and/or other materials provided with the distribution. 13*88a9940aSMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 14*88a9940aSMilanka Ringwald * contributors may be used to endorse or promote products derived 15*88a9940aSMilanka Ringwald * from this software without specific prior written permission. 16*88a9940aSMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 17*88a9940aSMilanka Ringwald * personal benefit and not for any commercial purpose or for 18*88a9940aSMilanka Ringwald * monetary gain. 19*88a9940aSMilanka Ringwald * 20*88a9940aSMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*88a9940aSMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*88a9940aSMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*88a9940aSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*88a9940aSMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*88a9940aSMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*88a9940aSMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*88a9940aSMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*88a9940aSMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*88a9940aSMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*88a9940aSMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*88a9940aSMilanka Ringwald * SUCH DAMAGE. 32*88a9940aSMilanka Ringwald * 33*88a9940aSMilanka Ringwald * Please inquire about commercial licensing options at 34*88a9940aSMilanka Ringwald * [email protected] 35*88a9940aSMilanka Ringwald * 36*88a9940aSMilanka Ringwald */ 37*88a9940aSMilanka Ringwald 38*88a9940aSMilanka Ringwald // ***************************************************************************** 39*88a9940aSMilanka Ringwald // 40*88a9940aSMilanka Ringwald // SBC decoder tests 41*88a9940aSMilanka Ringwald // 42*88a9940aSMilanka Ringwald // ***************************************************************************** 43*88a9940aSMilanka Ringwald 44*88a9940aSMilanka Ringwald #include "btstack_config.h" 45*88a9940aSMilanka Ringwald 46*88a9940aSMilanka Ringwald #include <stdint.h> 47*88a9940aSMilanka Ringwald #include <stdio.h> 48*88a9940aSMilanka Ringwald #include <stdlib.h> 49*88a9940aSMilanka Ringwald #include <string.h> 50*88a9940aSMilanka Ringwald #include <fcntl.h> 51*88a9940aSMilanka Ringwald #include <unistd.h> 52*88a9940aSMilanka Ringwald #include "oi_codec_sbc.h" 53*88a9940aSMilanka Ringwald #include "oi_assert.h" 54*88a9940aSMilanka Ringwald 55*88a9940aSMilanka Ringwald 56*88a9940aSMilanka Ringwald static uint8_t data[10000]; 57*88a9940aSMilanka Ringwald static OI_INT16 pcmData[1000]; 58*88a9940aSMilanka Ringwald static uint8_t buf[4]; 59*88a9940aSMilanka Ringwald 60*88a9940aSMilanka Ringwald static OI_UINT32 decoderData[10000]; 61*88a9940aSMilanka Ringwald static OI_CODEC_SBC_DECODER_CONTEXT context; 62*88a9940aSMilanka Ringwald 63*88a9940aSMilanka Ringwald void OI_AssertFail(char* file, int line, char* reason){ 64*88a9940aSMilanka Ringwald printf("AssertFail file %s, line %d, reason %s\n", file, line, reason); 65*88a9940aSMilanka Ringwald } 66*88a9940aSMilanka Ringwald 67*88a9940aSMilanka Ringwald static void show_usage(void){ 68*88a9940aSMilanka Ringwald printf("Usage: ./sbc_decoder_test input.sbc"); 69*88a9940aSMilanka Ringwald } 70*88a9940aSMilanka Ringwald 71*88a9940aSMilanka Ringwald static ssize_t __read(int fd, void *buf, size_t count){ 72*88a9940aSMilanka Ringwald ssize_t len, pos = 0; 73*88a9940aSMilanka Ringwald 74*88a9940aSMilanka Ringwald while (count > 0) { 75*88a9940aSMilanka Ringwald len = read(fd, buf + pos, count); 76*88a9940aSMilanka Ringwald if (len <= 0) 77*88a9940aSMilanka Ringwald return pos; 78*88a9940aSMilanka Ringwald 79*88a9940aSMilanka Ringwald count -= len; 80*88a9940aSMilanka Ringwald pos += len; 81*88a9940aSMilanka Ringwald } 82*88a9940aSMilanka Ringwald return pos; 83*88a9940aSMilanka Ringwald } 84*88a9940aSMilanka Ringwald 85*88a9940aSMilanka Ringwald void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){ 86*88a9940aSMilanka Ringwald buffer[pos++] = value; 87*88a9940aSMilanka Ringwald buffer[pos++] = value >> 8; 88*88a9940aSMilanka Ringwald } 89*88a9940aSMilanka Ringwald 90*88a9940aSMilanka Ringwald void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){ 91*88a9940aSMilanka Ringwald buffer[pos++] = value; 92*88a9940aSMilanka Ringwald buffer[pos++] = value >> 8; 93*88a9940aSMilanka Ringwald buffer[pos++] = value >> 16; 94*88a9940aSMilanka Ringwald buffer[pos++] = value >> 24; 95*88a9940aSMilanka Ringwald } 96*88a9940aSMilanka Ringwald 97*88a9940aSMilanka Ringwald void little_endian_fstore_16(FILE *wav_file, uint16_t value){ 98*88a9940aSMilanka Ringwald little_endian_store_32(buf, 0, value); 99*88a9940aSMilanka Ringwald fwrite(&buf, 1, 2, wav_file); 100*88a9940aSMilanka Ringwald } 101*88a9940aSMilanka Ringwald 102*88a9940aSMilanka Ringwald void little_endian_fstore_32(FILE *wav_file, uint32_t value){ 103*88a9940aSMilanka Ringwald little_endian_store_32(buf, 0, value); 104*88a9940aSMilanka Ringwald fwrite(&buf, 1, 4, wav_file); 105*88a9940aSMilanka Ringwald } 106*88a9940aSMilanka Ringwald 107*88a9940aSMilanka Ringwald static void write_wav_header(FILE * wav_file, int num_samples, int num_channels, int sample_rate, int frame_count){ 108*88a9940aSMilanka Ringwald unsigned int bytes_per_sample = 2; 109*88a9940aSMilanka Ringwald 110*88a9940aSMilanka Ringwald /* write RIFF header */ 111*88a9940aSMilanka Ringwald fwrite("RIFF", 1, 4, wav_file); 112*88a9940aSMilanka Ringwald // num_samples = blocks * subbands 113*88a9940aSMilanka Ringwald uint32_t data_bytes = (uint32_t) (bytes_per_sample * num_samples * frame_count * num_channels); 114*88a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes + 36); 115*88a9940aSMilanka Ringwald fwrite("WAVE", 1, 4, wav_file); 116*88a9940aSMilanka Ringwald 117*88a9940aSMilanka Ringwald int byte_rate = sample_rate * num_channels * bytes_per_sample; 118*88a9940aSMilanka Ringwald int bits_per_sample = 8 * bytes_per_sample; 119*88a9940aSMilanka Ringwald int block_align = num_channels * bits_per_sample; 120*88a9940aSMilanka Ringwald int fmt_length = 16; 121*88a9940aSMilanka Ringwald int fmt_format_tag = 1; // PCM 122*88a9940aSMilanka Ringwald 123*88a9940aSMilanka Ringwald /* write fmt chunk */ 124*88a9940aSMilanka Ringwald fwrite("fmt ", 1, 4, wav_file); 125*88a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, fmt_length); 126*88a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, fmt_format_tag); 127*88a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, num_channels); 128*88a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, sample_rate); 129*88a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, byte_rate); 130*88a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, block_align); 131*88a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, bits_per_sample); 132*88a9940aSMilanka Ringwald 133*88a9940aSMilanka Ringwald /* write data chunk */ 134*88a9940aSMilanka Ringwald fwrite("data", 1, 4, wav_file); 135*88a9940aSMilanka Ringwald little_endian_fstore_32(wav_file, data_bytes); 136*88a9940aSMilanka Ringwald } 137*88a9940aSMilanka Ringwald 138*88a9940aSMilanka Ringwald static void write_wav_data(FILE * wav_file, unsigned long num_samples, unsigned int num_channels, int16_t * data){ 139*88a9940aSMilanka Ringwald int i; 140*88a9940aSMilanka Ringwald for (i=0; i < num_samples; i++){ 141*88a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, (uint16_t)data[i]); 142*88a9940aSMilanka Ringwald if (num_channels == 2){ 143*88a9940aSMilanka Ringwald little_endian_fstore_16(wav_file, (uint16_t)data); 144*88a9940aSMilanka Ringwald } 145*88a9940aSMilanka Ringwald } 146*88a9940aSMilanka Ringwald } 147*88a9940aSMilanka Ringwald 148*88a9940aSMilanka Ringwald 149*88a9940aSMilanka Ringwald int main (int argc, const char * argv[]){ 150*88a9940aSMilanka Ringwald if (argc < 2){ 151*88a9940aSMilanka Ringwald show_usage(); 152*88a9940aSMilanka Ringwald return -1; 153*88a9940aSMilanka Ringwald } 154*88a9940aSMilanka Ringwald 155*88a9940aSMilanka Ringwald const char * sbc_filename = argv[1]; 156*88a9940aSMilanka Ringwald const char * wav_filename = argv[2]; 157*88a9940aSMilanka Ringwald 158*88a9940aSMilanka Ringwald 159*88a9940aSMilanka Ringwald int fd = open(sbc_filename, O_RDONLY); 160*88a9940aSMilanka Ringwald if (fd < 0) { 161*88a9940aSMilanka Ringwald printf("Can't open file %s", sbc_filename); 162*88a9940aSMilanka Ringwald return -1; 163*88a9940aSMilanka Ringwald } 164*88a9940aSMilanka Ringwald printf("Open sbc file: %s\n", sbc_filename); 165*88a9940aSMilanka Ringwald 166*88a9940aSMilanka Ringwald OI_UINT32 frameBytes = 0; 167*88a9940aSMilanka Ringwald 168*88a9940aSMilanka Ringwald OI_UINT32 bytesRead = __read(fd, data, sizeof(data)); 169*88a9940aSMilanka Ringwald frameBytes += bytesRead; 170*88a9940aSMilanka Ringwald const OI_BYTE *frameData = data; 171*88a9940aSMilanka Ringwald 172*88a9940aSMilanka Ringwald OI_UINT32 pcmBytes = sizeof(pcmData); 173*88a9940aSMilanka Ringwald 174*88a9940aSMilanka Ringwald OI_STATUS status = OI_CODEC_SBC_DecoderReset(&context, decoderData, sizeof(decoderData), 1, 1, FALSE); 175*88a9940aSMilanka Ringwald 176*88a9940aSMilanka Ringwald if (status != 0){ 177*88a9940aSMilanka Ringwald printf("Reset decoder error %d\n", status); 178*88a9940aSMilanka Ringwald return -1; 179*88a9940aSMilanka Ringwald } 180*88a9940aSMilanka Ringwald 181*88a9940aSMilanka Ringwald int num_samples = 0; 182*88a9940aSMilanka Ringwald int num_channels = 0; 183*88a9940aSMilanka Ringwald int sample_rate = 0; 184*88a9940aSMilanka Ringwald int frame_count = 0; 185*88a9940aSMilanka Ringwald FILE * wav_file = fopen(wav_filename, "wb"); 186*88a9940aSMilanka Ringwald 187*88a9940aSMilanka Ringwald while (frameBytes != 0){ 188*88a9940aSMilanka Ringwald status = OI_CODEC_SBC_DecodeFrame(&context, &frameData, &frameBytes, pcmData, &pcmBytes); 189*88a9940aSMilanka Ringwald num_samples = context.common.frameInfo.nrof_blocks * context.common.frameInfo.nrof_subbands; 190*88a9940aSMilanka Ringwald num_channels = context.common.frameInfo.nrof_channels; 191*88a9940aSMilanka Ringwald sample_rate = context.common.frameInfo.frequency; 192*88a9940aSMilanka Ringwald 193*88a9940aSMilanka Ringwald if (status != 0){ 194*88a9940aSMilanka Ringwald if (status != OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA && status != OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA){ 195*88a9940aSMilanka Ringwald printf("Frame decode error %d\n", status); 196*88a9940aSMilanka Ringwald break; 197*88a9940aSMilanka Ringwald } 198*88a9940aSMilanka Ringwald printf("Not enough data, read next %u bytes\n", bytesRead-frameBytes); 199*88a9940aSMilanka Ringwald 200*88a9940aSMilanka Ringwald memmove(data, data + bytesRead - frameBytes, frameBytes); 201*88a9940aSMilanka Ringwald bytesRead = __read(fd, data + frameBytes, sizeof(data) - frameBytes); 202*88a9940aSMilanka Ringwald frameBytes += bytesRead; 203*88a9940aSMilanka Ringwald bytesRead = frameBytes; 204*88a9940aSMilanka Ringwald frameData = data; 205*88a9940aSMilanka Ringwald continue; 206*88a9940aSMilanka Ringwald } 207*88a9940aSMilanka Ringwald 208*88a9940aSMilanka Ringwald if (frame_count == 0){ 209*88a9940aSMilanka Ringwald write_wav_header(wav_file, num_samples, num_channels, sample_rate, 0); 210*88a9940aSMilanka Ringwald } 211*88a9940aSMilanka Ringwald 212*88a9940aSMilanka Ringwald write_wav_data(wav_file, num_samples, num_channels, pcmData); 213*88a9940aSMilanka Ringwald frame_count++; 214*88a9940aSMilanka Ringwald } 215*88a9940aSMilanka Ringwald rewind(wav_file); 216*88a9940aSMilanka Ringwald write_wav_header(wav_file, num_samples, num_channels, sample_rate, frame_count); 217*88a9940aSMilanka Ringwald 218*88a9940aSMilanka Ringwald fclose(wav_file); 219*88a9940aSMilanka Ringwald printf("Write %d frames to wav file: %s\n", frame_count, wav_filename); 220*88a9940aSMilanka Ringwald 221*88a9940aSMilanka Ringwald close(fd); 222*88a9940aSMilanka Ringwald } 223