Line data Source code
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 "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
19 :
20 : #ifdef WEBRTC_ARCH_ARM_V7
21 :
22 : // allpass filter coefficients.
23 : static const uint32_t kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
24 : static const uint32_t 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 :
30 : static __inline int32_t MUL_ACCUM_1(int32_t tbl_value,
31 : int32_t diff,
32 : int32_t state) {
33 : int32_t result;
34 : __asm __volatile ("smlawb %0, %1, %2, %3": "=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 :
46 : static __inline int32_t MUL_ACCUM_2(int32_t tbl_value,
47 : int32_t diff,
48 : int32_t state) {
49 : int32_t result;
50 : __asm __volatile ("smmla %0, %1, %2, %3": "=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 uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
59 : static const uint16_t 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_V7
66 :
67 :
68 : // decimator
69 : #if !defined(MIPS32_LE)
70 0 : void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len,
71 : int16_t* out, int32_t* filtState) {
72 : int32_t tmp1, tmp2, diff, in32, out32;
73 : size_t i;
74 :
75 0 : register int32_t state0 = filtState[0];
76 0 : register int32_t state1 = filtState[1];
77 0 : register int32_t state2 = filtState[2];
78 0 : register int32_t state3 = filtState[3];
79 0 : register int32_t state4 = filtState[4];
80 0 : register int32_t state5 = filtState[5];
81 0 : register int32_t state6 = filtState[6];
82 0 : register int32_t state7 = filtState[7];
83 :
84 0 : for (i = (len >> 1); i > 0; i--) {
85 : // lower allpass filter
86 0 : in32 = (int32_t)(*in++) << 10;
87 0 : diff = in32 - state1;
88 0 : tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
89 0 : state0 = in32;
90 0 : diff = tmp1 - state2;
91 0 : tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
92 0 : state1 = tmp1;
93 0 : diff = tmp2 - state3;
94 0 : state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
95 0 : state2 = tmp2;
96 :
97 : // upper allpass filter
98 0 : in32 = (int32_t)(*in++) << 10;
99 0 : diff = in32 - state5;
100 0 : tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
101 0 : state4 = in32;
102 0 : diff = tmp1 - state6;
103 0 : tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
104 0 : state5 = tmp1;
105 0 : diff = tmp2 - state7;
106 0 : state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
107 0 : state6 = tmp2;
108 :
109 : // add two allpass outputs, divide by two and round
110 0 : out32 = (state3 + state7 + 1024) >> 11;
111 :
112 : // limit amplitude to prevent wrap-around, and write to output array
113 0 : *out++ = WebRtcSpl_SatW32ToW16(out32);
114 : }
115 :
116 0 : filtState[0] = state0;
117 0 : filtState[1] = state1;
118 0 : filtState[2] = state2;
119 0 : filtState[3] = state3;
120 0 : filtState[4] = state4;
121 0 : filtState[5] = state5;
122 0 : filtState[6] = state6;
123 0 : filtState[7] = state7;
124 0 : }
125 : #endif // #if defined(MIPS32_LE)
126 :
127 :
128 0 : void WebRtcSpl_UpsampleBy2(const int16_t* in, size_t len,
129 : int16_t* out, int32_t* filtState) {
130 : int32_t tmp1, tmp2, diff, in32, out32;
131 : size_t i;
132 :
133 0 : register int32_t state0 = filtState[0];
134 0 : register int32_t state1 = filtState[1];
135 0 : register int32_t state2 = filtState[2];
136 0 : register int32_t state3 = filtState[3];
137 0 : register int32_t state4 = filtState[4];
138 0 : register int32_t state5 = filtState[5];
139 0 : register int32_t state6 = filtState[6];
140 0 : register int32_t state7 = filtState[7];
141 :
142 0 : for (i = len; i > 0; i--) {
143 : // lower allpass filter
144 0 : in32 = (int32_t)(*in++) << 10;
145 0 : diff = in32 - state1;
146 0 : tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
147 0 : state0 = in32;
148 0 : diff = tmp1 - state2;
149 0 : tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1);
150 0 : state1 = tmp1;
151 0 : diff = tmp2 - state3;
152 0 : state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2);
153 0 : state2 = tmp2;
154 :
155 : // round; limit amplitude to prevent wrap-around; write to output array
156 0 : out32 = (state3 + 512) >> 10;
157 0 : *out++ = WebRtcSpl_SatW32ToW16(out32);
158 :
159 : // upper allpass filter
160 0 : diff = in32 - state5;
161 0 : tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4);
162 0 : state4 = in32;
163 0 : diff = tmp1 - state6;
164 0 : tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5);
165 0 : state5 = tmp1;
166 0 : diff = tmp2 - state7;
167 0 : state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6);
168 0 : state6 = tmp2;
169 :
170 : // round; limit amplitude to prevent wrap-around; write to output array
171 0 : out32 = (state7 + 512) >> 10;
172 0 : *out++ = WebRtcSpl_SatW32ToW16(out32);
173 : }
174 :
175 0 : filtState[0] = state0;
176 0 : filtState[1] = state1;
177 0 : filtState[2] = state2;
178 0 : filtState[3] = state3;
179 0 : filtState[4] = state4;
180 0 : filtState[5] = state5;
181 0 : filtState[6] = state6;
182 0 : filtState[7] = state7;
183 0 : }
|