1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 /*
12  * filterbanks.c
13  *
14  * This file contains function WebRtcIsac_AllPassFilter2Float,
15  * WebRtcIsac_SplitAndFilter, and WebRtcIsac_FilterAndCombine
16  * which implement filterbanks that produce decimated lowpass and
17  * highpass versions of a signal, and performs reconstruction.
18  *
19  */
20 
21 #include "settings.h"
22 #include "filterbank_tables.h"
23 #include "codec.h"
24 
25 /* This function performs all-pass filtering--a series of first order all-pass
26  * sections are used to filter the input in a cascade manner.
27  * The input is overwritten!!
28  */
WebRtcIsac_AllPassFilter2Float(float * InOut,const float * APSectionFactors,int lengthInOut,int NumberOfSections,float * FilterState)29 static void WebRtcIsac_AllPassFilter2Float(float *InOut, const float *APSectionFactors,
30                                            int lengthInOut, int NumberOfSections,
31                                            float *FilterState)
32 {
33   int n, j;
34   float temp;
35   for (j=0; j<NumberOfSections; j++){
36     for (n=0;n<lengthInOut;n++){
37       temp = FilterState[j] + APSectionFactors[j] * InOut[n];
38       FilterState[j] = -APSectionFactors[j] * temp + InOut[n];
39       InOut[n] = temp;
40     }
41   }
42 }
43 
44 /* HPstcoeff_in = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
45 static const float kHpStCoefInFloat[4] =
46 {-1.94895953203325f, 0.94984516000000f, -0.05101826139794f, 0.05015484000000f};
47 
48 /* Function WebRtcIsac_SplitAndFilter
49  * This function creates low-pass and high-pass decimated versions of part of
50  the input signal, and part of the signal in the input 'lookahead buffer'.
51 
52  INPUTS:
53  in: a length FRAMESAMPLES array of input samples
54  prefiltdata: input data structure containing the filterbank states
55  and lookahead samples from the previous encoding
56  iteration.
57  OUTPUTS:
58  LP: a FRAMESAMPLES_HALF array of low-pass filtered samples that
59  have been phase equalized.  The first QLOOKAHEAD samples are
60  based on the samples in the two prefiltdata->INLABUFx arrays
61  each of length QLOOKAHEAD.
62  The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
63  on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
64  array in[].
65  HP: a FRAMESAMPLES_HALF array of high-pass filtered samples that
66  have been phase equalized.  The first QLOOKAHEAD samples are
67  based on the samples in the two prefiltdata->INLABUFx arrays
68  each of length QLOOKAHEAD.
69  The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
70  on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
71  array in[].
72 
73  LP_la: a FRAMESAMPLES_HALF array of low-pass filtered samples.
74  These samples are not phase equalized. They are computed
75  from the samples in the in[] array.
76  HP_la: a FRAMESAMPLES_HALF array of high-pass filtered samples
77  that are not phase equalized. They are computed from
78  the in[] vector.
79  prefiltdata: this input data structure's filterbank state and
80  lookahead sample buffers are updated for the next
81  encoding iteration.
82 */
WebRtcIsac_SplitAndFilterFloat(float * pin,float * LP,float * HP,double * LP_la,double * HP_la,PreFiltBankstr * prefiltdata)83 void WebRtcIsac_SplitAndFilterFloat(float *pin, float *LP, float *HP,
84                                     double *LP_la, double *HP_la,
85                                     PreFiltBankstr *prefiltdata)
86 {
87   int k,n;
88   float CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
89   float ForTransform_CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
90   float ForTransform_CompositeAPFilterState2[NUMBEROFCOMPOSITEAPSECTIONS];
91   float tempinoutvec[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
92   float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
93   float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
94   float in[FRAMESAMPLES];
95   float ftmp;
96 
97 
98   /* High pass filter */
99 
100   for (k=0;k<FRAMESAMPLES;k++) {
101     in[k] = pin[k] + kHpStCoefInFloat[2] * prefiltdata->HPstates_float[0] +
102         kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1];
103     ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] -
104         kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1];
105     prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0];
106     prefiltdata->HPstates_float[0] = ftmp;
107   }
108 
109   /*
110     % backwards all-pass filtering to obtain zero-phase
111     [tmp1(N2+LA:-1:LA+1, 1), state1] = filter(Q.coef, Q.coef(end:-1:1), in(N:-2:2));
112     tmp1(LA:-1:1) = filter(Q.coef, Q.coef(end:-1:1), Q.LookAheadBuf1, state1);
113     Q.LookAheadBuf1 = in(N:-2:N-2*LA+2);
114   */
115   /*Backwards all-pass filter the odd samples of the input (upper channel)
116     to eventually obtain zero phase.  The composite all-pass filter (comprised of both
117     the upper and lower channel all-pass filsters in series) is used for the
118     filtering. */
119 
120   /* First Channel */
121 
122   /*initial state of composite filter is zero */
123   for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){
124     CompositeAPFilterState[k] = 0.0;
125   }
126   /* put every other sample of input into a temporary vector in reverse (backward) order*/
127   for (k=0;k<FRAMESAMPLES_HALF;k++) {
128     tempinoutvec[k] = in[FRAMESAMPLES-1-2*k];
129   }
130 
131   /* now all-pass filter the backwards vector.  Output values overwrite the input vector. */
132   WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat,
133                                  FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
134 
135   /* save the backwards filtered output for later forward filtering,
136      but write it in forward order*/
137   for (k=0;k<FRAMESAMPLES_HALF;k++) {
138     tempin_ch1[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k];
139   }
140 
141   /* save the backwards filter state  becaue it will be transformed
142      later into a forward state */
143   for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) {
144     ForTransform_CompositeAPFilterState[k] = CompositeAPFilterState[k];
145   }
146 
147   /* now backwards filter the samples in the lookahead buffer. The samples were
148      placed there in the encoding of the previous frame.  The output samples
149      overwrite the input samples */
150   WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF1_float,
151                                  WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,
152                                  NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
153 
154   /* save the output, but write it in forward order */
155   /* write the lookahead samples for the next encoding iteration. Every other
156      sample at the end of the input frame is written in reverse order for the
157      lookahead length. Exported in the prefiltdata structure. */
158   for (k=0;k<QLOOKAHEAD;k++) {
159     tempin_ch1[QLOOKAHEAD-1-k]=prefiltdata->INLABUF1_float[k];
160     prefiltdata->INLABUF1_float[k]=in[FRAMESAMPLES-1-2*k];
161   }
162 
163   /* Second Channel.  This is exactly like the first channel, except that the
164      even samples are now filtered instead (lower channel). */
165   for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){
166     CompositeAPFilterState[k] = 0.0;
167   }
168 
169   for (k=0;k<FRAMESAMPLES_HALF;k++) {
170     tempinoutvec[k] = in[FRAMESAMPLES-2-2*k];
171   }
172 
173   WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat,
174                                  FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
175 
176   for (k=0;k<FRAMESAMPLES_HALF;k++) {
177     tempin_ch2[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k];
178   }
179 
180   for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) {
181     ForTransform_CompositeAPFilterState2[k] = CompositeAPFilterState[k];
182   }
183 
184 
185   WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF2_float,
186                                  WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,NUMBEROFCOMPOSITEAPSECTIONS,
187                                  CompositeAPFilterState);
188 
189   for (k=0;k<QLOOKAHEAD;k++) {
190     tempin_ch2[QLOOKAHEAD-1-k]=prefiltdata->INLABUF2_float[k];
191     prefiltdata->INLABUF2_float[k]=in[FRAMESAMPLES-2-2*k];
192   }
193 
194   /* Transform filter states from backward to forward */
195   /*At this point, each of the states of the backwards composite filters for the
196     two channels are transformed into forward filtering states for the corresponding
197     forward channel filters.  Each channel's forward filtering state from the previous
198     encoding iteration is added to the transformed state to get a proper forward state */
199 
200   /* So the existing NUMBEROFCOMPOSITEAPSECTIONS x 1 (4x1) state vector is multiplied by a
201      NUMBEROFCHANNELAPSECTIONSxNUMBEROFCOMPOSITEAPSECTIONS (2x4) transform matrix to get the
202      new state that is added to the previous 2x1 input state */
203 
204   for (k=0;k<NUMBEROFCHANNELAPSECTIONS;k++){ /* k is row variable */
205     for (n=0; n<NUMBEROFCOMPOSITEAPSECTIONS;n++){/* n is column variable */
206       prefiltdata->INSTAT1_float[k] += ForTransform_CompositeAPFilterState[n]*
207           WebRtcIsac_kTransform1Float[k*NUMBEROFCHANNELAPSECTIONS+n];
208       prefiltdata->INSTAT2_float[k] += ForTransform_CompositeAPFilterState2[n]*
209           WebRtcIsac_kTransform2Float[k*NUMBEROFCHANNELAPSECTIONS+n];
210     }
211   }
212 
213   /*obtain polyphase components by forward all-pass filtering through each channel */
214   /* the backward filtered samples are now forward filtered with the corresponding channel filters */
215   /* The all pass filtering automatically updates the filter states which are exported in the
216      prefiltdata structure */
217   WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
218                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_float);
219   WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
220                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_float);
221 
222   /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
223   for (k=0; k<FRAMESAMPLES_HALF; k++) {
224     LP[k] = 0.5f*(tempin_ch1[k] + tempin_ch2[k]);/* low pass signal*/
225     HP[k] = 0.5f*(tempin_ch1[k] - tempin_ch2[k]);/* high pass signal*/
226   }
227 
228   /* Lookahead LP and HP signals */
229   /* now create low pass and high pass signals of the input vector.  However, no
230      backwards filtering is performed, and hence no phase equalization is involved.
231      Also, the input contains some samples that are lookahead samples.  The high pass
232      and low pass signals that are created are used outside this function for analysis
233      (not encoding) purposes */
234 
235   /* set up input */
236   for (k=0; k<FRAMESAMPLES_HALF; k++) {
237     tempin_ch1[k]=in[2*k+1];
238     tempin_ch2[k]=in[2*k];
239   }
240 
241   /* the input filter states are passed in and updated by the all-pass filtering routine and
242      exported in the prefiltdata structure*/
243   WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
244                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA1_float);
245   WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
246                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA2_float);
247 
248   for (k=0; k<FRAMESAMPLES_HALF; k++) {
249     LP_la[k] = (float)(0.5f*(tempin_ch1[k] + tempin_ch2[k])); /*low pass */
250     HP_la[k] = (double)(0.5f*(tempin_ch1[k] - tempin_ch2[k])); /* high pass */
251   }
252 
253 
254 }/*end of WebRtcIsac_SplitAndFilter */
255 
256 
257 /* Combining */
258 
259 /* HPstcoeff_out_1 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
260 static const float kHpStCoefOut1Float[4] =
261 {-1.99701049409000f, 0.99714204490000f, 0.01701049409000f, -0.01704204490000f};
262 
263 /* HPstcoeff_out_2 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
264 static const float kHpStCoefOut2Float[4] =
265 {-1.98645294509837f, 0.98672435560000f, 0.00645294509837f, -0.00662435560000f};
266 
267 
268 /* Function WebRtcIsac_FilterAndCombine */
269 /* This is a decoder function that takes the decimated
270    length FRAMESAMPLES_HALF input low-pass and
271    high-pass signals and creates a reconstructed fullband
272    output signal of length FRAMESAMPLES. WebRtcIsac_FilterAndCombine
273    is the sibling function of WebRtcIsac_SplitAndFilter */
274 /* INPUTS:
275    inLP: a length FRAMESAMPLES_HALF array of input low-pass
276    samples.
277    inHP: a length FRAMESAMPLES_HALF array of input high-pass
278    samples.
279    postfiltdata: input data structure containing the filterbank
280    states from the previous decoding iteration.
281    OUTPUTS:
282    Out: a length FRAMESAMPLES array of output reconstructed
283    samples (fullband) based on the input low-pass and
284    high-pass signals.
285    postfiltdata: the input data structure containing the filterbank
286    states is updated for the next decoding iteration */
WebRtcIsac_FilterAndCombineFloat(float * InLP,float * InHP,float * Out,PostFiltBankstr * postfiltdata)287 void WebRtcIsac_FilterAndCombineFloat(float *InLP,
288                                       float *InHP,
289                                       float *Out,
290                                       PostFiltBankstr *postfiltdata)
291 {
292   int k;
293   float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
294   float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
295   float ftmp, ftmp2;
296 
297   /* Form the polyphase signals*/
298   for (k=0;k<FRAMESAMPLES_HALF;k++) {
299     tempin_ch1[k]=InLP[k]+InHP[k]; /* Construct a new upper channel signal*/
300     tempin_ch2[k]=InLP[k]-InHP[k]; /* Construct a new lower channel signal*/
301   }
302 
303 
304   /* all-pass filter the new upper channel signal. HOWEVER, use the all-pass filter factors
305      that were used as a lower channel at the encoding side.  So at the decoder, the
306      corresponding all-pass filter factors for each channel are swapped.*/
307   WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kLowerApFactorsFloat,
308                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_UPPER_float);
309 
310   /* Now, all-pass filter the new lower channel signal. But since all-pass filter factors
311      at the decoder are swapped from the ones at the encoder, the 'upper' channel
312      all-pass filter factors (WebRtcIsac_kUpperApFactorsFloat) are used to filter this new
313      lower channel signal */
314   WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat,
315                                  FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float);
316 
317 
318   /* Merge outputs to form the full length output signal.*/
319   for (k=0;k<FRAMESAMPLES_HALF;k++) {
320     Out[2*k]=tempin_ch2[k];
321     Out[2*k+1]=tempin_ch1[k];
322   }
323 
324 
325   /* High pass filter */
326 
327   for (k=0;k<FRAMESAMPLES;k++) {
328     ftmp2 = Out[k] + kHpStCoefOut1Float[2] * postfiltdata->HPstates1_float[0] +
329         kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1];
330     ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] -
331         kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1];
332     postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0];
333     postfiltdata->HPstates1_float[0] = ftmp;
334     Out[k] = ftmp2;
335   }
336 
337   for (k=0;k<FRAMESAMPLES;k++) {
338     ftmp2 = Out[k] + kHpStCoefOut2Float[2] * postfiltdata->HPstates2_float[0] +
339         kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1];
340     ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] -
341         kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1];
342     postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0];
343     postfiltdata->HPstates2_float[0] = ftmp;
344     Out[k] = ftmp2;
345   }
346 }
347