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 /*
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 #include "signal_processing_library.h"
19
20 #ifdef WEBRTC_ARCH_ARM_V7A
21
22 // allpass filter coefficients.
23 static const WebRtc_UWord32 kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
24 static const WebRtc_UWord32 kResampleAllpass2[3] =
25 {12199, 37471 << 15, 60255 << 15};
26
27 // Multiply two 32-bit values and accumulate to another input value.
28 // Return: state + ((diff * tbl_value) >> 16)
29
MUL_ACCUM_1(WebRtc_Word32 tbl_value,WebRtc_Word32 diff,WebRtc_Word32 state)30 static __inline WebRtc_Word32 MUL_ACCUM_1(WebRtc_Word32 tbl_value,
31 WebRtc_Word32 diff,
32 WebRtc_Word32 state) {
33 WebRtc_Word32 result;
34 __asm__("smlawb %r0, %r1, %r2, %r3": "=r"(result): "r"(diff),
35 "r"(tbl_value), "r"(state));
36 return result;
37 }
38
39 // Multiply two 32-bit values and accumulate to another input value.
40 // Return: Return: state + (((diff << 1) * tbl_value) >> 32)
41 //
42 // The reason to introduce this function is that, in case we can't use smlawb
43 // instruction (in MUL_ACCUM_1) due to input value range, we can still use
44 // smmla to save some cycles.
45
MUL_ACCUM_2(WebRtc_Word32 tbl_value,WebRtc_Word32 diff,WebRtc_Word32 state)46 static __inline WebRtc_Word32 MUL_ACCUM_2(WebRtc_Word32 tbl_value,
47 WebRtc_Word32 diff,
48 WebRtc_Word32 state) {
49 WebRtc_Word32 result;
50 __asm__("smmla %r0, %r1, %r2, %r3": "=r"(result): "r"(diff << 1),
51 "r"(tbl_value), "r"(state));
52 return result;
53 }
54
55 #else
56
57 // allpass filter coefficients.
58 static const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528};
59 static const WebRtc_UWord16 kResampleAllpass2[3] = {12199, 37471, 60255};
60
61 // Multiply a 32-bit value with a 16-bit value and accumulate to another input:
62 #define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
63 #define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
64
65 #endif // WEBRTC_ARCH_ARM_V7A
66
67
68 // decimator
WebRtcSpl_DownsampleBy2(const WebRtc_Word16 * in,const WebRtc_Word16 len,WebRtc_Word16 * out,WebRtc_Word32 * filtState)69 void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len,
70 WebRtc_Word16* out, WebRtc_Word32* filtState) {
71 WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
72 WebRtc_Word16 i;
73
74 register WebRtc_Word32 state0 = filtState[0];
75 register WebRtc_Word32 state1 = filtState[1];
76 register WebRtc_Word32 state2 = filtState[2];
77 register WebRtc_Word32 state3 = filtState[3];
78 register WebRtc_Word32 state4 = filtState[4];
79 register WebRtc_Word32 state5 = filtState[5];
80 register WebRtc_Word32 state6 = filtState[6];
81 register WebRtc_Word32 state7 = filtState[7];
82
83 for (i = (len >> 1); i > 0; i--) {
84 // lower allpass filter
85 in32 = (WebRtc_Word32)(*in++) << 10;
86 diff = in32 - state1;
87 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
88 state0 = in32;
89 diff = tmp1 - state2;
90 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
91 state1 = tmp1;
92 diff = tmp2 - state3;
93 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
94 state2 = tmp2;
95
96 // upper allpass filter
97 in32 = (WebRtc_Word32)(*in++) << 10;
98 diff = in32 - state5;
99 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
100 state4 = in32;
101 diff = tmp1 - state6;
102 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
103 state5 = tmp1;
104 diff = tmp2 - state7;
105 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
106 state6 = tmp2;
107
108 // add two allpass outputs, divide by two and round
109 out32 = (state3 + state7 + 1024) >> 11;
110
111 // limit amplitude to prevent wrap-around, and write to output array
112 *out++ = WebRtcSpl_SatW32ToW16(out32);
113 }
114
115 filtState[0] = state0;
116 filtState[1] = state1;
117 filtState[2] = state2;
118 filtState[3] = state3;
119 filtState[4] = state4;
120 filtState[5] = state5;
121 filtState[6] = state6;
122 filtState[7] = state7;
123 }
124
125
WebRtcSpl_UpsampleBy2(const WebRtc_Word16 * in,WebRtc_Word16 len,WebRtc_Word16 * out,WebRtc_Word32 * filtState)126 void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len,
127 WebRtc_Word16* out, WebRtc_Word32* filtState) {
128 WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
129 WebRtc_Word16 i;
130
131 register WebRtc_Word32 state0 = filtState[0];
132 register WebRtc_Word32 state1 = filtState[1];
133 register WebRtc_Word32 state2 = filtState[2];
134 register WebRtc_Word32 state3 = filtState[3];
135 register WebRtc_Word32 state4 = filtState[4];
136 register WebRtc_Word32 state5 = filtState[5];
137 register WebRtc_Word32 state6 = filtState[6];
138 register WebRtc_Word32 state7 = filtState[7];
139
140 for (i = len; i > 0; i--) {
141 // lower allpass filter
142 in32 = (WebRtc_Word32)(*in++) << 10;
143 diff = in32 - state1;
144 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
145 state0 = in32;
146 diff = tmp1 - state2;
147 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1);
148 state1 = tmp1;
149 diff = tmp2 - state3;
150 state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2);
151 state2 = tmp2;
152
153 // round; limit amplitude to prevent wrap-around; write to output array
154 out32 = (state3 + 512) >> 10;
155 *out++ = WebRtcSpl_SatW32ToW16(out32);
156
157 // upper allpass filter
158 diff = in32 - state5;
159 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4);
160 state4 = in32;
161 diff = tmp1 - state6;
162 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5);
163 state5 = tmp1;
164 diff = tmp2 - state7;
165 state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6);
166 state6 = tmp2;
167
168 // round; limit amplitude to prevent wrap-around; write to output array
169 out32 = (state7 + 512) >> 10;
170 *out++ = WebRtcSpl_SatW32ToW16(out32);
171 }
172
173 filtState[0] = state0;
174 filtState[1] = state1;
175 filtState[2] = state2;
176 filtState[3] = state3;
177 filtState[4] = state4;
178 filtState[5] = state5;
179 filtState[6] = state6;
180 filtState[7] = state7;
181 }
182