Home | History | Annotate | Download | only in signal_processing
      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  * This file contains the splitting filter functions.
     13  *
     14  */
     15 
     16 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     17 
     18 #include <assert.h>
     19 
     20 // Maximum number of samples in a low/high-band frame.
     21 enum
     22 {
     23     kMaxBandFrameLength = 240  // 10 ms at 48 kHz.
     24 };
     25 
     26 // QMF filter coefficients in Q16.
     27 static const uint16_t WebRtcSpl_kAllPassFilter1[3] = {6418, 36982, 57261};
     28 static const uint16_t WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
     29 
     30 ///////////////////////////////////////////////////////////////////////////////////////////////
     31 // WebRtcSpl_AllPassQMF(...)
     32 //
     33 // Allpass filter used by the analysis and synthesis parts of the QMF filter.
     34 //
     35 // Input:
     36 //    - in_data             : Input data sequence (Q10)
     37 //    - data_length         : Length of data sequence (>2)
     38 //    - filter_coefficients : Filter coefficients (length 3, Q16)
     39 //
     40 // Input & Output:
     41 //    - filter_state        : Filter state (length 6, Q10).
     42 //
     43 // Output:
     44 //    - out_data            : Output data sequence (Q10), length equal to
     45 //                            |data_length|
     46 //
     47 
     48 void WebRtcSpl_AllPassQMF(int32_t* in_data, int16_t data_length,
     49                           int32_t* out_data, const uint16_t* filter_coefficients,
     50                           int32_t* filter_state)
     51 {
     52     // The procedure is to filter the input with three first order all pass filters
     53     // (cascade operations).
     54     //
     55     //         a_3 + q^-1    a_2 + q^-1    a_1 + q^-1
     56     // y[n] =  -----------   -----------   -----------   x[n]
     57     //         1 + a_3q^-1   1 + a_2q^-1   1 + a_1q^-1
     58     //
     59     // The input vector |filter_coefficients| includes these three filter coefficients.
     60     // The filter state contains the in_data state, in_data[-1], followed by
     61     // the out_data state, out_data[-1]. This is repeated for each cascade.
     62     // The first cascade filter will filter the |in_data| and store the output in
     63     // |out_data|. The second will the take the |out_data| as input and make an
     64     // intermediate storage in |in_data|, to save memory. The third, and final, cascade
     65     // filter operation takes the |in_data| (which is the output from the previous cascade
     66     // filter) and store the output in |out_data|.
     67     // Note that the input vector values are changed during the process.
     68     int16_t k;
     69     int32_t diff;
     70     // First all-pass cascade; filter from in_data to out_data.
     71 
     72     // Let y_i[n] indicate the output of cascade filter i (with filter coefficient a_i) at
     73     // vector position n. Then the final output will be y[n] = y_3[n]
     74 
     75     // First loop, use the states stored in memory.
     76     // "diff" should be safe from wrap around since max values are 2^25
     77     diff = WEBRTC_SPL_SUB_SAT_W32(in_data[0], filter_state[1]); // = (x[0] - y_1[-1])
     78     // y_1[0] =  x[-1] + a_1 * (x[0] - y_1[-1])
     79     out_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, filter_state[0]);
     80 
     81     // For the remaining loops, use previous values.
     82     for (k = 1; k < data_length; k++)
     83     {
     84         diff = WEBRTC_SPL_SUB_SAT_W32(in_data[k], out_data[k - 1]); // = (x[n] - y_1[n-1])
     85         // y_1[n] =  x[n-1] + a_1 * (x[n] - y_1[n-1])
     86         out_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, in_data[k - 1]);
     87     }
     88 
     89     // Update states.
     90     filter_state[0] = in_data[data_length - 1]; // x[N-1], becomes x[-1] next time
     91     filter_state[1] = out_data[data_length - 1]; // y_1[N-1], becomes y_1[-1] next time
     92 
     93     // Second all-pass cascade; filter from out_data to in_data.
     94     diff = WEBRTC_SPL_SUB_SAT_W32(out_data[0], filter_state[3]); // = (y_1[0] - y_2[-1])
     95     // y_2[0] =  y_1[-1] + a_2 * (y_1[0] - y_2[-1])
     96     in_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, filter_state[2]);
     97     for (k = 1; k < data_length; k++)
     98     {
     99         diff = WEBRTC_SPL_SUB_SAT_W32(out_data[k], in_data[k - 1]); // =(y_1[n] - y_2[n-1])
    100         // y_2[0] =  y_1[-1] + a_2 * (y_1[0] - y_2[-1])
    101         in_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, out_data[k-1]);
    102     }
    103 
    104     filter_state[2] = out_data[data_length - 1]; // y_1[N-1], becomes y_1[-1] next time
    105     filter_state[3] = in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
    106 
    107     // Third all-pass cascade; filter from in_data to out_data.
    108     diff = WEBRTC_SPL_SUB_SAT_W32(in_data[0], filter_state[5]); // = (y_2[0] - y[-1])
    109     // y[0] =  y_2[-1] + a_3 * (y_2[0] - y[-1])
    110     out_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, filter_state[4]);
    111     for (k = 1; k < data_length; k++)
    112     {
    113         diff = WEBRTC_SPL_SUB_SAT_W32(in_data[k], out_data[k - 1]); // = (y_2[n] - y[n-1])
    114         // y[n] =  y_2[n-1] + a_3 * (y_2[n] - y[n-1])
    115         out_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, in_data[k-1]);
    116     }
    117     filter_state[4] = in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
    118     filter_state[5] = out_data[data_length - 1]; // y[N-1], becomes y[-1] next time
    119 }
    120 
    121 void WebRtcSpl_AnalysisQMF(const int16_t* in_data, int in_data_length,
    122                            int16_t* low_band, int16_t* high_band,
    123                            int32_t* filter_state1, int32_t* filter_state2)
    124 {
    125     int16_t i;
    126     int16_t k;
    127     int32_t tmp;
    128     int32_t half_in1[kMaxBandFrameLength];
    129     int32_t half_in2[kMaxBandFrameLength];
    130     int32_t filter1[kMaxBandFrameLength];
    131     int32_t filter2[kMaxBandFrameLength];
    132     const int band_length = in_data_length / 2;
    133     assert(in_data_length % 2 == 0);
    134     assert(band_length <= kMaxBandFrameLength);
    135 
    136     // Split even and odd samples. Also shift them to Q10.
    137     for (i = 0, k = 0; i < band_length; i++, k += 2)
    138     {
    139         half_in2[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)in_data[k], 10);
    140         half_in1[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)in_data[k + 1], 10);
    141     }
    142 
    143     // All pass filter even and odd samples, independently.
    144     WebRtcSpl_AllPassQMF(half_in1, band_length, filter1,
    145                          WebRtcSpl_kAllPassFilter1, filter_state1);
    146     WebRtcSpl_AllPassQMF(half_in2, band_length, filter2,
    147                          WebRtcSpl_kAllPassFilter2, filter_state2);
    148 
    149     // Take the sum and difference of filtered version of odd and even
    150     // branches to get upper & lower band.
    151     for (i = 0; i < band_length; i++)
    152     {
    153         tmp = filter1[i] + filter2[i] + 1024;
    154         tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11);
    155         low_band[i] = WebRtcSpl_SatW32ToW16(tmp);
    156 
    157         tmp = filter1[i] - filter2[i] + 1024;
    158         tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11);
    159         high_band[i] = WebRtcSpl_SatW32ToW16(tmp);
    160     }
    161 }
    162 
    163 void WebRtcSpl_SynthesisQMF(const int16_t* low_band, const int16_t* high_band,
    164                             int band_length, int16_t* out_data,
    165                             int32_t* filter_state1, int32_t* filter_state2)
    166 {
    167     int32_t tmp;
    168     int32_t half_in1[kMaxBandFrameLength];
    169     int32_t half_in2[kMaxBandFrameLength];
    170     int32_t filter1[kMaxBandFrameLength];
    171     int32_t filter2[kMaxBandFrameLength];
    172     int16_t i;
    173     int16_t k;
    174     assert(band_length <= kMaxBandFrameLength);
    175 
    176     // Obtain the sum and difference channels out of upper and lower-band channels.
    177     // Also shift to Q10 domain.
    178     for (i = 0; i < band_length; i++)
    179     {
    180         tmp = (int32_t)low_band[i] + (int32_t)high_band[i];
    181         half_in1[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
    182         tmp = (int32_t)low_band[i] - (int32_t)high_band[i];
    183         half_in2[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
    184     }
    185 
    186     // all-pass filter the sum and difference channels
    187     WebRtcSpl_AllPassQMF(half_in1, band_length, filter1,
    188                          WebRtcSpl_kAllPassFilter2, filter_state1);
    189     WebRtcSpl_AllPassQMF(half_in2, band_length, filter2,
    190                          WebRtcSpl_kAllPassFilter1, filter_state2);
    191 
    192     // The filtered signals are even and odd samples of the output. Combine
    193     // them. The signals are Q10 should shift them back to Q0 and take care of
    194     // saturation.
    195     for (i = 0, k = 0; i < band_length; i++)
    196     {
    197         tmp = WEBRTC_SPL_RSHIFT_W32(filter2[i] + 512, 10);
    198         out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
    199 
    200         tmp = WEBRTC_SPL_RSHIFT_W32(filter1[i] + 512, 10);
    201         out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
    202     }
    203 
    204 }
    205