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>
521ff8adc5SMilanka Ringwald
5388a9940aSMilanka Ringwald #include "oi_assert.h"
5488a9940aSMilanka Ringwald
55aa6493c2SMilanka Ringwald #include "btstack.h"
560c87db9eSMilanka Ringwald #include "btstack_sbc.h"
57aa6493c2SMilanka Ringwald
58249f614dSMilanka Ringwald #include "wav_util.h"
5988a9940aSMilanka Ringwald
60e1df0eeaSMilanka Ringwald static uint8_t read_buffer[118];
61249f614dSMilanka Ringwald static int total_num_samples = 0;
62249f614dSMilanka Ringwald static int frame_count = 0;
63e1df0eeaSMilanka Ringwald static int wav_writer_opened = 0;
64e1df0eeaSMilanka Ringwald static char wav_filename[1000];
65082d19a8SMilanka Ringwald
66d6ec9a32SMilanka Ringwald static uint8_t indices0[] = { 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d,
67d6ec9a32SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
68d6ec9a32SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
69d6ec9a32SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
70d6ec9a32SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c};
71d6ec9a32SMilanka Ringwald
72d6ec9a32SMilanka Ringwald
show_usage(void)7388a9940aSMilanka Ringwald static void show_usage(void){
74d6ec9a32SMilanka Ringwald printf("\n\nUsage: ./sbc_decoder_test input_file [0-sbc|1-msbc] enable_partial_frame_corruption enable_plc corrupt_whole_frame_period \n\n");
75d6ec9a32SMilanka Ringwald printf("Example: ./sbc_decoder_test data/data/sine-stereo 0 1 0 0\n");
76d6ec9a32SMilanka Ringwald printf("Example: ./sbc_decoder_test data/data/sine-stereo 1 1 0 0\n\n");
7788a9940aSMilanka Ringwald }
7888a9940aSMilanka Ringwald
__read(int fd,void * buf,size_t count)7988a9940aSMilanka Ringwald static ssize_t __read(int fd, void *buf, size_t count){
8088a9940aSMilanka Ringwald ssize_t len, pos = 0;
8188a9940aSMilanka Ringwald
8288a9940aSMilanka Ringwald while (count > 0) {
83249f614dSMilanka Ringwald len = read(fd, (int8_t * )buf + pos, count);
8488a9940aSMilanka Ringwald if (len <= 0)
8588a9940aSMilanka Ringwald return pos;
8688a9940aSMilanka Ringwald
8788a9940aSMilanka Ringwald count -= len;
8888a9940aSMilanka Ringwald pos += len;
8988a9940aSMilanka Ringwald }
9088a9940aSMilanka Ringwald return pos;
9188a9940aSMilanka Ringwald }
9288a9940aSMilanka Ringwald
handle_pcm_data(int16_t * data,int num_samples,int num_channels,int sample_rate,void * context)93082d19a8SMilanka Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
946276d22aSMilanka Ringwald UNUSED(context);
95e1df0eeaSMilanka Ringwald if (!wav_writer_opened){
96e1df0eeaSMilanka Ringwald wav_writer_opened = 1;
97e1df0eeaSMilanka Ringwald wav_writer_open(wav_filename, num_channels, sample_rate);
989846e07cSMilanka Ringwald
99e1df0eeaSMilanka Ringwald }
100e1df0eeaSMilanka Ringwald
101d6ec9a32SMilanka Ringwald // printf("Sampels: num_samples %u, num_channels %u, sample_rate %u\n", num_samples, num_channels, sample_rate);
1029846e07cSMilanka Ringwald // printf_hexdump(data, num_samples * num_channels * 2);
103d6ec9a32SMilanka Ringwald // int i;
104d6ec9a32SMilanka Ringwald // for (i=0;i<num_channels*num_samples;i += 2){
105d6ec9a32SMilanka Ringwald // if ((i%24) == 0) printf("\n");
106d6ec9a32SMilanka Ringwald // printf ("%12d ", data[i]);
107d6ec9a32SMilanka Ringwald // }
108d6ec9a32SMilanka Ringwald // printf("\n");
109e1df0eeaSMilanka Ringwald wav_writer_write_int16(num_samples*num_channels, data);
110e1df0eeaSMilanka Ringwald
111e1df0eeaSMilanka Ringwald total_num_samples+=num_samples*num_channels;
112249f614dSMilanka Ringwald frame_count++;
113082d19a8SMilanka Ringwald }
114082d19a8SMilanka Ringwald
main(int argc,const char * argv[])11588a9940aSMilanka Ringwald int main (int argc, const char * argv[]){
116d6ec9a32SMilanka Ringwald if (argc < 6){
11788a9940aSMilanka Ringwald show_usage();
11888a9940aSMilanka Ringwald return -1;
11988a9940aSMilanka Ringwald }
12088a9940aSMilanka Ringwald
121fd1cbf30SMatthias Ringwald char sbc_filename[1000];
122e1df0eeaSMilanka Ringwald int argv_pos = 1;
123e1df0eeaSMilanka Ringwald const char * filename = argv[argv_pos++];
124e1df0eeaSMilanka Ringwald
125e1df0eeaSMilanka Ringwald btstack_sbc_mode_t mode = atoi(argv[argv_pos++]) == 0? SBC_MODE_STANDARD : SBC_MODE_mSBC;
126d6ec9a32SMilanka Ringwald const int partial_frame_corruption = atoi(argv[argv_pos++]);
127e1df0eeaSMilanka Ringwald const int plc_enabled = atoi(argv[argv_pos++]);
128e1df0eeaSMilanka Ringwald const int corrupt_frame_period = atoi(argv[argv_pos++]);
129743c1aeaSMilanka Ringwald
130d6ec9a32SMilanka Ringwald static unsigned g_phase = 0;
131d6ec9a32SMilanka Ringwald static unsigned g_phase2 = 0;
132d6ec9a32SMilanka Ringwald
133743c1aeaSMilanka Ringwald strcpy(sbc_filename, filename);
134743c1aeaSMilanka Ringwald strcpy(wav_filename, filename);
135743c1aeaSMilanka Ringwald
136611ca09fSMilanka Ringwald printf("\n");
137743c1aeaSMilanka Ringwald if (mode == SBC_MODE_mSBC){
138e1df0eeaSMilanka Ringwald printf("Using SBC_MODE_mSBC mode.\n");
139743c1aeaSMilanka Ringwald strcat(sbc_filename, ".msbc");
140743c1aeaSMilanka Ringwald } else {
141e1df0eeaSMilanka Ringwald printf("Using SBC_MODE_STANDARD mode.\n");
142743c1aeaSMilanka Ringwald strcat(sbc_filename, ".sbc");
143743c1aeaSMilanka Ringwald }
144743c1aeaSMilanka Ringwald
145743c1aeaSMilanka Ringwald if (plc_enabled){
146e1df0eeaSMilanka Ringwald printf("PLC enabled.\n");
1479846e07cSMilanka Ringwald strcat(wav_filename, "_decoded_bludroid_plc.wav");
148743c1aeaSMilanka Ringwald } else {
149e1df0eeaSMilanka Ringwald printf("PLC disbled.\n");
1509846e07cSMilanka Ringwald strcat(wav_filename, "_decoded_bludroid.wav");
151fcb08cdbSMilanka Ringwald }
15288a9940aSMilanka Ringwald
153e1df0eeaSMilanka Ringwald if (corrupt_frame_period > 0){
154e1df0eeaSMilanka Ringwald printf("Corrupt frame period: every %d frames.\n", corrupt_frame_period);
155e1df0eeaSMilanka Ringwald }
156e1df0eeaSMilanka Ringwald
157249f614dSMilanka Ringwald
15888a9940aSMilanka Ringwald int fd = open(sbc_filename, O_RDONLY);
15988a9940aSMilanka Ringwald if (fd < 0) {
16088a9940aSMilanka Ringwald printf("Can't open file %s", sbc_filename);
16188a9940aSMilanka Ringwald return -1;
16288a9940aSMilanka Ringwald }
16388a9940aSMilanka Ringwald printf("Open sbc file: %s\n", sbc_filename);
164249f614dSMilanka Ringwald
16548e0f806SMilanka Ringwald
1662afeea7fSMilanka Ringwald btstack_sbc_decoder_state_t state;
167249f614dSMilanka Ringwald btstack_sbc_decoder_init(&state, mode, &handle_pcm_data, NULL);
168249f614dSMilanka Ringwald
169d6ec9a32SMilanka Ringwald if (!plc_enabled){
170*9137e118SMatthias Ringwald btstack_sbc_decoder_test_set_plc_enabled(0);
171d6ec9a32SMilanka Ringwald }
172743c1aeaSMilanka Ringwald if (corrupt_frame_period > 0){
1732afeea7fSMilanka Ringwald btstack_sbc_decoder_test_simulate_corrupt_frames(corrupt_frame_period);
174743c1aeaSMilanka Ringwald }
175743c1aeaSMilanka Ringwald
1767a2baf07SMilanka Ringwald while (1){
177dc2354f3SMilanka Ringwald // get next chunk
1787a2baf07SMilanka Ringwald int bytes_read = __read(fd, read_buffer, sizeof(read_buffer));
1797a2baf07SMilanka Ringwald if (0 >= bytes_read) break;
180d6ec9a32SMilanka Ringwald
181d6ec9a32SMilanka Ringwald if (partial_frame_corruption) {
182d6ec9a32SMilanka Ringwald // Inject errors every now and then.
183d6ec9a32SMilanka Ringwald if ((g_phase & 0x7f) >= 128-8){
184d6ec9a32SMilanka Ringwald uint8_t * data = indices0;
185d6ec9a32SMilanka Ringwald data[g_phase2] = 0xff;
186d6ec9a32SMilanka Ringwald g_phase2++;
187d6ec9a32SMilanka Ringwald } else {
188d6ec9a32SMilanka Ringwald g_phase2 = 0;
189d6ec9a32SMilanka Ringwald }
190d6ec9a32SMilanka Ringwald g_phase++;
191d6ec9a32SMilanka Ringwald }
192d6ec9a32SMilanka Ringwald
193d6ec9a32SMilanka Ringwald btstack_sbc_decoder_process_data(&state, 0, indices0, sizeof(indices0));
19488a9940aSMilanka Ringwald }
19522d3119aSMilanka Ringwald
196249f614dSMilanka Ringwald wav_writer_close();
19788a9940aSMilanka Ringwald close(fd);
198611ca09fSMilanka Ringwald int total_frames_nr = state.good_frames_nr + state.bad_frames_nr + state.zero_frames_nr;
199082d19a8SMilanka Ringwald
200d6ec9a32SMilanka Ringwald printf("WAV Writer: Decoding done. Processed totaly %d frames:\n - %d good\n - %d bad\n", total_frames_nr, state.good_frames_nr, total_frames_nr - state.good_frames_nr);
201249f614dSMilanka Ringwald printf("Write %d frames to wav file: %s\n\n", frame_count, wav_filename);
202082d19a8SMilanka Ringwald
20388a9940aSMilanka Ringwald }
204