blob: dbda042277c06a0a2bd2e461b83c29d181786889 [file] [log] [blame]
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +00001/*
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
pbos@webrtc.orgabf0cd82013-05-27 09:49:58 +000016#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000017
andrew@webrtc.org926e88a2014-01-07 17:45:09 +000018#include <assert.h>
19
20// Maximum number of samples in a low/high-band frame.
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000021enum
22{
andrew@webrtc.org926e88a2014-01-07 17:45:09 +000023 kMaxBandFrameLength = 240 // 10 ms at 48 kHz.
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000024};
25
26// QMF filter coefficients in Q16.
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000027static const uint16_t WebRtcSpl_kAllPassFilter1[3] = {6418, 36982, 57261};
28static const uint16_t WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000029
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
pbos@webrtc.org60003b22013-05-14 09:24:49 +000048void WebRtcSpl_AllPassQMF(int32_t* in_data, int16_t data_length,
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000049 int32_t* out_data, const uint16_t* filter_coefficients,
50 int32_t* filter_state)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000051{
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.
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000068 int16_t k;
69 int32_t diff;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000070 // 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
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000121void 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)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000124{
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000125 int16_t i;
126 int16_t k;
127 int32_t tmp;
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000128 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);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000135
136 // Split even and odd samples. Also shift them to Q10.
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000137 for (i = 0, k = 0; i < band_length; i++, k += 2)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000138 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000139 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);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000141 }
142
143 // All pass filter even and odd samples, independently.
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000144 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);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000148
149 // Take the sum and difference of filtered version of odd and even
150 // branches to get upper & lower band.
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000151 for (i = 0; i < band_length; i++)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000152 {
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
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000163void WebRtcSpl_SynthesisQMF(const int16_t* low_band, const int16_t* high_band,
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000164 int band_length, int16_t* out_data,
165 int32_t* filter_state1, int32_t* filter_state2)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000166{
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000167 int32_t tmp;
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000168 int32_t half_in1[kMaxBandFrameLength];
169 int32_t half_in2[kMaxBandFrameLength];
170 int32_t filter1[kMaxBandFrameLength];
171 int32_t filter2[kMaxBandFrameLength];
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000172 int16_t i;
173 int16_t k;
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000174 assert(band_length <= kMaxBandFrameLength);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000175
176 // Obtain the sum and difference channels out of upper and lower-band channels.
177 // Also shift to Q10 domain.
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000178 for (i = 0; i < band_length; i++)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000179 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000180 tmp = (int32_t)low_band[i] + (int32_t)high_band[i];
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000181 half_in1[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000182 tmp = (int32_t)low_band[i] - (int32_t)high_band[i];
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000183 half_in2[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
184 }
185
186 // all-pass filter the sum and difference channels
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000187 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);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000191
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.
andrew@webrtc.org926e88a2014-01-07 17:45:09 +0000195 for (i = 0, k = 0; i < band_length; i++)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000196 {
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}