Line data Source code
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 : */
29 0 : 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 0 : for (j=0; j<NumberOfSections; j++){
36 0 : for (n=0;n<lengthInOut;n++){
37 0 : temp = FilterState[j] + APSectionFactors[j] * InOut[n];
38 0 : FilterState[j] = -APSectionFactors[j] * temp + InOut[n];
39 0 : InOut[n] = temp;
40 : }
41 : }
42 0 : }
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 : */
83 0 : 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 0 : for (k=0;k<FRAMESAMPLES;k++) {
101 0 : in[k] = pin[k] + kHpStCoefInFloat[2] * prefiltdata->HPstates_float[0] +
102 0 : kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1];
103 0 : ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] -
104 0 : kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1];
105 0 : prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0];
106 0 : 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 0 : for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){
124 0 : CompositeAPFilterState[k] = 0.0;
125 : }
126 : /* put every other sample of input into a temporary vector in reverse (backward) order*/
127 0 : for (k=0;k<FRAMESAMPLES_HALF;k++) {
128 0 : tempinoutvec[k] = in[FRAMESAMPLES-1-2*k];
129 : }
130 :
131 : /* now all-pass filter the backwards vector. Output values overwrite the input vector. */
132 0 : 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 0 : for (k=0;k<FRAMESAMPLES_HALF;k++) {
138 0 : 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 0 : for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) {
144 0 : 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 0 : 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 0 : for (k=0;k<QLOOKAHEAD;k++) {
159 0 : tempin_ch1[QLOOKAHEAD-1-k]=prefiltdata->INLABUF1_float[k];
160 0 : 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 0 : for (k=0;k<NUMBEROFCOMPOSITEAPSECTIONS;k++){
166 0 : CompositeAPFilterState[k] = 0.0;
167 : }
168 :
169 0 : for (k=0;k<FRAMESAMPLES_HALF;k++) {
170 0 : tempinoutvec[k] = in[FRAMESAMPLES-2-2*k];
171 : }
172 :
173 0 : WebRtcIsac_AllPassFilter2Float(tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat,
174 : FRAMESAMPLES_HALF, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
175 :
176 0 : for (k=0;k<FRAMESAMPLES_HALF;k++) {
177 0 : tempin_ch2[FRAMESAMPLES_HALF+QLOOKAHEAD-1-k] = tempinoutvec[k];
178 : }
179 :
180 0 : for (k=0; k<NUMBEROFCOMPOSITEAPSECTIONS; k++) {
181 0 : ForTransform_CompositeAPFilterState2[k] = CompositeAPFilterState[k];
182 : }
183 :
184 :
185 0 : WebRtcIsac_AllPassFilter2Float(prefiltdata->INLABUF2_float,
186 : WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,NUMBEROFCOMPOSITEAPSECTIONS,
187 : CompositeAPFilterState);
188 :
189 0 : for (k=0;k<QLOOKAHEAD;k++) {
190 0 : tempin_ch2[QLOOKAHEAD-1-k]=prefiltdata->INLABUF2_float[k];
191 0 : 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 0 : for (k=0;k<NUMBEROFCHANNELAPSECTIONS;k++){ /* k is row variable */
205 0 : for (n=0; n<NUMBEROFCOMPOSITEAPSECTIONS;n++){/* n is column variable */
206 0 : prefiltdata->INSTAT1_float[k] += ForTransform_CompositeAPFilterState[n]*
207 0 : WebRtcIsac_kTransform1Float[k*NUMBEROFCHANNELAPSECTIONS+n];
208 0 : prefiltdata->INSTAT2_float[k] += ForTransform_CompositeAPFilterState2[n]*
209 0 : 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 0 : WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
218 0 : FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_float);
219 0 : WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
220 0 : FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_float);
221 :
222 : /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
223 0 : for (k=0; k<FRAMESAMPLES_HALF; k++) {
224 0 : LP[k] = 0.5f*(tempin_ch1[k] + tempin_ch2[k]);/* low pass signal*/
225 0 : 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 0 : for (k=0; k<FRAMESAMPLES_HALF; k++) {
237 0 : tempin_ch1[k]=in[2*k+1];
238 0 : 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 0 : WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
244 0 : FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA1_float);
245 0 : WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
246 0 : FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA2_float);
247 :
248 0 : for (k=0; k<FRAMESAMPLES_HALF; k++) {
249 0 : LP_la[k] = (float)(0.5f*(tempin_ch1[k] + tempin_ch2[k])); /*low pass */
250 0 : HP_la[k] = (double)(0.5f*(tempin_ch1[k] - tempin_ch2[k])); /* high pass */
251 : }
252 :
253 :
254 0 : }/*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 */
287 0 : 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 0 : for (k=0;k<FRAMESAMPLES_HALF;k++) {
299 0 : tempin_ch1[k]=InLP[k]+InHP[k]; /* Construct a new upper channel signal*/
300 0 : 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 0 : WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kLowerApFactorsFloat,
308 0 : 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 0 : WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat,
315 0 : FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float);
316 :
317 :
318 : /* Merge outputs to form the full length output signal.*/
319 0 : for (k=0;k<FRAMESAMPLES_HALF;k++) {
320 0 : Out[2*k]=tempin_ch2[k];
321 0 : Out[2*k+1]=tempin_ch1[k];
322 : }
323 :
324 :
325 : /* High pass filter */
326 :
327 0 : for (k=0;k<FRAMESAMPLES;k++) {
328 0 : ftmp2 = Out[k] + kHpStCoefOut1Float[2] * postfiltdata->HPstates1_float[0] +
329 0 : kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1];
330 0 : ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] -
331 0 : kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1];
332 0 : postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0];
333 0 : postfiltdata->HPstates1_float[0] = ftmp;
334 0 : Out[k] = ftmp2;
335 : }
336 :
337 0 : for (k=0;k<FRAMESAMPLES;k++) {
338 0 : ftmp2 = Out[k] + kHpStCoefOut2Float[2] * postfiltdata->HPstates2_float[0] +
339 0 : kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1];
340 0 : ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] -
341 0 : kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1];
342 0 : postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0];
343 0 : postfiltdata->HPstates2_float[0] = ftmp;
344 0 : Out[k] = ftmp2;
345 : }
346 0 : }
|