blob: 73e19506542ab3bc9afeff52e52f923793f91af4 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "common_audio/signal_processing/include/signal_processing_library.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
kma@webrtc.org94771cb2012-08-28 04:09:50 +000020#ifdef WEBRTC_ARCH_ARM_V7
kma@google.com961885a2011-09-26 16:35:25 +000021
22// allpass filter coefficients.
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000023static const uint32_t kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
24static const uint32_t kResampleAllpass2[3] =
kma@google.com961885a2011-09-26 16:35:25 +000025 {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
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000030static __inline int32_t MUL_ACCUM_1(int32_t tbl_value,
31 int32_t diff,
32 int32_t state) {
33 int32_t result;
kma@webrtc.org55cd78c2012-11-17 00:22:46 +000034 __asm __volatile ("smlawb %0, %1, %2, %3": "=r"(result): "r"(diff),
35 "r"(tbl_value), "r"(state));
kma@google.com961885a2011-09-26 16:35:25 +000036 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
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000046static __inline int32_t MUL_ACCUM_2(int32_t tbl_value,
47 int32_t diff,
48 int32_t state) {
49 int32_t result;
kma@webrtc.org55cd78c2012-11-17 00:22:46 +000050 __asm __volatile ("smmla %0, %1, %2, %3": "=r"(result): "r"(diff << 1),
51 "r"(tbl_value), "r"(state));
kma@google.com961885a2011-09-26 16:35:25 +000052 return result;
53}
54
55#else
56
niklase@google.com470e71d2011-07-07 08:21:25 +000057// allpass filter coefficients.
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000058static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
59static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
niklase@google.com470e71d2011-07-07 08:21:25 +000060
kma@google.com961885a2011-09-26 16:35:25 +000061// 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
kma@webrtc.org94771cb2012-08-28 04:09:50 +000065#endif // WEBRTC_ARCH_ARM_V7
kma@google.com961885a2011-09-26 16:35:25 +000066
67
niklase@google.com470e71d2011-07-07 08:21:25 +000068// decimator
andrew@webrtc.org5140e242013-02-21 20:12:21 +000069#if !defined(MIPS32_LE)
Peter Kastingdce40cf2015-08-24 14:52:23 -070070void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len,
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000071 int16_t* out, int32_t* filtState) {
72 int32_t tmp1, tmp2, diff, in32, out32;
Peter Kastingdce40cf2015-08-24 14:52:23 -070073 size_t i;
niklase@google.com470e71d2011-07-07 08:21:25 +000074
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000075 register int32_t state0 = filtState[0];
76 register int32_t state1 = filtState[1];
77 register int32_t state2 = filtState[2];
78 register int32_t state3 = filtState[3];
79 register int32_t state4 = filtState[4];
80 register int32_t state5 = filtState[5];
81 register int32_t state6 = filtState[6];
82 register int32_t state7 = filtState[7];
kma@google.com88110322011-08-08 15:40:10 +000083
kma@google.com961885a2011-09-26 16:35:25 +000084 for (i = (len >> 1); i > 0; i--) {
85 // lower allpass filter
Alex Loikob9f53612017-10-24 09:58:00 +020086 in32 = (int32_t)(*in++) * (1 << 10);
kma@google.com961885a2011-09-26 16:35:25 +000087 diff = in32 - state1;
88 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
89 state0 = in32;
90 diff = tmp1 - state2;
91 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
92 state1 = tmp1;
93 diff = tmp2 - state3;
94 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
95 state2 = tmp2;
niklase@google.com470e71d2011-07-07 08:21:25 +000096
kma@google.com961885a2011-09-26 16:35:25 +000097 // upper allpass filter
Alex Loikob9f53612017-10-24 09:58:00 +020098 in32 = (int32_t)(*in++) * (1 << 10);
kma@google.com961885a2011-09-26 16:35:25 +000099 diff = in32 - state5;
100 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
101 state4 = in32;
102 diff = tmp1 - state6;
103 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
104 state5 = tmp1;
105 diff = tmp2 - state7;
106 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
107 state6 = tmp2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000108
kma@google.com961885a2011-09-26 16:35:25 +0000109 // add two allpass outputs, divide by two and round
110 out32 = (state3 + state7 + 1024) >> 11;
niklase@google.com470e71d2011-07-07 08:21:25 +0000111
kma@google.com961885a2011-09-26 16:35:25 +0000112 // limit amplitude to prevent wrap-around, and write to output array
113 *out++ = WebRtcSpl_SatW32ToW16(out32);
114 }
kma@google.com88110322011-08-08 15:40:10 +0000115
kma@google.com961885a2011-09-26 16:35:25 +0000116 filtState[0] = state0;
117 filtState[1] = state1;
118 filtState[2] = state2;
119 filtState[3] = state3;
120 filtState[4] = state4;
121 filtState[5] = state5;
122 filtState[6] = state6;
123 filtState[7] = state7;
niklase@google.com470e71d2011-07-07 08:21:25 +0000124}
andrew@webrtc.org5140e242013-02-21 20:12:21 +0000125#endif // #if defined(MIPS32_LE)
niklase@google.com470e71d2011-07-07 08:21:25 +0000126
niklase@google.com470e71d2011-07-07 08:21:25 +0000127
Peter Kastingdce40cf2015-08-24 14:52:23 -0700128void WebRtcSpl_UpsampleBy2(const int16_t* in, size_t len,
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000129 int16_t* out, int32_t* filtState) {
130 int32_t tmp1, tmp2, diff, in32, out32;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700131 size_t i;
kma@google.com88110322011-08-08 15:40:10 +0000132
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000133 register int32_t state0 = filtState[0];
134 register int32_t state1 = filtState[1];
135 register int32_t state2 = filtState[2];
136 register int32_t state3 = filtState[3];
137 register int32_t state4 = filtState[4];
138 register int32_t state5 = filtState[5];
139 register int32_t state6 = filtState[6];
140 register int32_t state7 = filtState[7];
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
kma@google.com961885a2011-09-26 16:35:25 +0000142 for (i = len; i > 0; i--) {
143 // lower allpass filter
Alex Loiko187c6992017-10-27 16:21:31 +0200144 in32 = (int32_t)(*in++) * (1 << 10);
kma@google.com961885a2011-09-26 16:35:25 +0000145 diff = in32 - state1;
146 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
147 state0 = in32;
148 diff = tmp1 - state2;
149 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1);
150 state1 = tmp1;
151 diff = tmp2 - state3;
152 state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2);
153 state2 = tmp2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000154
kma@google.com961885a2011-09-26 16:35:25 +0000155 // round; limit amplitude to prevent wrap-around; write to output array
156 out32 = (state3 + 512) >> 10;
157 *out++ = WebRtcSpl_SatW32ToW16(out32);
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
kma@google.com961885a2011-09-26 16:35:25 +0000159 // upper allpass filter
160 diff = in32 - state5;
161 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4);
162 state4 = in32;
163 diff = tmp1 - state6;
164 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5);
165 state5 = tmp1;
166 diff = tmp2 - state7;
167 state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6);
168 state6 = tmp2;
169
170 // round; limit amplitude to prevent wrap-around; write to output array
171 out32 = (state7 + 512) >> 10;
172 *out++ = WebRtcSpl_SatW32ToW16(out32);
173 }
174
175 filtState[0] = state0;
176 filtState[1] = state1;
177 filtState[2] = state2;
178 filtState[3] = state3;
179 filtState[4] = state4;
180 filtState[5] = state5;
181 filtState[6] = state6;
182 filtState[7] = state7;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}