14e074f72SMilanka Ringwald /* 24e074f72SMilanka Ringwald * Copyright (C) 2016 BlueKitchen GmbH 34e074f72SMilanka Ringwald * 44e074f72SMilanka Ringwald * Redistribution and use in source and binary forms, with or without 54e074f72SMilanka Ringwald * modification, are permitted provided that the following conditions 64e074f72SMilanka Ringwald * are met: 74e074f72SMilanka Ringwald * 84e074f72SMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 94e074f72SMilanka Ringwald * notice, this list of conditions and the following disclaimer. 104e074f72SMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 114e074f72SMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 124e074f72SMilanka Ringwald * documentation and/or other materials provided with the distribution. 134e074f72SMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 144e074f72SMilanka Ringwald * contributors may be used to endorse or promote products derived 154e074f72SMilanka Ringwald * from this software without specific prior written permission. 164e074f72SMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 174e074f72SMilanka Ringwald * personal benefit and not for any commercial purpose or for 184e074f72SMilanka Ringwald * monetary gain. 194e074f72SMilanka Ringwald * 204e074f72SMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 214e074f72SMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 224e074f72SMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 234e074f72SMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 244e074f72SMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 254e074f72SMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 264e074f72SMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 274e074f72SMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 284e074f72SMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 294e074f72SMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 304e074f72SMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 314e074f72SMilanka Ringwald * SUCH DAMAGE. 324e074f72SMilanka Ringwald * 334e074f72SMilanka Ringwald * Please inquire about commercial licensing options at 344e074f72SMilanka Ringwald * [email protected] 354e074f72SMilanka Ringwald * 364e074f72SMilanka Ringwald */ 374e074f72SMilanka Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_sbc_plc.c" 39ab2c6ae4SMatthias Ringwald 404e074f72SMilanka Ringwald /* 41e7a41128SMilanka Ringwald * btstack_sbc_plc.c 424e074f72SMilanka Ringwald * 434e074f72SMilanka Ringwald */ 444e074f72SMilanka Ringwald 454e074f72SMilanka Ringwald #include <stdint.h> 464e074f72SMilanka Ringwald #include <stdlib.h> 474e074f72SMilanka Ringwald #include <string.h> 484e074f72SMilanka Ringwald 49650b64aaSMilanka Ringwald #ifdef OCTAVE_OUTPUT 50650b64aaSMilanka Ringwald #include <stdio.h> 51650b64aaSMilanka Ringwald #endif 52650b64aaSMilanka Ringwald 534e074f72SMilanka Ringwald #include "btstack_sbc_plc.h" 54de854f9aSMilanka Ringwald #include "btstack_debug.h" 554e074f72SMilanka Ringwald 564e4f6f26SMatthias Ringwald #define SAMPLE_FORMAT int16_t 574e4f6f26SMatthias Ringwald 584e074f72SMilanka Ringwald static uint8_t indices0[] = { 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 594e074f72SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 604e074f72SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 614e074f72SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 624e074f72SMilanka Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c}; 634e074f72SMilanka Ringwald 644e074f72SMilanka Ringwald /* Raised COSine table for OLA */ 657e6b1e83SMilanka Ringwald static float rcos[SBC_OLAL] = { 664e074f72SMilanka Ringwald 0.99148655f,0.96623611f,0.92510857f,0.86950446f, 674e074f72SMilanka Ringwald 0.80131732f,0.72286918f,0.63683150f,0.54613418f, 684e074f72SMilanka Ringwald 0.45386582f,0.36316850f,0.27713082f,0.19868268f, 694e074f72SMilanka Ringwald 0.13049554f,0.07489143f,0.03376389f,0.00851345f}; 704e074f72SMilanka Ringwald 7140e1e61cSMilanka Ringwald // taken from http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi 7240e1e61cSMilanka Ringwald // Algorithm: Babylonian Method + some manipulations on IEEE 32 bit floating point representation 7340e1e61cSMilanka Ringwald static float sqrt3(const float x){ 7440e1e61cSMilanka Ringwald union { 7540e1e61cSMilanka Ringwald int i; 7640e1e61cSMilanka Ringwald float x; 7740e1e61cSMilanka Ringwald } u; 7840e1e61cSMilanka Ringwald u.x = x; 7940e1e61cSMilanka Ringwald u.i = (1<<29) + (u.i >> 1) - (1<<22); 8040e1e61cSMilanka Ringwald 8140e1e61cSMilanka Ringwald // Two Babylonian Steps (simplified from:) 8240e1e61cSMilanka Ringwald // u.x = 0.5f * (u.x + x/u.x); 8340e1e61cSMilanka Ringwald // u.x = 0.5f * (u.x + x/u.x); 84c1ab6cc1SMatthias Ringwald u.x = u.x + (x/u.x); 85c1ab6cc1SMatthias Ringwald u.x = (0.25f*u.x) + (x/u.x); 8640e1e61cSMilanka Ringwald 8740e1e61cSMilanka Ringwald return u.x; 8840e1e61cSMilanka Ringwald } 8940e1e61cSMilanka Ringwald 9040e1e61cSMilanka Ringwald static float absolute(float x){ 9140e1e61cSMilanka Ringwald if (x < 0) x = -x; 9240e1e61cSMilanka Ringwald return x; 9340e1e61cSMilanka Ringwald } 9440e1e61cSMilanka Ringwald 954e4f6f26SMatthias Ringwald static float CrossCorrelation(SAMPLE_FORMAT *x, SAMPLE_FORMAT *y){ 96c5e169ecSMilanka Ringwald float num = 0; 97c5e169ecSMilanka Ringwald float den = 0; 98c5e169ecSMilanka Ringwald float x2 = 0; 99c5e169ecSMilanka Ringwald float y2 = 0; 100c5e169ecSMilanka Ringwald int m; 101c5e169ecSMilanka Ringwald for (m=0;m<SBC_M;m++){ 102c5e169ecSMilanka Ringwald num+=((float)x[m])*y[m]; 103c5e169ecSMilanka Ringwald x2+=((float)x[m])*x[m]; 104c5e169ecSMilanka Ringwald y2+=((float)y[m])*y[m]; 105c5e169ecSMilanka Ringwald } 10640e1e61cSMilanka Ringwald den = (float)sqrt3(x2*y2); 107c5e169ecSMilanka Ringwald return num/den; 108c5e169ecSMilanka Ringwald } 109c5e169ecSMilanka Ringwald 1104e4f6f26SMatthias Ringwald static int PatternMatch(SAMPLE_FORMAT *y){ 1114e4f6f26SMatthias Ringwald float maxCn = -999999.0; // large negative number 112c5e169ecSMilanka Ringwald int bestmatch = 0; 113c5e169ecSMilanka Ringwald float Cn; 114c5e169ecSMilanka Ringwald int n; 115c5e169ecSMilanka Ringwald for (n=0;n<SBC_N;n++){ 1164e4f6f26SMatthias Ringwald Cn = CrossCorrelation(&y[SBC_LHIST-SBC_M], &y[n]); 117c5e169ecSMilanka Ringwald if (Cn>maxCn){ 118c5e169ecSMilanka Ringwald bestmatch=n; 119c5e169ecSMilanka Ringwald maxCn = Cn; 120c5e169ecSMilanka Ringwald } 121c5e169ecSMilanka Ringwald } 122c5e169ecSMilanka Ringwald return bestmatch; 123c5e169ecSMilanka Ringwald } 124c5e169ecSMilanka Ringwald 1254e4f6f26SMatthias Ringwald static float AmplitudeMatch(SAMPLE_FORMAT *y, SAMPLE_FORMAT bestmatch) { 126c5e169ecSMilanka Ringwald int i; 127c5e169ecSMilanka Ringwald float sumx = 0; 128c5e169ecSMilanka Ringwald float sumy = 0.000001f; 129c5e169ecSMilanka Ringwald float sf; 130c5e169ecSMilanka Ringwald 131c5e169ecSMilanka Ringwald for (i=0;i<SBC_FS;i++){ 13240e1e61cSMilanka Ringwald sumx += absolute(y[SBC_LHIST-SBC_FS+i]); 13340e1e61cSMilanka Ringwald sumy += absolute(y[bestmatch+i]); 134c5e169ecSMilanka Ringwald } 135c5e169ecSMilanka Ringwald sf = sumx/sumy; 1364e4f6f26SMatthias Ringwald // This is not in the paper, but limit the scaling factor to something reasonable to avoid creating artifacts 137c5e169ecSMilanka Ringwald if (sf<0.75f) sf=0.75f; 138ee5b2fc6SMilanka Ringwald if (sf>1.0f) sf=1.0f; 139c5e169ecSMilanka Ringwald return sf; 140c5e169ecSMilanka Ringwald } 1414e074f72SMilanka Ringwald 1424e4f6f26SMatthias Ringwald static SAMPLE_FORMAT crop_sample(float val){ 143250a1e4aSMilanka Ringwald float croped_val = val; 144250a1e4aSMilanka Ringwald if (croped_val > 32767.0) croped_val= 32767.0; 145250a1e4aSMilanka Ringwald if (croped_val < -32768.0) croped_val=-32768.0; 1464e4f6f26SMatthias Ringwald return (SAMPLE_FORMAT) croped_val; 1477e6b1e83SMilanka Ringwald } 1487e6b1e83SMilanka Ringwald 149e7a41128SMilanka Ringwald uint8_t * btstack_sbc_plc_zero_signal_frame(void){ 1504e074f72SMilanka Ringwald return (uint8_t *)&indices0; 1514e074f72SMilanka Ringwald } 1524e074f72SMilanka Ringwald 153e7a41128SMilanka Ringwald void btstack_sbc_plc_init(btstack_sbc_plc_state_t *plc_state){ 1544e074f72SMilanka Ringwald plc_state->nbf=0; 1554e074f72SMilanka Ringwald plc_state->bestlag=0; 156b3f76298SMilanka Ringwald memset(plc_state->hist,0,sizeof(plc_state->hist)); 1574e074f72SMilanka Ringwald } 1584e074f72SMilanka Ringwald 159ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 160ee5b2fc6SMilanka Ringwald typedef enum { 161ee5b2fc6SMilanka Ringwald OCTAVE_FRAME_TYPE_UNKNOWN = 0, 162ee5b2fc6SMilanka Ringwald OCTAVE_FRAME_TYPE_GOOD, 163ee5b2fc6SMilanka Ringwald OCTAVE_FRAME_TYPE_BAD 164ee5b2fc6SMilanka Ringwald } octave_frame_type_t; 165ee5b2fc6SMilanka Ringwald 166ee5b2fc6SMilanka Ringwald static const char * octave_frame_type_name[] = { 167ee5b2fc6SMilanka Ringwald "unknown", 168ee5b2fc6SMilanka Ringwald "good", 169ee5b2fc6SMilanka Ringwald "bad" 170ee5b2fc6SMilanka Ringwald }; 171ee5b2fc6SMilanka Ringwald 172ee5b2fc6SMilanka Ringwald static octave_frame_type_t octave_frame_type; 173ee5b2fc6SMilanka Ringwald static char octave_base_name[1000]; 174ee5b2fc6SMilanka Ringwald 175ee5b2fc6SMilanka Ringwald const char * octave_frame_type2str(int index){ 176ee5b2fc6SMilanka Ringwald if (index <= 0 || index >= sizeof(octave_frame_type_t)) return octave_frame_type_name[0]; 177ee5b2fc6SMilanka Ringwald return octave_frame_type_name[index]; 178ee5b2fc6SMilanka Ringwald } 179ee5b2fc6SMilanka Ringwald 180d1550f90SMilanka Ringwald void btstack_sbc_plc_octave_set_base_name(const char * base_name){ 181ee5b2fc6SMilanka Ringwald strcpy(octave_base_name, base_name); 182ee5b2fc6SMilanka Ringwald printf("OCTAVE: base name set to %s\n", octave_base_name); 183ee5b2fc6SMilanka Ringwald } 184ee5b2fc6SMilanka Ringwald 185ee5b2fc6SMilanka Ringwald static void octave_fprintf_array_int16(FILE * oct_file, char * name, int data_len, int16_t * data){ 186ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%s = [", name); 187ee5b2fc6SMilanka Ringwald int i; 188ee5b2fc6SMilanka Ringwald for (i = 0; i < data_len - 1; i++){ 189ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%d, ", data[i]); 190ee5b2fc6SMilanka Ringwald } 191ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%d", data[i]); 192ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%s", "];\n"); 193ee5b2fc6SMilanka Ringwald } 194ee5b2fc6SMilanka Ringwald 195ee5b2fc6SMilanka Ringwald static FILE * open_octave_file(btstack_sbc_plc_state_t *plc_state, octave_frame_type_t frame_type){ 196ee5b2fc6SMilanka Ringwald char oct_file_name[1200]; 197ee5b2fc6SMilanka Ringwald octave_frame_type = frame_type; 198*ff7d6aeaSMatthias Ringwald snprintf(oct_file_name, sizeof(oct_file_name), "%s_octave_plc_%d_%s.m", 199*ff7d6aeaSMatthias Ringwald octave_base_name, plc_state->frame_count, 200*ff7d6aeaSMatthias Ringwald octave_frame_type2str(octave_frame_type)); 201*ff7d6aeaSMatthias Ringwald oct_file_name[sizeof(oct_file_name) - 1] = 0; 202ee5b2fc6SMilanka Ringwald 203ee5b2fc6SMilanka Ringwald FILE * oct_file = fopen(oct_file_name, "wb"); 204ee5b2fc6SMilanka Ringwald if (oct_file == NULL){ 205ee5b2fc6SMilanka Ringwald printf("OCTAVE: could not open file %s\n", oct_file_name); 206ee5b2fc6SMilanka Ringwald return NULL; 207ee5b2fc6SMilanka Ringwald } 208ee5b2fc6SMilanka Ringwald printf("OCTAVE: opened file %s\n", oct_file_name); 209ee5b2fc6SMilanka Ringwald return oct_file; 210ee5b2fc6SMilanka Ringwald } 211ee5b2fc6SMilanka Ringwald 212ee5b2fc6SMilanka Ringwald static void octave_fprintf_plot_history_frame(btstack_sbc_plc_state_t *plc_state, FILE * oct_file, int frame_nr){ 213ee5b2fc6SMilanka Ringwald char title[100]; 214ee5b2fc6SMilanka Ringwald char hist_name[10]; 215*ff7d6aeaSMatthias Ringwald snprintf(hist_name, sizeof(hist_name), "hist%d", plc_state->nbf); 216*ff7d6aeaSMatthias Ringwald hist_name[sizeof(hist_name) - 1] = 0; 217ee5b2fc6SMilanka Ringwald 218ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, hist_name, SBC_LHIST, plc_state->hist); 219ee5b2fc6SMilanka Ringwald 220ee5b2fc6SMilanka Ringwald fprintf(oct_file, "y = [min(%s):1000:max(%s)];\n", hist_name, hist_name); 221ee5b2fc6SMilanka Ringwald fprintf(oct_file, "x = zeros(1, size(y,2));\n"); 222ee5b2fc6SMilanka Ringwald fprintf(oct_file, "b = [0: %d];\n", SBC_LHIST+SBC_FS+SBC_RT+SBC_OLAL); 223ee5b2fc6SMilanka Ringwald 224ee5b2fc6SMilanka Ringwald int pos = SBC_FS; 225ee5b2fc6SMilanka Ringwald fprintf(oct_file, "shift_x = x + %d;\n", pos); 226ee5b2fc6SMilanka Ringwald 227ee5b2fc6SMilanka Ringwald pos = SBC_LHIST - 1; 228ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_x = x + %d;\n", pos); 229ee5b2fc6SMilanka Ringwald pos += SBC_OLAL; 230ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_olal1_x = x + %d;\n", pos); 231ee5b2fc6SMilanka Ringwald pos += SBC_FS - SBC_OLAL; 232ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_fs_x = x + %d;\n", pos); 233ee5b2fc6SMilanka Ringwald pos += SBC_OLAL; 234ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_olal2_x = x + %d;\n", pos); 235ee5b2fc6SMilanka Ringwald pos += SBC_RT; 236ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_rt_x = x + %d;\n", pos); 237ee5b2fc6SMilanka Ringwald 238ee5b2fc6SMilanka Ringwald fprintf(oct_file, "pattern_window_x = x + %d;\n", SBC_LHIST - SBC_M); 239ee5b2fc6SMilanka Ringwald 240ee5b2fc6SMilanka Ringwald fprintf(oct_file, "hf = figure();\n"); 241*ff7d6aeaSMatthias Ringwald snprintf(title, sizeof(title), "PLC %s frame %d", 242*ff7d6aeaSMatthias Ringwald octave_frame_type2str(octave_frame_type), frame_nr); 243*ff7d6aeaSMatthias Ringwald title[sizeof(title) - 1] = 0; 244ee5b2fc6SMilanka Ringwald 245ee5b2fc6SMilanka Ringwald fprintf(oct_file, "hold on;\n"); 246ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h1 = plot(%s); \n", hist_name); 247ee5b2fc6SMilanka Ringwald 248ee5b2fc6SMilanka Ringwald fprintf(oct_file, "title(\"%s\");\n", title); 249ee5b2fc6SMilanka Ringwald 250ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_x, y, 'k'); \n"); 251ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_x) - 10, max(y)+1000, 'lhist'); \n"); 252ee5b2fc6SMilanka Ringwald 253ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_olal1_x, y, 'k'); \n"); 254ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_olal1_x) - 10, max(y)+1000, 'OLAL'); \n"); 255ee5b2fc6SMilanka Ringwald 256ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_fs_x, y, 'k'); \n"); 257ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_fs_x) - 10, max(y)+1000, 'FS'); \n"); 258ee5b2fc6SMilanka Ringwald 259ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_olal2_x, y, 'k'); \n"); 260ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_olal2_x) - 10, max(y)+1000, 'OLAL'); \n"); 261ee5b2fc6SMilanka Ringwald 262ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_rt_x, y, 'k');\n"); 263ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_rt_x) - 10, max(y)+1000, 'RT'); \n"); 264ee5b2fc6SMilanka Ringwald 265ee5b2fc6SMilanka Ringwald if (octave_frame_type == OCTAVE_FRAME_TYPE_GOOD) return; 266ee5b2fc6SMilanka Ringwald 267ee5b2fc6SMilanka Ringwald int x0 = plc_state->bestlag; 268ee5b2fc6SMilanka Ringwald int x1 = plc_state->bestlag + SBC_M - 1; 269ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'rd'); \n", x0, x1, hist_name, x0, x1); 270ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(%d - 10, -10, 'bestlag'); \n", x0); 271ee5b2fc6SMilanka Ringwald 272ee5b2fc6SMilanka Ringwald x0 = plc_state->bestlag + SBC_M ; 273ee5b2fc6SMilanka Ringwald x1 = plc_state->bestlag + SBC_M + SBC_FS - 1; 274ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'kd'); \n", x0, x1, hist_name, x0, x1); 275ee5b2fc6SMilanka Ringwald 276ee5b2fc6SMilanka Ringwald x0 = SBC_LHIST - SBC_M; 277ee5b2fc6SMilanka Ringwald x1 = SBC_LHIST - 1; 278ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'rd'); \n", x0, x1, hist_name, x0, x1); 279ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(pattern_window_x, y, 'g'); \n"); 280ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(pattern_window_x) - 10, max(y)+1000, 'M'); \n"); 281ee5b2fc6SMilanka Ringwald } 282ee5b2fc6SMilanka Ringwald 283ee5b2fc6SMilanka Ringwald static void octave_fprintf_plot_output(btstack_sbc_plc_state_t *plc_state, FILE * oct_file){ 284ee5b2fc6SMilanka Ringwald if (!oct_file) return; 285ee5b2fc6SMilanka Ringwald char out_name[10]; 286*ff7d6aeaSMatthias Ringwald snprintf(out_name, sizeof(out_name), "out%d", plc_state->nbf); 287*ff7d6aeaSMatthias Ringwald out_name[sizeof(out_name) - 1] = 0; 288ee5b2fc6SMilanka Ringwald int x0 = SBC_LHIST; 289ee5b2fc6SMilanka Ringwald int x1 = x0 + SBC_FS - 1; 290ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, out_name, SBC_FS, plc_state->hist+x0); 291ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h2 = plot(b(%d:%d), %s, 'cd'); \n", x0, x1, out_name); 292ee5b2fc6SMilanka Ringwald 293ee5b2fc6SMilanka Ringwald char rest_hist_name[10]; 294*ff7d6aeaSMatthias Ringwald snprintf(rest_hist_name, sizeof(rest_hist_name), "rest%d", plc_state->nbf); 295*ff7d6aeaSMatthias Ringwald rest_hist_name[sizeof(rest_hist_name) - 1] = 0; 296ee5b2fc6SMilanka Ringwald x0 = SBC_LHIST + SBC_FS; 297ee5b2fc6SMilanka Ringwald x1 = x0 + SBC_OLAL + SBC_RT - 1; 298ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, rest_hist_name, SBC_OLAL + SBC_RT, plc_state->hist+x0); 299ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h3 = plot(b(%d:%d), %s, 'kd'); \n", x0, x1, rest_hist_name); 300ee5b2fc6SMilanka Ringwald 301ee5b2fc6SMilanka Ringwald char new_hist_name[10]; 302*ff7d6aeaSMatthias Ringwald snprintf(new_hist_name, sizeof(new_hist_name), "hist%d", plc_state->nbf); 303*ff7d6aeaSMatthias Ringwald new_hist_name[sizeof(new_hist_name) - 1] = 0; 304ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, new_hist_name, SBC_LHIST, plc_state->hist); 305ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h4 = plot(%s, 'r--'); \n", new_hist_name); 306ee5b2fc6SMilanka Ringwald 307ee5b2fc6SMilanka Ringwald fprintf(oct_file, "legend ([h1, h2, h3, h4], {\"hist\", \"out\", \"rest\", \"new hist\"}, \"location\", \"northeast\");\n "); 308ee5b2fc6SMilanka Ringwald 309ee5b2fc6SMilanka Ringwald char fig_name[1200]; 310*ff7d6aeaSMatthias Ringwald snprintf(fig_name, sizeof(fig_name), "../%s_octave_plc_%d_%s", 311*ff7d6aeaSMatthias Ringwald octave_base_name, plc_state->frame_count, 312*ff7d6aeaSMatthias Ringwald octave_frame_type2str(octave_frame_type)); 313*ff7d6aeaSMatthias Ringwald fig_name[sizeof(fig_name) - 1] = 0; 314ee5b2fc6SMilanka Ringwald fprintf(oct_file, "print(hf, \"%s.jpg\", \"-djpg\");", fig_name); 315ee5b2fc6SMilanka Ringwald } 316ee5b2fc6SMilanka Ringwald #endif 317ee5b2fc6SMilanka Ringwald 318ee5b2fc6SMilanka Ringwald 3194e4f6f26SMatthias Ringwald void btstack_sbc_plc_bad_frame(btstack_sbc_plc_state_t *plc_state, SAMPLE_FORMAT *ZIRbuf, SAMPLE_FORMAT *out){ 3204e074f72SMilanka Ringwald float val; 3219b037397SMilanka Ringwald int i; 3227e6b1e83SMilanka Ringwald float sf = 1; 3237e6b1e83SMilanka Ringwald 3249b037397SMilanka Ringwald plc_state->nbf++; 325de854f9aSMilanka Ringwald plc_state->bad_frames_nr++; 326de854f9aSMilanka Ringwald plc_state->frame_count++; 3279b037397SMilanka Ringwald 328de854f9aSMilanka Ringwald if (plc_state->max_consecutive_bad_frames_nr < plc_state->nbf){ 329de854f9aSMilanka Ringwald plc_state->max_consecutive_bad_frames_nr = plc_state->nbf; 330de854f9aSMilanka Ringwald } 331de854f9aSMilanka Ringwald 3324e074f72SMilanka Ringwald if (plc_state->nbf==1){ 33322183937SMilanka Ringwald // printf("first bad frame\n"); 3344e4f6f26SMatthias Ringwald // Perform pattern matching to find where to replicate 3354e074f72SMilanka Ringwald plc_state->bestlag = PatternMatch(plc_state->hist); 336ee5b2fc6SMilanka Ringwald } 337ee5b2fc6SMilanka Ringwald 338ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 339ee5b2fc6SMilanka Ringwald FILE * oct_file = open_octave_file(plc_state, OCTAVE_FRAME_TYPE_BAD); 340ee5b2fc6SMilanka Ringwald if (oct_file){ 341ee5b2fc6SMilanka Ringwald octave_fprintf_plot_history_frame(plc_state, oct_file, plc_state->frame_count); 342ee5b2fc6SMilanka Ringwald } 343ee5b2fc6SMilanka Ringwald #endif 344ee5b2fc6SMilanka Ringwald 345ee5b2fc6SMilanka Ringwald if (plc_state->nbf==1){ 3464e4f6f26SMatthias Ringwald // the replication begins after the template match 3477e6b1e83SMilanka Ringwald plc_state->bestlag += SBC_M; 3484e074f72SMilanka Ringwald 3494e4f6f26SMatthias Ringwald // Compute Scale Factor to Match Amplitude of Substitution Packet to that of Preceding Packet 3504e074f72SMilanka Ringwald sf = AmplitudeMatch(plc_state->hist, plc_state->bestlag); 35122183937SMilanka Ringwald // printf("sf Apmlitude Match %f, new data %d, bestlag+M %d\n", sf, ZIRbuf[0], plc_state->hist[plc_state->bestlag]); 3527e6b1e83SMilanka Ringwald for (i=0; i<SBC_OLAL; i++){ 3537e6b1e83SMilanka Ringwald float left = ZIRbuf[i]; 3547e6b1e83SMilanka Ringwald float right = sf*plc_state->hist[plc_state->bestlag+i]; 355c1ab6cc1SMatthias Ringwald val = (left*rcos[i]) + (right*rcos[SBC_OLAL-1-i]); 356ee5b2fc6SMilanka Ringwald // val = sf*plc_state->hist[plc_state->bestlag+i]; 3574e4f6f26SMatthias Ringwald plc_state->hist[SBC_LHIST+i] = crop_sample(val); 3584e074f72SMilanka Ringwald } 3594e074f72SMilanka Ringwald 3609b037397SMilanka Ringwald for (i=SBC_OLAL; i<SBC_FS; i++){ 3617e6b1e83SMilanka Ringwald val = sf*plc_state->hist[plc_state->bestlag+i]; 3624e4f6f26SMatthias Ringwald plc_state->hist[SBC_LHIST+i] = crop_sample(val); 3634e074f72SMilanka Ringwald } 3644e074f72SMilanka Ringwald 3659b037397SMilanka Ringwald for (i=SBC_FS; i<(SBC_FS+SBC_OLAL); i++){ 3667e6b1e83SMilanka Ringwald float left = sf*plc_state->hist[plc_state->bestlag+i]; 3677e6b1e83SMilanka Ringwald float right = plc_state->hist[plc_state->bestlag+i]; 368c1ab6cc1SMatthias Ringwald val = (left*rcos[i-SBC_FS])+(right*rcos[SBC_OLAL-1-i+SBC_FS]); 3694e4f6f26SMatthias Ringwald plc_state->hist[SBC_LHIST+i] = crop_sample(val); 3704e074f72SMilanka Ringwald } 3714e074f72SMilanka Ringwald 3729b037397SMilanka Ringwald for (i=(SBC_FS+SBC_OLAL); i<(SBC_FS+SBC_RT+SBC_OLAL); i++){ 3737e6b1e83SMilanka Ringwald plc_state->hist[SBC_LHIST+i] = plc_state->hist[plc_state->bestlag+i]; 3747e6b1e83SMilanka Ringwald } 3754e074f72SMilanka Ringwald } else { 37622183937SMilanka Ringwald // printf("succesive bad frame nr %d\n", plc_state->nbf); 3779b037397SMilanka Ringwald for (i=0; i<(SBC_FS+SBC_RT+SBC_OLAL); i++){ 3787e6b1e83SMilanka Ringwald plc_state->hist[SBC_LHIST+i] = plc_state->hist[plc_state->bestlag+i]; 3794e074f72SMilanka Ringwald } 380c5e169ecSMilanka Ringwald } 3817e6b1e83SMilanka Ringwald for (i=0; i<SBC_FS; i++){ 3827e6b1e83SMilanka Ringwald out[i] = plc_state->hist[SBC_LHIST+i]; 3837e6b1e83SMilanka Ringwald } 3844e074f72SMilanka Ringwald 3854e4f6f26SMatthias Ringwald // shift the history buffer 3860e588213SMatthias Ringwald for (i=0; i<(SBC_LHIST+SBC_RT+SBC_OLAL); i++){ 3877e6b1e83SMilanka Ringwald plc_state->hist[i] = plc_state->hist[i+SBC_FS]; 3887e6b1e83SMilanka Ringwald } 389ee5b2fc6SMilanka Ringwald 390ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 391ee5b2fc6SMilanka Ringwald if (oct_file){ 392ee5b2fc6SMilanka Ringwald octave_fprintf_plot_output(plc_state, oct_file); 393ee5b2fc6SMilanka Ringwald fclose(oct_file); 394ee5b2fc6SMilanka Ringwald } 395ee5b2fc6SMilanka Ringwald #endif 3964e074f72SMilanka Ringwald } 3974e074f72SMilanka Ringwald 3984e4f6f26SMatthias Ringwald void btstack_sbc_plc_good_frame(btstack_sbc_plc_state_t *plc_state, SAMPLE_FORMAT *in, SAMPLE_FORMAT *out){ 3997e6b1e83SMilanka Ringwald float val; 4007e6b1e83SMilanka Ringwald int i = 0; 401de854f9aSMilanka Ringwald plc_state->good_frames_nr++; 402de854f9aSMilanka Ringwald plc_state->frame_count++; 403de854f9aSMilanka Ringwald 404ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 405ee5b2fc6SMilanka Ringwald FILE * oct_file = NULL; 406ee5b2fc6SMilanka Ringwald if (plc_state->nbf>0){ 407ee5b2fc6SMilanka Ringwald oct_file = open_octave_file(plc_state, OCTAVE_FRAME_TYPE_GOOD); 408ee5b2fc6SMilanka Ringwald if (oct_file){ 409ee5b2fc6SMilanka Ringwald octave_fprintf_plot_history_frame(plc_state, oct_file, plc_state->frame_count); 410ee5b2fc6SMilanka Ringwald } 411ee5b2fc6SMilanka Ringwald } 412ee5b2fc6SMilanka Ringwald #endif 413ee5b2fc6SMilanka Ringwald 4144e074f72SMilanka Ringwald if (plc_state->nbf>0){ 4157e6b1e83SMilanka Ringwald for (i=0;i<SBC_RT;i++){ 4167e6b1e83SMilanka Ringwald out[i] = plc_state->hist[SBC_LHIST+i]; 4174e074f72SMilanka Ringwald } 4187e6b1e83SMilanka Ringwald 419c1ab6cc1SMatthias Ringwald for (i = SBC_RT;i<(SBC_RT+SBC_OLAL);i++){ 4207e6b1e83SMilanka Ringwald float left = plc_state->hist[SBC_LHIST+i]; 4217e6b1e83SMilanka Ringwald float right = in[i]; 422c1ab6cc1SMatthias Ringwald val = (left*rcos[i-SBC_RT]) + (right*rcos[SBC_OLAL+SBC_RT-1-i]); 423ee5b2fc6SMilanka Ringwald out[i] = crop_sample(val); 4247e6b1e83SMilanka Ringwald } 4257e6b1e83SMilanka Ringwald } 4264e4f6f26SMatthias Ringwald 4277e6b1e83SMilanka Ringwald for (;i<SBC_FS;i++){ 4284e074f72SMilanka Ringwald out[i] = in[i]; 4297e6b1e83SMilanka Ringwald } 4304e4f6f26SMatthias Ringwald // Copy the output to the history buffer 4317e6b1e83SMilanka Ringwald for (i=0;i<SBC_FS;i++){ 4327e6b1e83SMilanka Ringwald plc_state->hist[SBC_LHIST+i] = out[i]; 4337e6b1e83SMilanka Ringwald } 434ee5b2fc6SMilanka Ringwald 4354e4f6f26SMatthias Ringwald // shift the history buffer 4367e6b1e83SMilanka Ringwald for (i=0;i<SBC_LHIST;i++){ 4377e6b1e83SMilanka Ringwald plc_state->hist[i] = plc_state->hist[i+SBC_FS]; 4387e6b1e83SMilanka Ringwald } 4397e6b1e83SMilanka Ringwald 440ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 441ee5b2fc6SMilanka Ringwald if (oct_file){ 442ee5b2fc6SMilanka Ringwald octave_fprintf_plot_output(plc_state, oct_file); 443ee5b2fc6SMilanka Ringwald fclose(oct_file); 444ee5b2fc6SMilanka Ringwald } 445ee5b2fc6SMilanka Ringwald #endif 4464e074f72SMilanka Ringwald plc_state->nbf=0; 4474e074f72SMilanka Ringwald } 448de854f9aSMilanka Ringwald 449de854f9aSMilanka Ringwald void btstack_sbc_dump_statistics(btstack_sbc_plc_state_t * state){ 450de854f9aSMilanka Ringwald log_info("Good frames: %d\n", state->good_frames_nr); 451de854f9aSMilanka Ringwald log_info("Bad frames: %d\n", state->bad_frames_nr); 452de854f9aSMilanka Ringwald log_info("Max Consecutive bad frames: %d\n", state->max_consecutive_bad_frames_nr); 453de854f9aSMilanka Ringwald } 454