1*a58d3d2aSXin Li /* Copyright (c) 2017-2018 Mozilla */
2*a58d3d2aSXin Li /*
3*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
4*a58d3d2aSXin Li modification, are permitted provided that the following conditions
5*a58d3d2aSXin Li are met:
6*a58d3d2aSXin Li
7*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright
8*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer.
9*a58d3d2aSXin Li
10*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
11*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
12*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
13*a58d3d2aSXin Li
14*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15*a58d3d2aSXin Li ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16*a58d3d2aSXin Li LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17*a58d3d2aSXin Li A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
18*a58d3d2aSXin Li CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*a58d3d2aSXin Li EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*a58d3d2aSXin Li PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21*a58d3d2aSXin Li PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22*a58d3d2aSXin Li LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23*a58d3d2aSXin Li NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24*a58d3d2aSXin Li SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*a58d3d2aSXin Li */
26*a58d3d2aSXin Li
27*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
28*a58d3d2aSXin Li #include "config.h"
29*a58d3d2aSXin Li #endif
30*a58d3d2aSXin Li
31*a58d3d2aSXin Li #include <stdlib.h>
32*a58d3d2aSXin Li #include <string.h>
33*a58d3d2aSXin Li #include <stdio.h>
34*a58d3d2aSXin Li #include "kiss_fft.h"
35*a58d3d2aSXin Li #include <math.h>
36*a58d3d2aSXin Li #include "freq.h"
37*a58d3d2aSXin Li #include "pitch.h"
38*a58d3d2aSXin Li #include "arch.h"
39*a58d3d2aSXin Li #include "burg.h"
40*a58d3d2aSXin Li #include <assert.h>
41*a58d3d2aSXin Li #include "os_support.h"
42*a58d3d2aSXin Li
43*a58d3d2aSXin Li #define SQUARE(x) ((x)*(x))
44*a58d3d2aSXin Li
45*a58d3d2aSXin Li static const opus_int16 eband5ms[] = {
46*a58d3d2aSXin Li /*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k*/
47*a58d3d2aSXin Li 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40
48*a58d3d2aSXin Li };
49*a58d3d2aSXin Li
50*a58d3d2aSXin Li static const float compensation[] = {
51*a58d3d2aSXin Li 0.8f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.666667f, 0.5f, 0.5f, 0.5f, 0.333333f, 0.25f, 0.25f, 0.2f, 0.166667f, 0.173913f
52*a58d3d2aSXin Li };
53*a58d3d2aSXin Li
54*a58d3d2aSXin Li
55*a58d3d2aSXin Li extern const kiss_fft_state kfft;
56*a58d3d2aSXin Li extern const float half_window[OVERLAP_SIZE];
57*a58d3d2aSXin Li extern const float dct_table[NB_BANDS*NB_BANDS];
58*a58d3d2aSXin Li
59*a58d3d2aSXin Li
compute_band_energy_inverse(float * bandE,const kiss_fft_cpx * X)60*a58d3d2aSXin Li static void compute_band_energy_inverse(float *bandE, const kiss_fft_cpx *X) {
61*a58d3d2aSXin Li int i;
62*a58d3d2aSXin Li float sum[NB_BANDS] = {0};
63*a58d3d2aSXin Li for (i=0;i<NB_BANDS-1;i++)
64*a58d3d2aSXin Li {
65*a58d3d2aSXin Li int j;
66*a58d3d2aSXin Li int band_size;
67*a58d3d2aSXin Li band_size = (eband5ms[i+1]-eband5ms[i])*WINDOW_SIZE_5MS;
68*a58d3d2aSXin Li for (j=0;j<band_size;j++) {
69*a58d3d2aSXin Li float tmp;
70*a58d3d2aSXin Li float frac = (float)j/band_size;
71*a58d3d2aSXin Li tmp = SQUARE(X[(eband5ms[i]*WINDOW_SIZE_5MS) + j].r);
72*a58d3d2aSXin Li tmp += SQUARE(X[(eband5ms[i]*WINDOW_SIZE_5MS) + j].i);
73*a58d3d2aSXin Li tmp = 1.f/(tmp + 1e-9);
74*a58d3d2aSXin Li sum[i] += (1-frac)*tmp;
75*a58d3d2aSXin Li sum[i+1] += frac*tmp;
76*a58d3d2aSXin Li }
77*a58d3d2aSXin Li }
78*a58d3d2aSXin Li sum[0] *= 2;
79*a58d3d2aSXin Li sum[NB_BANDS-1] *= 2;
80*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++)
81*a58d3d2aSXin Li {
82*a58d3d2aSXin Li bandE[i] = sum[i];
83*a58d3d2aSXin Li }
84*a58d3d2aSXin Li }
85*a58d3d2aSXin Li
lpcn_lpc(opus_val16 * lpc,opus_val16 * rc,const opus_val32 * ac,int p)86*a58d3d2aSXin Li static float lpcn_lpc(
87*a58d3d2aSXin Li opus_val16 *lpc, /* out: [0...p-1] LPC coefficients */
88*a58d3d2aSXin Li opus_val16 *rc,
89*a58d3d2aSXin Li const opus_val32 *ac, /* in: [0...p] autocorrelation values */
90*a58d3d2aSXin Li int p
91*a58d3d2aSXin Li )
92*a58d3d2aSXin Li {
93*a58d3d2aSXin Li int i, j;
94*a58d3d2aSXin Li opus_val32 r;
95*a58d3d2aSXin Li opus_val32 error = ac[0];
96*a58d3d2aSXin Li
97*a58d3d2aSXin Li OPUS_CLEAR(lpc, p);
98*a58d3d2aSXin Li OPUS_CLEAR(rc, p);
99*a58d3d2aSXin Li if (ac[0] != 0)
100*a58d3d2aSXin Li {
101*a58d3d2aSXin Li for (i = 0; i < p; i++) {
102*a58d3d2aSXin Li /* Sum up this iteration's reflection coefficient */
103*a58d3d2aSXin Li opus_val32 rr = 0;
104*a58d3d2aSXin Li for (j = 0; j < i; j++)
105*a58d3d2aSXin Li rr += MULT32_32_Q31(lpc[j],ac[i - j]);
106*a58d3d2aSXin Li rr += SHR32(ac[i + 1],3);
107*a58d3d2aSXin Li r = -SHL32(rr,3)/error;
108*a58d3d2aSXin Li rc[i] = r;
109*a58d3d2aSXin Li /* Update LPC coefficients and total error */
110*a58d3d2aSXin Li lpc[i] = SHR32(r,3);
111*a58d3d2aSXin Li for (j = 0; j < (i+1)>>1; j++)
112*a58d3d2aSXin Li {
113*a58d3d2aSXin Li opus_val32 tmp1, tmp2;
114*a58d3d2aSXin Li tmp1 = lpc[j];
115*a58d3d2aSXin Li tmp2 = lpc[i-1-j];
116*a58d3d2aSXin Li lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
117*a58d3d2aSXin Li lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
118*a58d3d2aSXin Li }
119*a58d3d2aSXin Li
120*a58d3d2aSXin Li error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
121*a58d3d2aSXin Li /* Bail out once we get 30 dB gain */
122*a58d3d2aSXin Li if (error<.001f*ac[0])
123*a58d3d2aSXin Li break;
124*a58d3d2aSXin Li }
125*a58d3d2aSXin Li }
126*a58d3d2aSXin Li return error;
127*a58d3d2aSXin Li }
128*a58d3d2aSXin Li
129*a58d3d2aSXin Li
130*a58d3d2aSXin Li
lpcn_compute_band_energy(float * bandE,const kiss_fft_cpx * X)131*a58d3d2aSXin Li void lpcn_compute_band_energy(float *bandE, const kiss_fft_cpx *X) {
132*a58d3d2aSXin Li int i;
133*a58d3d2aSXin Li float sum[NB_BANDS] = {0};
134*a58d3d2aSXin Li for (i=0;i<NB_BANDS-1;i++)
135*a58d3d2aSXin Li {
136*a58d3d2aSXin Li int j;
137*a58d3d2aSXin Li int band_size;
138*a58d3d2aSXin Li band_size = (eband5ms[i+1]-eband5ms[i])*WINDOW_SIZE_5MS;
139*a58d3d2aSXin Li for (j=0;j<band_size;j++) {
140*a58d3d2aSXin Li float tmp;
141*a58d3d2aSXin Li float frac = (float)j/band_size;
142*a58d3d2aSXin Li tmp = SQUARE(X[(eband5ms[i]*WINDOW_SIZE_5MS) + j].r);
143*a58d3d2aSXin Li tmp += SQUARE(X[(eband5ms[i]*WINDOW_SIZE_5MS) + j].i);
144*a58d3d2aSXin Li sum[i] += (1-frac)*tmp;
145*a58d3d2aSXin Li sum[i+1] += frac*tmp;
146*a58d3d2aSXin Li }
147*a58d3d2aSXin Li }
148*a58d3d2aSXin Li sum[0] *= 2;
149*a58d3d2aSXin Li sum[NB_BANDS-1] *= 2;
150*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++)
151*a58d3d2aSXin Li {
152*a58d3d2aSXin Li bandE[i] = sum[i];
153*a58d3d2aSXin Li }
154*a58d3d2aSXin Li }
155*a58d3d2aSXin Li
compute_burg_cepstrum(const float * pcm,float * burg_cepstrum,int len,int order)156*a58d3d2aSXin Li static void compute_burg_cepstrum(const float *pcm, float *burg_cepstrum, int len, int order) {
157*a58d3d2aSXin Li int i;
158*a58d3d2aSXin Li float burg_in[FRAME_SIZE];
159*a58d3d2aSXin Li float burg_lpc[LPC_ORDER];
160*a58d3d2aSXin Li float x[WINDOW_SIZE];
161*a58d3d2aSXin Li float Eburg[NB_BANDS];
162*a58d3d2aSXin Li float g;
163*a58d3d2aSXin Li kiss_fft_cpx LPC[FREQ_SIZE];
164*a58d3d2aSXin Li float Ly[NB_BANDS];
165*a58d3d2aSXin Li float logMax = -2;
166*a58d3d2aSXin Li float follow = -2;
167*a58d3d2aSXin Li assert(order <= LPC_ORDER);
168*a58d3d2aSXin Li assert(len <= FRAME_SIZE);
169*a58d3d2aSXin Li for (i=0;i<len-1;i++) burg_in[i] = pcm[i+1] - PREEMPHASIS*pcm[i];
170*a58d3d2aSXin Li g = silk_burg_analysis(burg_lpc, burg_in, 1e-3, len-1, 1, order);
171*a58d3d2aSXin Li g /= len - 2*(order-1);
172*a58d3d2aSXin Li OPUS_CLEAR(x, WINDOW_SIZE);
173*a58d3d2aSXin Li x[0] = 1;
174*a58d3d2aSXin Li for (i=0;i<order;i++) x[i+1] = -burg_lpc[i]*pow(.995, i+1);
175*a58d3d2aSXin Li forward_transform(LPC, x);
176*a58d3d2aSXin Li compute_band_energy_inverse(Eburg, LPC);
177*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++) Eburg[i] *= .45*g*(1.f/((float)WINDOW_SIZE*WINDOW_SIZE*WINDOW_SIZE));
178*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++) {
179*a58d3d2aSXin Li Ly[i] = log10(1e-2+Eburg[i]);
180*a58d3d2aSXin Li Ly[i] = MAX16(logMax-8, MAX16(follow-2.5, Ly[i]));
181*a58d3d2aSXin Li logMax = MAX16(logMax, Ly[i]);
182*a58d3d2aSXin Li follow = MAX16(follow-2.5, Ly[i]);
183*a58d3d2aSXin Li }
184*a58d3d2aSXin Li dct(burg_cepstrum, Ly);
185*a58d3d2aSXin Li burg_cepstrum[0] += - 4;
186*a58d3d2aSXin Li }
187*a58d3d2aSXin Li
burg_cepstral_analysis(float * ceps,const float * x)188*a58d3d2aSXin Li void burg_cepstral_analysis(float *ceps, const float *x) {
189*a58d3d2aSXin Li int i;
190*a58d3d2aSXin Li compute_burg_cepstrum(x, &ceps[0 ], FRAME_SIZE/2, LPC_ORDER);
191*a58d3d2aSXin Li compute_burg_cepstrum(&x[FRAME_SIZE/2], &ceps[NB_BANDS], FRAME_SIZE/2, LPC_ORDER);
192*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++) {
193*a58d3d2aSXin Li float c0, c1;
194*a58d3d2aSXin Li c0 = ceps[i];
195*a58d3d2aSXin Li c1 = ceps[NB_BANDS+i];
196*a58d3d2aSXin Li ceps[i ] = .5*(c0+c1);
197*a58d3d2aSXin Li ceps[NB_BANDS+i] = (c0-c1);
198*a58d3d2aSXin Li }
199*a58d3d2aSXin Li }
200*a58d3d2aSXin Li
201*a58d3d2aSXin Li
interp_band_gain(float * g,const float * bandE)202*a58d3d2aSXin Li static void interp_band_gain(float *g, const float *bandE) {
203*a58d3d2aSXin Li int i;
204*a58d3d2aSXin Li memset(g, 0, FREQ_SIZE);
205*a58d3d2aSXin Li for (i=0;i<NB_BANDS-1;i++)
206*a58d3d2aSXin Li {
207*a58d3d2aSXin Li int j;
208*a58d3d2aSXin Li int band_size;
209*a58d3d2aSXin Li band_size = (eband5ms[i+1]-eband5ms[i])*WINDOW_SIZE_5MS;
210*a58d3d2aSXin Li for (j=0;j<band_size;j++) {
211*a58d3d2aSXin Li float frac = (float)j/band_size;
212*a58d3d2aSXin Li g[(eband5ms[i]*WINDOW_SIZE_5MS) + j] = (1-frac)*bandE[i] + frac*bandE[i+1];
213*a58d3d2aSXin Li }
214*a58d3d2aSXin Li }
215*a58d3d2aSXin Li }
216*a58d3d2aSXin Li
217*a58d3d2aSXin Li
dct(float * out,const float * in)218*a58d3d2aSXin Li void dct(float *out, const float *in) {
219*a58d3d2aSXin Li int i;
220*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++) {
221*a58d3d2aSXin Li int j;
222*a58d3d2aSXin Li float sum = 0;
223*a58d3d2aSXin Li for (j=0;j<NB_BANDS;j++) {
224*a58d3d2aSXin Li sum += in[j] * dct_table[j*NB_BANDS + i];
225*a58d3d2aSXin Li }
226*a58d3d2aSXin Li out[i] = sum*sqrt(2./NB_BANDS);
227*a58d3d2aSXin Li }
228*a58d3d2aSXin Li }
229*a58d3d2aSXin Li
idct(float * out,const float * in)230*a58d3d2aSXin Li static void idct(float *out, const float *in) {
231*a58d3d2aSXin Li int i;
232*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++) {
233*a58d3d2aSXin Li int j;
234*a58d3d2aSXin Li float sum = 0;
235*a58d3d2aSXin Li for (j=0;j<NB_BANDS;j++) {
236*a58d3d2aSXin Li sum += in[j] * dct_table[i*NB_BANDS + j];
237*a58d3d2aSXin Li }
238*a58d3d2aSXin Li out[i] = sum*sqrt(2./NB_BANDS);
239*a58d3d2aSXin Li }
240*a58d3d2aSXin Li }
241*a58d3d2aSXin Li
forward_transform(kiss_fft_cpx * out,const float * in)242*a58d3d2aSXin Li void forward_transform(kiss_fft_cpx *out, const float *in) {
243*a58d3d2aSXin Li int i;
244*a58d3d2aSXin Li kiss_fft_cpx x[WINDOW_SIZE];
245*a58d3d2aSXin Li kiss_fft_cpx y[WINDOW_SIZE];
246*a58d3d2aSXin Li for (i=0;i<WINDOW_SIZE;i++) {
247*a58d3d2aSXin Li x[i].r = in[i];
248*a58d3d2aSXin Li x[i].i = 0;
249*a58d3d2aSXin Li }
250*a58d3d2aSXin Li opus_fft(&kfft, x, y, 0);
251*a58d3d2aSXin Li for (i=0;i<FREQ_SIZE;i++) {
252*a58d3d2aSXin Li out[i] = y[i];
253*a58d3d2aSXin Li }
254*a58d3d2aSXin Li }
255*a58d3d2aSXin Li
inverse_transform(float * out,const kiss_fft_cpx * in)256*a58d3d2aSXin Li static void inverse_transform(float *out, const kiss_fft_cpx *in) {
257*a58d3d2aSXin Li int i;
258*a58d3d2aSXin Li kiss_fft_cpx x[WINDOW_SIZE];
259*a58d3d2aSXin Li kiss_fft_cpx y[WINDOW_SIZE];
260*a58d3d2aSXin Li for (i=0;i<FREQ_SIZE;i++) {
261*a58d3d2aSXin Li x[i] = in[i];
262*a58d3d2aSXin Li }
263*a58d3d2aSXin Li for (;i<WINDOW_SIZE;i++) {
264*a58d3d2aSXin Li x[i].r = x[WINDOW_SIZE - i].r;
265*a58d3d2aSXin Li x[i].i = -x[WINDOW_SIZE - i].i;
266*a58d3d2aSXin Li }
267*a58d3d2aSXin Li opus_fft(&kfft, x, y, 0);
268*a58d3d2aSXin Li /* output in reverse order for IFFT. */
269*a58d3d2aSXin Li out[0] = WINDOW_SIZE*y[0].r;
270*a58d3d2aSXin Li for (i=1;i<WINDOW_SIZE;i++) {
271*a58d3d2aSXin Li out[i] = WINDOW_SIZE*y[WINDOW_SIZE - i].r;
272*a58d3d2aSXin Li }
273*a58d3d2aSXin Li }
274*a58d3d2aSXin Li
lpc_from_bands(float * lpc,const float * Ex)275*a58d3d2aSXin Li static float lpc_from_bands(float *lpc, const float *Ex)
276*a58d3d2aSXin Li {
277*a58d3d2aSXin Li int i;
278*a58d3d2aSXin Li float e;
279*a58d3d2aSXin Li float ac[LPC_ORDER+1];
280*a58d3d2aSXin Li float rc[LPC_ORDER];
281*a58d3d2aSXin Li float Xr[FREQ_SIZE];
282*a58d3d2aSXin Li kiss_fft_cpx X_auto[FREQ_SIZE];
283*a58d3d2aSXin Li float x_auto[WINDOW_SIZE];
284*a58d3d2aSXin Li interp_band_gain(Xr, Ex);
285*a58d3d2aSXin Li Xr[FREQ_SIZE-1] = 0;
286*a58d3d2aSXin Li OPUS_CLEAR(X_auto, FREQ_SIZE);
287*a58d3d2aSXin Li for (i=0;i<FREQ_SIZE;i++) X_auto[i].r = Xr[i];
288*a58d3d2aSXin Li inverse_transform(x_auto, X_auto);
289*a58d3d2aSXin Li for (i=0;i<LPC_ORDER+1;i++) ac[i] = x_auto[i];
290*a58d3d2aSXin Li
291*a58d3d2aSXin Li /* -40 dB noise floor. */
292*a58d3d2aSXin Li ac[0] += ac[0]*1e-4 + 320/12/38.;
293*a58d3d2aSXin Li /* Lag windowing. */
294*a58d3d2aSXin Li for (i=1;i<LPC_ORDER+1;i++) ac[i] *= (1 - 6e-5*i*i);
295*a58d3d2aSXin Li e = lpcn_lpc(lpc, rc, ac, LPC_ORDER);
296*a58d3d2aSXin Li return e;
297*a58d3d2aSXin Li }
298*a58d3d2aSXin Li
lpc_weighting(float * lpc,float gamma)299*a58d3d2aSXin Li void lpc_weighting(float *lpc, float gamma)
300*a58d3d2aSXin Li {
301*a58d3d2aSXin Li int i;
302*a58d3d2aSXin Li float gamma_i = gamma;
303*a58d3d2aSXin Li for (i = 0; i < LPC_ORDER; i++)
304*a58d3d2aSXin Li {
305*a58d3d2aSXin Li lpc[i] *= gamma_i;
306*a58d3d2aSXin Li gamma_i *= gamma;
307*a58d3d2aSXin Li }
308*a58d3d2aSXin Li }
309*a58d3d2aSXin Li
lpc_from_cepstrum(float * lpc,const float * cepstrum)310*a58d3d2aSXin Li float lpc_from_cepstrum(float *lpc, const float *cepstrum)
311*a58d3d2aSXin Li {
312*a58d3d2aSXin Li int i;
313*a58d3d2aSXin Li float Ex[NB_BANDS];
314*a58d3d2aSXin Li float tmp[NB_BANDS];
315*a58d3d2aSXin Li OPUS_COPY(tmp, cepstrum, NB_BANDS);
316*a58d3d2aSXin Li tmp[0] += 4;
317*a58d3d2aSXin Li idct(Ex, tmp);
318*a58d3d2aSXin Li for (i=0;i<NB_BANDS;i++) Ex[i] = pow(10.f, Ex[i])*compensation[i];
319*a58d3d2aSXin Li return lpc_from_bands(lpc, Ex);
320*a58d3d2aSXin Li }
321*a58d3d2aSXin Li
apply_window(float * x)322*a58d3d2aSXin Li void apply_window(float *x) {
323*a58d3d2aSXin Li int i;
324*a58d3d2aSXin Li for (i=0;i<OVERLAP_SIZE;i++) {
325*a58d3d2aSXin Li x[i] *= half_window[i];
326*a58d3d2aSXin Li x[WINDOW_SIZE - 1 - i] *= half_window[i];
327*a58d3d2aSXin Li }
328*a58d3d2aSXin Li }
329