blob: f41bab75198f9aa781bb6d49d798cb774d55dedf [file] [log] [blame]
andrew@webrtc.org5140e242013-02-21 20:12:211/*
2 * Copyright (c) 2013 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/*
13 * This file contains the resampling by two functions.
14 * The description header can be found in signal_processing_library.h
15 *
16 */
17
18#if defined(MIPS32_LE)
19
Mirko Bonadei92ea95e2017-09-15 04:47:3120#include "common_audio/signal_processing/include/signal_processing_library.h"
andrew@webrtc.org5140e242013-02-21 20:12:2121
Gordana Cmiljanovic5b069062017-07-18 09:41:5322#if !defined(MIPS_DSP_R2_LE)
andrew@webrtc.org5140e242013-02-21 20:12:2123// allpass filter coefficients.
pbos@webrtc.orgb0913072013-04-09 16:40:2824static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
25static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
Gordana Cmiljanovic5b069062017-07-18 09:41:5326#endif
andrew@webrtc.org5140e242013-02-21 20:12:2127
28// Multiply a 32-bit value with a 16-bit value and accumulate to another input:
29#define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
30#define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
31
32// decimator
pbos@webrtc.orgb0913072013-04-09 16:40:2833void WebRtcSpl_DownsampleBy2(const int16_t* in,
Peter Kastingdce40cf2015-08-24 21:52:2334 size_t len,
pbos@webrtc.orgb0913072013-04-09 16:40:2835 int16_t* out,
36 int32_t* filtState) {
37 int32_t out32;
Peter Kastingdce40cf2015-08-24 21:52:2338 size_t i, len1;
andrew@webrtc.org5140e242013-02-21 20:12:2139
pbos@webrtc.orgb0913072013-04-09 16:40:2840 register int32_t state0 = filtState[0];
41 register int32_t state1 = filtState[1];
42 register int32_t state2 = filtState[2];
43 register int32_t state3 = filtState[3];
44 register int32_t state4 = filtState[4];
45 register int32_t state5 = filtState[5];
46 register int32_t state6 = filtState[6];
47 register int32_t state7 = filtState[7];
andrew@webrtc.org5140e242013-02-21 20:12:2148
49#if defined(MIPS_DSP_R2_LE)
pbos@webrtc.orgb0913072013-04-09 16:40:2850 int32_t k1Res0, k1Res1, k1Res2, k2Res0, k2Res1, k2Res2;
andrew@webrtc.org5140e242013-02-21 20:12:2151
52 k1Res0= 3284;
53 k1Res1= 24441;
54 k1Res2= 49528;
55 k2Res0= 12199;
56 k2Res1= 37471;
57 k2Res2= 60255;
58 len1 = (len >> 1);
59
pbos@webrtc.orgb0913072013-04-09 16:40:2860 const int32_t* inw = (int32_t*)in;
61 int32_t tmp11, tmp12, tmp21, tmp22;
62 int32_t in322, in321;
63 int32_t diff1, diff2;
andrew@webrtc.org5140e242013-02-21 20:12:2164 for (i = len1; i > 0; i--) {
65 __asm__ volatile (
66 "lh %[in321], 0(%[inw]) \n\t"
67 "lh %[in322], 2(%[inw]) \n\t"
68
69 "sll %[in321], %[in321], 10 \n\t"
70 "sll %[in322], %[in322], 10 \n\t"
71
72 "addiu %[inw], %[inw], 4 \n\t"
73
74 "subu %[diff1], %[in321], %[state1] \n\t"
75 "subu %[diff2], %[in322], %[state5] \n\t"
76
77 : [in322] "=&r" (in322), [in321] "=&r" (in321),
78 [diff1] "=&r" (diff1), [diff2] "=r" (diff2), [inw] "+r" (inw)
79 : [state1] "r" (state1), [state5] "r" (state5)
80 : "memory"
81 );
82
83 __asm__ volatile (
84 "mult $ac0, %[diff1], %[k2Res0] \n\t"
85 "mult $ac1, %[diff2], %[k1Res0] \n\t"
86
87 "extr.w %[tmp11], $ac0, 16 \n\t"
88 "extr.w %[tmp12], $ac1, 16 \n\t"
89
90 "addu %[tmp11], %[state0], %[tmp11] \n\t"
91 "addu %[tmp12], %[state4], %[tmp12] \n\t"
92
93 "addiu %[state0], %[in321], 0 \n\t"
94 "addiu %[state4], %[in322], 0 \n\t"
95
96 "subu %[diff1], %[tmp11], %[state2] \n\t"
97 "subu %[diff2], %[tmp12], %[state6] \n\t"
98
99 "mult $ac0, %[diff1], %[k2Res1] \n\t"
100 "mult $ac1, %[diff2], %[k1Res1] \n\t"
101
102 "extr.w %[tmp21], $ac0, 16 \n\t"
103 "extr.w %[tmp22], $ac1, 16 \n\t"
104
105 "addu %[tmp21], %[state1], %[tmp21] \n\t"
106 "addu %[tmp22], %[state5], %[tmp22] \n\t"
107
108 "addiu %[state1], %[tmp11], 0 \n\t"
109 "addiu %[state5], %[tmp12], 0 \n\t"
110 : [tmp22] "=r" (tmp22), [tmp21] "=&r" (tmp21),
111 [tmp11] "=&r" (tmp11), [state0] "+r" (state0),
112 [state1] "+r" (state1),
113 [state2] "+r" (state2),
114 [state4] "+r" (state4), [tmp12] "=&r" (tmp12),
115 [state6] "+r" (state6), [state5] "+r" (state5)
116 : [k1Res1] "r" (k1Res1), [k2Res1] "r" (k2Res1), [k2Res0] "r" (k2Res0),
117 [diff2] "r" (diff2), [diff1] "r" (diff1), [in322] "r" (in322),
118 [in321] "r" (in321), [k1Res0] "r" (k1Res0)
119 : "hi", "lo", "$ac1hi", "$ac1lo"
120 );
121
122 // upper allpass filter
123 __asm__ volatile (
124 "subu %[diff1], %[tmp21], %[state3] \n\t"
125 "subu %[diff2], %[tmp22], %[state7] \n\t"
126
127 "mult $ac0, %[diff1], %[k2Res2] \n\t"
128 "mult $ac1, %[diff2], %[k1Res2] \n\t"
129 "extr.w %[state3], $ac0, 16 \n\t"
130 "extr.w %[state7], $ac1, 16 \n\t"
131 "addu %[state3], %[state2], %[state3] \n\t"
132 "addu %[state7], %[state6], %[state7] \n\t"
133
134 "addiu %[state2], %[tmp21], 0 \n\t"
135 "addiu %[state6], %[tmp22], 0 \n\t"
136
137 // add two allpass outputs, divide by two and round
138 "addu %[out32], %[state3], %[state7] \n\t"
139 "addiu %[out32], %[out32], 1024 \n\t"
140 "sra %[out32], %[out32], 11 \n\t"
141 : [state3] "+r" (state3), [state6] "+r" (state6),
142 [state2] "+r" (state2), [diff2] "=&r" (diff2),
143 [out32] "=r" (out32), [diff1] "=&r" (diff1), [state7] "+r" (state7)
144 : [tmp22] "r" (tmp22), [tmp21] "r" (tmp21),
145 [k1Res2] "r" (k1Res2), [k2Res2] "r" (k2Res2)
146 : "hi", "lo", "$ac1hi", "$ac1lo"
147 );
148
149 // limit amplitude to prevent wrap-around, and write to output array
150 *out++ = WebRtcSpl_SatW32ToW16(out32);
151 }
152#else // #if defined(MIPS_DSP_R2_LE)
pbos@webrtc.orgb0913072013-04-09 16:40:28153 int32_t tmp1, tmp2, diff;
154 int32_t in32;
andrew@webrtc.org5140e242013-02-21 20:12:21155 len1 = (len >> 1)/4;
156 for (i = len1; i > 0; i--) {
157 // lower allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28158 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21159 diff = in32 - state1;
160 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
161 state0 = in32;
162 diff = tmp1 - state2;
163 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
164 state1 = tmp1;
165 diff = tmp2 - state3;
166 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
167 state2 = tmp2;
168
169 // upper allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28170 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21171 diff = in32 - state5;
172 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
173 state4 = in32;
174 diff = tmp1 - state6;
175 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
176 state5 = tmp1;
177 diff = tmp2 - state7;
178 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
179 state6 = tmp2;
180
181 // add two allpass outputs, divide by two and round
182 out32 = (state3 + state7 + 1024) >> 11;
183
184 // limit amplitude to prevent wrap-around, and write to output array
185 *out++ = WebRtcSpl_SatW32ToW16(out32);
186 // lower allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28187 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21188 diff = in32 - state1;
189 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
190 state0 = in32;
191 diff = tmp1 - state2;
192 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
193 state1 = tmp1;
194 diff = tmp2 - state3;
195 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
196 state2 = tmp2;
197
198 // upper allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28199 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21200 diff = in32 - state5;
201 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
202 state4 = in32;
203 diff = tmp1 - state6;
204 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
205 state5 = tmp1;
206 diff = tmp2 - state7;
207 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
208 state6 = tmp2;
209
210 // add two allpass outputs, divide by two and round
211 out32 = (state3 + state7 + 1024) >> 11;
212
213 // limit amplitude to prevent wrap-around, and write to output array
214 *out++ = WebRtcSpl_SatW32ToW16(out32);
215 // lower allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28216 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21217 diff = in32 - state1;
218 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
219 state0 = in32;
220 diff = tmp1 - state2;
221 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
222 state1 = tmp1;
223 diff = tmp2 - state3;
224 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
225 state2 = tmp2;
226
227 // upper allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28228 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21229 diff = in32 - state5;
230 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
231 state4 = in32;
232 diff = tmp1 - state6;
233 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
234 state5 = tmp1;
235 diff = tmp2 - state7;
236 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
237 state6 = tmp2;
238
239 // add two allpass outputs, divide by two and round
240 out32 = (state3 + state7 + 1024) >> 11;
241
242 // limit amplitude to prevent wrap-around, and write to output array
243 *out++ = WebRtcSpl_SatW32ToW16(out32);
244 // lower allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28245 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21246 diff = in32 - state1;
247 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
248 state0 = in32;
249 diff = tmp1 - state2;
250 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
251 state1 = tmp1;
252 diff = tmp2 - state3;
253 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
254 state2 = tmp2;
255
256 // upper allpass filter
pbos@webrtc.orgb0913072013-04-09 16:40:28257 in32 = (int32_t)(*in++) << 10;
andrew@webrtc.org5140e242013-02-21 20:12:21258 diff = in32 - state5;
259 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
260 state4 = in32;
261 diff = tmp1 - state6;
262 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
263 state5 = tmp1;
264 diff = tmp2 - state7;
265 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
266 state6 = tmp2;
267
268 // add two allpass outputs, divide by two and round
269 out32 = (state3 + state7 + 1024) >> 11;
270
271 // limit amplitude to prevent wrap-around, and write to output array
272 *out++ = WebRtcSpl_SatW32ToW16(out32);
273 }
274#endif // #if defined(MIPS_DSP_R2_LE)
275 __asm__ volatile (
276 "sw %[state0], 0(%[filtState]) \n\t"
277 "sw %[state1], 4(%[filtState]) \n\t"
278 "sw %[state2], 8(%[filtState]) \n\t"
279 "sw %[state3], 12(%[filtState]) \n\t"
280 "sw %[state4], 16(%[filtState]) \n\t"
281 "sw %[state5], 20(%[filtState]) \n\t"
282 "sw %[state6], 24(%[filtState]) \n\t"
283 "sw %[state7], 28(%[filtState]) \n\t"
284 :
285 : [state0] "r" (state0), [state1] "r" (state1), [state2] "r" (state2),
286 [state3] "r" (state3), [state4] "r" (state4), [state5] "r" (state5),
287 [state6] "r" (state6), [state7] "r" (state7), [filtState] "r" (filtState)
288 : "memory"
289 );
290}
291
292#endif // #if defined(MIPS32_LE)