xref: /btstack/test/sbc/sbc_decoder_test.c (revision 9137e11839e2a0b1e3e7aa4004cdc3877f9a1a3f)
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