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 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 */ 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 */ 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