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