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