summaryrefslogtreecommitdiff
path: root/third_party/webrtc/src/webrtc/common_audio/signal_processing/resample_by_2.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/webrtc/src/webrtc/common_audio/signal_processing/resample_by_2.c')
-rw-r--r--third_party/webrtc/src/webrtc/common_audio/signal_processing/resample_by_2.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/third_party/webrtc/src/webrtc/common_audio/signal_processing/resample_by_2.c b/third_party/webrtc/src/webrtc/common_audio/signal_processing/resample_by_2.c
new file mode 100644
index 00000000..dcba82e3
--- /dev/null
+++ b/third_party/webrtc/src/webrtc/common_audio/signal_processing/resample_by_2.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the resampling by two functions.
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
+
+#ifdef WEBRTC_ARCH_ARM_V7
+
+// allpass filter coefficients.
+static const uint32_t kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
+static const uint32_t kResampleAllpass2[3] =
+ {12199, 37471 << 15, 60255 << 15};
+
+// Multiply two 32-bit values and accumulate to another input value.
+// Return: state + ((diff * tbl_value) >> 16)
+
+static __inline int32_t MUL_ACCUM_1(int32_t tbl_value,
+ int32_t diff,
+ int32_t state) {
+ int32_t result;
+ __asm __volatile ("smlawb %0, %1, %2, %3": "=r"(result): "r"(diff),
+ "r"(tbl_value), "r"(state));
+ return result;
+}
+
+// Multiply two 32-bit values and accumulate to another input value.
+// Return: Return: state + (((diff << 1) * tbl_value) >> 32)
+//
+// The reason to introduce this function is that, in case we can't use smlawb
+// instruction (in MUL_ACCUM_1) due to input value range, we can still use
+// smmla to save some cycles.
+
+static __inline int32_t MUL_ACCUM_2(int32_t tbl_value,
+ int32_t diff,
+ int32_t state) {
+ int32_t result;
+ __asm __volatile ("smmla %0, %1, %2, %3": "=r"(result): "r"(diff << 1),
+ "r"(tbl_value), "r"(state));
+ return result;
+}
+
+#else
+
+// allpass filter coefficients.
+static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
+static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
+
+// Multiply a 32-bit value with a 16-bit value and accumulate to another input:
+#define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
+#define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
+
+#endif // WEBRTC_ARCH_ARM_V7
+
+
+// decimator
+#if !defined(MIPS32_LE)
+void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len,
+ int16_t* out, int32_t* filtState) {
+ int32_t tmp1, tmp2, diff, in32, out32;
+ size_t i;
+
+ register int32_t state0 = filtState[0];
+ register int32_t state1 = filtState[1];
+ register int32_t state2 = filtState[2];
+ register int32_t state3 = filtState[3];
+ register int32_t state4 = filtState[4];
+ register int32_t state5 = filtState[5];
+ register int32_t state6 = filtState[6];
+ register int32_t state7 = filtState[7];
+
+ for (i = (len >> 1); i > 0; i--) {
+ // lower allpass filter
+ in32 = (int32_t)(*in++) << 10;
+ diff = in32 - state1;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
+ state0 = in32;
+ diff = tmp1 - state2;
+ tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
+ state1 = tmp1;
+ diff = tmp2 - state3;
+ state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
+ state2 = tmp2;
+
+ // upper allpass filter
+ in32 = (int32_t)(*in++) << 10;
+ diff = in32 - state5;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
+ state4 = in32;
+ diff = tmp1 - state6;
+ tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
+ state5 = tmp1;
+ diff = tmp2 - state7;
+ state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
+ state6 = tmp2;
+
+ // add two allpass outputs, divide by two and round
+ out32 = (state3 + state7 + 1024) >> 11;
+
+ // limit amplitude to prevent wrap-around, and write to output array
+ *out++ = WebRtcSpl_SatW32ToW16(out32);
+ }
+
+ filtState[0] = state0;
+ filtState[1] = state1;
+ filtState[2] = state2;
+ filtState[3] = state3;
+ filtState[4] = state4;
+ filtState[5] = state5;
+ filtState[6] = state6;
+ filtState[7] = state7;
+}
+#endif // #if defined(MIPS32_LE)
+
+
+void WebRtcSpl_UpsampleBy2(const int16_t* in, size_t len,
+ int16_t* out, int32_t* filtState) {
+ int32_t tmp1, tmp2, diff, in32, out32;
+ size_t i;
+
+ register int32_t state0 = filtState[0];
+ register int32_t state1 = filtState[1];
+ register int32_t state2 = filtState[2];
+ register int32_t state3 = filtState[3];
+ register int32_t state4 = filtState[4];
+ register int32_t state5 = filtState[5];
+ register int32_t state6 = filtState[6];
+ register int32_t state7 = filtState[7];
+
+ for (i = len; i > 0; i--) {
+ // lower allpass filter
+ in32 = (int32_t)(*in++) << 10;
+ diff = in32 - state1;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
+ state0 = in32;
+ diff = tmp1 - state2;
+ tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1);
+ state1 = tmp1;
+ diff = tmp2 - state3;
+ state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2);
+ state2 = tmp2;
+
+ // round; limit amplitude to prevent wrap-around; write to output array
+ out32 = (state3 + 512) >> 10;
+ *out++ = WebRtcSpl_SatW32ToW16(out32);
+
+ // upper allpass filter
+ diff = in32 - state5;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4);
+ state4 = in32;
+ diff = tmp1 - state6;
+ tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5);
+ state5 = tmp1;
+ diff = tmp2 - state7;
+ state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6);
+ state6 = tmp2;
+
+ // round; limit amplitude to prevent wrap-around; write to output array
+ out32 = (state7 + 512) >> 10;
+ *out++ = WebRtcSpl_SatW32ToW16(out32);
+ }
+
+ filtState[0] = state0;
+ filtState[1] = state1;
+ filtState[2] = state2;
+ filtState[3] = state3;
+ filtState[4] = state4;
+ filtState[5] = state5;
+ filtState[6] = state6;
+ filtState[7] = state7;
+}