2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
13 * This file contains the resampling by two functions.
14 * The description header can be found in signal_processing_library.h
18 #if defined(MIPS32_LE)
20 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
22 // allpass filter coefficients.
23 static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
24 static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
26 // Multiply a 32-bit value with a 16-bit value and accumulate to another input:
27 #define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
28 #define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
31 void WebRtcSpl_DownsampleBy2(const int16_t* in,
38 register int32_t state0 = filtState[0];
39 register int32_t state1 = filtState[1];
40 register int32_t state2 = filtState[2];
41 register int32_t state3 = filtState[3];
42 register int32_t state4 = filtState[4];
43 register int32_t state5 = filtState[5];
44 register int32_t state6 = filtState[6];
45 register int32_t state7 = filtState[7];
47 #if defined(MIPS_DSP_R2_LE)
48 int32_t k1Res0, k1Res1, k1Res2, k2Res0, k2Res1, k2Res2;
58 const int32_t* inw = (int32_t*)in;
59 int32_t tmp11, tmp12, tmp21, tmp22;
62 for (i = len1; i > 0; i--) {
64 "lh %[in321], 0(%[inw]) \n\t"
65 "lh %[in322], 2(%[inw]) \n\t"
67 "sll %[in321], %[in321], 10 \n\t"
68 "sll %[in322], %[in322], 10 \n\t"
70 "addiu %[inw], %[inw], 4 \n\t"
72 "subu %[diff1], %[in321], %[state1] \n\t"
73 "subu %[diff2], %[in322], %[state5] \n\t"
75 : [in322] "=&r" (in322), [in321] "=&r" (in321),
76 [diff1] "=&r" (diff1), [diff2] "=r" (diff2), [inw] "+r" (inw)
77 : [state1] "r" (state1), [state5] "r" (state5)
82 "mult $ac0, %[diff1], %[k2Res0] \n\t"
83 "mult $ac1, %[diff2], %[k1Res0] \n\t"
85 "extr.w %[tmp11], $ac0, 16 \n\t"
86 "extr.w %[tmp12], $ac1, 16 \n\t"
88 "addu %[tmp11], %[state0], %[tmp11] \n\t"
89 "addu %[tmp12], %[state4], %[tmp12] \n\t"
91 "addiu %[state0], %[in321], 0 \n\t"
92 "addiu %[state4], %[in322], 0 \n\t"
94 "subu %[diff1], %[tmp11], %[state2] \n\t"
95 "subu %[diff2], %[tmp12], %[state6] \n\t"
97 "mult $ac0, %[diff1], %[k2Res1] \n\t"
98 "mult $ac1, %[diff2], %[k1Res1] \n\t"
100 "extr.w %[tmp21], $ac0, 16 \n\t"
101 "extr.w %[tmp22], $ac1, 16 \n\t"
103 "addu %[tmp21], %[state1], %[tmp21] \n\t"
104 "addu %[tmp22], %[state5], %[tmp22] \n\t"
106 "addiu %[state1], %[tmp11], 0 \n\t"
107 "addiu %[state5], %[tmp12], 0 \n\t"
108 : [tmp22] "=r" (tmp22), [tmp21] "=&r" (tmp21),
109 [tmp11] "=&r" (tmp11), [state0] "+r" (state0),
110 [state1] "+r" (state1),
111 [state2] "+r" (state2),
112 [state4] "+r" (state4), [tmp12] "=&r" (tmp12),
113 [state6] "+r" (state6), [state5] "+r" (state5)
114 : [k1Res1] "r" (k1Res1), [k2Res1] "r" (k2Res1), [k2Res0] "r" (k2Res0),
115 [diff2] "r" (diff2), [diff1] "r" (diff1), [in322] "r" (in322),
116 [in321] "r" (in321), [k1Res0] "r" (k1Res0)
117 : "hi", "lo", "$ac1hi", "$ac1lo"
120 // upper allpass filter
122 "subu %[diff1], %[tmp21], %[state3] \n\t"
123 "subu %[diff2], %[tmp22], %[state7] \n\t"
125 "mult $ac0, %[diff1], %[k2Res2] \n\t"
126 "mult $ac1, %[diff2], %[k1Res2] \n\t"
127 "extr.w %[state3], $ac0, 16 \n\t"
128 "extr.w %[state7], $ac1, 16 \n\t"
129 "addu %[state3], %[state2], %[state3] \n\t"
130 "addu %[state7], %[state6], %[state7] \n\t"
132 "addiu %[state2], %[tmp21], 0 \n\t"
133 "addiu %[state6], %[tmp22], 0 \n\t"
135 // add two allpass outputs, divide by two and round
136 "addu %[out32], %[state3], %[state7] \n\t"
137 "addiu %[out32], %[out32], 1024 \n\t"
138 "sra %[out32], %[out32], 11 \n\t"
139 : [state3] "+r" (state3), [state6] "+r" (state6),
140 [state2] "+r" (state2), [diff2] "=&r" (diff2),
141 [out32] "=r" (out32), [diff1] "=&r" (diff1), [state7] "+r" (state7)
142 : [tmp22] "r" (tmp22), [tmp21] "r" (tmp21),
143 [k1Res2] "r" (k1Res2), [k2Res2] "r" (k2Res2)
144 : "hi", "lo", "$ac1hi", "$ac1lo"
147 // limit amplitude to prevent wrap-around, and write to output array
148 *out++ = WebRtcSpl_SatW32ToW16(out32);
150 #else // #if defined(MIPS_DSP_R2_LE)
151 int32_t tmp1, tmp2, diff;
154 for (i = len1; i > 0; i--) {
155 // lower allpass filter
156 in32 = (int32_t)(*in++) << 10;
157 diff = in32 - state1;
158 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
160 diff = tmp1 - state2;
161 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
163 diff = tmp2 - state3;
164 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
167 // upper allpass filter
168 in32 = (int32_t)(*in++) << 10;
169 diff = in32 - state5;
170 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
172 diff = tmp1 - state6;
173 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
175 diff = tmp2 - state7;
176 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
179 // add two allpass outputs, divide by two and round
180 out32 = (state3 + state7 + 1024) >> 11;
182 // limit amplitude to prevent wrap-around, and write to output array
183 *out++ = WebRtcSpl_SatW32ToW16(out32);
184 // lower allpass filter
185 in32 = (int32_t)(*in++) << 10;
186 diff = in32 - state1;
187 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
189 diff = tmp1 - state2;
190 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
192 diff = tmp2 - state3;
193 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
196 // upper allpass filter
197 in32 = (int32_t)(*in++) << 10;
198 diff = in32 - state5;
199 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
201 diff = tmp1 - state6;
202 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
204 diff = tmp2 - state7;
205 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
208 // add two allpass outputs, divide by two and round
209 out32 = (state3 + state7 + 1024) >> 11;
211 // limit amplitude to prevent wrap-around, and write to output array
212 *out++ = WebRtcSpl_SatW32ToW16(out32);
213 // lower allpass filter
214 in32 = (int32_t)(*in++) << 10;
215 diff = in32 - state1;
216 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
218 diff = tmp1 - state2;
219 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
221 diff = tmp2 - state3;
222 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
225 // upper allpass filter
226 in32 = (int32_t)(*in++) << 10;
227 diff = in32 - state5;
228 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
230 diff = tmp1 - state6;
231 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
233 diff = tmp2 - state7;
234 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
237 // add two allpass outputs, divide by two and round
238 out32 = (state3 + state7 + 1024) >> 11;
240 // limit amplitude to prevent wrap-around, and write to output array
241 *out++ = WebRtcSpl_SatW32ToW16(out32);
242 // lower allpass filter
243 in32 = (int32_t)(*in++) << 10;
244 diff = in32 - state1;
245 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
247 diff = tmp1 - state2;
248 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
250 diff = tmp2 - state3;
251 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
254 // upper allpass filter
255 in32 = (int32_t)(*in++) << 10;
256 diff = in32 - state5;
257 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
259 diff = tmp1 - state6;
260 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
262 diff = tmp2 - state7;
263 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
266 // add two allpass outputs, divide by two and round
267 out32 = (state3 + state7 + 1024) >> 11;
269 // limit amplitude to prevent wrap-around, and write to output array
270 *out++ = WebRtcSpl_SatW32ToW16(out32);
272 #endif // #if defined(MIPS_DSP_R2_LE)
274 "sw %[state0], 0(%[filtState]) \n\t"
275 "sw %[state1], 4(%[filtState]) \n\t"
276 "sw %[state2], 8(%[filtState]) \n\t"
277 "sw %[state3], 12(%[filtState]) \n\t"
278 "sw %[state4], 16(%[filtState]) \n\t"
279 "sw %[state5], 20(%[filtState]) \n\t"
280 "sw %[state6], 24(%[filtState]) \n\t"
281 "sw %[state7], 28(%[filtState]) \n\t"
283 : [state0] "r" (state0), [state1] "r" (state1), [state2] "r" (state2),
284 [state3] "r" (state3), [state4] "r" (state4), [state5] "r" (state5),
285 [state6] "r" (state6), [state7] "r" (state7), [filtState] "r" (filtState)
290 #endif // #if defined(MIPS32_LE)