Home | History | Annotate | Download | only in source
      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