• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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