xref: /btstack/src/classic/btstack_sbc_plc.c (revision b3f76298ca1ccca314e568b77c5d0fcf231f5b47)
1 /*
2  * Copyright (C) 2016 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 /*
39  * btstack_sbc_plc.c
40  *
41  */
42 
43 #include <stdint.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <math.h>
50 
51 #include "btstack_sbc_plc.h"
52 
53 static uint8_t indices0[] = { 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d,
54 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
55 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
56 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
57 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c};
58 
59 /* Raised COSine table for OLA */
60 static float rcos[OLAL] = {
61     0.99148655f,0.96623611f,0.92510857f,0.86950446f,
62     0.80131732f,0.72286918f,0.63683150f,0.54613418f,
63     0.45386582f,0.36316850f,0.27713082f,0.19868268f,
64     0.13049554f,0.07489143f,0.03376389f,0.00851345f};
65 
66 static float CrossCorrelation(int16_t *x, int16_t *y);
67 static int PatternMatch(int16_t *y);
68 static float AmplitudeMatch(int16_t *y, int16_t bestmatch);
69 
70 uint8_t * btstack_sbc_plc_zero_signal_frame(void){
71     return (uint8_t *)&indices0;
72 }
73 
74 void btstack_sbc_plc_init(btstack_sbc_plc_state_t *plc_state){
75     int i;
76     plc_state->nbf=0;
77     plc_state->bestlag=0;
78     // for (i=0;i<LHIST+FS+CVSDRT+OLAL;i++){
79     //     plc_state->hist[i] = 0;
80     // }
81     memset(plc_state->hist,0,sizeof(plc_state->hist));
82 
83 }
84 
85 void btstack_sbc_plc_bad_frame(btstack_sbc_plc_state_t *plc_state, int16_t *ZIRbuf, int16_t *out){
86     int   i;
87     float val;
88     float sf;
89     plc_state->nbf++;
90     sf=1.0f;
91 
92     i=0;
93     if (plc_state->nbf==1){
94         /* Perform pattern matching to find where to replicate */
95         plc_state->bestlag = PatternMatch(plc_state->hist);
96         /* the replication begins after the template match */
97         plc_state->bestlag += M;
98 
99         /* Compute Scale Factor to Match Amplitude of Substitution Packet to that of Preceding Packet */
100         sf = AmplitudeMatch(plc_state->hist, plc_state->bestlag);
101         for (i=0;i<OLAL;i++){
102             val = ZIRbuf[i]*rcos[i] + sf*plc_state->hist[plc_state->bestlag+i]*rcos[OLAL-i-1];
103             if (val >  32767.0) val= 32767.0;
104             if (val < -32768.0) val=-32768.0;
105              plc_state->hist[LHIST+i] = (int16_t)val;
106         }
107 
108         for (;i<FS;i++){
109             val = sf*plc_state->hist[plc_state->bestlag+i]; if (val > 32767.0) val= 32767.0;
110             if (val < -32768.0) val=-32768.0; plc_state->hist[LHIST+i] = (int16_t)val;
111         }
112 
113         for (;i<FS+OLAL;i++){
114             val = sf*plc_state->hist[plc_state->bestlag+i]*rcos[i-FS]+plc_state->hist[plc_state->bestlag+i]*rcos[OLAL-1-i+FS];
115             if (val >  32767.0) val= 32767.0;
116             if (val < -32768.0) val=-32768.0;
117             plc_state->hist[LHIST+i] = (int16_t)val;
118         }
119 
120         for (;i<FS+SBCRT+OLAL;i++)
121             plc_state->hist[LHIST+i] = plc_state->hist[plc_state->bestlag+i];
122     } else {
123         for (;i<FS;i++)
124             plc_state->hist[LHIST+i] = plc_state->hist[plc_state->bestlag+i];
125         for (;i<FS+SBCRT+OLAL;i++)
126             plc_state->hist[LHIST+i] = plc_state->hist[plc_state->bestlag+i];
127     }
128     for (i=0;i<FS;i++)
129         out[i] = plc_state->hist[LHIST+i];
130 
131    /* shift the history buffer */
132    for (i=0;i<LHIST+SBCRT+OLAL;i++)
133         plc_state->hist[i] = plc_state->hist[i+FS];
134 
135 }
136 
137 void btstack_sbc_plc_good_frame(btstack_sbc_plc_state_t *plc_state, int16_t *in, int16_t *out){
138     int i;
139     i=0;
140     if (plc_state->nbf>0){
141         for (i=0;i<SBCRT;i++)
142             out[i] = plc_state->hist[LHIST+i];
143         for (;i<SBCRT+OLAL;i++)
144             out[i] = (int16_t)(plc_state->hist[LHIST+i]*rcos[i-SBCRT] + in[i]*rcos[OLAL-1-i+SBCRT]);
145     }
146     for (;i<FS;i++)
147         out[i] = in[i];
148     /*Copy the output to the history buffer */
149     for (i=0;i<FS;i++)
150         plc_state->hist[LHIST+i] = out[i];
151     /* shift the history buffer */
152     for (i=0;i<LHIST;i++)
153         plc_state->hist[i] = plc_state->hist[i+FS];
154     plc_state->nbf=0;
155 }
156 
157 
158 float CrossCorrelation(int16_t *x, int16_t *y){
159     int   m;
160     float num;
161     float den;
162     float Cn;
163     float x2, y2;
164     num=0;
165     den=0;
166     x2=0.0;
167     y2=0.0;
168     for (m=0;m<M;m++){
169         num+=((float)x[m])*y[m];
170         x2+=((float)x[m])*x[m];
171         y2+=((float)y[m])*y[m];
172     }
173     den = (float)sqrt(x2*y2);
174     Cn = num/den;
175     return(Cn);
176 }
177 
178 int PatternMatch(int16_t *y){
179     int   n;
180     float maxCn;
181     float Cn;
182     int   bestmatch;
183     maxCn=-999999.0;  /* large negative number */
184     bestmatch=0;
185     for (n=0;n<N;n++){
186         Cn = CrossCorrelation(&y[LHIST-M] /* x */, &y[n]);
187         if (Cn>maxCn){
188             bestmatch=n;
189             maxCn = Cn;
190         }
191     }
192     return(bestmatch);
193 }
194 
195 
196 float AmplitudeMatch(int16_t *y, int16_t bestmatch) {
197     int   i;
198     float sumx;
199     float sumy;
200     float sf;
201     sumx = 0.0;
202     sumy = 0.000001f;
203     for (i=0;i<FS;i++){
204         sumx += abs(y[LHIST-FS+i]);
205         sumy += abs(y[bestmatch+i]);
206     }
207     sf = sumx/sumy;
208     /* This is not in the paper, but limit the scaling factor to something reasonable to avoid creating artifacts */
209     if (sf<0.75f) sf=0.75f;
210     if (sf>1.2f) sf=1.2f;
211     return(sf);
212 }