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 58*a2c7346fSMatthias Ringwald // Zero Frame (57 bytes) with padding zeros to avoid out of bound reads 59*a2c7346fSMatthias Ringwald static uint8_t indices0[] = { 60*a2c7346fSMatthias Ringwald 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 61*a2c7346fSMatthias Ringwald 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 62*a2c7346fSMatthias Ringwald 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 63*a2c7346fSMatthias Ringwald 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 64*a2c7346fSMatthias Ringwald 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6, 65*a2c7346fSMatthias Ringwald 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 66*a2c7346fSMatthias Ringwald /* padding */ 0x00, 0x00, 0x00 67*a2c7346fSMatthias Ringwald }; 684e074f72SMilanka Ringwald 694e074f72SMilanka Ringwald /* Raised COSine table for OLA */ 707e6b1e83SMilanka Ringwald static float rcos[SBC_OLAL] = { 714e074f72SMilanka Ringwald 0.99148655f,0.96623611f,0.92510857f,0.86950446f, 724e074f72SMilanka Ringwald 0.80131732f,0.72286918f,0.63683150f,0.54613418f, 734e074f72SMilanka Ringwald 0.45386582f,0.36316850f,0.27713082f,0.19868268f, 74*a2c7346fSMatthias Ringwald 0.13049554f,0.07489143f,0.03376389f,0.00851345f 75*a2c7346fSMatthias Ringwald }; 764e074f72SMilanka Ringwald 7740e1e61cSMilanka Ringwald // taken from http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi 7840e1e61cSMilanka Ringwald // Algorithm: Babylonian Method + some manipulations on IEEE 32 bit floating point representation 7940e1e61cSMilanka Ringwald static float sqrt3(const float x){ 8040e1e61cSMilanka Ringwald union { 8140e1e61cSMilanka Ringwald int i; 8240e1e61cSMilanka Ringwald float x; 8340e1e61cSMilanka Ringwald } u; 8440e1e61cSMilanka Ringwald u.x = x; 8540e1e61cSMilanka Ringwald u.i = (1<<29) + (u.i >> 1) - (1<<22); 8640e1e61cSMilanka Ringwald 8740e1e61cSMilanka Ringwald // Two Babylonian Steps (simplified from:) 8840e1e61cSMilanka Ringwald // u.x = 0.5f * (u.x + x/u.x); 8940e1e61cSMilanka Ringwald // u.x = 0.5f * (u.x + x/u.x); 90c1ab6cc1SMatthias Ringwald u.x = u.x + (x/u.x); 91c1ab6cc1SMatthias Ringwald u.x = (0.25f*u.x) + (x/u.x); 9240e1e61cSMilanka Ringwald 9340e1e61cSMilanka Ringwald return u.x; 9440e1e61cSMilanka Ringwald } 9540e1e61cSMilanka Ringwald 9640e1e61cSMilanka Ringwald static float absolute(float x){ 9740e1e61cSMilanka Ringwald if (x < 0) x = -x; 9840e1e61cSMilanka Ringwald return x; 9940e1e61cSMilanka Ringwald } 10040e1e61cSMilanka Ringwald 1014e4f6f26SMatthias Ringwald static float CrossCorrelation(SAMPLE_FORMAT *x, SAMPLE_FORMAT *y){ 102c5e169ecSMilanka Ringwald float num = 0; 103c5e169ecSMilanka Ringwald float den = 0; 104c5e169ecSMilanka Ringwald float x2 = 0; 105c5e169ecSMilanka Ringwald float y2 = 0; 106c5e169ecSMilanka Ringwald int m; 107c5e169ecSMilanka Ringwald for (m=0;m<SBC_M;m++){ 108c5e169ecSMilanka Ringwald num+=((float)x[m])*y[m]; 109c5e169ecSMilanka Ringwald x2+=((float)x[m])*x[m]; 110c5e169ecSMilanka Ringwald y2+=((float)y[m])*y[m]; 111c5e169ecSMilanka Ringwald } 11240e1e61cSMilanka Ringwald den = (float)sqrt3(x2*y2); 113c5e169ecSMilanka Ringwald return num/den; 114c5e169ecSMilanka Ringwald } 115c5e169ecSMilanka Ringwald 1164e4f6f26SMatthias Ringwald static int PatternMatch(SAMPLE_FORMAT *y){ 1174e4f6f26SMatthias Ringwald float maxCn = -999999.0; // large negative number 118c5e169ecSMilanka Ringwald int bestmatch = 0; 119c5e169ecSMilanka Ringwald float Cn; 120c5e169ecSMilanka Ringwald int n; 121c5e169ecSMilanka Ringwald for (n=0;n<SBC_N;n++){ 1224e4f6f26SMatthias Ringwald Cn = CrossCorrelation(&y[SBC_LHIST-SBC_M], &y[n]); 123c5e169ecSMilanka Ringwald if (Cn>maxCn){ 124c5e169ecSMilanka Ringwald bestmatch=n; 125c5e169ecSMilanka Ringwald maxCn = Cn; 126c5e169ecSMilanka Ringwald } 127c5e169ecSMilanka Ringwald } 128c5e169ecSMilanka Ringwald return bestmatch; 129c5e169ecSMilanka Ringwald } 130c5e169ecSMilanka Ringwald 1314e4f6f26SMatthias Ringwald static float AmplitudeMatch(SAMPLE_FORMAT *y, SAMPLE_FORMAT bestmatch) { 132c5e169ecSMilanka Ringwald int i; 133c5e169ecSMilanka Ringwald float sumx = 0; 134c5e169ecSMilanka Ringwald float sumy = 0.000001f; 135c5e169ecSMilanka Ringwald float sf; 136c5e169ecSMilanka Ringwald 137c5e169ecSMilanka Ringwald for (i=0;i<SBC_FS;i++){ 13840e1e61cSMilanka Ringwald sumx += absolute(y[SBC_LHIST-SBC_FS+i]); 13940e1e61cSMilanka Ringwald sumy += absolute(y[bestmatch+i]); 140c5e169ecSMilanka Ringwald } 141c5e169ecSMilanka Ringwald sf = sumx/sumy; 1424e4f6f26SMatthias Ringwald // This is not in the paper, but limit the scaling factor to something reasonable to avoid creating artifacts 143c5e169ecSMilanka Ringwald if (sf<0.75f) sf=0.75f; 144ee5b2fc6SMilanka Ringwald if (sf>1.0f) sf=1.0f; 145c5e169ecSMilanka Ringwald return sf; 146c5e169ecSMilanka Ringwald } 1474e074f72SMilanka Ringwald 1484e4f6f26SMatthias Ringwald static SAMPLE_FORMAT crop_sample(float val){ 149250a1e4aSMilanka Ringwald float croped_val = val; 150250a1e4aSMilanka Ringwald if (croped_val > 32767.0) croped_val= 32767.0; 151250a1e4aSMilanka Ringwald if (croped_val < -32768.0) croped_val=-32768.0; 1524e4f6f26SMatthias Ringwald return (SAMPLE_FORMAT) croped_val; 1537e6b1e83SMilanka Ringwald } 1547e6b1e83SMilanka Ringwald 155e7a41128SMilanka Ringwald uint8_t * btstack_sbc_plc_zero_signal_frame(void){ 1564e074f72SMilanka Ringwald return (uint8_t *)&indices0; 1574e074f72SMilanka Ringwald } 1584e074f72SMilanka Ringwald 159e7a41128SMilanka Ringwald void btstack_sbc_plc_init(btstack_sbc_plc_state_t *plc_state){ 1604e074f72SMilanka Ringwald plc_state->nbf=0; 1614e074f72SMilanka Ringwald plc_state->bestlag=0; 162b3f76298SMilanka Ringwald memset(plc_state->hist,0,sizeof(plc_state->hist)); 1634e074f72SMilanka Ringwald } 1644e074f72SMilanka Ringwald 165ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 166ee5b2fc6SMilanka Ringwald typedef enum { 167ee5b2fc6SMilanka Ringwald OCTAVE_FRAME_TYPE_UNKNOWN = 0, 168ee5b2fc6SMilanka Ringwald OCTAVE_FRAME_TYPE_GOOD, 169ee5b2fc6SMilanka Ringwald OCTAVE_FRAME_TYPE_BAD 170ee5b2fc6SMilanka Ringwald } octave_frame_type_t; 171ee5b2fc6SMilanka Ringwald 172ee5b2fc6SMilanka Ringwald static const char * octave_frame_type_name[] = { 173ee5b2fc6SMilanka Ringwald "unknown", 174ee5b2fc6SMilanka Ringwald "good", 175ee5b2fc6SMilanka Ringwald "bad" 176ee5b2fc6SMilanka Ringwald }; 177ee5b2fc6SMilanka Ringwald 178ee5b2fc6SMilanka Ringwald static octave_frame_type_t octave_frame_type; 179ee5b2fc6SMilanka Ringwald static char octave_base_name[1000]; 180ee5b2fc6SMilanka Ringwald 181ee5b2fc6SMilanka Ringwald const char * octave_frame_type2str(int index){ 182ee5b2fc6SMilanka Ringwald if (index <= 0 || index >= sizeof(octave_frame_type_t)) return octave_frame_type_name[0]; 183ee5b2fc6SMilanka Ringwald return octave_frame_type_name[index]; 184ee5b2fc6SMilanka Ringwald } 185ee5b2fc6SMilanka Ringwald 186d1550f90SMilanka Ringwald void btstack_sbc_plc_octave_set_base_name(const char * base_name){ 187ee5b2fc6SMilanka Ringwald strcpy(octave_base_name, base_name); 188ee5b2fc6SMilanka Ringwald printf("OCTAVE: base name set to %s\n", octave_base_name); 189ee5b2fc6SMilanka Ringwald } 190ee5b2fc6SMilanka Ringwald 191ee5b2fc6SMilanka Ringwald static void octave_fprintf_array_int16(FILE * oct_file, char * name, int data_len, int16_t * data){ 192ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%s = [", name); 193ee5b2fc6SMilanka Ringwald int i; 194ee5b2fc6SMilanka Ringwald for (i = 0; i < data_len - 1; i++){ 195ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%d, ", data[i]); 196ee5b2fc6SMilanka Ringwald } 197ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%d", data[i]); 198ee5b2fc6SMilanka Ringwald fprintf(oct_file, "%s", "];\n"); 199ee5b2fc6SMilanka Ringwald } 200ee5b2fc6SMilanka Ringwald 201ee5b2fc6SMilanka Ringwald static FILE * open_octave_file(btstack_sbc_plc_state_t *plc_state, octave_frame_type_t frame_type){ 202ee5b2fc6SMilanka Ringwald char oct_file_name[1200]; 203ee5b2fc6SMilanka Ringwald octave_frame_type = frame_type; 204ff7d6aeaSMatthias Ringwald snprintf(oct_file_name, sizeof(oct_file_name), "%s_octave_plc_%d_%s.m", 205ff7d6aeaSMatthias Ringwald octave_base_name, plc_state->frame_count, 206ff7d6aeaSMatthias Ringwald octave_frame_type2str(octave_frame_type)); 207ff7d6aeaSMatthias Ringwald oct_file_name[sizeof(oct_file_name) - 1] = 0; 208ee5b2fc6SMilanka Ringwald 209ee5b2fc6SMilanka Ringwald FILE * oct_file = fopen(oct_file_name, "wb"); 210ee5b2fc6SMilanka Ringwald if (oct_file == NULL){ 211ee5b2fc6SMilanka Ringwald printf("OCTAVE: could not open file %s\n", oct_file_name); 212ee5b2fc6SMilanka Ringwald return NULL; 213ee5b2fc6SMilanka Ringwald } 214ee5b2fc6SMilanka Ringwald printf("OCTAVE: opened file %s\n", oct_file_name); 215ee5b2fc6SMilanka Ringwald return oct_file; 216ee5b2fc6SMilanka Ringwald } 217ee5b2fc6SMilanka Ringwald 218ee5b2fc6SMilanka Ringwald static void octave_fprintf_plot_history_frame(btstack_sbc_plc_state_t *plc_state, FILE * oct_file, int frame_nr){ 219ee5b2fc6SMilanka Ringwald char title[100]; 220ee5b2fc6SMilanka Ringwald char hist_name[10]; 221ff7d6aeaSMatthias Ringwald snprintf(hist_name, sizeof(hist_name), "hist%d", plc_state->nbf); 222ff7d6aeaSMatthias Ringwald hist_name[sizeof(hist_name) - 1] = 0; 223ee5b2fc6SMilanka Ringwald 224ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, hist_name, SBC_LHIST, plc_state->hist); 225ee5b2fc6SMilanka Ringwald 226ee5b2fc6SMilanka Ringwald fprintf(oct_file, "y = [min(%s):1000:max(%s)];\n", hist_name, hist_name); 227ee5b2fc6SMilanka Ringwald fprintf(oct_file, "x = zeros(1, size(y,2));\n"); 228ee5b2fc6SMilanka Ringwald fprintf(oct_file, "b = [0: %d];\n", SBC_LHIST+SBC_FS+SBC_RT+SBC_OLAL); 229ee5b2fc6SMilanka Ringwald 230ee5b2fc6SMilanka Ringwald int pos = SBC_FS; 231ee5b2fc6SMilanka Ringwald fprintf(oct_file, "shift_x = x + %d;\n", pos); 232ee5b2fc6SMilanka Ringwald 233ee5b2fc6SMilanka Ringwald pos = SBC_LHIST - 1; 234ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_x = x + %d;\n", pos); 235ee5b2fc6SMilanka Ringwald pos += SBC_OLAL; 236ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_olal1_x = x + %d;\n", pos); 237ee5b2fc6SMilanka Ringwald pos += SBC_FS - SBC_OLAL; 238ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_fs_x = x + %d;\n", pos); 239ee5b2fc6SMilanka Ringwald pos += SBC_OLAL; 240ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_olal2_x = x + %d;\n", pos); 241ee5b2fc6SMilanka Ringwald pos += SBC_RT; 242ee5b2fc6SMilanka Ringwald fprintf(oct_file, "lhist_rt_x = x + %d;\n", pos); 243ee5b2fc6SMilanka Ringwald 244ee5b2fc6SMilanka Ringwald fprintf(oct_file, "pattern_window_x = x + %d;\n", SBC_LHIST - SBC_M); 245ee5b2fc6SMilanka Ringwald 246ee5b2fc6SMilanka Ringwald fprintf(oct_file, "hf = figure();\n"); 247ff7d6aeaSMatthias Ringwald snprintf(title, sizeof(title), "PLC %s frame %d", 248ff7d6aeaSMatthias Ringwald octave_frame_type2str(octave_frame_type), frame_nr); 249ff7d6aeaSMatthias Ringwald title[sizeof(title) - 1] = 0; 250ee5b2fc6SMilanka Ringwald 251ee5b2fc6SMilanka Ringwald fprintf(oct_file, "hold on;\n"); 252ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h1 = plot(%s); \n", hist_name); 253ee5b2fc6SMilanka Ringwald 254ee5b2fc6SMilanka Ringwald fprintf(oct_file, "title(\"%s\");\n", title); 255ee5b2fc6SMilanka Ringwald 256ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_x, y, 'k'); \n"); 257ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_x) - 10, max(y)+1000, 'lhist'); \n"); 258ee5b2fc6SMilanka Ringwald 259ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_olal1_x, y, 'k'); \n"); 260ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_olal1_x) - 10, max(y)+1000, 'OLAL'); \n"); 261ee5b2fc6SMilanka Ringwald 262ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_fs_x, y, 'k'); \n"); 263ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_fs_x) - 10, max(y)+1000, 'FS'); \n"); 264ee5b2fc6SMilanka Ringwald 265ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_olal2_x, y, 'k'); \n"); 266ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_olal2_x) - 10, max(y)+1000, 'OLAL'); \n"); 267ee5b2fc6SMilanka Ringwald 268ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(lhist_rt_x, y, 'k');\n"); 269ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(lhist_rt_x) - 10, max(y)+1000, 'RT'); \n"); 270ee5b2fc6SMilanka Ringwald 271ee5b2fc6SMilanka Ringwald if (octave_frame_type == OCTAVE_FRAME_TYPE_GOOD) return; 272ee5b2fc6SMilanka Ringwald 273ee5b2fc6SMilanka Ringwald int x0 = plc_state->bestlag; 274ee5b2fc6SMilanka Ringwald int x1 = plc_state->bestlag + SBC_M - 1; 275ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'rd'); \n", x0, x1, hist_name, x0, x1); 276ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(%d - 10, -10, 'bestlag'); \n", x0); 277ee5b2fc6SMilanka Ringwald 278ee5b2fc6SMilanka Ringwald x0 = plc_state->bestlag + SBC_M ; 279ee5b2fc6SMilanka Ringwald x1 = plc_state->bestlag + SBC_M + SBC_FS - 1; 280ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'kd'); \n", x0, x1, hist_name, x0, x1); 281ee5b2fc6SMilanka Ringwald 282ee5b2fc6SMilanka Ringwald x0 = SBC_LHIST - SBC_M; 283ee5b2fc6SMilanka Ringwald x1 = SBC_LHIST - 1; 284ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(b(%d:%d), %s(%d:%d), 'rd'); \n", x0, x1, hist_name, x0, x1); 285ee5b2fc6SMilanka Ringwald fprintf(oct_file, "plot(pattern_window_x, y, 'g'); \n"); 286ee5b2fc6SMilanka Ringwald fprintf(oct_file, "text(max(pattern_window_x) - 10, max(y)+1000, 'M'); \n"); 287ee5b2fc6SMilanka Ringwald } 288ee5b2fc6SMilanka Ringwald 289ee5b2fc6SMilanka Ringwald static void octave_fprintf_plot_output(btstack_sbc_plc_state_t *plc_state, FILE * oct_file){ 290ee5b2fc6SMilanka Ringwald if (!oct_file) return; 291ee5b2fc6SMilanka Ringwald char out_name[10]; 292ff7d6aeaSMatthias Ringwald snprintf(out_name, sizeof(out_name), "out%d", plc_state->nbf); 293ff7d6aeaSMatthias Ringwald out_name[sizeof(out_name) - 1] = 0; 294ee5b2fc6SMilanka Ringwald int x0 = SBC_LHIST; 295ee5b2fc6SMilanka Ringwald int x1 = x0 + SBC_FS - 1; 296ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, out_name, SBC_FS, plc_state->hist+x0); 297ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h2 = plot(b(%d:%d), %s, 'cd'); \n", x0, x1, out_name); 298ee5b2fc6SMilanka Ringwald 299ee5b2fc6SMilanka Ringwald char rest_hist_name[10]; 300ff7d6aeaSMatthias Ringwald snprintf(rest_hist_name, sizeof(rest_hist_name), "rest%d", plc_state->nbf); 301ff7d6aeaSMatthias Ringwald rest_hist_name[sizeof(rest_hist_name) - 1] = 0; 302ee5b2fc6SMilanka Ringwald x0 = SBC_LHIST + SBC_FS; 303ee5b2fc6SMilanka Ringwald x1 = x0 + SBC_OLAL + SBC_RT - 1; 304ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, rest_hist_name, SBC_OLAL + SBC_RT, plc_state->hist+x0); 305ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h3 = plot(b(%d:%d), %s, 'kd'); \n", x0, x1, rest_hist_name); 306ee5b2fc6SMilanka Ringwald 307ee5b2fc6SMilanka Ringwald char new_hist_name[10]; 308ff7d6aeaSMatthias Ringwald snprintf(new_hist_name, sizeof(new_hist_name), "hist%d", plc_state->nbf); 309ff7d6aeaSMatthias Ringwald new_hist_name[sizeof(new_hist_name) - 1] = 0; 310ee5b2fc6SMilanka Ringwald octave_fprintf_array_int16(oct_file, new_hist_name, SBC_LHIST, plc_state->hist); 311ee5b2fc6SMilanka Ringwald fprintf(oct_file, "h4 = plot(%s, 'r--'); \n", new_hist_name); 312ee5b2fc6SMilanka Ringwald 313ee5b2fc6SMilanka Ringwald fprintf(oct_file, "legend ([h1, h2, h3, h4], {\"hist\", \"out\", \"rest\", \"new hist\"}, \"location\", \"northeast\");\n "); 314ee5b2fc6SMilanka Ringwald 315ee5b2fc6SMilanka Ringwald char fig_name[1200]; 316ff7d6aeaSMatthias Ringwald snprintf(fig_name, sizeof(fig_name), "../%s_octave_plc_%d_%s", 317ff7d6aeaSMatthias Ringwald octave_base_name, plc_state->frame_count, 318ff7d6aeaSMatthias Ringwald octave_frame_type2str(octave_frame_type)); 319ff7d6aeaSMatthias Ringwald fig_name[sizeof(fig_name) - 1] = 0; 320ee5b2fc6SMilanka Ringwald fprintf(oct_file, "print(hf, \"%s.jpg\", \"-djpg\");", fig_name); 321ee5b2fc6SMilanka Ringwald } 322ee5b2fc6SMilanka Ringwald #endif 323ee5b2fc6SMilanka Ringwald 324ee5b2fc6SMilanka Ringwald 3254e4f6f26SMatthias Ringwald void btstack_sbc_plc_bad_frame(btstack_sbc_plc_state_t *plc_state, SAMPLE_FORMAT *ZIRbuf, SAMPLE_FORMAT *out){ 3264e074f72SMilanka Ringwald float val; 3279b037397SMilanka Ringwald int i; 3287e6b1e83SMilanka Ringwald float sf = 1; 3297e6b1e83SMilanka Ringwald 3309b037397SMilanka Ringwald plc_state->nbf++; 331de854f9aSMilanka Ringwald plc_state->bad_frames_nr++; 332de854f9aSMilanka Ringwald plc_state->frame_count++; 3339b037397SMilanka Ringwald 334de854f9aSMilanka Ringwald if (plc_state->max_consecutive_bad_frames_nr < plc_state->nbf){ 335de854f9aSMilanka Ringwald plc_state->max_consecutive_bad_frames_nr = plc_state->nbf; 336de854f9aSMilanka Ringwald } 337de854f9aSMilanka Ringwald 3384e074f72SMilanka Ringwald if (plc_state->nbf==1){ 33922183937SMilanka Ringwald // printf("first bad frame\n"); 3404e4f6f26SMatthias Ringwald // Perform pattern matching to find where to replicate 3414e074f72SMilanka Ringwald plc_state->bestlag = PatternMatch(plc_state->hist); 342ee5b2fc6SMilanka Ringwald } 343ee5b2fc6SMilanka Ringwald 344ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 345ee5b2fc6SMilanka Ringwald FILE * oct_file = open_octave_file(plc_state, OCTAVE_FRAME_TYPE_BAD); 346ee5b2fc6SMilanka Ringwald if (oct_file){ 347ee5b2fc6SMilanka Ringwald octave_fprintf_plot_history_frame(plc_state, oct_file, plc_state->frame_count); 348ee5b2fc6SMilanka Ringwald } 349ee5b2fc6SMilanka Ringwald #endif 350ee5b2fc6SMilanka Ringwald 351ee5b2fc6SMilanka Ringwald if (plc_state->nbf==1){ 3524e4f6f26SMatthias Ringwald // the replication begins after the template match 3537e6b1e83SMilanka Ringwald plc_state->bestlag += SBC_M; 3544e074f72SMilanka Ringwald 3554e4f6f26SMatthias Ringwald // Compute Scale Factor to Match Amplitude of Substitution Packet to that of Preceding Packet 3564e074f72SMilanka Ringwald sf = AmplitudeMatch(plc_state->hist, plc_state->bestlag); 35722183937SMilanka Ringwald // printf("sf Apmlitude Match %f, new data %d, bestlag+M %d\n", sf, ZIRbuf[0], plc_state->hist[plc_state->bestlag]); 3587e6b1e83SMilanka Ringwald for (i=0; i<SBC_OLAL; i++){ 3597e6b1e83SMilanka Ringwald float left = ZIRbuf[i]; 3607e6b1e83SMilanka Ringwald float right = sf*plc_state->hist[plc_state->bestlag+i]; 361c1ab6cc1SMatthias Ringwald val = (left*rcos[i]) + (right*rcos[SBC_OLAL-1-i]); 362ee5b2fc6SMilanka Ringwald // val = sf*plc_state->hist[plc_state->bestlag+i]; 3634e4f6f26SMatthias Ringwald plc_state->hist[SBC_LHIST+i] = crop_sample(val); 3644e074f72SMilanka Ringwald } 3654e074f72SMilanka Ringwald 3669b037397SMilanka Ringwald for (i=SBC_OLAL; i<SBC_FS; i++){ 3677e6b1e83SMilanka Ringwald val = sf*plc_state->hist[plc_state->bestlag+i]; 3684e4f6f26SMatthias Ringwald plc_state->hist[SBC_LHIST+i] = crop_sample(val); 3694e074f72SMilanka Ringwald } 3704e074f72SMilanka Ringwald 3719b037397SMilanka Ringwald for (i=SBC_FS; i<(SBC_FS+SBC_OLAL); i++){ 3727e6b1e83SMilanka Ringwald float left = sf*plc_state->hist[plc_state->bestlag+i]; 3737e6b1e83SMilanka Ringwald float right = plc_state->hist[plc_state->bestlag+i]; 374c1ab6cc1SMatthias Ringwald val = (left*rcos[i-SBC_FS])+(right*rcos[SBC_OLAL-1-i+SBC_FS]); 3754e4f6f26SMatthias Ringwald plc_state->hist[SBC_LHIST+i] = crop_sample(val); 3764e074f72SMilanka Ringwald } 3774e074f72SMilanka Ringwald 3789b037397SMilanka Ringwald for (i=(SBC_FS+SBC_OLAL); i<(SBC_FS+SBC_RT+SBC_OLAL); i++){ 3797e6b1e83SMilanka Ringwald plc_state->hist[SBC_LHIST+i] = plc_state->hist[plc_state->bestlag+i]; 3807e6b1e83SMilanka Ringwald } 3814e074f72SMilanka Ringwald } else { 38222183937SMilanka Ringwald // printf("succesive bad frame nr %d\n", plc_state->nbf); 3839b037397SMilanka Ringwald for (i=0; i<(SBC_FS+SBC_RT+SBC_OLAL); i++){ 3847e6b1e83SMilanka Ringwald plc_state->hist[SBC_LHIST+i] = plc_state->hist[plc_state->bestlag+i]; 3854e074f72SMilanka Ringwald } 386c5e169ecSMilanka Ringwald } 3877e6b1e83SMilanka Ringwald for (i=0; i<SBC_FS; i++){ 3887e6b1e83SMilanka Ringwald out[i] = plc_state->hist[SBC_LHIST+i]; 3897e6b1e83SMilanka Ringwald } 3904e074f72SMilanka Ringwald 3914e4f6f26SMatthias Ringwald // shift the history buffer 3920e588213SMatthias Ringwald for (i=0; i<(SBC_LHIST+SBC_RT+SBC_OLAL); i++){ 3937e6b1e83SMilanka Ringwald plc_state->hist[i] = plc_state->hist[i+SBC_FS]; 3947e6b1e83SMilanka Ringwald } 395ee5b2fc6SMilanka Ringwald 396ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 397ee5b2fc6SMilanka Ringwald if (oct_file){ 398ee5b2fc6SMilanka Ringwald octave_fprintf_plot_output(plc_state, oct_file); 399ee5b2fc6SMilanka Ringwald fclose(oct_file); 400ee5b2fc6SMilanka Ringwald } 401ee5b2fc6SMilanka Ringwald #endif 4024e074f72SMilanka Ringwald } 4034e074f72SMilanka Ringwald 4044e4f6f26SMatthias Ringwald void btstack_sbc_plc_good_frame(btstack_sbc_plc_state_t *plc_state, SAMPLE_FORMAT *in, SAMPLE_FORMAT *out){ 4057e6b1e83SMilanka Ringwald float val; 4067e6b1e83SMilanka Ringwald int i = 0; 407de854f9aSMilanka Ringwald plc_state->good_frames_nr++; 408de854f9aSMilanka Ringwald plc_state->frame_count++; 409de854f9aSMilanka Ringwald 410ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 411ee5b2fc6SMilanka Ringwald FILE * oct_file = NULL; 412ee5b2fc6SMilanka Ringwald if (plc_state->nbf>0){ 413ee5b2fc6SMilanka Ringwald oct_file = open_octave_file(plc_state, OCTAVE_FRAME_TYPE_GOOD); 414ee5b2fc6SMilanka Ringwald if (oct_file){ 415ee5b2fc6SMilanka Ringwald octave_fprintf_plot_history_frame(plc_state, oct_file, plc_state->frame_count); 416ee5b2fc6SMilanka Ringwald } 417ee5b2fc6SMilanka Ringwald } 418ee5b2fc6SMilanka Ringwald #endif 419ee5b2fc6SMilanka Ringwald 4204e074f72SMilanka Ringwald if (plc_state->nbf>0){ 4217e6b1e83SMilanka Ringwald for (i=0;i<SBC_RT;i++){ 4227e6b1e83SMilanka Ringwald out[i] = plc_state->hist[SBC_LHIST+i]; 4234e074f72SMilanka Ringwald } 4247e6b1e83SMilanka Ringwald 425c1ab6cc1SMatthias Ringwald for (i = SBC_RT;i<(SBC_RT+SBC_OLAL);i++){ 4267e6b1e83SMilanka Ringwald float left = plc_state->hist[SBC_LHIST+i]; 4277e6b1e83SMilanka Ringwald float right = in[i]; 428c1ab6cc1SMatthias Ringwald val = (left*rcos[i-SBC_RT]) + (right*rcos[SBC_OLAL+SBC_RT-1-i]); 429ee5b2fc6SMilanka Ringwald out[i] = crop_sample(val); 4307e6b1e83SMilanka Ringwald } 4317e6b1e83SMilanka Ringwald } 4324e4f6f26SMatthias Ringwald 4337e6b1e83SMilanka Ringwald for (;i<SBC_FS;i++){ 4344e074f72SMilanka Ringwald out[i] = in[i]; 4357e6b1e83SMilanka Ringwald } 4364e4f6f26SMatthias Ringwald // Copy the output to the history buffer 4377e6b1e83SMilanka Ringwald for (i=0;i<SBC_FS;i++){ 4387e6b1e83SMilanka Ringwald plc_state->hist[SBC_LHIST+i] = out[i]; 4397e6b1e83SMilanka Ringwald } 440ee5b2fc6SMilanka Ringwald 4414e4f6f26SMatthias Ringwald // shift the history buffer 4427e6b1e83SMilanka Ringwald for (i=0;i<SBC_LHIST;i++){ 4437e6b1e83SMilanka Ringwald plc_state->hist[i] = plc_state->hist[i+SBC_FS]; 4447e6b1e83SMilanka Ringwald } 4457e6b1e83SMilanka Ringwald 446ee5b2fc6SMilanka Ringwald #ifdef OCTAVE_OUTPUT 447ee5b2fc6SMilanka Ringwald if (oct_file){ 448ee5b2fc6SMilanka Ringwald octave_fprintf_plot_output(plc_state, oct_file); 449ee5b2fc6SMilanka Ringwald fclose(oct_file); 450ee5b2fc6SMilanka Ringwald } 451ee5b2fc6SMilanka Ringwald #endif 4524e074f72SMilanka Ringwald plc_state->nbf=0; 4534e074f72SMilanka Ringwald } 454de854f9aSMilanka Ringwald 455de854f9aSMilanka Ringwald void btstack_sbc_dump_statistics(btstack_sbc_plc_state_t * state){ 456de854f9aSMilanka Ringwald log_info("Good frames: %d\n", state->good_frames_nr); 457de854f9aSMilanka Ringwald log_info("Bad frames: %d\n", state->bad_frames_nr); 458de854f9aSMilanka Ringwald log_info("Max Consecutive bad frames: %d\n", state->max_consecutive_bad_frames_nr); 459de854f9aSMilanka Ringwald } 460