LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/codecs/isac/main/source - filterbanks.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 93 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.13