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