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
WebRtcSpl_AllPassQMF(WebRtc_Word32 * in_data,const WebRtc_Word16 data_length,WebRtc_Word32 * out_data,const WebRtc_UWord16 * filter_coefficients,WebRtc_Word32 * filter_state)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
WebRtcSpl_AnalysisQMF(const WebRtc_Word16 * in_data,WebRtc_Word16 * low_band,WebRtc_Word16 * high_band,WebRtc_Word32 * filter_state1,WebRtc_Word32 * filter_state2)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
WebRtcSpl_SynthesisQMF(const WebRtc_Word16 * low_band,const WebRtc_Word16 * high_band,WebRtc_Word16 * out_data,WebRtc_Word32 * filter_state1,WebRtc_Word32 * filter_state2)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