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