Move src/ -> webrtc/
TBR=niklas.enbom@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/915006
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@2963 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/common_audio/OWNERS b/common_audio/OWNERS
new file mode 100644
index 0000000..84582f2
--- /dev/null
+++ b/common_audio/OWNERS
@@ -0,0 +1,4 @@
+bjornv@webrtc.org
+tina.legrand@webrtc.org
+jan.skoglund@webrtc.org
+andrew@webrtc.org
diff --git a/common_audio/common_audio.gyp b/common_audio/common_audio.gyp
new file mode 100644
index 0000000..3d3da3f
--- /dev/null
+++ b/common_audio/common_audio.gyp
@@ -0,0 +1,16 @@
+# 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.
+
+{
+ 'includes': [
+ '../build/common.gypi',
+ 'signal_processing/signal_processing.gypi',
+ 'resampler/resampler.gypi',
+ 'vad/vad.gypi',
+ ],
+}
diff --git a/common_audio/resampler/Android.mk b/common_audio/resampler/Android.mk
new file mode 100644
index 0000000..b1d630a
--- /dev/null
+++ b/common_audio/resampler/Android.mk
@@ -0,0 +1,47 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/../../../android-webrtc.mk
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libwebrtc_resampler
+LOCAL_MODULE_TAGS := optional
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := resampler.cc
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := \
+ $(MY_WEBRTC_COMMON_DEFS)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../.. \
+ $(LOCAL_PATH)/../signal_processing/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl \
+ libstlport
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl -lpthread
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
diff --git a/common_audio/resampler/include/resampler.h b/common_audio/resampler/include/resampler.h
new file mode 100644
index 0000000..38e6bd3
--- /dev/null
+++ b/common_audio/resampler/include/resampler.h
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+
+/*
+ * A wrapper for resampling a numerous amount of sampling combinations.
+ */
+
+#ifndef WEBRTC_RESAMPLER_RESAMPLER_H_
+#define WEBRTC_RESAMPLER_RESAMPLER_H_
+
+#include "typedefs.h"
+
+namespace webrtc
+{
+
+// TODO(andrew): the implementation depends on the exact values of this enum.
+// It should be rewritten in a less fragile way.
+enum ResamplerType
+{
+ // 4 MSB = Number of channels
+ // 4 LSB = Synchronous or asynchronous
+
+ kResamplerSynchronous = 0x10,
+ kResamplerAsynchronous = 0x11,
+ kResamplerSynchronousStereo = 0x20,
+ kResamplerAsynchronousStereo = 0x21,
+ kResamplerInvalid = 0xff
+};
+
+// TODO(andrew): doesn't need to be part of the interface.
+enum ResamplerMode
+{
+ kResamplerMode1To1,
+ kResamplerMode1To2,
+ kResamplerMode1To3,
+ kResamplerMode1To4,
+ kResamplerMode1To6,
+ kResamplerMode1To12,
+ kResamplerMode2To3,
+ kResamplerMode2To11,
+ kResamplerMode4To11,
+ kResamplerMode8To11,
+ kResamplerMode11To16,
+ kResamplerMode11To32,
+ kResamplerMode2To1,
+ kResamplerMode3To1,
+ kResamplerMode4To1,
+ kResamplerMode6To1,
+ kResamplerMode12To1,
+ kResamplerMode3To2,
+ kResamplerMode11To2,
+ kResamplerMode11To4,
+ kResamplerMode11To8
+};
+
+class Resampler
+{
+
+public:
+ Resampler();
+ // TODO(andrew): use an init function instead.
+ Resampler(int inFreq, int outFreq, ResamplerType type);
+ ~Resampler();
+
+ // Reset all states
+ int Reset(int inFreq, int outFreq, ResamplerType type);
+
+ // Reset all states if any parameter has changed
+ int ResetIfNeeded(int inFreq, int outFreq, ResamplerType type);
+
+ // Synchronous resampling, all output samples are written to samplesOut
+ int Push(const WebRtc_Word16* samplesIn, int lengthIn, WebRtc_Word16* samplesOut,
+ int maxLen, int &outLen);
+
+ // Asynchronous resampling, input
+ int Insert(WebRtc_Word16* samplesIn, int lengthIn);
+
+ // Asynchronous resampling output, remaining samples are buffered
+ int Pull(WebRtc_Word16* samplesOut, int desiredLen, int &outLen);
+
+private:
+ // Generic pointers since we don't know what states we'll need
+ void* state1_;
+ void* state2_;
+ void* state3_;
+
+ // Storage if needed
+ WebRtc_Word16* in_buffer_;
+ WebRtc_Word16* out_buffer_;
+ int in_buffer_size_;
+ int out_buffer_size_;
+ int in_buffer_size_max_;
+ int out_buffer_size_max_;
+
+ // State
+ int my_in_frequency_khz_;
+ int my_out_frequency_khz_;
+ ResamplerMode my_mode_;
+ ResamplerType my_type_;
+
+ // Extra instance for stereo
+ Resampler* slave_left_;
+ Resampler* slave_right_;
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_RESAMPLER_RESAMPLER_H_
diff --git a/common_audio/resampler/resampler.cc b/common_audio/resampler/resampler.cc
new file mode 100644
index 0000000..2db27b1
--- /dev/null
+++ b/common_audio/resampler/resampler.cc
@@ -0,0 +1,1084 @@
+/*
+ * 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.
+ */
+
+
+/*
+ * A wrapper for resampling a numerous amount of sampling combinations.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "signal_processing_library.h"
+#include "resampler.h"
+
+
+namespace webrtc
+{
+
+Resampler::Resampler()
+{
+ state1_ = NULL;
+ state2_ = NULL;
+ state3_ = NULL;
+ in_buffer_ = NULL;
+ out_buffer_ = NULL;
+ in_buffer_size_ = 0;
+ out_buffer_size_ = 0;
+ in_buffer_size_max_ = 0;
+ out_buffer_size_max_ = 0;
+ // we need a reset before we will work
+ my_in_frequency_khz_ = 0;
+ my_out_frequency_khz_ = 0;
+ my_mode_ = kResamplerMode1To1;
+ my_type_ = kResamplerInvalid;
+ slave_left_ = NULL;
+ slave_right_ = NULL;
+}
+
+Resampler::Resampler(int inFreq, int outFreq, ResamplerType type)
+{
+ state1_ = NULL;
+ state2_ = NULL;
+ state3_ = NULL;
+ in_buffer_ = NULL;
+ out_buffer_ = NULL;
+ in_buffer_size_ = 0;
+ out_buffer_size_ = 0;
+ in_buffer_size_max_ = 0;
+ out_buffer_size_max_ = 0;
+ // we need a reset before we will work
+ my_in_frequency_khz_ = 0;
+ my_out_frequency_khz_ = 0;
+ my_mode_ = kResamplerMode1To1;
+ my_type_ = kResamplerInvalid;
+ slave_left_ = NULL;
+ slave_right_ = NULL;
+
+ Reset(inFreq, outFreq, type);
+}
+
+Resampler::~Resampler()
+{
+ if (state1_)
+ {
+ free(state1_);
+ }
+ if (state2_)
+ {
+ free(state2_);
+ }
+ if (state3_)
+ {
+ free(state3_);
+ }
+ if (in_buffer_)
+ {
+ free(in_buffer_);
+ }
+ if (out_buffer_)
+ {
+ free(out_buffer_);
+ }
+ if (slave_left_)
+ {
+ delete slave_left_;
+ }
+ if (slave_right_)
+ {
+ delete slave_right_;
+ }
+}
+
+int Resampler::ResetIfNeeded(int inFreq, int outFreq, ResamplerType type)
+{
+ int tmpInFreq_kHz = inFreq / 1000;
+ int tmpOutFreq_kHz = outFreq / 1000;
+
+ if ((tmpInFreq_kHz != my_in_frequency_khz_) || (tmpOutFreq_kHz != my_out_frequency_khz_)
+ || (type != my_type_))
+ {
+ return Reset(inFreq, outFreq, type);
+ } else
+ {
+ return 0;
+ }
+}
+
+int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
+{
+
+ if (state1_)
+ {
+ free(state1_);
+ state1_ = NULL;
+ }
+ if (state2_)
+ {
+ free(state2_);
+ state2_ = NULL;
+ }
+ if (state3_)
+ {
+ free(state3_);
+ state3_ = NULL;
+ }
+ if (in_buffer_)
+ {
+ free(in_buffer_);
+ in_buffer_ = NULL;
+ }
+ if (out_buffer_)
+ {
+ free(out_buffer_);
+ out_buffer_ = NULL;
+ }
+ if (slave_left_)
+ {
+ delete slave_left_;
+ slave_left_ = NULL;
+ }
+ if (slave_right_)
+ {
+ delete slave_right_;
+ slave_right_ = NULL;
+ }
+
+ in_buffer_size_ = 0;
+ out_buffer_size_ = 0;
+ in_buffer_size_max_ = 0;
+ out_buffer_size_max_ = 0;
+
+ // This might be overridden if parameters are not accepted.
+ my_type_ = type;
+
+ // Start with a math exercise, Euclid's algorithm to find the gcd:
+
+ int a = inFreq;
+ int b = outFreq;
+ int c = a % b;
+ while (c != 0)
+ {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+ // b is now the gcd;
+
+ // We need to track what domain we're in.
+ my_in_frequency_khz_ = inFreq / 1000;
+ my_out_frequency_khz_ = outFreq / 1000;
+
+ // Scale with GCD
+ inFreq = inFreq / b;
+ outFreq = outFreq / b;
+
+ // Do we need stereo?
+ if ((my_type_ & 0xf0) == 0x20)
+ {
+ // Change type to mono
+ type = static_cast<ResamplerType>(
+ ((static_cast<int>(type) & 0x0f) + 0x10));
+ slave_left_ = new Resampler(inFreq, outFreq, type);
+ slave_right_ = new Resampler(inFreq, outFreq, type);
+ }
+
+ if (inFreq == outFreq)
+ {
+ my_mode_ = kResamplerMode1To1;
+ } else if (inFreq == 1)
+ {
+ switch (outFreq)
+ {
+ case 2:
+ my_mode_ = kResamplerMode1To2;
+ break;
+ case 3:
+ my_mode_ = kResamplerMode1To3;
+ break;
+ case 4:
+ my_mode_ = kResamplerMode1To4;
+ break;
+ case 6:
+ my_mode_ = kResamplerMode1To6;
+ break;
+ case 12:
+ my_mode_ = kResamplerMode1To12;
+ break;
+ default:
+ my_type_ = kResamplerInvalid;
+ return -1;
+ }
+ } else if (outFreq == 1)
+ {
+ switch (inFreq)
+ {
+ case 2:
+ my_mode_ = kResamplerMode2To1;
+ break;
+ case 3:
+ my_mode_ = kResamplerMode3To1;
+ break;
+ case 4:
+ my_mode_ = kResamplerMode4To1;
+ break;
+ case 6:
+ my_mode_ = kResamplerMode6To1;
+ break;
+ case 12:
+ my_mode_ = kResamplerMode12To1;
+ break;
+ default:
+ my_type_ = kResamplerInvalid;
+ return -1;
+ }
+ } else if ((inFreq == 2) && (outFreq == 3))
+ {
+ my_mode_ = kResamplerMode2To3;
+ } else if ((inFreq == 2) && (outFreq == 11))
+ {
+ my_mode_ = kResamplerMode2To11;
+ } else if ((inFreq == 4) && (outFreq == 11))
+ {
+ my_mode_ = kResamplerMode4To11;
+ } else if ((inFreq == 8) && (outFreq == 11))
+ {
+ my_mode_ = kResamplerMode8To11;
+ } else if ((inFreq == 3) && (outFreq == 2))
+ {
+ my_mode_ = kResamplerMode3To2;
+ } else if ((inFreq == 11) && (outFreq == 2))
+ {
+ my_mode_ = kResamplerMode11To2;
+ } else if ((inFreq == 11) && (outFreq == 4))
+ {
+ my_mode_ = kResamplerMode11To4;
+ } else if ((inFreq == 11) && (outFreq == 16))
+ {
+ my_mode_ = kResamplerMode11To16;
+ } else if ((inFreq == 11) && (outFreq == 32))
+ {
+ my_mode_ = kResamplerMode11To32;
+ } else if ((inFreq == 11) && (outFreq == 8))
+ {
+ my_mode_ = kResamplerMode11To8;
+ } else
+ {
+ my_type_ = kResamplerInvalid;
+ return -1;
+ }
+
+ // Now create the states we need
+ switch (my_mode_)
+ {
+ case kResamplerMode1To1:
+ // No state needed;
+ break;
+ case kResamplerMode1To2:
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode1To3:
+ state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
+ WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_);
+ break;
+ case kResamplerMode1To4:
+ // 1:2
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ // 2:4
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode1To6:
+ // 1:2
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ // 2:6
+ state2_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
+ WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state2_);
+ break;
+ case kResamplerMode1To12:
+ // 1:2
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ // 2:4
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+ // 4:12
+ state3_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
+ WebRtcSpl_ResetResample16khzTo48khz(
+ (WebRtcSpl_State16khzTo48khz*) state3_);
+ break;
+ case kResamplerMode2To3:
+ // 2:6
+ state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
+ WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_);
+ // 6:3
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode2To11:
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+
+ state2_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz));
+ WebRtcSpl_ResetResample8khzTo22khz((WebRtcSpl_State8khzTo22khz *)state2_);
+ break;
+ case kResamplerMode4To11:
+ state1_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz));
+ WebRtcSpl_ResetResample8khzTo22khz((WebRtcSpl_State8khzTo22khz *)state1_);
+ break;
+ case kResamplerMode8To11:
+ state1_ = malloc(sizeof(WebRtcSpl_State16khzTo22khz));
+ WebRtcSpl_ResetResample16khzTo22khz((WebRtcSpl_State16khzTo22khz *)state1_);
+ break;
+ case kResamplerMode11To16:
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+
+ state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
+ WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_);
+ break;
+ case kResamplerMode11To32:
+ // 11 -> 22
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+
+ // 22 -> 16
+ state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
+ WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_);
+
+ // 16 -> 32
+ state3_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state3_, 0, 8 * sizeof(WebRtc_Word32));
+
+ break;
+ case kResamplerMode2To1:
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode3To1:
+ state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
+ WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_);
+ break;
+ case kResamplerMode4To1:
+ // 4:2
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ // 2:1
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode6To1:
+ // 6:2
+ state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
+ WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_);
+ // 2:1
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode12To1:
+ // 12:4
+ state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
+ WebRtcSpl_ResetResample48khzTo16khz(
+ (WebRtcSpl_State48khzTo16khz*) state1_);
+ // 4:2
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+ // 2:1
+ state3_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state3_, 0, 8 * sizeof(WebRtc_Word32));
+ break;
+ case kResamplerMode3To2:
+ // 3:6
+ state1_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
+ // 6:2
+ state2_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
+ WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state2_);
+ break;
+ case kResamplerMode11To2:
+ state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz));
+ WebRtcSpl_ResetResample22khzTo8khz((WebRtcSpl_State22khzTo8khz *)state1_);
+
+ state2_ = malloc(8 * sizeof(WebRtc_Word32));
+ memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
+
+ break;
+ case kResamplerMode11To4:
+ state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz));
+ WebRtcSpl_ResetResample22khzTo8khz((WebRtcSpl_State22khzTo8khz *)state1_);
+ break;
+ case kResamplerMode11To8:
+ state1_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
+ WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state1_);
+ break;
+
+ }
+
+ return 0;
+}
+
+// Synchronous resampling, all output samples are written to samplesOut
+int Resampler::Push(const WebRtc_Word16 * samplesIn, int lengthIn, WebRtc_Word16* samplesOut,
+ int maxLen, int &outLen)
+{
+ // Check that the resampler is not in asynchronous mode
+ if (my_type_ & 0x0f)
+ {
+ return -1;
+ }
+
+ // Do we have a stereo signal?
+ if ((my_type_ & 0xf0) == 0x20)
+ {
+
+ // Split up the signal and call the slave object for each channel
+
+ WebRtc_Word16* left = (WebRtc_Word16*)malloc(lengthIn * sizeof(WebRtc_Word16) / 2);
+ WebRtc_Word16* right = (WebRtc_Word16*)malloc(lengthIn * sizeof(WebRtc_Word16) / 2);
+ WebRtc_Word16* out_left = (WebRtc_Word16*)malloc(maxLen / 2 * sizeof(WebRtc_Word16));
+ WebRtc_Word16* out_right =
+ (WebRtc_Word16*)malloc(maxLen / 2 * sizeof(WebRtc_Word16));
+ int res = 0;
+ for (int i = 0; i < lengthIn; i += 2)
+ {
+ left[i >> 1] = samplesIn[i];
+ right[i >> 1] = samplesIn[i + 1];
+ }
+
+ // It's OK to overwrite the local parameter, since it's just a copy
+ lengthIn = lengthIn / 2;
+
+ int actualOutLen_left = 0;
+ int actualOutLen_right = 0;
+ // Do resampling for right channel
+ res |= slave_left_->Push(left, lengthIn, out_left, maxLen / 2, actualOutLen_left);
+ res |= slave_right_->Push(right, lengthIn, out_right, maxLen / 2, actualOutLen_right);
+ if (res || (actualOutLen_left != actualOutLen_right))
+ {
+ free(left);
+ free(right);
+ free(out_left);
+ free(out_right);
+ return -1;
+ }
+
+ // Reassemble the signal
+ for (int i = 0; i < actualOutLen_left; i++)
+ {
+ samplesOut[i * 2] = out_left[i];
+ samplesOut[i * 2 + 1] = out_right[i];
+ }
+ outLen = 2 * actualOutLen_left;
+
+ free(left);
+ free(right);
+ free(out_left);
+ free(out_right);
+
+ return 0;
+ }
+
+ // Containers for temp samples
+ WebRtc_Word16* tmp;
+ WebRtc_Word16* tmp_2;
+ // tmp data for resampling routines
+ WebRtc_Word32* tmp_mem;
+
+ switch (my_mode_)
+ {
+ case kResamplerMode1To1:
+ memcpy(samplesOut, samplesIn, lengthIn * sizeof(WebRtc_Word16));
+ outLen = lengthIn;
+ break;
+ case kResamplerMode1To2:
+ if (maxLen < (lengthIn * 2))
+ {
+ return -1;
+ }
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)state1_);
+ outLen = lengthIn * 2;
+ return 0;
+ case kResamplerMode1To3:
+
+ // We can only handle blocks of 160 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 160) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < (lengthIn * 3))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 160)
+ {
+ WebRtcSpl_Resample16khzTo48khz(samplesIn + i, samplesOut + i * 3,
+ (WebRtcSpl_State16khzTo48khz *)state1_,
+ tmp_mem);
+ }
+ outLen = lengthIn * 3;
+ free(tmp_mem);
+ return 0;
+ case kResamplerMode1To4:
+ if (maxLen < (lengthIn * 4))
+ {
+ return -1;
+ }
+
+ tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn);
+ // 1:2
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
+ // 2:4
+ WebRtcSpl_UpsampleBy2(tmp, lengthIn * 2, samplesOut, (WebRtc_Word32*)state2_);
+ outLen = lengthIn * 4;
+ free(tmp);
+ return 0;
+ case kResamplerMode1To6:
+ // We can only handle blocks of 80 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 80) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < (lengthIn * 6))
+ {
+ return -1;
+ }
+
+ //1:2
+
+ tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn);
+
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
+ outLen = lengthIn * 2;
+
+ for (int i = 0; i < outLen; i += 160)
+ {
+ WebRtcSpl_Resample16khzTo48khz(tmp + i, samplesOut + i * 3,
+ (WebRtcSpl_State16khzTo48khz *)state2_,
+ tmp_mem);
+ }
+ outLen = outLen * 3;
+ free(tmp_mem);
+ free(tmp);
+
+ return 0;
+ case kResamplerMode1To12:
+ // We can only handle blocks of 40 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 40) != 0) {
+ return -1;
+ }
+ if (maxLen < (lengthIn * 12)) {
+ return -1;
+ }
+
+ tmp_mem = (WebRtc_Word32*) malloc(336 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*) malloc(sizeof(WebRtc_Word16) * 4 * lengthIn);
+ //1:2
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut,
+ (WebRtc_Word32*) state1_);
+ outLen = lengthIn * 2;
+ //2:4
+ WebRtcSpl_UpsampleBy2(samplesOut, outLen, tmp, (WebRtc_Word32*) state2_);
+ outLen = outLen * 2;
+ // 4:12
+ for (int i = 0; i < outLen; i += 160) {
+ // WebRtcSpl_Resample16khzTo48khz() takes a block of 160 samples
+ // as input and outputs a resampled block of 480 samples. The
+ // data is now actually in 32 kHz sampling rate, despite the
+ // function name, and with a resampling factor of three becomes
+ // 96 kHz.
+ WebRtcSpl_Resample16khzTo48khz(tmp + i, samplesOut + i * 3,
+ (WebRtcSpl_State16khzTo48khz*) state3_,
+ tmp_mem);
+ }
+ outLen = outLen * 3;
+ free(tmp_mem);
+ free(tmp);
+
+ return 0;
+ case kResamplerMode2To3:
+ if (maxLen < (lengthIn * 3 / 2))
+ {
+ return -1;
+ }
+ // 2:6
+ // We can only handle blocks of 160 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 160) != 0)
+ {
+ return -1;
+ }
+ tmp = static_cast<WebRtc_Word16*> (malloc(sizeof(WebRtc_Word16) * lengthIn * 3));
+ tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32));
+ for (int i = 0; i < lengthIn; i += 160)
+ {
+ WebRtcSpl_Resample16khzTo48khz(samplesIn + i, tmp + i * 3,
+ (WebRtcSpl_State16khzTo48khz *)state1_,
+ tmp_mem);
+ }
+ lengthIn = lengthIn * 3;
+ // 6:3
+ WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, (WebRtc_Word32*)state2_);
+ outLen = lengthIn / 2;
+ free(tmp);
+ free(tmp_mem);
+ return 0;
+ case kResamplerMode2To11:
+
+ // We can only handle blocks of 80 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 80) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 11) / 2))
+ {
+ return -1;
+ }
+ tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn);
+ // 1:2
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
+ lengthIn *= 2;
+
+ tmp_mem = (WebRtc_Word32*)malloc(98 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 80)
+ {
+ WebRtcSpl_Resample8khzTo22khz(tmp + i, samplesOut + (i * 11) / 4,
+ (WebRtcSpl_State8khzTo22khz *)state2_,
+ tmp_mem);
+ }
+ outLen = (lengthIn * 11) / 4;
+ free(tmp_mem);
+ free(tmp);
+ return 0;
+ case kResamplerMode4To11:
+
+ // We can only handle blocks of 80 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 80) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 11) / 4))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(98 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 80)
+ {
+ WebRtcSpl_Resample8khzTo22khz(samplesIn + i, samplesOut + (i * 11) / 4,
+ (WebRtcSpl_State8khzTo22khz *)state1_,
+ tmp_mem);
+ }
+ outLen = (lengthIn * 11) / 4;
+ free(tmp_mem);
+ return 0;
+ case kResamplerMode8To11:
+ // We can only handle blocks of 160 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 160) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 11) / 8))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(88 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 160)
+ {
+ WebRtcSpl_Resample16khzTo22khz(samplesIn + i, samplesOut + (i * 11) / 8,
+ (WebRtcSpl_State16khzTo22khz *)state1_,
+ tmp_mem);
+ }
+ outLen = (lengthIn * 11) / 8;
+ free(tmp_mem);
+ return 0;
+
+ case kResamplerMode11To16:
+ // We can only handle blocks of 110 samples
+ if ((lengthIn % 110) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 16) / 11))
+ {
+ return -1;
+ }
+
+ tmp_mem = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn * 2));
+
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
+
+ for (int i = 0; i < (lengthIn * 2); i += 220)
+ {
+ WebRtcSpl_Resample22khzTo16khz(tmp + i, samplesOut + (i / 220) * 160,
+ (WebRtcSpl_State22khzTo16khz *)state2_,
+ tmp_mem);
+ }
+
+ outLen = (lengthIn * 16) / 11;
+
+ free(tmp_mem);
+ free(tmp);
+ return 0;
+
+ case kResamplerMode11To32:
+
+ // We can only handle blocks of 110 samples
+ if ((lengthIn % 110) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 32) / 11))
+ {
+ return -1;
+ }
+
+ tmp_mem = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn * 2));
+
+ // 11 -> 22 kHz in samplesOut
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)state1_);
+
+ // 22 -> 16 in tmp
+ for (int i = 0; i < (lengthIn * 2); i += 220)
+ {
+ WebRtcSpl_Resample22khzTo16khz(samplesOut + i, tmp + (i / 220) * 160,
+ (WebRtcSpl_State22khzTo16khz *)state2_,
+ tmp_mem);
+ }
+
+ // 16 -> 32 in samplesOut
+ WebRtcSpl_UpsampleBy2(tmp, (lengthIn * 16) / 11, samplesOut,
+ (WebRtc_Word32*)state3_);
+
+ outLen = (lengthIn * 32) / 11;
+
+ free(tmp_mem);
+ free(tmp);
+ return 0;
+
+ case kResamplerMode2To1:
+ if (maxLen < (lengthIn / 2))
+ {
+ return -1;
+ }
+ WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)state1_);
+ outLen = lengthIn / 2;
+ return 0;
+ case kResamplerMode3To1:
+ // We can only handle blocks of 480 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 480) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < (lengthIn / 3))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 480)
+ {
+ WebRtcSpl_Resample48khzTo16khz(samplesIn + i, samplesOut + i / 3,
+ (WebRtcSpl_State48khzTo16khz *)state1_,
+ tmp_mem);
+ }
+ outLen = lengthIn / 3;
+ free(tmp_mem);
+ return 0;
+ case kResamplerMode4To1:
+ if (maxLen < (lengthIn / 4))
+ {
+ return -1;
+ }
+ tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * lengthIn / 2);
+ // 4:2
+ WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
+ // 2:1
+ WebRtcSpl_DownsampleBy2(tmp, lengthIn / 2, samplesOut, (WebRtc_Word32*)state2_);
+ outLen = lengthIn / 4;
+ free(tmp);
+ return 0;
+
+ case kResamplerMode6To1:
+ // We can only handle blocks of 480 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 480) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < (lengthIn / 6))
+ {
+ return -1;
+ }
+
+ tmp_mem = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn) / 3);
+
+ for (int i = 0; i < lengthIn; i += 480)
+ {
+ WebRtcSpl_Resample48khzTo16khz(samplesIn + i, tmp + i / 3,
+ (WebRtcSpl_State48khzTo16khz *)state1_,
+ tmp_mem);
+ }
+ outLen = lengthIn / 3;
+ free(tmp_mem);
+ WebRtcSpl_DownsampleBy2(tmp, outLen, samplesOut, (WebRtc_Word32*)state2_);
+ free(tmp);
+ outLen = outLen / 2;
+ return 0;
+ case kResamplerMode12To1:
+ // We can only handle blocks of 480 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 480) != 0) {
+ return -1;
+ }
+ if (maxLen < (lengthIn / 12)) {
+ return -1;
+ }
+
+ tmp_mem = (WebRtc_Word32*) malloc(496 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*) malloc((sizeof(WebRtc_Word16) * lengthIn) / 3);
+ tmp_2 = (WebRtc_Word16*) malloc((sizeof(WebRtc_Word16) * lengthIn) / 6);
+ // 12:4
+ for (int i = 0; i < lengthIn; i += 480) {
+ // WebRtcSpl_Resample48khzTo16khz() takes a block of 480 samples
+ // as input and outputs a resampled block of 160 samples. The
+ // data is now actually in 96 kHz sampling rate, despite the
+ // function name, and with a resampling factor of 1/3 becomes
+ // 32 kHz.
+ WebRtcSpl_Resample48khzTo16khz(samplesIn + i, tmp + i / 3,
+ (WebRtcSpl_State48khzTo16khz*) state1_,
+ tmp_mem);
+ }
+ outLen = lengthIn / 3;
+ free(tmp_mem);
+ // 4:2
+ WebRtcSpl_DownsampleBy2(tmp, outLen, tmp_2,
+ (WebRtc_Word32*) state2_);
+ outLen = outLen / 2;
+ free(tmp);
+ // 2:1
+ WebRtcSpl_DownsampleBy2(tmp_2, outLen, samplesOut,
+ (WebRtc_Word32*) state3_);
+ free(tmp_2);
+ outLen = outLen / 2;
+ return 0;
+ case kResamplerMode3To2:
+ if (maxLen < (lengthIn * 2 / 3))
+ {
+ return -1;
+ }
+ // 3:6
+ tmp = static_cast<WebRtc_Word16*> (malloc(sizeof(WebRtc_Word16) * lengthIn * 2));
+ WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
+ lengthIn *= 2;
+ // 6:2
+ // We can only handle blocks of 480 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 480) != 0)
+ {
+ free(tmp);
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32));
+ for (int i = 0; i < lengthIn; i += 480)
+ {
+ WebRtcSpl_Resample48khzTo16khz(tmp + i, samplesOut + i / 3,
+ (WebRtcSpl_State48khzTo16khz *)state2_,
+ tmp_mem);
+ }
+ outLen = lengthIn / 3;
+ free(tmp);
+ free(tmp_mem);
+ return 0;
+ case kResamplerMode11To2:
+ // We can only handle blocks of 220 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 220) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 2) / 11))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(126 * sizeof(WebRtc_Word32));
+ tmp = (WebRtc_Word16*)malloc((lengthIn * 4) / 11 * sizeof(WebRtc_Word16));
+
+ for (int i = 0; i < lengthIn; i += 220)
+ {
+ WebRtcSpl_Resample22khzTo8khz(samplesIn + i, tmp + (i * 4) / 11,
+ (WebRtcSpl_State22khzTo8khz *)state1_,
+ tmp_mem);
+ }
+ lengthIn = (lengthIn * 4) / 11;
+
+ WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, (WebRtc_Word32*)state2_);
+ outLen = lengthIn / 2;
+
+ free(tmp_mem);
+ free(tmp);
+ return 0;
+ case kResamplerMode11To4:
+ // We can only handle blocks of 220 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 220) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 4) / 11))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(126 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 220)
+ {
+ WebRtcSpl_Resample22khzTo8khz(samplesIn + i, samplesOut + (i * 4) / 11,
+ (WebRtcSpl_State22khzTo8khz *)state1_,
+ tmp_mem);
+ }
+ outLen = (lengthIn * 4) / 11;
+ free(tmp_mem);
+ return 0;
+ case kResamplerMode11To8:
+ // We can only handle blocks of 160 samples
+ // Can be fixed, but I don't think it's needed
+ if ((lengthIn % 220) != 0)
+ {
+ return -1;
+ }
+ if (maxLen < ((lengthIn * 8) / 11))
+ {
+ return -1;
+ }
+ tmp_mem = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32));
+
+ for (int i = 0; i < lengthIn; i += 220)
+ {
+ WebRtcSpl_Resample22khzTo16khz(samplesIn + i, samplesOut + (i * 8) / 11,
+ (WebRtcSpl_State22khzTo16khz *)state1_,
+ tmp_mem);
+ }
+ outLen = (lengthIn * 8) / 11;
+ free(tmp_mem);
+ return 0;
+ break;
+
+ }
+ return 0;
+}
+
+// Asynchronous resampling, input
+int Resampler::Insert(WebRtc_Word16 * samplesIn, int lengthIn)
+{
+ if (my_type_ != kResamplerAsynchronous)
+ {
+ return -1;
+ }
+ int sizeNeeded, tenMsblock;
+
+ // Determine need for size of outBuffer
+ sizeNeeded = out_buffer_size_ + ((lengthIn + in_buffer_size_) * my_out_frequency_khz_)
+ / my_in_frequency_khz_;
+ if (sizeNeeded > out_buffer_size_max_)
+ {
+ // Round the value upwards to complete 10 ms blocks
+ tenMsblock = my_out_frequency_khz_ * 10;
+ sizeNeeded = (sizeNeeded / tenMsblock + 1) * tenMsblock;
+ out_buffer_ = (WebRtc_Word16*)realloc(out_buffer_, sizeNeeded * sizeof(WebRtc_Word16));
+ out_buffer_size_max_ = sizeNeeded;
+ }
+
+ // If we need to use inBuffer, make sure all input data fits there.
+
+ tenMsblock = my_in_frequency_khz_ * 10;
+ if (in_buffer_size_ || (lengthIn % tenMsblock))
+ {
+ // Check if input buffer size is enough
+ if ((in_buffer_size_ + lengthIn) > in_buffer_size_max_)
+ {
+ // Round the value upwards to complete 10 ms blocks
+ sizeNeeded = ((in_buffer_size_ + lengthIn) / tenMsblock + 1) * tenMsblock;
+ in_buffer_ = (WebRtc_Word16*)realloc(in_buffer_,
+ sizeNeeded * sizeof(WebRtc_Word16));
+ in_buffer_size_max_ = sizeNeeded;
+ }
+ // Copy in data to input buffer
+ memcpy(in_buffer_ + in_buffer_size_, samplesIn, lengthIn * sizeof(WebRtc_Word16));
+
+ // Resample all available 10 ms blocks
+ int lenOut;
+ int dataLenToResample = (in_buffer_size_ / tenMsblock) * tenMsblock;
+ Push(in_buffer_, dataLenToResample, out_buffer_ + out_buffer_size_,
+ out_buffer_size_max_ - out_buffer_size_, lenOut);
+ out_buffer_size_ += lenOut;
+
+ // Save the rest
+ memmove(in_buffer_, in_buffer_ + dataLenToResample,
+ (in_buffer_size_ - dataLenToResample) * sizeof(WebRtc_Word16));
+ in_buffer_size_ -= dataLenToResample;
+ } else
+ {
+ // Just resample
+ int lenOut;
+ Push(in_buffer_, lengthIn, out_buffer_ + out_buffer_size_,
+ out_buffer_size_max_ - out_buffer_size_, lenOut);
+ out_buffer_size_ += lenOut;
+ }
+
+ return 0;
+}
+
+// Asynchronous resampling output, remaining samples are buffered
+int Resampler::Pull(WebRtc_Word16* samplesOut, int desiredLen, int &outLen)
+{
+ if (my_type_ != kResamplerAsynchronous)
+ {
+ return -1;
+ }
+
+ // Check that we have enough data
+ if (desiredLen <= out_buffer_size_)
+ {
+ // Give out the date
+ memcpy(samplesOut, out_buffer_, desiredLen * sizeof(WebRtc_Word32));
+
+ // Shuffle down remaining
+ memmove(out_buffer_, out_buffer_ + desiredLen,
+ (out_buffer_size_ - desiredLen) * sizeof(WebRtc_Word16));
+
+ // Update remaining size
+ out_buffer_size_ -= desiredLen;
+
+ return 0;
+ } else
+ {
+ return -1;
+ }
+}
+
+} // namespace webrtc
diff --git a/common_audio/resampler/resampler.gypi b/common_audio/resampler/resampler.gypi
new file mode 100644
index 0000000..75997fd
--- /dev/null
+++ b/common_audio/resampler/resampler.gypi
@@ -0,0 +1,55 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'resampler',
+ 'type': '<(library)',
+ 'dependencies': [
+ 'signal_processing',
+ ],
+ 'include_dirs': [
+ 'include',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ 'include',
+ ],
+ },
+ 'sources': [
+ 'include/resampler.h',
+ 'resampler.cc',
+ ],
+ },
+ ], # targets
+ 'conditions': [
+ ['include_tests==1', {
+ 'targets' : [
+ {
+ 'target_name': 'resampler_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'resampler',
+ '<(webrtc_root)/test/test.gyp:test_support_main',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'resampler_unittest.cc',
+ ],
+ }, # resampler_unittests
+ ], # targets
+ }], # include_tests
+ ], # conditions
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/common_audio/resampler/resampler_unittest.cc b/common_audio/resampler/resampler_unittest.cc
new file mode 100644
index 0000000..9b1061a
--- /dev/null
+++ b/common_audio/resampler/resampler_unittest.cc
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+#include "gtest/gtest.h"
+
+#include "common_audio/resampler/include/resampler.h"
+
+// TODO(andrew): this is a work-in-progress. Many more tests are needed.
+
+namespace webrtc {
+namespace {
+const ResamplerType kTypes[] = {
+ kResamplerSynchronous,
+ kResamplerAsynchronous,
+ kResamplerSynchronousStereo,
+ kResamplerAsynchronousStereo
+ // kResamplerInvalid excluded
+};
+const size_t kTypesSize = sizeof(kTypes) / sizeof(*kTypes);
+
+// Rates we must support.
+const int kMaxRate = 96000;
+const int kRates[] = {
+ 8000,
+ 16000,
+ 32000,
+ 44000,
+ 48000,
+ kMaxRate
+};
+const size_t kRatesSize = sizeof(kRates) / sizeof(*kRates);
+const int kMaxChannels = 2;
+const size_t kDataSize = static_cast<size_t> (kMaxChannels * kMaxRate / 100);
+
+// TODO(andrew): should we be supporting these combinations?
+bool ValidRates(int in_rate, int out_rate) {
+ // Not the most compact notation, for clarity.
+ if ((in_rate == 44000 && (out_rate == 48000 || out_rate == 96000)) ||
+ (out_rate == 44000 && (in_rate == 48000 || in_rate == 96000))) {
+ return false;
+ }
+
+ return true;
+}
+
+class ResamplerTest : public testing::Test {
+ protected:
+ ResamplerTest();
+ virtual void SetUp();
+ virtual void TearDown();
+
+ Resampler rs_;
+ int16_t data_in_[kDataSize];
+ int16_t data_out_[kDataSize];
+};
+
+ResamplerTest::ResamplerTest() {}
+
+void ResamplerTest::SetUp() {
+ // Initialize input data with anything. The tests are content independent.
+ memset(data_in_, 1, sizeof(data_in_));
+}
+
+void ResamplerTest::TearDown() {}
+
+TEST_F(ResamplerTest, Reset) {
+ // The only failure mode for the constructor is if Reset() fails. For the
+ // time being then (until an Init function is added), we rely on Reset()
+ // to test the constructor.
+
+ // Check that all required combinations are supported.
+ for (size_t i = 0; i < kRatesSize; ++i) {
+ for (size_t j = 0; j < kRatesSize; ++j) {
+ for (size_t k = 0; k < kTypesSize; ++k) {
+ std::ostringstream ss;
+ ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j]
+ << ", type: " << kTypes[k];
+ SCOPED_TRACE(ss.str());
+ if (ValidRates(kRates[i], kRates[j]))
+ EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kTypes[k]));
+ else
+ EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kTypes[k]));
+ }
+ }
+ }
+}
+
+// TODO(tlegrand): Replace code inside the two tests below with a function
+// with number of channels and ResamplerType as input.
+TEST_F(ResamplerTest, Synchronous) {
+ for (size_t i = 0; i < kRatesSize; ++i) {
+ for (size_t j = 0; j < kRatesSize; ++j) {
+ std::ostringstream ss;
+ ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j];
+ SCOPED_TRACE(ss.str());
+
+ if (ValidRates(kRates[i], kRates[j])) {
+ int in_length = kRates[i] / 100;
+ int out_length = 0;
+ EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j], kResamplerSynchronous));
+ EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize,
+ out_length));
+ EXPECT_EQ(kRates[j] / 100, out_length);
+ } else {
+ EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j], kResamplerSynchronous));
+ }
+ }
+ }
+}
+
+TEST_F(ResamplerTest, SynchronousStereo) {
+ // Number of channels is 2, stereo mode.
+ const int kChannels = 2;
+ for (size_t i = 0; i < kRatesSize; ++i) {
+ for (size_t j = 0; j < kRatesSize; ++j) {
+ std::ostringstream ss;
+ ss << "Input rate: " << kRates[i] << ", output rate: " << kRates[j];
+ SCOPED_TRACE(ss.str());
+
+ if (ValidRates(kRates[i], kRates[j])) {
+ int in_length = kChannels * kRates[i] / 100;
+ int out_length = 0;
+ EXPECT_EQ(0, rs_.Reset(kRates[i], kRates[j],
+ kResamplerSynchronousStereo));
+ EXPECT_EQ(0, rs_.Push(data_in_, in_length, data_out_, kDataSize,
+ out_length));
+ EXPECT_EQ(kChannels * kRates[j] / 100, out_length);
+ } else {
+ EXPECT_EQ(-1, rs_.Reset(kRates[i], kRates[j],
+ kResamplerSynchronousStereo));
+ }
+ }
+ }
+}
+} // namespace
+} // namespace webrtc
diff --git a/common_audio/signal_processing/Android.mk b/common_audio/signal_processing/Android.mk
new file mode 100644
index 0000000..a0ebd6d
--- /dev/null
+++ b/common_audio/signal_processing/Android.mk
@@ -0,0 +1,124 @@
+# Copyright (c) 2012 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/../../../android-webrtc.mk
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libwebrtc_spl
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+ auto_corr_to_refl_coef.c \
+ auto_correlation.c \
+ complex_fft.c \
+ copy_set_operations.c \
+ cross_correlation.c \
+ division_operations.c \
+ dot_product_with_scale.c \
+ downsample_fast.c \
+ energy.c \
+ filter_ar.c \
+ filter_ma_fast_q12.c \
+ get_hanning_window.c \
+ get_scaling_square.c \
+ ilbc_specific_functions.c \
+ levinson_durbin.c \
+ lpc_to_refl_coef.c \
+ min_max_operations.c \
+ randomization_functions.c \
+ real_fft.c \
+ refl_coef_to_lpc.c \
+ resample.c \
+ resample_48khz.c \
+ resample_by_2.c \
+ resample_by_2_internal.c \
+ resample_fractional.c \
+ spl_init.c \
+ spl_sqrt.c \
+ spl_version.c \
+ splitting_filter.c \
+ sqrt_of_one_minus_x_squared.c \
+ vector_scaling_operations.c
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := \
+ $(MY_WEBRTC_COMMON_DEFS)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../..
+
+ifeq ($(ARCH_ARM_HAVE_ARMV7A),true)
+LOCAL_SRC_FILES += \
+ filter_ar_fast_q12_armv7.s
+else
+LOCAL_SRC_FILES += \
+ filter_ar_fast_q12.c
+endif
+
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_SRC_FILES += \
+ complex_bit_reverse_arm.s \
+ spl_sqrt_floor_arm.s
+else
+LOCAL_SRC_FILES += \
+ complex_bit_reverse.c \
+ spl_sqrt_floor.c
+endif
+
+LOCAL_SHARED_LIBRARIES := libstlport
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl -lpthread
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
+
+#########################
+# Build the neon library.
+ifeq ($(WEBRTC_BUILD_NEON_LIBS),true)
+
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libwebrtc_spl_neon
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+ cross_correlation_neon.s \
+ downsample_fast_neon.s \
+ min_max_operations_neon.s \
+ vector_scaling_operations_neon.s
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := \
+ $(MY_WEBRTC_COMMON_DEFS) \
+ $(MY_ARM_CFLAGS_NEON)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../..
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
+
+endif # ifeq ($(WEBRTC_BUILD_NEON_LIBS),true)
+
diff --git a/common_audio/signal_processing/auto_corr_to_refl_coef.c b/common_audio/signal_processing/auto_corr_to_refl_coef.c
new file mode 100644
index 0000000..b7e8858
--- /dev/null
+++ b/common_audio/signal_processing/auto_corr_to_refl_coef.c
@@ -0,0 +1,103 @@
+/*
+ * 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 function WebRtcSpl_AutoCorrToReflCoef().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_AutoCorrToReflCoef(G_CONST WebRtc_Word32 *R, int use_order, WebRtc_Word16 *K)
+{
+ int i, n;
+ WebRtc_Word16 tmp;
+ G_CONST WebRtc_Word32 *rptr;
+ WebRtc_Word32 L_num, L_den;
+ WebRtc_Word16 *acfptr, *pptr, *wptr, *p1ptr, *w1ptr, ACF[WEBRTC_SPL_MAX_LPC_ORDER],
+ P[WEBRTC_SPL_MAX_LPC_ORDER], W[WEBRTC_SPL_MAX_LPC_ORDER];
+
+ // Initialize loop and pointers.
+ acfptr = ACF;
+ rptr = R;
+ pptr = P;
+ p1ptr = &P[1];
+ w1ptr = &W[1];
+ wptr = w1ptr;
+
+ // First loop; n=0. Determine shifting.
+ tmp = WebRtcSpl_NormW32(*R);
+ *acfptr = (WebRtc_Word16)((*rptr++ << tmp) >> 16);
+ *pptr++ = *acfptr++;
+
+ // Initialize ACF, P and W.
+ for (i = 1; i <= use_order; i++)
+ {
+ *acfptr = (WebRtc_Word16)((*rptr++ << tmp) >> 16);
+ *wptr++ = *acfptr;
+ *pptr++ = *acfptr++;
+ }
+
+ // Compute reflection coefficients.
+ for (n = 1; n <= use_order; n++, K++)
+ {
+ tmp = WEBRTC_SPL_ABS_W16(*p1ptr);
+ if (*P < tmp)
+ {
+ for (i = n; i <= use_order; i++)
+ *K++ = 0;
+
+ return;
+ }
+
+ // Division: WebRtcSpl_div(tmp, *P)
+ *K = 0;
+ if (tmp != 0)
+ {
+ L_num = tmp;
+ L_den = *P;
+ i = 15;
+ while (i--)
+ {
+ (*K) <<= 1;
+ L_num <<= 1;
+ if (L_num >= L_den)
+ {
+ L_num -= L_den;
+ (*K)++;
+ }
+ }
+ if (*p1ptr > 0)
+ *K = -*K;
+ }
+
+ // Last iteration; don't do Schur recursion.
+ if (n == use_order)
+ return;
+
+ // Schur recursion.
+ pptr = P;
+ wptr = w1ptr;
+ tmp = (WebRtc_Word16)(((WebRtc_Word32)*p1ptr * (WebRtc_Word32)*K + 16384) >> 15);
+ *pptr = WEBRTC_SPL_ADD_SAT_W16( *pptr, tmp );
+ pptr++;
+ for (i = 1; i <= use_order - n; i++)
+ {
+ tmp = (WebRtc_Word16)(((WebRtc_Word32)*wptr * (WebRtc_Word32)*K + 16384) >> 15);
+ *pptr = WEBRTC_SPL_ADD_SAT_W16( *(pptr+1), tmp );
+ pptr++;
+ tmp = (WebRtc_Word16)(((WebRtc_Word32)*pptr * (WebRtc_Word32)*K + 16384) >> 15);
+ *wptr = WEBRTC_SPL_ADD_SAT_W16( *wptr, tmp );
+ wptr++;
+ }
+ }
+}
diff --git a/common_audio/signal_processing/auto_correlation.c b/common_audio/signal_processing/auto_correlation.c
new file mode 100644
index 0000000..bd954cf
--- /dev/null
+++ b/common_audio/signal_processing/auto_correlation.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
+ int in_vector_length,
+ int order,
+ int32_t* result,
+ int* scale) {
+ int32_t sum = 0;
+ int i = 0, j = 0;
+ int16_t smax = 0;
+ int scaling = 0;
+
+ if (order > in_vector_length) {
+ /* Undefined */
+ return -1;
+ } else if (order < 0) {
+ order = in_vector_length;
+ }
+
+ // Find the maximum absolute value of the samples.
+ smax = WebRtcSpl_MaxAbsValueW16(in_vector, in_vector_length);
+
+ // In order to avoid overflow when computing the sum we should scale the
+ // samples so that (in_vector_length * smax * smax) will not overflow.
+ if (smax == 0) {
+ scaling = 0;
+ } else {
+ // Number of bits in the sum loop.
+ int nbits = WebRtcSpl_GetSizeInBits(in_vector_length);
+ // Number of bits to normalize smax.
+ int t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax));
+
+ if (t > nbits) {
+ scaling = 0;
+ } else {
+ scaling = nbits - t;
+ }
+ }
+
+ // Perform the actual correlation calculation.
+ for (i = 0; i < order + 1; i++) {
+ sum = 0;
+ /* Unroll the loop to improve performance. */
+ for (j = 0; j < in_vector_length - i - 3; j += 4) {
+ sum += (in_vector[j + 0] * in_vector[i + j + 0]) >> scaling;
+ sum += (in_vector[j + 1] * in_vector[i + j + 1]) >> scaling;
+ sum += (in_vector[j + 2] * in_vector[i + j + 2]) >> scaling;
+ sum += (in_vector[j + 3] * in_vector[i + j + 3]) >> scaling;
+ }
+ for (; j < in_vector_length - i; j++) {
+ sum += (in_vector[j] * in_vector[i + j]) >> scaling;
+ }
+ *result++ = sum;
+ }
+
+ *scale = scaling;
+ return order + 1;
+}
diff --git a/common_audio/signal_processing/complex_bit_reverse.c b/common_audio/signal_processing/complex_bit_reverse.c
new file mode 100644
index 0000000..02fde1e
--- /dev/null
+++ b/common_audio/signal_processing/complex_bit_reverse.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "signal_processing_library.h"
+
+/* Tables for data buffer indexes that are bit reversed and thus need to be
+ * swapped. Note that, index_7[{0, 2, 4, ...}] are for the left side of the swap
+ * operations, while index_7[{1, 3, 5, ...}] are for the right side of the
+ * operation. Same for index_8.
+ */
+
+/* Indexes for the case of stages == 7. */
+static const int16_t index_7[112] = {
+ 1, 64, 2, 32, 3, 96, 4, 16, 5, 80, 6, 48, 7, 112, 9, 72, 10, 40, 11, 104,
+ 12, 24, 13, 88, 14, 56, 15, 120, 17, 68, 18, 36, 19, 100, 21, 84, 22, 52,
+ 23, 116, 25, 76, 26, 44, 27, 108, 29, 92, 30, 60, 31, 124, 33, 66, 35, 98,
+ 37, 82, 38, 50, 39, 114, 41, 74, 43, 106, 45, 90, 46, 58, 47, 122, 49, 70,
+ 51, 102, 53, 86, 55, 118, 57, 78, 59, 110, 61, 94, 63, 126, 67, 97, 69,
+ 81, 71, 113, 75, 105, 77, 89, 79, 121, 83, 101, 87, 117, 91, 109, 95, 125,
+ 103, 115, 111, 123
+};
+
+/* Indexes for the case of stages == 8. */
+static const int16_t index_8[240] = {
+ 1, 128, 2, 64, 3, 192, 4, 32, 5, 160, 6, 96, 7, 224, 8, 16, 9, 144, 10, 80,
+ 11, 208, 12, 48, 13, 176, 14, 112, 15, 240, 17, 136, 18, 72, 19, 200, 20,
+ 40, 21, 168, 22, 104, 23, 232, 25, 152, 26, 88, 27, 216, 28, 56, 29, 184,
+ 30, 120, 31, 248, 33, 132, 34, 68, 35, 196, 37, 164, 38, 100, 39, 228, 41,
+ 148, 42, 84, 43, 212, 44, 52, 45, 180, 46, 116, 47, 244, 49, 140, 50, 76,
+ 51, 204, 53, 172, 54, 108, 55, 236, 57, 156, 58, 92, 59, 220, 61, 188, 62,
+ 124, 63, 252, 65, 130, 67, 194, 69, 162, 70, 98, 71, 226, 73, 146, 74, 82,
+ 75, 210, 77, 178, 78, 114, 79, 242, 81, 138, 83, 202, 85, 170, 86, 106, 87,
+ 234, 89, 154, 91, 218, 93, 186, 94, 122, 95, 250, 97, 134, 99, 198, 101,
+ 166, 103, 230, 105, 150, 107, 214, 109, 182, 110, 118, 111, 246, 113, 142,
+ 115, 206, 117, 174, 119, 238, 121, 158, 123, 222, 125, 190, 127, 254, 131,
+ 193, 133, 161, 135, 225, 137, 145, 139, 209, 141, 177, 143, 241, 147, 201,
+ 149, 169, 151, 233, 155, 217, 157, 185, 159, 249, 163, 197, 167, 229, 171,
+ 213, 173, 181, 175, 245, 179, 205, 183, 237, 187, 221, 191, 253, 199, 227,
+ 203, 211, 207, 243, 215, 235, 223, 251, 239, 247
+};
+
+void WebRtcSpl_ComplexBitReverse(int16_t* __restrict complex_data, int stages) {
+ /* For any specific value of stages, we know exactly the indexes that are
+ * bit reversed. Currently (Feb. 2012) in WebRTC the only possible values of
+ * stages are 7 and 8, so we use tables to save unnecessary iterations and
+ * calculations for these two cases.
+ */
+ if (stages == 7 || stages == 8) {
+ int m = 0;
+ int length = 112;
+ const int16_t* index = index_7;
+
+ if (stages == 8) {
+ length = 240;
+ index = index_8;
+ }
+
+ /* Decimation in time. Swap the elements with bit-reversed indexes. */
+ for (m = 0; m < length; m += 2) {
+ /* We declare a int32_t* type pointer, to load both the 16-bit real
+ * and imaginary elements from complex_data in one instruction, reducing
+ * complexity.
+ */
+ int32_t* complex_data_ptr = (int32_t*)complex_data;
+ int32_t temp = 0;
+
+ temp = complex_data_ptr[index[m]]; /* Real and imaginary */
+ complex_data_ptr[index[m]] = complex_data_ptr[index[m + 1]];
+ complex_data_ptr[index[m + 1]] = temp;
+ }
+ }
+ else {
+ int m = 0, mr = 0, l = 0;
+ int n = 1 << stages;
+ int nn = n - 1;
+
+ /* Decimation in time - re-order data */
+ for (m = 1; m <= nn; ++m) {
+ int32_t* complex_data_ptr = (int32_t*)complex_data;
+ int32_t temp = 0;
+
+ /* Find out indexes that are bit-reversed. */
+ l = n;
+ do {
+ l >>= 1;
+ } while (l > nn - mr);
+ mr = (mr & (l - 1)) + l;
+
+ if (mr <= m) {
+ continue;
+ }
+
+ /* Swap the elements with bit-reversed indexes.
+ * This is similar to the loop in the stages == 7 or 8 cases.
+ */
+ temp = complex_data_ptr[m]; /* Real and imaginary */
+ complex_data_ptr[m] = complex_data_ptr[mr];
+ complex_data_ptr[mr] = temp;
+ }
+ }
+}
+
diff --git a/common_audio/signal_processing/complex_bit_reverse_arm.s b/common_audio/signal_processing/complex_bit_reverse_arm.s
new file mode 100644
index 0000000..4828077
--- /dev/null
+++ b/common_audio/signal_processing/complex_bit_reverse_arm.s
@@ -0,0 +1,126 @@
+@
+@ Copyright (c) 2012 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 function WebRtcSpl_ComplexBitReverse(), optimized
+@ for ARMv5 platforms.
+@ Reference C code is in file complex_bit_reverse.c. Bit-exact.
+
+.arch armv5
+
+.global WebRtcSpl_ComplexBitReverse
+
+.align 2
+
+WebRtcSpl_ComplexBitReverse:
+.fnstart
+
+ push {r4-r7}
+
+ cmp r1, #7
+ adr r3, index_7 @ Table pointer.
+ mov r4, #112 @ Number of interations.
+ beq PRE_LOOP_STAGES_7_OR_8
+
+ cmp r1, #8
+ adr r3, index_8 @ Table pointer.
+ mov r4, #240 @ Number of interations.
+ beq PRE_LOOP_STAGES_7_OR_8
+
+ mov r3, #1 @ Initialize m.
+ mov r1, r3, asl r1 @ n = 1 << stages;
+ subs r6, r1, #1 @ nn = n - 1;
+ ble END
+
+ mov r5, r0 @ &complex_data
+ mov r4, #0 @ ml
+
+LOOP_GENERIC:
+ rsb r12, r4, r6 @ l > nn - mr
+ mov r2, r1 @ n
+
+LOOP_SHIFT:
+ asr r2, #1 @ l >>= 1;
+ cmp r2, r12
+ bgt LOOP_SHIFT
+
+ sub r12, r2, #1
+ and r4, r12, r4
+ add r4, r2 @ mr = (mr & (l - 1)) + l;
+ cmp r4, r3 @ mr <= m ?
+ ble UPDATE_REGISTERS
+
+ mov r12, r4, asl #2
+ ldr r7, [r5, #4] @ complex_data[2 * m, 2 * m + 1].
+ @ Offset 4 due to m incrementing from 1.
+ ldr r2, [r0, r12] @ complex_data[2 * mr, 2 * mr + 1].
+ str r7, [r0, r12]
+ str r2, [r5, #4]
+
+UPDATE_REGISTERS:
+ add r3, r3, #1
+ add r5, #4
+ cmp r3, r1
+ bne LOOP_GENERIC
+
+ b END
+
+PRE_LOOP_STAGES_7_OR_8:
+ add r4, r3, r4, asl #1
+
+LOOP_STAGES_7_OR_8:
+ ldrsh r2, [r3], #2 @ index[m]
+ ldrsh r5, [r3], #2 @ index[m + 1]
+ ldr r1, [r0, r2] @ complex_data[index[m], index[m] + 1]
+ ldr r12, [r0, r5] @ complex_data[index[m + 1], index[m + 1] + 1]
+ cmp r3, r4
+ str r1, [r0, r5]
+ str r12, [r0, r2]
+ bne LOOP_STAGES_7_OR_8
+
+END:
+ pop {r4-r7}
+ bx lr
+
+.fnend
+
+
+@ The index tables. Note the values are doubles of the actual indexes for 16-bit
+@ elements, different from the generic C code. It actually provides byte offsets
+@ for the indexes.
+
+.align 2
+index_7: @ Indexes for stages == 7.
+ .hword 4, 256, 8, 128, 12, 384, 16, 64, 20, 320, 24, 192, 28, 448, 36, 288
+ .hword 40, 160, 44, 416, 48, 96, 52, 352, 56, 224, 60, 480, 68, 272, 72, 144
+ .hword 76, 400, 84, 336, 88, 208, 92, 464, 100, 304, 104, 176, 108, 432, 116
+ .hword 368, 120, 240, 124, 496, 132, 264, 140, 392, 148, 328, 152, 200, 156
+ .hword 456, 164, 296, 172, 424, 180, 360, 184, 232, 188, 488, 196, 280, 204
+ .hword 408, 212, 344, 220, 472, 228, 312, 236, 440, 244, 376, 252, 504, 268
+ .hword 388, 276, 324, 284, 452, 300, 420, 308, 356, 316, 484, 332, 404, 348
+ .hword 468, 364, 436, 380, 500, 412, 460, 444, 492
+
+index_8: @ Indexes for stages == 8.
+ .hword 4, 512, 8, 256, 12, 768, 16, 128, 20, 640, 24, 384, 28, 896, 32, 64
+ .hword 36, 576, 40, 320, 44, 832, 48, 192, 52, 704, 56, 448, 60, 960, 68, 544
+ .hword 72, 288, 76, 800, 80, 160, 84, 672, 88, 416, 92, 928, 100, 608, 104
+ .hword 352, 108, 864, 112, 224, 116, 736, 120, 480, 124, 992, 132, 528, 136
+ .hword 272, 140, 784, 148, 656, 152, 400, 156, 912, 164, 592, 168, 336, 172
+ .hword 848, 176, 208, 180, 720, 184, 464, 188, 976, 196, 560, 200, 304, 204
+ .hword 816, 212, 688, 216, 432, 220, 944, 228, 624, 232, 368, 236, 880, 244
+ .hword 752, 248, 496, 252, 1008, 260, 520, 268, 776, 276, 648, 280, 392, 284
+ .hword 904, 292, 584, 296, 328, 300, 840, 308, 712, 312, 456, 316, 968, 324
+ .hword 552, 332, 808, 340, 680, 344, 424, 348, 936, 356, 616, 364, 872, 372
+ .hword 744, 376, 488, 380, 1000, 388, 536, 396, 792, 404, 664, 412, 920, 420
+ .hword 600, 428, 856, 436, 728, 440, 472, 444, 984, 452, 568, 460, 824, 468
+ .hword 696, 476, 952, 484, 632, 492, 888, 500, 760, 508, 1016, 524, 772, 532
+ .hword 644, 540, 900, 548, 580, 556, 836, 564, 708, 572, 964, 588, 804, 596
+ .hword 676, 604, 932, 620, 868, 628, 740, 636, 996, 652, 788, 668, 916, 684
+ .hword 852, 692, 724, 700, 980, 716, 820, 732, 948, 748, 884, 764, 1012, 796
+ .hword 908, 812, 844, 828, 972, 860, 940, 892, 1004, 956, 988
diff --git a/common_audio/signal_processing/complex_fft.c b/common_audio/signal_processing/complex_fft.c
new file mode 100644
index 0000000..3f06ab3
--- /dev/null
+++ b/common_audio/signal_processing/complex_fft.c
@@ -0,0 +1,425 @@
+/*
+ * 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 function WebRtcSpl_ComplexFFT().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#define CFFTSFT 14
+#define CFFTRND 1
+#define CFFTRND2 16384
+
+#define CIFFTSFT 14
+#define CIFFTRND 1
+
+static const WebRtc_Word16 kSinTable1024[] = {
+ 0, 201, 402, 603, 804, 1005, 1206, 1406,
+ 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011,
+ 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608,
+ 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195,
+ 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766,
+ 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319,
+ 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849,
+ 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353,
+ 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827,
+ 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268,
+ 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672,
+ 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036,
+ 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357,
+ 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631,
+ 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855,
+ 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027,
+ 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143,
+ 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201,
+ 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198,
+ 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132,
+ 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001,
+ 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802,
+ 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534,
+ 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195,
+ 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783,
+ 30851, 30918, 30984, 31049,
+ 31113, 31175, 31236, 31297,
+ 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735,
+ 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097,
+ 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382,
+ 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588,
+ 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717,
+ 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766,
+ 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736,
+ 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628,
+ 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441,
+ 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176,
+ 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833,
+ 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413,
+ 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918,
+ 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349,
+ 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706,
+ 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992,
+ 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208,
+ 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355,
+ 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437,
+ 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456,
+ 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413,
+ 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311,
+ 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153,
+ 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942,
+ 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680,
+ 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371,
+ 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017,
+ 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623,
+ 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191,
+ 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724,
+ 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227,
+ 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703,
+ 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156,
+ 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589,
+ 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006,
+ 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411,
+ 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808,
+ 1607, 1406, 1206, 1005, 804, 603, 402, 201,
+ 0, -201, -402, -603, -804, -1005, -1206, -1406,
+ -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011,
+ -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608,
+ -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195,
+ -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766,
+ -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319,
+ -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849,
+ -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353,
+ -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827,
+ -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268,
+ -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672,
+ -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036,
+ -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357,
+ -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631,
+ -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855,
+ -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027,
+ -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143,
+ -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201,
+ -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198,
+ -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132,
+ -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001,
+ -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802,
+ -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534,
+ -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195,
+ -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783,
+ -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297,
+ -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735,
+ -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097,
+ -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382,
+ -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588,
+ -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717,
+ -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766,
+ -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736,
+ -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628,
+ -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441,
+ -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176,
+ -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833,
+ -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413,
+ -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918,
+ -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349,
+ -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706,
+ -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992,
+ -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208,
+ -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355,
+ -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437,
+ -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456,
+ -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413,
+ -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311,
+ -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153,
+ -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942,
+ -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680,
+ -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371,
+ -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017,
+ -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623,
+ -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191,
+ -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724,
+ -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227,
+ -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703,
+ -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156,
+ -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589,
+ -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006,
+ -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411,
+ -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808,
+ -1607, -1406, -1206, -1005, -804, -603, -402, -201
+};
+
+int WebRtcSpl_ComplexFFT(WebRtc_Word16 frfi[], int stages, int mode)
+{
+ int i, j, l, k, istep, n, m;
+ WebRtc_Word16 wr, wi;
+ WebRtc_Word32 tr32, ti32, qr32, qi32;
+
+ /* The 1024-value is a constant given from the size of kSinTable1024[],
+ * and should not be changed depending on the input parameter 'stages'
+ */
+ n = 1 << stages;
+ if (n > 1024)
+ return -1;
+
+ l = 1;
+ k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
+ depending on the input parameter 'stages' */
+
+ if (mode == 0)
+ {
+ // mode==0: Low-complexity and Low-accuracy mode
+ while (l < n)
+ {
+ istep = l << 1;
+
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = -kSinTable1024[j];
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+ tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
+ - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15);
+
+ ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
+ + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15);
+
+ qr32 = (WebRtc_Word32)frfi[2 * i];
+ qi32 = (WebRtc_Word32)frfi[2 * i + 1];
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1);
+ }
+ }
+
+ --k;
+ l = istep;
+
+ }
+
+ } else
+ {
+ // mode==1: High-complexity and High-accuracy mode
+ while (l < n)
+ {
+ istep = l << 1;
+
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = -kSinTable1024[j];
+
+#ifdef WEBRTC_ARCH_ARM_V7
+ WebRtc_Word32 wri;
+ WebRtc_Word32 frfi_r;
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
+ "r"((WebRtc_Word32)wr), "r"((WebRtc_Word32)wi));
+#endif
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+#ifdef WEBRTC_ARCH_ARM_V7
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(frfi_r) :
+ "r"((WebRtc_Word32)frfi[2*j]), "r"((WebRtc_Word32)frfi[2*j +1]));
+ __asm__("smlsd %0, %1, %2, %3" : "=r"(tr32) :
+ "r"(wri), "r"(frfi_r), "r"(CFFTRND));
+ __asm__("smladx %0, %1, %2, %3" : "=r"(ti32) :
+ "r"(wri), "r"(frfi_r), "r"(CFFTRND));
+
+#else
+ tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
+ - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND;
+
+ ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
+ + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND;
+#endif
+
+ tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CFFTSFT);
+ ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CFFTSFT);
+
+ qr32 = ((WebRtc_Word32)frfi[2 * i]) << CFFTSFT;
+ qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CFFTSFT;
+
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT);
+ }
+ }
+
+ --k;
+ l = istep;
+ }
+ }
+ return 0;
+}
+
+int WebRtcSpl_ComplexIFFT(WebRtc_Word16 frfi[], int stages, int mode)
+{
+ int i, j, l, k, istep, n, m, scale, shift;
+ WebRtc_Word16 wr, wi;
+ WebRtc_Word32 tr32, ti32, qr32, qi32;
+ WebRtc_Word32 tmp32, round2;
+
+ /* The 1024-value is a constant given from the size of kSinTable1024[],
+ * and should not be changed depending on the input parameter 'stages'
+ */
+ n = 1 << stages;
+ if (n > 1024)
+ return -1;
+
+ scale = 0;
+
+ l = 1;
+ k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
+ depending on the input parameter 'stages' */
+
+ while (l < n)
+ {
+ // variable scaling, depending upon data
+ shift = 0;
+ round2 = 8192;
+
+ tmp32 = (WebRtc_Word32)WebRtcSpl_MaxAbsValueW16(frfi, 2 * n);
+ if (tmp32 > 13573)
+ {
+ shift++;
+ scale++;
+ round2 <<= 1;
+ }
+ if (tmp32 > 27146)
+ {
+ shift++;
+ scale++;
+ round2 <<= 1;
+ }
+
+ istep = l << 1;
+
+ if (mode == 0)
+ {
+ // mode==0: Low-complexity and Low-accuracy mode
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = kSinTable1024[j];
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+ tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0)
+ - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0)), 15);
+
+ ti32 = WEBRTC_SPL_RSHIFT_W32(
+ (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0)
+ + WEBRTC_SPL_MUL_16_16_RSFT(wi,frfi[2*j],0)), 15);
+
+ qr32 = (WebRtc_Word32)frfi[2 * i];
+ qi32 = (WebRtc_Word32)frfi[2 * i + 1];
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, shift);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, shift);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, shift);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, shift);
+ }
+ }
+ } else
+ {
+ // mode==1: High-complexity and High-accuracy mode
+
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = kSinTable1024[j];
+
+#ifdef WEBRTC_ARCH_ARM_V7
+ WebRtc_Word32 wri;
+ WebRtc_Word32 frfi_r;
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
+ "r"((WebRtc_Word32)wr), "r"((WebRtc_Word32)wi));
+#endif
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+#ifdef WEBRTC_ARCH_ARM_V7
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(frfi_r) :
+ "r"((WebRtc_Word32)frfi[2*j]), "r"((WebRtc_Word32)frfi[2*j +1]));
+ __asm__("smlsd %0, %1, %2, %3" : "=r"(tr32) :
+ "r"(wri), "r"(frfi_r), "r"(CIFFTRND));
+ __asm__("smladx %0, %1, %2, %3" : "=r"(ti32) :
+ "r"(wri), "r"(frfi_r), "r"(CIFFTRND));
+#else
+
+ tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
+ - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CIFFTRND;
+
+ ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
+ + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CIFFTRND;
+#endif
+ tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CIFFTSFT);
+ ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CIFFTSFT);
+
+ qr32 = ((WebRtc_Word32)frfi[2 * i]) << CIFFTSFT;
+ qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CIFFTSFT;
+
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2),
+ shift+CIFFTSFT);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 - ti32 + round2), shift + CIFFTSFT);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2),
+ shift + CIFFTSFT);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 + ti32 + round2), shift + CIFFTSFT);
+ }
+ }
+
+ }
+ --k;
+ l = istep;
+ }
+ return scale;
+}
diff --git a/common_audio/signal_processing/copy_set_operations.c b/common_audio/signal_processing/copy_set_operations.c
new file mode 100644
index 0000000..8247337
--- /dev/null
+++ b/common_audio/signal_processing/copy_set_operations.c
@@ -0,0 +1,108 @@
+/*
+ * 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 implementation of functions
+ * WebRtcSpl_MemSetW16()
+ * WebRtcSpl_MemSetW32()
+ * WebRtcSpl_MemCpyReversedOrder()
+ * WebRtcSpl_CopyFromEndW16()
+ * WebRtcSpl_ZerosArrayW16()
+ * WebRtcSpl_ZerosArrayW32()
+ * WebRtcSpl_OnesArrayW16()
+ * WebRtcSpl_OnesArrayW32()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include <string.h>
+#include "signal_processing_library.h"
+
+
+void WebRtcSpl_MemSetW16(WebRtc_Word16 *ptr, WebRtc_Word16 set_value, int length)
+{
+ int j;
+ WebRtc_Word16 *arrptr = ptr;
+
+ for (j = length; j > 0; j--)
+ {
+ *arrptr++ = set_value;
+ }
+}
+
+void WebRtcSpl_MemSetW32(WebRtc_Word32 *ptr, WebRtc_Word32 set_value, int length)
+{
+ int j;
+ WebRtc_Word32 *arrptr = ptr;
+
+ for (j = length; j > 0; j--)
+ {
+ *arrptr++ = set_value;
+ }
+}
+
+void WebRtcSpl_MemCpyReversedOrder(WebRtc_Word16* dest, WebRtc_Word16* source, int length)
+{
+ int j;
+ WebRtc_Word16* destPtr = dest;
+ WebRtc_Word16* sourcePtr = source;
+
+ for (j = 0; j < length; j++)
+ {
+ *destPtr-- = *sourcePtr++;
+ }
+}
+
+WebRtc_Word16 WebRtcSpl_CopyFromEndW16(G_CONST WebRtc_Word16 *vector_in,
+ WebRtc_Word16 length,
+ WebRtc_Word16 samples,
+ WebRtc_Word16 *vector_out)
+{
+ // Copy the last <samples> of the input vector to vector_out
+ WEBRTC_SPL_MEMCPY_W16(vector_out, &vector_in[length - samples], samples);
+
+ return samples;
+}
+
+WebRtc_Word16 WebRtcSpl_ZerosArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtcSpl_MemSetW16(vector, 0, length);
+ return length;
+}
+
+WebRtc_Word16 WebRtcSpl_ZerosArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length)
+{
+ WebRtcSpl_MemSetW32(vector, 0, length);
+ return length;
+}
+
+WebRtc_Word16 WebRtcSpl_OnesArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 i;
+ WebRtc_Word16 *tmpvec = vector;
+ for (i = 0; i < length; i++)
+ {
+ *tmpvec++ = 1;
+ }
+ return length;
+}
+
+WebRtc_Word16 WebRtcSpl_OnesArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 i;
+ WebRtc_Word32 *tmpvec = vector;
+ for (i = 0; i < length; i++)
+ {
+ *tmpvec++ = 1;
+ }
+ return length;
+}
diff --git a/common_audio/signal_processing/cross_correlation.c b/common_audio/signal_processing/cross_correlation.c
new file mode 100644
index 0000000..05506a7
--- /dev/null
+++ b/common_audio/signal_processing/cross_correlation.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "signal_processing_library.h"
+
+/* C version of WebRtcSpl_CrossCorrelation() for generic platforms. */
+void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation,
+ const int16_t* seq1,
+ const int16_t* seq2,
+ int16_t dim_seq,
+ int16_t dim_cross_correlation,
+ int16_t right_shifts,
+ int16_t step_seq2) {
+ int i = 0, j = 0;
+
+ for (i = 0; i < dim_cross_correlation; i++) {
+ *cross_correlation = 0;
+ /* Unrolling doesn't seem to improve performance. */
+ for (j = 0; j < dim_seq; j++) {
+ *cross_correlation += (seq1[j] * seq2[step_seq2 * i + j]) >> right_shifts;
+ }
+ cross_correlation++;
+ }
+}
diff --git a/common_audio/signal_processing/cross_correlation_neon.s b/common_audio/signal_processing/cross_correlation_neon.s
new file mode 100644
index 0000000..a18f672
--- /dev/null
+++ b/common_audio/signal_processing/cross_correlation_neon.s
@@ -0,0 +1,168 @@
+@
+@ 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.
+@
+
+@ cross_correlation_neon.s
+@ This file contains the function WebRtcSpl_CrossCorrelationNeon(),
+@ optimized for ARM Neon platform.
+@
+@ Reference Ccode at end of this file.
+@ Output is bit-exact with the reference C code, but not with the generic
+@ C code in file cross_correlation.c, due to reduction of shift operations
+@ from using Neon registers.
+
+@ Register usage:
+@
+@ r0: *cross_correlation (function argument)
+@ r1: *seq1 (function argument)
+@ r2: *seq2 (function argument)
+@ r3: dim_seq (function argument); then, total iteration of LOOP_DIM_SEQ
+@ r4: counter for LOOP_DIM_CROSS_CORRELATION
+@ r5: seq2_ptr
+@ r6: seq1_ptr
+@ r7: Total iteration of LOOP_DIM_SEQ_RESIDUAL
+@ r8, r9, r10, r11, r12: scratch
+
+.arch armv7-a
+.fpu neon
+
+.align 2
+.global WebRtcSpl_CrossCorrelationNeon
+
+WebRtcSpl_CrossCorrelationNeon:
+
+.fnstart
+
+.save {r4-r11}
+ push {r4-r11}
+
+ @ Put the shift value (-right_shifts) into a Neon register.
+ ldrsh r10, [sp, #36]
+ rsb r10, r10, #0
+ mov r8, r10, asr #31
+ vmov.32 d16, r10, r8
+
+ @ Initialize loop counters.
+ and r7, r3, #7 @ inner_loop_len2 = dim_seq % 8;
+ asr r3, r3, #3 @ inner_loop_len1 = dim_seq / 8;
+ ldrsh r4, [sp, #32] @ dim_cross_correlation
+
+LOOP_DIM_CROSS_CORRELATION:
+ vmov.i32 q9, #0
+ vmov.i32 q14, #0
+ movs r8, r3 @ inner_loop_len1
+ mov r6, r1 @ seq1_ptr
+ mov r5, r2 @ seq2_ptr
+ ble POST_LOOP_DIM_SEQ
+
+LOOP_DIM_SEQ:
+ vld1.16 {d20, d21}, [r6]! @ seq1_ptr
+ vld1.16 {d22, d23}, [r5]! @ seq2_ptr
+ subs r8, r8, #1
+ vmull.s16 q12, d20, d22
+ vmull.s16 q13, d21, d23
+ vpadal.s32 q9, q12
+ vpadal.s32 q14, q13
+ bgt LOOP_DIM_SEQ
+
+POST_LOOP_DIM_SEQ:
+ movs r10, r7 @ Loop counter
+ mov r12, #0
+ mov r8, #0
+ ble POST_LOOP_DIM_SEQ_RESIDUAL
+
+LOOP_DIM_SEQ_RESIDUAL:
+ ldrh r11, [r6], #2
+ ldrh r9, [r5], #2
+ smulbb r11, r11, r9
+ adds r8, r8, r11
+ adc r12, r12, r11, asr #31
+ subs r10, #1
+ bgt LOOP_DIM_SEQ_RESIDUAL
+
+POST_LOOP_DIM_SEQ_RESIDUAL: @ Sum the results up and do the shift.
+ vadd.i64 d18, d19
+ vadd.i64 d28, d29
+ vadd.i64 d18, d28
+ vmov.32 d17[0], r8
+ vmov.32 d17[1], r12
+ vadd.i64 d17, d18
+ vshl.s64 d17, d16
+ vst1.32 d17[0], [r0]! @ Store the output
+
+ ldr r8, [sp, #40] @ step_seq2
+ add r2, r8, lsl #1 @ prepare for seq2_ptr(r5) in the next loop.
+
+ subs r4, #1
+ bgt LOOP_DIM_CROSS_CORRELATION
+
+ pop {r4-r11}
+ bx lr
+
+.fnend
+
+
+@ TODO(kma): Place this piece of reference code into a C code file.
+@ void WebRtcSpl_CrossCorrelationNeon(WebRtc_Word32* cross_correlation,
+@ WebRtc_Word16* seq1,
+@ WebRtc_Word16* seq2,
+@ WebRtc_Word16 dim_seq,
+@ WebRtc_Word16 dim_cross_correlation,
+@ WebRtc_Word16 right_shifts,
+@ WebRtc_Word16 step_seq2) {
+@ int i = 0;
+@ int j = 0;
+@ int inner_loop_len1 = dim_seq >> 3;
+@ int inner_loop_len2 = dim_seq - (inner_loop_len1 << 3);
+@
+@ assert(dim_cross_correlation > 0);
+@ assert(dim_seq > 0);
+@
+@ for (i = 0; i < dim_cross_correlation; i++) {
+@ int16_t *seq1_ptr = seq1;
+@ int16_t *seq2_ptr = seq2 + (step_seq2 * i);
+@ int64_t sum = 0;
+@
+@ for (j = inner_loop_len1; j > 0; j -= 1) {
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ }
+@
+@ // Calculate the rest of the samples.
+@ for (j = inner_loop_len2; j > 0; j -= 1) {
+@ sum += WEBRTC_SPL_MUL_16_16(*seq1_ptr, *seq2_ptr);
+@ seq1_ptr++;
+@ seq2_ptr++;
+@ }
+@
+@ *cross_correlation++ = (int32_t)(sum >> right_shifts);
+@ }
+@ }
diff --git a/common_audio/signal_processing/division_operations.c b/common_audio/signal_processing/division_operations.c
new file mode 100644
index 0000000..b143373
--- /dev/null
+++ b/common_audio/signal_processing/division_operations.c
@@ -0,0 +1,144 @@
+/*
+ * 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 implementations of the divisions
+ * WebRtcSpl_DivU32U16()
+ * WebRtcSpl_DivW32W16()
+ * WebRtcSpl_DivW32W16ResW16()
+ * WebRtcSpl_DivResultInQ31()
+ * WebRtcSpl_DivW32HiLow()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den)
+{
+ // Guard against division with 0
+ if (den != 0)
+ {
+ return (WebRtc_UWord32)(num / den);
+ } else
+ {
+ return (WebRtc_UWord32)0xFFFFFFFF;
+ }
+}
+
+WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den)
+{
+ // Guard against division with 0
+ if (den != 0)
+ {
+ return (WebRtc_Word32)(num / den);
+ } else
+ {
+ return (WebRtc_Word32)0x7FFFFFFF;
+ }
+}
+
+WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den)
+{
+ // Guard against division with 0
+ if (den != 0)
+ {
+ return (WebRtc_Word16)(num / den);
+ } else
+ {
+ return (WebRtc_Word16)0x7FFF;
+ }
+}
+
+WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den)
+{
+ WebRtc_Word32 L_num = num;
+ WebRtc_Word32 L_den = den;
+ WebRtc_Word32 div = 0;
+ int k = 31;
+ int change_sign = 0;
+
+ if (num == 0)
+ return 0;
+
+ if (num < 0)
+ {
+ change_sign++;
+ L_num = -num;
+ }
+ if (den < 0)
+ {
+ change_sign++;
+ L_den = -den;
+ }
+ while (k--)
+ {
+ div <<= 1;
+ L_num <<= 1;
+ if (L_num >= L_den)
+ {
+ L_num -= L_den;
+ div++;
+ }
+ }
+ if (change_sign == 1)
+ {
+ div = -div;
+ }
+ return div;
+}
+
+WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi,
+ WebRtc_Word16 den_low)
+{
+ WebRtc_Word16 approx, tmp_hi, tmp_low, num_hi, num_low;
+ WebRtc_Word32 tmpW32;
+
+ approx = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)0x1FFFFFFF, den_hi);
+ // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
+
+ // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
+ tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1)
+ + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1);
+ // tmpW32 = den * approx
+
+ tmpW32 = (WebRtc_Word32)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
+
+ // Store tmpW32 in hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // tmpW32 = 1/den in Q29
+ tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx)
+ >> 15)) << 1);
+
+ // 1/den in hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // Store num in hi and low format
+ num_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(num, 16);
+ num_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((num
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)num_hi, 16)), 1);
+
+ // num * (1/den) by 32 bit multiplication (result in Q28)
+
+ tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low)
+ >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15));
+
+ // Put result in Q31 (convert from Q28)
+ tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
+
+ return tmpW32;
+}
diff --git a/common_audio/signal_processing/dot_product_with_scale.c b/common_audio/signal_processing/dot_product_with_scale.c
new file mode 100644
index 0000000..4868260
--- /dev/null
+++ b/common_audio/signal_processing/dot_product_with_scale.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "signal_processing_library.h"
+
+int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
+ const int16_t* vector2,
+ int length,
+ int scaling) {
+ int32_t sum = 0;
+ int i = 0;
+
+ /* Unroll the loop to improve performance. */
+ for (i = 0; i < length - 3; i += 4) {
+ sum += (vector1[i + 0] * vector2[i + 0]) >> scaling;
+ sum += (vector1[i + 1] * vector2[i + 1]) >> scaling;
+ sum += (vector1[i + 2] * vector2[i + 2]) >> scaling;
+ sum += (vector1[i + 3] * vector2[i + 3]) >> scaling;
+ }
+ for (; i < length; i++) {
+ sum += (vector1[i] * vector2[i]) >> scaling;
+ }
+
+ return sum;
+}
diff --git a/common_audio/signal_processing/downsample_fast.c b/common_audio/signal_processing/downsample_fast.c
new file mode 100644
index 0000000..4784aba
--- /dev/null
+++ b/common_audio/signal_processing/downsample_fast.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "signal_processing_library.h"
+
+// TODO(Bjornv): Change the function parameter order to WebRTC code style.
+// C version of WebRtcSpl_DownsampleFast() for generic platforms.
+int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
+ int data_in_length,
+ int16_t* data_out,
+ int data_out_length,
+ const int16_t* __restrict coefficients,
+ int coefficients_length,
+ int factor,
+ int delay) {
+ int i = 0;
+ int j = 0;
+ int32_t out_s32 = 0;
+ int endpos = delay + factor * (data_out_length - 1) + 1;
+
+ // Return error if any of the running conditions doesn't meet.
+ if (data_out_length <= 0 || coefficients_length <= 0
+ || data_in_length < endpos) {
+ return -1;
+ }
+
+ for (i = delay; i < endpos; i += factor) {
+ out_s32 = 2048; // Round value, 0.5 in Q12.
+
+ for (j = 0; j < coefficients_length; j++) {
+ out_s32 += coefficients[j] * data_in[i - j]; // Q12.
+ }
+
+ out_s32 >>= 12; // Q0.
+
+ // Saturate and store the output.
+ *data_out++ = WebRtcSpl_SatW32ToW16(out_s32);
+ }
+
+ return 0;
+}
diff --git a/common_audio/signal_processing/downsample_fast_neon.s b/common_audio/signal_processing/downsample_fast_neon.s
new file mode 100644
index 0000000..13a825d
--- /dev/null
+++ b/common_audio/signal_processing/downsample_fast_neon.s
@@ -0,0 +1,222 @@
+@
+@ Copyright (c) 2012 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 function WebRtcSpl_DownsampleFastNeon(), optimized for
+@ ARM Neon platform. The description header can be found in
+@ signal_processing_library.h
+@
+@ The reference C code is in file downsample_fast.c. Bit-exact.
+
+.arch armv7-a
+.fpu neon
+
+.align 2
+.global WebRtcSpl_DownsampleFastNeon
+
+WebRtcSpl_DownsampleFastNeon:
+
+.fnstart
+
+.save {r4-r11}
+ push {r4-r11}
+
+ cmp r3, #0 @ data_out_length <= 0?
+ movle r0, #-1
+ ble END
+
+ ldrsh r12, [sp, #44]
+ ldr r5, [sp, #40] @ r5: factor
+ add r4, r12, #1 @ r4: delay + 1
+ sub r3, r3, #1 @ r3: data_out_length - 1
+ smulbb r3, r5, r3
+ ldr r8, [sp, #32] @ &coefficients[0]
+ mov r9, r12 @ Iteration counter for outer loops.
+ add r3, r4 @ delay + factor * (out_length-1) +1
+
+ cmp r3, r1 @ data_in_length < endpos?
+ movgt r0, #-1
+ bgt END
+
+ @ Initializations.
+ sub r3, r5, asl #3
+ add r11, r0, r12, asl #1 @ &data_in[delay]
+ ldr r0, [sp, #36] @ coefficients_length
+ add r3, r5 @ endpos - factor * 7
+
+ cmp r0, #0 @ coefficients_length <= 0 ?
+ movle r0, #-1
+ ble END
+
+ add r8, r0, asl #1 @ &coeffieient[coefficients_length]
+ cmp r9, r3
+ bge POST_LOOP_ENDPOS @ branch when Iteration < 8 times.
+
+@
+@ First part, unroll the loop 8 times, with 3 subcases (factor == 2, 4, others)
+@
+ mov r4, #-2
+
+ @ Direct program flow to the right channel.
+
+ @ r10 is an offset to &data_in[] in the loop. After an iteration, we need to
+ @ move the pointer back to original after advancing 16 bytes by a vld1, and
+ @ then move 2 bytes forward to increment one more sample.
+ cmp r5, #2
+ moveq r10, #-14
+ beq LOOP_ENDPOS_FACTOR2 @ Branch when factor == 2
+
+ @ Similar here, for r10, we need to move the pointer back to original after
+ @ advancing 32 bytes, then move 2 bytes forward to increment one sample.
+ cmp r5, #4
+ moveq r10, #-30
+ beq LOOP_ENDPOS_FACTOR4 @ Branch when factor == 4
+
+ @ For r10, we need to move the pointer back to original after advancing
+ @ (factor * 7 * 2) bytes, then move 2 bytes forward to increment one sample.
+ mov r10, r5, asl #4
+ rsb r10, #2
+ add r10, r5, asl #1
+ lsl r5, #1 @ r5 = factor * sizeof(data_in)
+
+@ The general case (factor != 2 && factor != 4)
+LOOP_ENDPOS_GENERAL:
+ @ Initializations.
+ vmov.i32 q2, #2048
+ vmov.i32 q3, #2048
+ sub r7, r8, #2
+ sub r12, r0, #1 @ coefficients_length - 1
+ sub r1, r11, r12, asl #1 @ &data_in[i - j]
+
+LOOP_COEFF_LENGTH_GENERAL:
+ vld1.16 {d2[], d3[]}, [r7], r4 @ coefficients[j]
+ vld1.16 d0[0], [r1], r5 @ data_in[i - j]
+ vld1.16 d0[1], [r1], r5 @ data_in[i + factor - j]
+ vld1.16 d0[2], [r1], r5 @ data_in[i + factor * 2 - j]
+ vld1.16 d0[3], [r1], r5 @ data_in[i + factor * 3 - j]
+ vld1.16 d1[0], [r1], r5 @ data_in[i + factor * 4 - j]
+ vld1.16 d1[1], [r1], r5 @ data_in[i + factor * 5 - j]
+ vld1.16 d1[2], [r1], r5 @ data_in[i + factor * 6 - j]
+ vld1.16 d1[3], [r1], r10 @ data_in[i + factor * 7 - j]
+ subs r12, #1
+ vmlal.s16 q2, d0, d2
+ vmlal.s16 q3, d1, d3
+ bge LOOP_COEFF_LENGTH_GENERAL
+
+ @ Shift, saturate, and store the result.
+ vqshrn.s32 d0, q2, #12
+ vqshrn.s32 d1, q3, #12
+ vst1.16 {d0, d1}, [r2]!
+
+ add r11, r5, asl #3 @ r11 -> &data_in[i + factor * 8]
+ add r9, r5, asl #2 @ Counter i = delay + factor * 8.
+ cmp r9, r3 @ i < endpos - factor * 7 ?
+ blt LOOP_ENDPOS_GENERAL
+ asr r5, #1 @ Restore r5 to the value of factor.
+ b POST_LOOP_ENDPOS
+
+@ The case for factor == 2.
+LOOP_ENDPOS_FACTOR2:
+ @ Initializations.
+ vmov.i32 q2, #2048
+ vmov.i32 q3, #2048
+ sub r7, r8, #2
+ sub r12, r0, #1 @ coefficients_length - 1
+ sub r1, r11, r12, asl #1 @ &data_in[i - j]
+
+LOOP_COEFF_LENGTH_FACTOR2:
+ vld1.16 {d16[], d17[]}, [r7], r4 @ coefficients[j]
+ vld2.16 {d0, d1}, [r1]! @ data_in[]
+ vld2.16 {d2, d3}, [r1], r10 @ data_in[]
+ subs r12, #1
+ vmlal.s16 q2, d0, d16
+ vmlal.s16 q3, d2, d17
+ bge LOOP_COEFF_LENGTH_FACTOR2
+
+ @ Shift, saturate, and store the result.
+ vqshrn.s32 d0, q2, #12
+ vqshrn.s32 d1, q3, #12
+ vst1.16 {d0, d1}, [r2]!
+
+ add r11, r5, asl #4 @ r11 -> &data_in[i + factor * 8]
+ add r9, r5, asl #3 @ Counter i = delay + factor * 8.
+ cmp r9, r3 @ i < endpos - factor * 7 ?
+ blt LOOP_ENDPOS_FACTOR2
+ b POST_LOOP_ENDPOS
+
+@ The case for factor == 4.
+LOOP_ENDPOS_FACTOR4:
+ @ Initializations.
+ vmov.i32 q2, #2048
+ vmov.i32 q3, #2048
+ sub r7, r8, #2
+ sub r12, r0, #1 @ coefficients_length - 1
+ sub r1, r11, r12, asl #1 @ &data_in[i - j]
+
+LOOP_COEFF_LENGTH_FACTOR4:
+ vld1.16 {d16[], d17[]}, [r7], r4 @ coefficients[j]
+ vld4.16 {d0, d1, d2, d3}, [r1]! @ data_in[]
+ vld4.16 {d18, d19, d20, d21}, [r1], r10 @ data_in[]
+ subs r12, #1
+ vmlal.s16 q2, d0, d16
+ vmlal.s16 q3, d18, d17
+ bge LOOP_COEFF_LENGTH_FACTOR4
+
+ @ Shift, saturate, and store the result.
+ vqshrn.s32 d0, q2, #12
+ vqshrn.s32 d1, q3, #12
+ vst1.16 {d0, d1}, [r2]!
+
+ add r11, r5, asl #4 @ r11 -> &data_in[i + factor * 8]
+ add r9, r5, asl #3 @ Counter i = delay + factor * 8.
+ cmp r9, r3 @ i < endpos - factor * 7 ?
+ blt LOOP_ENDPOS_FACTOR4
+
+@
+@ Second part, do the rest iterations (if any).
+@
+
+POST_LOOP_ENDPOS:
+ add r3, r5, asl #3
+ sub r3, r5 @ Restore r3 to endpos.
+ cmp r9, r3
+ movge r0, #0
+ bge END
+
+LOOP2_ENDPOS:
+ @ Initializations.
+ mov r7, r8
+ sub r12, r0, #1 @ coefficients_length - 1
+ sub r6, r11, r12, asl #1 @ &data_in[i - j]
+
+ mov r1, #2048
+
+LOOP2_COEFF_LENGTH:
+ ldrsh r4, [r7, #-2]! @ coefficients[j]
+ ldrsh r10, [r6], #2 @ data_in[i - j]
+ smlabb r1, r4, r10, r1
+ subs r12, #1
+ bge LOOP2_COEFF_LENGTH
+
+ @ Shift, saturate, and store the result.
+ ssat r1, #16, r1, asr #12
+ strh r1, [r2], #2
+
+ add r11, r5, asl #1 @ r11 -> &data_in[i + factor]
+ add r9, r5 @ Counter i = delay + factor.
+ cmp r9, r3 @ i < endpos?
+ blt LOOP2_ENDPOS
+
+ mov r0, #0
+
+END:
+ pop {r4-r11}
+ bx lr
+
+.fnend
diff --git a/common_audio/signal_processing/energy.c b/common_audio/signal_processing/energy.c
new file mode 100644
index 0000000..e8fdf94
--- /dev/null
+++ b/common_audio/signal_processing/energy.c
@@ -0,0 +1,36 @@
+/*
+ * 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 function WebRtcSpl_Energy().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_Word32 WebRtcSpl_Energy(WebRtc_Word16* vector, int vector_length, int* scale_factor)
+{
+ WebRtc_Word32 en = 0;
+ int i;
+ int scaling = WebRtcSpl_GetScalingSquare(vector, vector_length, vector_length);
+ int looptimes = vector_length;
+ WebRtc_Word16 *vectorptr = vector;
+
+ for (i = 0; i < looptimes; i++)
+ {
+ en += WEBRTC_SPL_MUL_16_16_RSFT(*vectorptr, *vectorptr, scaling);
+ vectorptr++;
+ }
+ *scale_factor = scaling;
+
+ return en;
+}
diff --git a/common_audio/signal_processing/filter_ar.c b/common_audio/signal_processing/filter_ar.c
new file mode 100644
index 0000000..24e83a6
--- /dev/null
+++ b/common_audio/signal_processing/filter_ar.c
@@ -0,0 +1,89 @@
+/*
+ * 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 function WebRtcSpl_FilterAR().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_FilterAR(G_CONST WebRtc_Word16* a,
+ int a_length,
+ G_CONST WebRtc_Word16* x,
+ int x_length,
+ WebRtc_Word16* state,
+ int state_length,
+ WebRtc_Word16* state_low,
+ int state_low_length,
+ WebRtc_Word16* filtered,
+ WebRtc_Word16* filtered_low,
+ int filtered_low_length)
+{
+ WebRtc_Word32 o;
+ WebRtc_Word32 oLOW;
+ int i, j, stop;
+ G_CONST WebRtc_Word16* x_ptr = &x[0];
+ WebRtc_Word16* filteredFINAL_ptr = filtered;
+ WebRtc_Word16* filteredFINAL_LOW_ptr = filtered_low;
+
+ for (i = 0; i < x_length; i++)
+ {
+ // Calculate filtered[i] and filtered_low[i]
+ G_CONST WebRtc_Word16* a_ptr = &a[1];
+ WebRtc_Word16* filtered_ptr = &filtered[i - 1];
+ WebRtc_Word16* filtered_low_ptr = &filtered_low[i - 1];
+ WebRtc_Word16* state_ptr = &state[state_length - 1];
+ WebRtc_Word16* state_low_ptr = &state_low[state_length - 1];
+
+ o = (WebRtc_Word32)(*x_ptr++) << 12;
+ oLOW = (WebRtc_Word32)0;
+
+ stop = (i < a_length) ? i + 1 : a_length;
+ for (j = 1; j < stop; j++)
+ {
+ o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--);
+ oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--);
+ }
+ for (j = i + 1; j < a_length; j++)
+ {
+ o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *state_ptr--);
+ oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *state_low_ptr--);
+ }
+
+ o += (oLOW >> 12);
+ *filteredFINAL_ptr = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);
+ *filteredFINAL_LOW_ptr++ = (WebRtc_Word16)(o - ((WebRtc_Word32)(*filteredFINAL_ptr++)
+ << 12));
+ }
+
+ // Save the filter state
+ if (x_length >= state_length)
+ {
+ WebRtcSpl_CopyFromEndW16(filtered, x_length, a_length - 1, state);
+ WebRtcSpl_CopyFromEndW16(filtered_low, x_length, a_length - 1, state_low);
+ } else
+ {
+ for (i = 0; i < state_length - x_length; i++)
+ {
+ state[i] = state[i + x_length];
+ state_low[i] = state_low[i + x_length];
+ }
+ for (i = 0; i < x_length; i++)
+ {
+ state[state_length - x_length + i] = filtered[i];
+ state[state_length - x_length + i] = filtered_low[i];
+ }
+ }
+
+ return x_length;
+}
diff --git a/common_audio/signal_processing/filter_ar_fast_q12.c b/common_audio/signal_processing/filter_ar_fast_q12.c
new file mode 100644
index 0000000..0402302
--- /dev/null
+++ b/common_audio/signal_processing/filter_ar_fast_q12.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+#include <assert.h>
+
+#include "signal_processing_library.h"
+
+// TODO(bjornv): Change the return type to report errors.
+
+void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
+ int16_t* data_out,
+ const int16_t* __restrict coefficients,
+ int coefficients_length,
+ int data_length) {
+ int i = 0;
+ int j = 0;
+
+ assert(data_length > 0);
+ assert(coefficients_length > 1);
+
+ for (i = 0; i < data_length; i++) {
+ int32_t output = 0;
+ int32_t sum = 0;
+
+ for (j = coefficients_length - 1; j > 0; j--) {
+ sum += coefficients[j] * data_out[i - j];
+ }
+
+ output = coefficients[0] * data_in[i];
+ output -= sum;
+
+ // Saturate and store the output.
+ output = WEBRTC_SPL_SAT(134215679, output, -134217728);
+ data_out[i] = (int16_t)((output + 2048) >> 12);
+ }
+}
+
diff --git a/common_audio/signal_processing/filter_ar_fast_q12_armv7.s b/common_audio/signal_processing/filter_ar_fast_q12_armv7.s
new file mode 100644
index 0000000..5591bb8
--- /dev/null
+++ b/common_audio/signal_processing/filter_ar_fast_q12_armv7.s
@@ -0,0 +1,223 @@
+@
+@ Copyright (c) 2012 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 function WebRtcSpl_FilterARFastQ12(), optimized for
+@ ARMv7 platform. The description header can be found in
+@ signal_processing_library.h
+@
+@ Output is bit-exact with the generic C code as in filter_ar_fast_q12.c, and
+@ the reference C code at end of this file.
+
+@ Assumptions:
+@ (1) data_length > 0
+@ (2) coefficients_length > 1
+
+@ Register usage:
+@
+@ r0: &data_in[i]
+@ r1: &data_out[i], for result ouput
+@ r2: &coefficients[0]
+@ r3: coefficients_length
+@ r4: Iteration counter for the outer loop.
+@ r5: data_out[j] as multiplication inputs
+@ r6: Calculated value for output data_out[]; interation counter for inner loop
+@ r7: Partial sum of a filtering multiplication results
+@ r8: Partial sum of a filtering multiplication results
+@ r9: &data_out[], for filtering input; data_in[i]
+@ r10: coefficients[j]
+@ r11: Scratch
+@ r12: &coefficients[j]
+
+.arch armv7-a
+
+.align 2
+.global WebRtcSpl_FilterARFastQ12
+
+WebRtcSpl_FilterARFastQ12:
+
+.fnstart
+
+.save {r4-r11}
+ push {r4-r11}
+
+ ldrsh r12, [sp, #32] @ data_length
+ subs r4, r12, #1
+ beq ODD_LENGTH @ jump if data_length == 1
+
+LOOP_LENGTH:
+ add r12, r2, r3, lsl #1
+ sub r12, #4 @ &coefficients[coefficients_length - 2]
+ sub r9, r1, r3, lsl #1
+ add r9, #2 @ &data_out[i - coefficients_length + 1]
+ ldr r5, [r9], #4 @ data_out[i - coefficients_length + {1,2}]
+
+ mov r7, #0 @ sum1
+ mov r8, #0 @ sum2
+ subs r6, r3, #3 @ Iteration counter for inner loop.
+ beq ODD_A_LENGTH @ branch if coefficients_length == 3
+ blt POST_LOOP_A_LENGTH @ branch if coefficients_length == 2
+
+LOOP_A_LENGTH:
+ ldr r10, [r12], #-4 @ coefficients[j - 1], coefficients[j]
+ subs r6, #2
+ smlatt r8, r10, r5, r8 @ sum2 += coefficients[j] * data_out[i - j + 1];
+ smlatb r7, r10, r5, r7 @ sum1 += coefficients[j] * data_out[i - j];
+ smlabt r7, r10, r5, r7 @ coefficients[j - 1] * data_out[i - j + 1];
+ ldr r5, [r9], #4 @ data_out[i - j + 2], data_out[i - j + 3]
+ smlabb r8, r10, r5, r8 @ coefficients[j - 1] * data_out[i - j + 2];
+ bgt LOOP_A_LENGTH
+ blt POST_LOOP_A_LENGTH
+
+ODD_A_LENGTH:
+ ldrsh r10, [r12, #2] @ Filter coefficients coefficients[2]
+ sub r12, #2 @ &coefficients[0]
+ smlabb r7, r10, r5, r7 @ sum1 += coefficients[2] * data_out[i - 2];
+ smlabt r8, r10, r5, r8 @ sum2 += coefficients[2] * data_out[i - 1];
+ ldr r5, [r9, #-2] @ data_out[i - 1], data_out[i]
+
+POST_LOOP_A_LENGTH:
+ ldr r10, [r12] @ coefficients[0], coefficients[1]
+ smlatb r7, r10, r5, r7 @ sum1 += coefficients[1] * data_out[i - 1];
+
+ ldr r9, [r0], #4 @ data_in[i], data_in[i + 1]
+ smulbb r6, r10, r9 @ output1 = coefficients[0] * data_in[i];
+ sub r6, r7 @ output1 -= sum1;
+
+ sbfx r11, r6, #12, #16
+ ssat r7, #16, r6, asr #12
+ cmp r7, r11
+ addeq r6, r6, #2048
+ ssat r6, #16, r6, asr #12
+ strh r6, [r1], #2 @ Store data_out[i]
+
+ smlatb r8, r10, r6, r8 @ sum2 += coefficients[1] * data_out[i];
+ smulbt r6, r10, r9 @ output2 = coefficients[0] * data_in[i + 1];
+ sub r6, r8 @ output1 -= sum1;
+
+ sbfx r11, r6, #12, #16
+ ssat r7, #16, r6, asr #12
+ cmp r7, r11
+ addeq r6, r6, #2048
+ ssat r6, #16, r6, asr #12
+ strh r6, [r1], #2 @ Store data_out[i + 1]
+
+ subs r4, #2
+ bgt LOOP_LENGTH
+ blt END @ For even data_length, it's done. Jump to END.
+
+@ Process i = data_length -1, for the case of an odd length.
+ODD_LENGTH:
+ add r12, r2, r3, lsl #1
+ sub r12, #4 @ &coefficients[coefficients_length - 2]
+ sub r9, r1, r3, lsl #1
+ add r9, #2 @ &data_out[i - coefficients_length + 1]
+ mov r7, #0 @ sum1
+ mov r8, #0 @ sum1
+ subs r6, r3, #2 @ inner loop counter
+ beq EVEN_A_LENGTH @ branch if coefficients_length == 2
+
+LOOP2_A_LENGTH:
+ ldr r10, [r12], #-4 @ coefficients[j - 1], coefficients[j]
+ ldr r5, [r9], #4 @ data_out[i - j], data_out[i - j + 1]
+ subs r6, #2
+ smlatb r7, r10, r5, r7 @ sum1 += coefficients[j] * data_out[i - j];
+ smlabt r8, r10, r5, r8 @ coefficients[j - 1] * data_out[i - j + 1];
+ bgt LOOP2_A_LENGTH
+ addlt r12, #2
+ blt POST_LOOP2_A_LENGTH
+
+EVEN_A_LENGTH:
+ ldrsh r10, [r12, #2] @ Filter coefficients coefficients[1]
+ ldrsh r5, [r9] @ data_out[i - 1]
+ smlabb r7, r10, r5, r7 @ sum1 += coefficients[1] * data_out[i - 1];
+
+POST_LOOP2_A_LENGTH:
+ ldrsh r10, [r12] @ Filter coefficients coefficients[0]
+ ldrsh r9, [r0] @ data_in[i]
+ smulbb r6, r10, r9 @ output1 = coefficients[0] * data_in[i];
+ sub r6, r7 @ output1 -= sum1;
+ sub r6, r8 @ output1 -= sum1;
+ sbfx r8, r6, #12, #16
+ ssat r7, #16, r6, asr #12
+ cmp r7, r8
+ addeq r6, r6, #2048
+ ssat r6, #16, r6, asr #12
+ strh r6, [r1] @ Store the data_out[i]
+
+END:
+ pop {r4-r11}
+ bx lr
+
+.fnend
+
+
+@Reference C code:
+@
+@void WebRtcSpl_FilterARFastQ12(int16_t* data_in,
+@ int16_t* data_out,
+@ int16_t* __restrict coefficients,
+@ int coefficients_length,
+@ int data_length) {
+@ int i = 0;
+@ int j = 0;
+@
+@ for (i = 0; i < data_length - 1; i += 2) {
+@ int32_t output1 = 0;
+@ int32_t sum1 = 0;
+@ int32_t output2 = 0;
+@ int32_t sum2 = 0;
+@
+@ for (j = coefficients_length - 1; j > 2; j -= 2) {
+@ sum1 += coefficients[j] * data_out[i - j];
+@ sum1 += coefficients[j - 1] * data_out[i - j + 1];
+@ sum2 += coefficients[j] * data_out[i - j + 1];
+@ sum2 += coefficients[j - 1] * data_out[i - j + 2];
+@ }
+@
+@ if (j == 2) {
+@ sum1 += coefficients[2] * data_out[i - 2];
+@ sum2 += coefficients[2] * data_out[i - 1];
+@ }
+@
+@ sum1 += coefficients[1] * data_out[i - 1];
+@ output1 = coefficients[0] * data_in[i];
+@ output1 -= sum1;
+@ // Saturate and store the output.
+@ output1 = WEBRTC_SPL_SAT(134215679, output1, -134217728);
+@ data_out[i] = (int16_t)((output1 + 2048) >> 12);
+@
+@ sum2 += coefficients[1] * data_out[i];
+@ output2 = coefficients[0] * data_in[i + 1];
+@ output2 -= sum2;
+@ // Saturate and store the output.
+@ output2 = WEBRTC_SPL_SAT(134215679, output2, -134217728);
+@ data_out[i + 1] = (int16_t)((output2 + 2048) >> 12);
+@ }
+@
+@ if (i == data_length - 1) {
+@ int32_t output1 = 0;
+@ int32_t sum1 = 0;
+@
+@ for (j = coefficients_length - 1; j > 1; j -= 2) {
+@ sum1 += coefficients[j] * data_out[i - j];
+@ sum1 += coefficients[j - 1] * data_out[i - j + 1];
+@ }
+@
+@ if (j == 1) {
+@ sum1 += coefficients[1] * data_out[i - 1];
+@ }
+@
+@ output1 = coefficients[0] * data_in[i];
+@ output1 -= sum1;
+@ // Saturate and store the output.
+@ output1 = WEBRTC_SPL_SAT(134215679, output1, -134217728);
+@ data_out[i] = (int16_t)((output1 + 2048) >> 12);
+@ }
+@}
diff --git a/common_audio/signal_processing/filter_ma_fast_q12.c b/common_audio/signal_processing/filter_ma_fast_q12.c
new file mode 100644
index 0000000..19ad9b1
--- /dev/null
+++ b/common_audio/signal_processing/filter_ma_fast_q12.c
@@ -0,0 +1,49 @@
+/*
+ * 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 function WebRtcSpl_FilterMAFastQ12().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_FilterMAFastQ12(WebRtc_Word16* in_ptr,
+ WebRtc_Word16* out_ptr,
+ WebRtc_Word16* B,
+ WebRtc_Word16 B_length,
+ WebRtc_Word16 length)
+{
+ WebRtc_Word32 o;
+ int i, j;
+ for (i = 0; i < length; i++)
+ {
+ G_CONST WebRtc_Word16* b_ptr = &B[0];
+ G_CONST WebRtc_Word16* x_ptr = &in_ptr[i];
+
+ o = (WebRtc_Word32)0;
+
+ for (j = 0; j < B_length; j++)
+ {
+ o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--);
+ }
+
+ // If output is higher than 32768, saturate it. Same with negative side
+ // 2^27 = 134217728, which corresponds to 32768 in Q12
+
+ // Saturate the output
+ o = WEBRTC_SPL_SAT((WebRtc_Word32)134215679, o, (WebRtc_Word32)-134217728);
+
+ *out_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);
+ }
+ return;
+}
diff --git a/common_audio/signal_processing/get_hanning_window.c b/common_audio/signal_processing/get_hanning_window.c
new file mode 100644
index 0000000..6d67e60
--- /dev/null
+++ b/common_audio/signal_processing/get_hanning_window.c
@@ -0,0 +1,77 @@
+/*
+ * 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 function WebRtcSpl_GetHanningWindow().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+// Hanning table with 256 entries
+static const WebRtc_Word16 kHanningTable[] = {
+ 1, 2, 6, 10, 15, 22, 30, 39,
+ 50, 62, 75, 89, 104, 121, 138, 157,
+ 178, 199, 222, 246, 271, 297, 324, 353,
+ 383, 413, 446, 479, 513, 549, 586, 624,
+ 663, 703, 744, 787, 830, 875, 920, 967,
+ 1015, 1064, 1114, 1165, 1218, 1271, 1325, 1381,
+ 1437, 1494, 1553, 1612, 1673, 1734, 1796, 1859,
+ 1924, 1989, 2055, 2122, 2190, 2259, 2329, 2399,
+ 2471, 2543, 2617, 2691, 2765, 2841, 2918, 2995,
+ 3073, 3152, 3232, 3312, 3393, 3475, 3558, 3641,
+ 3725, 3809, 3895, 3980, 4067, 4154, 4242, 4330,
+ 4419, 4509, 4599, 4689, 4781, 4872, 4964, 5057,
+ 5150, 5244, 5338, 5432, 5527, 5622, 5718, 5814,
+ 5910, 6007, 6104, 6202, 6299, 6397, 6495, 6594,
+ 6693, 6791, 6891, 6990, 7090, 7189, 7289, 7389,
+ 7489, 7589, 7690, 7790, 7890, 7991, 8091, 8192,
+ 8293, 8393, 8494, 8594, 8694, 8795, 8895, 8995,
+ 9095, 9195, 9294, 9394, 9493, 9593, 9691, 9790,
+ 9889, 9987, 10085, 10182, 10280, 10377, 10474, 10570,
+10666, 10762, 10857, 10952, 11046, 11140, 11234, 11327,
+11420, 11512, 11603, 11695, 11785, 11875, 11965, 12054,
+12142, 12230, 12317, 12404, 12489, 12575, 12659, 12743,
+12826, 12909, 12991, 13072, 13152, 13232, 13311, 13389,
+13466, 13543, 13619, 13693, 13767, 13841, 13913, 13985,
+14055, 14125, 14194, 14262, 14329, 14395, 14460, 14525,
+14588, 14650, 14711, 14772, 14831, 14890, 14947, 15003,
+15059, 15113, 15166, 15219, 15270, 15320, 15369, 15417,
+15464, 15509, 15554, 15597, 15640, 15681, 15721, 15760,
+15798, 15835, 15871, 15905, 15938, 15971, 16001, 16031,
+16060, 16087, 16113, 16138, 16162, 16185, 16206, 16227,
+16246, 16263, 16280, 16295, 16309, 16322, 16334, 16345,
+16354, 16362, 16369, 16374, 16378, 16382, 16383, 16384
+};
+
+void WebRtcSpl_GetHanningWindow(WebRtc_Word16 *v, WebRtc_Word16 size)
+{
+ int jj;
+ WebRtc_Word16 *vptr1;
+
+ WebRtc_Word32 index;
+ WebRtc_Word32 factor = ((WebRtc_Word32)0x40000000);
+
+ factor = WebRtcSpl_DivW32W16(factor, size);
+ if (size < 513)
+ index = (WebRtc_Word32)-0x200000;
+ else
+ index = (WebRtc_Word32)-0x100000;
+ vptr1 = v;
+
+ for (jj = 0; jj < size; jj++)
+ {
+ index += factor;
+ (*vptr1++) = kHanningTable[index >> 22];
+ }
+
+}
diff --git a/common_audio/signal_processing/get_scaling_square.c b/common_audio/signal_processing/get_scaling_square.c
new file mode 100644
index 0000000..dccbf33
--- /dev/null
+++ b/common_audio/signal_processing/get_scaling_square.c
@@ -0,0 +1,44 @@
+/*
+ * 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 function WebRtcSpl_GetScalingSquare().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_GetScalingSquare(WebRtc_Word16 *in_vector, int in_vector_length, int times)
+{
+ int nbits = WebRtcSpl_GetSizeInBits(times);
+ int i;
+ WebRtc_Word16 smax = -1;
+ WebRtc_Word16 sabs;
+ WebRtc_Word16 *sptr = in_vector;
+ int t;
+ int looptimes = in_vector_length;
+
+ for (i = looptimes; i > 0; i--)
+ {
+ sabs = (*sptr > 0 ? *sptr++ : -*sptr++);
+ smax = (sabs > smax ? sabs : smax);
+ }
+ t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax));
+
+ if (smax == 0)
+ {
+ return 0; // Since norm(0) returns 0
+ } else
+ {
+ return (t > nbits) ? 0 : nbits - t;
+ }
+}
diff --git a/common_audio/signal_processing/ilbc_specific_functions.c b/common_audio/signal_processing/ilbc_specific_functions.c
new file mode 100644
index 0000000..3588ba4
--- /dev/null
+++ b/common_audio/signal_processing/ilbc_specific_functions.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012 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 implementations of the iLBC specific functions
+ * WebRtcSpl_ReverseOrderMultArrayElements()
+ * WebRtcSpl_ElementwiseVectorMult()
+ * WebRtcSpl_AddVectorsAndShift()
+ * WebRtcSpl_AddAffineVectorToVector()
+ * WebRtcSpl_AffineTransformVector()
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_ReverseOrderMultArrayElements(WebRtc_Word16 *out, G_CONST WebRtc_Word16 *in,
+ G_CONST WebRtc_Word16 *win,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+ WebRtc_Word16 *outptr = out;
+ G_CONST WebRtc_Word16 *inptr = in;
+ G_CONST WebRtc_Word16 *winptr = win;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++,
+ *winptr--, right_shifts);
+ }
+}
+
+void WebRtcSpl_ElementwiseVectorMult(WebRtc_Word16 *out, G_CONST WebRtc_Word16 *in,
+ G_CONST WebRtc_Word16 *win, WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+ WebRtc_Word16 *outptr = out;
+ G_CONST WebRtc_Word16 *inptr = in;
+ G_CONST WebRtc_Word16 *winptr = win;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++,
+ *winptr++, right_shifts);
+ }
+}
+
+void WebRtcSpl_AddVectorsAndShift(WebRtc_Word16 *out, G_CONST WebRtc_Word16 *in1,
+ G_CONST WebRtc_Word16 *in2, WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+ WebRtc_Word16 *outptr = out;
+ G_CONST WebRtc_Word16 *in1ptr = in1;
+ G_CONST WebRtc_Word16 *in2ptr = in2;
+ for (i = vector_length; i > 0; i--)
+ {
+ (*outptr++) = (WebRtc_Word16)(((*in1ptr++) + (*in2ptr++)) >> right_shifts);
+ }
+}
+
+void WebRtcSpl_AddAffineVectorToVector(WebRtc_Word16 *out, WebRtc_Word16 *in,
+ WebRtc_Word16 gain, WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts, int vector_length)
+{
+ WebRtc_Word16 *inPtr;
+ WebRtc_Word16 *outPtr;
+ int i;
+
+ inPtr = in;
+ outPtr = out;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outPtr++) += (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16((*inPtr++), gain)
+ + (WebRtc_Word32)add_constant) >> right_shifts);
+ }
+}
+
+void WebRtcSpl_AffineTransformVector(WebRtc_Word16 *out, WebRtc_Word16 *in,
+ WebRtc_Word16 gain, WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts, int vector_length)
+{
+ WebRtc_Word16 *inPtr;
+ WebRtc_Word16 *outPtr;
+ int i;
+
+ inPtr = in;
+ outPtr = out;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outPtr++) = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16((*inPtr++), gain)
+ + (WebRtc_Word32)add_constant) >> right_shifts);
+ }
+}
diff --git a/common_audio/signal_processing/include/real_fft.h b/common_audio/signal_processing/include/real_fft.h
new file mode 100644
index 0000000..4028b41
--- /dev/null
+++ b/common_audio/signal_processing/include/real_fft.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#ifndef WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
+#define WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
+
+#include "typedefs.h"
+
+struct RealFFT;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*RealForwardFFT)(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out);
+typedef int (*RealInverseFFT)(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out);
+
+extern RealForwardFFT WebRtcSpl_RealForwardFFT;
+extern RealInverseFFT WebRtcSpl_RealInverseFFT;
+
+struct RealFFT* WebRtcSpl_CreateRealFFT(int order);
+void WebRtcSpl_FreeRealFFT(struct RealFFT* self);
+
+// TODO(kma): Implement FFT functions for real signals.
+
+// Compute the forward FFT for a complex signal of length 2^order.
+// Input Arguments:
+// self - pointer to preallocated and initialized FFT specification structure.
+// data_in - the input signal.
+//
+// Output Arguments:
+// data_out - the output signal; must be different to data_in.
+//
+// Return Value:
+// 0 - FFT calculation is successful.
+// -1 - Error
+//
+int WebRtcSpl_RealForwardFFTC(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out);
+
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int WebRtcSpl_RealForwardFFTNeon(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out);
+#endif
+
+// Compute the inverse FFT for a complex signal of length 2^order.
+// Input Arguments:
+// self - pointer to preallocated and initialized FFT specification structure.
+// data_in - the input signal.
+//
+// Output Arguments:
+// data_out - the output signal; must be different to data_in.
+//
+// Return Value:
+// 0 or a positive number - a value that the elements in the |data_out| should
+// be shifted left with in order to get correct
+// physical values.
+// -1 - Error
+int WebRtcSpl_RealInverseFFTC(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out);
+
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int WebRtcSpl_RealInverseFFTNeon(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
diff --git a/common_audio/signal_processing/include/signal_processing_library.h b/common_audio/signal_processing/include/signal_processing_library.h
new file mode 100644
index 0000000..1738e8e
--- /dev/null
+++ b/common_audio/signal_processing/include/signal_processing_library.h
@@ -0,0 +1,1737 @@
+/*
+ * Copyright (c) 2012 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 header file includes all of the fix point signal processing library (SPL) function
+ * descriptions and declarations.
+ * For specific function calls, see bottom of file.
+ */
+
+#ifndef WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
+#define WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
+
+#include <string.h>
+#include "typedefs.h"
+
+// Macros specific for the fixed point implementation
+#define WEBRTC_SPL_WORD16_MAX 32767
+#define WEBRTC_SPL_WORD16_MIN -32768
+#define WEBRTC_SPL_WORD32_MAX (WebRtc_Word32)0x7fffffff
+#define WEBRTC_SPL_WORD32_MIN (WebRtc_Word32)0x80000000
+#define WEBRTC_SPL_MAX_LPC_ORDER 14
+#define WEBRTC_SPL_MAX_SEED_USED 0x80000000L
+#define WEBRTC_SPL_MIN(A, B) (A < B ? A : B) // Get min value
+#define WEBRTC_SPL_MAX(A, B) (A > B ? A : B) // Get max value
+// TODO(kma/bjorn): For the next two macros, investigate how to correct the code
+// for inputs of a = WEBRTC_SPL_WORD16_MIN or WEBRTC_SPL_WORD32_MIN.
+#define WEBRTC_SPL_ABS_W16(a) \
+ (((WebRtc_Word16)a >= 0) ? ((WebRtc_Word16)a) : -((WebRtc_Word16)a))
+#define WEBRTC_SPL_ABS_W32(a) \
+ (((WebRtc_Word32)a >= 0) ? ((WebRtc_Word32)a) : -((WebRtc_Word32)a))
+
+#ifdef WEBRTC_ARCH_LITTLE_ENDIAN
+#define WEBRTC_SPL_GET_BYTE(a, nr) (((WebRtc_Word8 *)a)[nr])
+#define WEBRTC_SPL_SET_BYTE(d_ptr, val, index) \
+ (((WebRtc_Word8 *)d_ptr)[index] = (val))
+#else
+#define WEBRTC_SPL_GET_BYTE(a, nr) \
+ ((((WebRtc_Word16 *)a)[nr >> 1]) >> (((nr + 1) & 0x1) * 8) & 0x00ff)
+#define WEBRTC_SPL_SET_BYTE(d_ptr, val, index) \
+ ((WebRtc_Word16 *)d_ptr)[index >> 1] = \
+ ((((WebRtc_Word16 *)d_ptr)[index >> 1]) \
+ & (0x00ff << (8 * ((index) & 0x1)))) | (val << (8 * ((index + 1) & 0x1)))
+#endif
+
+#define WEBRTC_SPL_MUL(a, b) \
+ ((WebRtc_Word32) ((WebRtc_Word32)(a) * (WebRtc_Word32)(b)))
+#define WEBRTC_SPL_UMUL(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord32)(b)))
+#define WEBRTC_SPL_UMUL_RSFT16(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord32)(b)) >> 16)
+#define WEBRTC_SPL_UMUL_16_16(a, b) \
+ ((WebRtc_UWord32) (WebRtc_UWord16)(a) * (WebRtc_UWord16)(b))
+#define WEBRTC_SPL_UMUL_16_16_RSFT16(a, b) \
+ (((WebRtc_UWord32) (WebRtc_UWord16)(a) * (WebRtc_UWord16)(b)) >> 16)
+#define WEBRTC_SPL_UMUL_32_16(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord16)(b)))
+#define WEBRTC_SPL_UMUL_32_16_RSFT16(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord16)(b)) >> 16)
+#define WEBRTC_SPL_MUL_16_U16(a, b) \
+ ((WebRtc_Word32)(WebRtc_Word16)(a) * (WebRtc_UWord16)(b))
+#define WEBRTC_SPL_DIV(a, b) \
+ ((WebRtc_Word32) ((WebRtc_Word32)(a) / (WebRtc_Word32)(b)))
+#define WEBRTC_SPL_UDIV(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) / (WebRtc_UWord32)(b)))
+
+#ifndef WEBRTC_ARCH_ARM_V7
+// For ARMv7 platforms, these are inline functions in spl_inl_armv7.h
+#define WEBRTC_SPL_MUL_16_16(a, b) \
+ ((WebRtc_Word32) (((WebRtc_Word16)(a)) * ((WebRtc_Word16)(b))))
+#define WEBRTC_SPL_MUL_16_32_RSFT16(a, b) \
+ (WEBRTC_SPL_MUL_16_16(a, b >> 16) \
+ + ((WEBRTC_SPL_MUL_16_16(a, (b & 0xffff) >> 1) + 0x4000) >> 15))
+#define WEBRTC_SPL_MUL_32_32_RSFT32(a32a, a32b, b32) \
+ ((WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT16(a32a, b32) \
+ + (WEBRTC_SPL_MUL_16_32_RSFT16(a32b, b32) >> 16)))
+#define WEBRTC_SPL_MUL_32_32_RSFT32BI(a32, b32) \
+ ((WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT16(( \
+ (WebRtc_Word16)(a32 >> 16)), b32) + \
+ (WEBRTC_SPL_MUL_16_32_RSFT16(( \
+ (WebRtc_Word16)((a32 & 0x0000FFFF) >> 1)), b32) >> 15)))
+#endif
+
+#define WEBRTC_SPL_MUL_16_32_RSFT11(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 5) \
+ + (((WEBRTC_SPL_MUL_16_U16(a, (WebRtc_UWord16)(b)) >> 1) + 0x0200) >> 10))
+#define WEBRTC_SPL_MUL_16_32_RSFT14(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 2) \
+ + (((WEBRTC_SPL_MUL_16_U16(a, (WebRtc_UWord16)(b)) >> 1) + 0x1000) >> 13))
+#define WEBRTC_SPL_MUL_16_32_RSFT15(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 1) \
+ + (((WEBRTC_SPL_MUL_16_U16(a, (WebRtc_UWord16)(b)) >> 1) + 0x2000) >> 14))
+
+#define WEBRTC_SPL_MUL_16_16_RSFT(a, b, c) \
+ (WEBRTC_SPL_MUL_16_16(a, b) >> (c))
+
+#define WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(a, b, c) \
+ ((WEBRTC_SPL_MUL_16_16(a, b) + ((WebRtc_Word32) \
+ (((WebRtc_Word32)1) << ((c) - 1)))) >> (c))
+#define WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, b) + ((WebRtc_Word32) (1 << 14))) >> 15)
+
+// C + the 32 most significant bits of A * B
+#define WEBRTC_SPL_SCALEDIFF32(A, B, C) \
+ (C + (B >> 16) * A + (((WebRtc_UWord32)(0x0000FFFF & B) * A) >> 16))
+
+#define WEBRTC_SPL_ADD_SAT_W32(a, b) WebRtcSpl_AddSatW32(a, b)
+#define WEBRTC_SPL_SAT(a, b, c) (b > a ? a : b < c ? c : b)
+#define WEBRTC_SPL_MUL_32_16(a, b) ((a) * (b))
+
+#define WEBRTC_SPL_SUB_SAT_W32(a, b) WebRtcSpl_SubSatW32(a, b)
+#define WEBRTC_SPL_ADD_SAT_W16(a, b) WebRtcSpl_AddSatW16(a, b)
+#define WEBRTC_SPL_SUB_SAT_W16(a, b) WebRtcSpl_SubSatW16(a, b)
+
+// We cannot do casting here due to signed/unsigned problem
+#define WEBRTC_SPL_IS_NEG(a) ((a) & 0x80000000)
+// Shifting with negative numbers allowed
+// Positive means left shift
+#define WEBRTC_SPL_SHIFT_W16(x, c) \
+ (((c) >= 0) ? ((x) << (c)) : ((x) >> (-(c))))
+#define WEBRTC_SPL_SHIFT_W32(x, c) \
+ (((c) >= 0) ? ((x) << (c)) : ((x) >> (-(c))))
+
+// Shifting with negative numbers not allowed
+// We cannot do casting here due to signed/unsigned problem
+#define WEBRTC_SPL_RSHIFT_W16(x, c) ((x) >> (c))
+#define WEBRTC_SPL_LSHIFT_W16(x, c) ((x) << (c))
+#define WEBRTC_SPL_RSHIFT_W32(x, c) ((x) >> (c))
+#define WEBRTC_SPL_LSHIFT_W32(x, c) ((x) << (c))
+
+#define WEBRTC_SPL_RSHIFT_U16(x, c) ((WebRtc_UWord16)(x) >> (c))
+#define WEBRTC_SPL_LSHIFT_U16(x, c) ((WebRtc_UWord16)(x) << (c))
+#define WEBRTC_SPL_RSHIFT_U32(x, c) ((WebRtc_UWord32)(x) >> (c))
+#define WEBRTC_SPL_LSHIFT_U32(x, c) ((WebRtc_UWord32)(x) << (c))
+
+#define WEBRTC_SPL_VNEW(t, n) (t *) malloc (sizeof (t) * (n))
+#define WEBRTC_SPL_FREE free
+
+#define WEBRTC_SPL_RAND(a) \
+ ((WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT((a), 18816, 7) & 0x00007fff))
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define WEBRTC_SPL_MEMCPY_W8(v1, v2, length) \
+ memcpy(v1, v2, (length) * sizeof(char))
+#define WEBRTC_SPL_MEMCPY_W16(v1, v2, length) \
+ memcpy(v1, v2, (length) * sizeof(WebRtc_Word16))
+
+#define WEBRTC_SPL_MEMMOVE_W16(v1, v2, length) \
+ memmove(v1, v2, (length) * sizeof(WebRtc_Word16))
+
+// inline functions:
+#include "spl_inl.h"
+
+// Initialize SPL. Currently it contains only function pointer initialization.
+// If the underlying platform is known to be ARM-Neon (WEBRTC_ARCH_ARM_NEON
+// defined), the pointers will be assigned to code optimized for Neon; otherwise
+// if run-time Neon detection (WEBRTC_DETECT_ARM_NEON) is enabled, the pointers
+// will be assigned to either Neon code or generic C code; otherwise, generic C
+// code will be assigned.
+// Note that this function MUST be called in any application that uses SPL
+// functions.
+void WebRtcSpl_Init();
+
+// Get SPL Version
+WebRtc_Word16 WebRtcSpl_get_version(char* version,
+ WebRtc_Word16 length_in_bytes);
+
+int WebRtcSpl_GetScalingSquare(WebRtc_Word16* in_vector,
+ int in_vector_length,
+ int times);
+
+// Copy and set operations. Implementation in copy_set_operations.c.
+// Descriptions at bottom of file.
+void WebRtcSpl_MemSetW16(WebRtc_Word16* vector,
+ WebRtc_Word16 set_value,
+ int vector_length);
+void WebRtcSpl_MemSetW32(WebRtc_Word32* vector,
+ WebRtc_Word32 set_value,
+ int vector_length);
+void WebRtcSpl_MemCpyReversedOrder(WebRtc_Word16* out_vector,
+ WebRtc_Word16* in_vector,
+ int vector_length);
+WebRtc_Word16 WebRtcSpl_CopyFromEndW16(G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16 in_vector_length,
+ WebRtc_Word16 samples,
+ WebRtc_Word16* out_vector);
+WebRtc_Word16 WebRtcSpl_ZerosArrayW16(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length);
+WebRtc_Word16 WebRtcSpl_ZerosArrayW32(WebRtc_Word32* vector,
+ WebRtc_Word16 vector_length);
+WebRtc_Word16 WebRtcSpl_OnesArrayW16(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length);
+WebRtc_Word16 WebRtcSpl_OnesArrayW32(WebRtc_Word32* vector,
+ WebRtc_Word16 vector_length);
+// End: Copy and set operations.
+
+
+// Minimum and maximum operation functions and their pointers.
+// Implementation in min_max_operations.c.
+
+// Returns the largest absolute value in a signed 16-bit vector.
+//
+// Input:
+// - vector : 16-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Maximum absolute value in vector;
+// or -1, if (vector == NULL || length <= 0).
+typedef int16_t (*MaxAbsValueW16)(const int16_t* vector, int length);
+extern MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16;
+int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, int length);
+#endif
+
+// Returns the largest absolute value in a signed 32-bit vector.
+//
+// Input:
+// - vector : 32-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Maximum absolute value in vector;
+// or -1, if (vector == NULL || length <= 0).
+typedef int32_t (*MaxAbsValueW32)(const int32_t* vector, int length);
+extern MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32;
+int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, int length);
+#endif
+
+// Returns the maximum value of a 16-bit vector.
+//
+// Input:
+// - vector : 16-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Maximum sample value in |vector|.
+// If (vector == NULL || length <= 0) WEBRTC_SPL_WORD16_MIN
+// is returned. Note that WEBRTC_SPL_WORD16_MIN is a feasible
+// value and we can't catch errors purely based on it.
+typedef int16_t (*MaxValueW16)(const int16_t* vector, int length);
+extern MaxValueW16 WebRtcSpl_MaxValueW16;
+int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, int length);
+#endif
+
+// Returns the maximum value of a 32-bit vector.
+//
+// Input:
+// - vector : 32-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Maximum sample value in |vector|.
+// If (vector == NULL || length <= 0) WEBRTC_SPL_WORD32_MIN
+// is returned. Note that WEBRTC_SPL_WORD32_MIN is a feasible
+// value and we can't catch errors purely based on it.
+typedef int32_t (*MaxValueW32)(const int32_t* vector, int length);
+extern MaxValueW32 WebRtcSpl_MaxValueW32;
+int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, int length);
+#endif
+
+// Returns the minimum value of a 16-bit vector.
+//
+// Input:
+// - vector : 16-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Minimum sample value in |vector|.
+// If (vector == NULL || length <= 0) WEBRTC_SPL_WORD16_MAX
+// is returned. Note that WEBRTC_SPL_WORD16_MAX is a feasible
+// value and we can't catch errors purely based on it.
+typedef int16_t (*MinValueW16)(const int16_t* vector, int length);
+extern MinValueW16 WebRtcSpl_MinValueW16;
+int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, int length);
+#endif
+
+// Returns the minimum value of a 32-bit vector.
+//
+// Input:
+// - vector : 32-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Minimum sample value in |vector|.
+// If (vector == NULL || length <= 0) WEBRTC_SPL_WORD32_MAX
+// is returned. Note that WEBRTC_SPL_WORD32_MAX is a feasible
+// value and we can't catch errors purely based on it.
+typedef int32_t (*MinValueW32)(const int32_t* vector, int length);
+extern MinValueW32 WebRtcSpl_MinValueW32;
+int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, int length);
+#endif
+
+// Returns the vector index to the largest absolute value of a 16-bit vector.
+//
+// Input:
+// - vector : 16-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Index to the maximum absolute value in vector, or -1,
+// if (vector == NULL || length <= 0).
+// If there are multiple equal maxima, return the index of the
+// first. -32768 will always have precedence over 32767 (despite
+// -32768 presenting an int16 absolute value of 32767);
+int WebRtcSpl_MaxAbsIndexW16(const int16_t* vector, int length);
+
+// Returns the vector index to the maximum sample value of a 16-bit vector.
+//
+// Input:
+// - vector : 16-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Index to the maximum value in vector (if multiple
+// indexes have the maximum, return the first);
+// or -1, if (vector == NULL || length <= 0).
+int WebRtcSpl_MaxIndexW16(const int16_t* vector, int length);
+
+// Returns the vector index to the maximum sample value of a 32-bit vector.
+//
+// Input:
+// - vector : 32-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Index to the maximum value in vector (if multiple
+// indexes have the maximum, return the first);
+// or -1, if (vector == NULL || length <= 0).
+int WebRtcSpl_MaxIndexW32(const int32_t* vector, int length);
+
+// Returns the vector index to the minimum sample value of a 16-bit vector.
+//
+// Input:
+// - vector : 16-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Index to the mimimum value in vector (if multiple
+// indexes have the minimum, return the first);
+// or -1, if (vector == NULL || length <= 0).
+int WebRtcSpl_MinIndexW16(const int16_t* vector, int length);
+
+// Returns the vector index to the minimum sample value of a 32-bit vector.
+//
+// Input:
+// - vector : 32-bit input vector.
+// - length : Number of samples in vector.
+//
+// Return value : Index to the mimimum value in vector (if multiple
+// indexes have the minimum, return the first);
+// or -1, if (vector == NULL || length <= 0).
+int WebRtcSpl_MinIndexW32(const int32_t* vector, int length);
+
+// End: Minimum and maximum operations.
+
+
+// Vector scaling operations. Implementation in vector_scaling_operations.c.
+// Description at bottom of file.
+void WebRtcSpl_VectorBitShiftW16(WebRtc_Word16* out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_VectorBitShiftW32(WebRtc_Word32* out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word32* in_vector,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_VectorBitShiftW32ToW16(WebRtc_Word16* out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word32* in_vector,
+ WebRtc_Word16 right_shifts);
+
+void WebRtcSpl_ScaleVector(G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_ScaleVectorWithSat(G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_ScaleAndAddVectors(G_CONST WebRtc_Word16* in_vector1,
+ WebRtc_Word16 gain1, int right_shifts1,
+ G_CONST WebRtc_Word16* in_vector2,
+ WebRtc_Word16 gain2, int right_shifts2,
+ WebRtc_Word16* out_vector,
+ int vector_length);
+
+// The functions (with related pointer) perform the vector operation:
+// out_vector[k] = ((scale1 * in_vector1[k]) + (scale2 * in_vector2[k])
+// + round_value) >> right_shifts,
+// where round_value = (1 << right_shifts) >> 1.
+//
+// Input:
+// - in_vector1 : Input vector 1
+// - in_vector1_scale : Gain to be used for vector 1
+// - in_vector2 : Input vector 2
+// - in_vector2_scale : Gain to be used for vector 2
+// - right_shifts : Number of right bit shifts to be applied
+// - length : Number of elements in the input vectors
+//
+// Output:
+// - out_vector : Output vector
+// Return value : 0 if OK, -1 if (in_vector1 == NULL
+// || in_vector2 == NULL || out_vector == NULL
+// || length <= 0 || right_shift < 0).
+typedef int (*ScaleAndAddVectorsWithRound)(const int16_t* in_vector1,
+ int16_t in_vector1_scale,
+ const int16_t* in_vector2,
+ int16_t in_vector2_scale,
+ int right_shifts,
+ int16_t* out_vector,
+ int length);
+extern ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound;
+int WebRtcSpl_ScaleAndAddVectorsWithRoundC(const int16_t* in_vector1,
+ int16_t in_vector1_scale,
+ const int16_t* in_vector2,
+ int16_t in_vector2_scale,
+ int right_shifts,
+ int16_t* out_vector,
+ int length);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int WebRtcSpl_ScaleAndAddVectorsWithRoundNeon(const int16_t* in_vector1,
+ int16_t in_vector1_scale,
+ const int16_t* in_vector2,
+ int16_t in_vector2_scale,
+ int right_shifts,
+ int16_t* out_vector,
+ int length);
+#endif
+// End: Vector scaling operations.
+
+// iLBC specific functions. Implementations in ilbc_specific_functions.c.
+// Description at bottom of file.
+void WebRtcSpl_ReverseOrderMultArrayElements(WebRtc_Word16* out_vector,
+ G_CONST WebRtc_Word16* in_vector,
+ G_CONST WebRtc_Word16* window,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_ElementwiseVectorMult(WebRtc_Word16* out_vector,
+ G_CONST WebRtc_Word16* in_vector,
+ G_CONST WebRtc_Word16* window,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_AddVectorsAndShift(WebRtc_Word16* out_vector,
+ G_CONST WebRtc_Word16* in_vector1,
+ G_CONST WebRtc_Word16* in_vector2,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_AddAffineVectorToVector(WebRtc_Word16* out_vector,
+ WebRtc_Word16* in_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts,
+ int vector_length);
+void WebRtcSpl_AffineTransformVector(WebRtc_Word16* out_vector,
+ WebRtc_Word16* in_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts,
+ int vector_length);
+// End: iLBC specific functions.
+
+// Signal processing operations.
+
+// A 32-bit fix-point implementation of auto-correlation computation
+//
+// Input:
+// - in_vector : Vector to calculate autocorrelation upon
+// - in_vector_length : Length (in samples) of |vector|
+// - order : The order up to which the autocorrelation should be
+// calculated
+//
+// Output:
+// - result : auto-correlation values (values should be seen
+// relative to each other since the absolute values
+// might have been down shifted to avoid overflow)
+//
+// - scale : The number of left shifts required to obtain the
+// auto-correlation in Q0
+//
+// Return value :
+// - -1, if |order| > |in_vector_length|;
+// - Number of samples in |result|, i.e. (order+1), otherwise.
+int WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
+ int in_vector_length,
+ int order,
+ int32_t* result,
+ int* scale);
+
+// A 32-bit fix-point implementation of the Levinson-Durbin algorithm that
+// does NOT use the 64 bit class
+//
+// Input:
+// - auto_corr : Vector with autocorrelation values of length >=
+// |use_order|+1
+// - use_order : The LPC filter order (support up to order 20)
+//
+// Output:
+// - lpc_coef : lpc_coef[0..use_order] LPC coefficients in Q12
+// - refl_coef : refl_coef[0...use_order-1]| Reflection coefficients in
+// Q15
+//
+// Return value : 1 for stable 0 for unstable
+WebRtc_Word16 WebRtcSpl_LevinsonDurbin(WebRtc_Word32* auto_corr,
+ WebRtc_Word16* lpc_coef,
+ WebRtc_Word16* refl_coef,
+ WebRtc_Word16 order);
+
+// Converts reflection coefficients |refl_coef| to LPC coefficients |lpc_coef|.
+// This version is a 16 bit operation.
+//
+// NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a
+// "slightly unstable" filter (i.e., a pole just outside the unit circle) in
+// "rare" cases even if the reflection coefficients are stable.
+//
+// Input:
+// - refl_coef : Reflection coefficients in Q15 that should be converted
+// to LPC coefficients
+// - use_order : Number of coefficients in |refl_coef|
+//
+// Output:
+// - lpc_coef : LPC coefficients in Q12
+void WebRtcSpl_ReflCoefToLpc(G_CONST WebRtc_Word16* refl_coef,
+ int use_order,
+ WebRtc_Word16* lpc_coef);
+
+// Converts LPC coefficients |lpc_coef| to reflection coefficients |refl_coef|.
+// This version is a 16 bit operation.
+// The conversion is implemented by the step-down algorithm.
+//
+// Input:
+// - lpc_coef : LPC coefficients in Q12, that should be converted to
+// reflection coefficients
+// - use_order : Number of coefficients in |lpc_coef|
+//
+// Output:
+// - refl_coef : Reflection coefficients in Q15.
+void WebRtcSpl_LpcToReflCoef(WebRtc_Word16* lpc_coef,
+ int use_order,
+ WebRtc_Word16* refl_coef);
+
+// Calculates reflection coefficients (16 bit) from auto-correlation values
+//
+// Input:
+// - auto_corr : Auto-correlation values
+// - use_order : Number of coefficients wanted be calculated
+//
+// Output:
+// - refl_coef : Reflection coefficients in Q15.
+void WebRtcSpl_AutoCorrToReflCoef(G_CONST WebRtc_Word32* auto_corr,
+ int use_order,
+ WebRtc_Word16* refl_coef);
+
+// The functions (with related pointer) calculate the cross-correlation between
+// two sequences |seq1| and |seq2|.
+// |seq1| is fixed and |seq2| slides as the pointer is increased with the
+// amount |step_seq2|. Note the arguments should obey the relationship:
+// |dim_seq| - 1 + |step_seq2| * (|dim_cross_correlation| - 1) <
+// buffer size of |seq2|
+//
+// Input:
+// - seq1 : First sequence (fixed throughout the correlation)
+// - seq2 : Second sequence (slides |step_vector2| for each
+// new correlation)
+// - dim_seq : Number of samples to use in the cross-correlation
+// - dim_cross_correlation : Number of cross-correlations to calculate (the
+// start position for |vector2| is updated for each
+// new one)
+// - right_shifts : Number of right bit shifts to use. This will
+// become the output Q-domain.
+// - step_seq2 : How many (positive or negative) steps the
+// |vector2| pointer should be updated for each new
+// cross-correlation value.
+//
+// Output:
+// - cross_correlation : The cross-correlation in Q(-right_shifts)
+typedef void (*CrossCorrelation)(int32_t* cross_correlation,
+ const int16_t* seq1,
+ const int16_t* seq2,
+ int16_t dim_seq,
+ int16_t dim_cross_correlation,
+ int16_t right_shifts,
+ int16_t step_seq2);
+extern CrossCorrelation WebRtcSpl_CrossCorrelation;
+void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation,
+ const int16_t* seq1,
+ const int16_t* seq2,
+ int16_t dim_seq,
+ int16_t dim_cross_correlation,
+ int16_t right_shifts,
+ int16_t step_seq2);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+void WebRtcSpl_CrossCorrelationNeon(int32_t* cross_correlation,
+ const int16_t* seq1,
+ const int16_t* seq2,
+ int16_t dim_seq,
+ int16_t dim_cross_correlation,
+ int16_t right_shifts,
+ int16_t step_seq2);
+#endif
+
+// Creates (the first half of) a Hanning window. Size must be at least 1 and
+// at most 512.
+//
+// Input:
+// - size : Length of the requested Hanning window (1 to 512)
+//
+// Output:
+// - window : Hanning vector in Q14.
+void WebRtcSpl_GetHanningWindow(WebRtc_Word16* window, WebRtc_Word16 size);
+
+// Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector
+// |in_vector|. Input and output values are in Q15.
+//
+// Inputs:
+// - in_vector : Values to calculate sqrt(1 - x^2) of
+// - vector_length : Length of vector |in_vector|
+//
+// Output:
+// - out_vector : Output values in Q15
+void WebRtcSpl_SqrtOfOneMinusXSquared(WebRtc_Word16* in_vector,
+ int vector_length,
+ WebRtc_Word16* out_vector);
+// End: Signal processing operations.
+
+// Randomization functions. Implementations collected in randomization_functions.c and
+// descriptions at bottom of this file.
+WebRtc_UWord32 WebRtcSpl_IncreaseSeed(WebRtc_UWord32* seed);
+WebRtc_Word16 WebRtcSpl_RandU(WebRtc_UWord32* seed);
+WebRtc_Word16 WebRtcSpl_RandN(WebRtc_UWord32* seed);
+WebRtc_Word16 WebRtcSpl_RandUArray(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length,
+ WebRtc_UWord32* seed);
+// End: Randomization functions.
+
+// Math functions
+WebRtc_Word32 WebRtcSpl_Sqrt(WebRtc_Word32 value);
+WebRtc_Word32 WebRtcSpl_SqrtFloor(WebRtc_Word32 value);
+
+// Divisions. Implementations collected in division_operations.c and
+// descriptions at bottom of this file.
+WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den);
+WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den);
+WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den);
+WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den);
+WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi,
+ WebRtc_Word16 den_low);
+// End: Divisions.
+
+WebRtc_Word32 WebRtcSpl_Energy(WebRtc_Word16* vector,
+ int vector_length,
+ int* scale_factor);
+
+// Calculates the dot product between two (WebRtc_Word16) vectors.
+//
+// Input:
+// - vector1 : Vector 1
+// - vector2 : Vector 2
+// - vector_length : Number of samples used in the dot product
+// - scaling : The number of right bit shifts to apply on each term
+// during calculation to avoid overflow, i.e., the
+// output will be in Q(-|scaling|)
+//
+// Return value : The dot product in Q(-scaling)
+int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
+ const int16_t* vector2,
+ int length,
+ int scaling);
+
+// Filter operations.
+int WebRtcSpl_FilterAR(G_CONST WebRtc_Word16* ar_coef, int ar_coef_length,
+ G_CONST WebRtc_Word16* in_vector, int in_vector_length,
+ WebRtc_Word16* filter_state, int filter_state_length,
+ WebRtc_Word16* filter_state_low,
+ int filter_state_low_length, WebRtc_Word16* out_vector,
+ WebRtc_Word16* out_vector_low, int out_vector_low_length);
+
+void WebRtcSpl_FilterMAFastQ12(WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16* ma_coef,
+ WebRtc_Word16 ma_coef_length,
+ WebRtc_Word16 vector_length);
+
+// Performs a AR filtering on a vector in Q12
+// Input:
+// - data_in : Input samples
+// - data_out : State information in positions
+// data_out[-order] .. data_out[-1]
+// - coefficients : Filter coefficients (in Q12)
+// - coefficients_length: Number of coefficients (order+1)
+// - data_length : Number of samples to be filtered
+// Output:
+// - data_out : Filtered samples
+void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
+ int16_t* data_out,
+ const int16_t* __restrict coefficients,
+ int coefficients_length,
+ int data_length);
+
+// The functions (with related pointer) perform a MA down sampling filter
+// on a vector.
+// Input:
+// - data_in : Input samples (state in positions
+// data_in[-order] .. data_in[-1])
+// - data_in_length : Number of samples in |data_in| to be filtered.
+// This must be at least
+// |delay| + |factor|*(|out_vector_length|-1) + 1)
+// - data_out_length : Number of down sampled samples desired
+// - coefficients : Filter coefficients (in Q12)
+// - coefficients_length: Number of coefficients (order+1)
+// - factor : Decimation factor
+// - delay : Delay of filter (compensated for in out_vector)
+// Output:
+// - data_out : Filtered samples
+// Return value : 0 if OK, -1 if |in_vector| is too short
+typedef int (*DownsampleFast)(const int16_t* data_in,
+ int data_in_length,
+ int16_t* data_out,
+ int data_out_length,
+ const int16_t* __restrict coefficients,
+ int coefficients_length,
+ int factor,
+ int delay);
+extern DownsampleFast WebRtcSpl_DownsampleFast;
+int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
+ int data_in_length,
+ int16_t* data_out,
+ int data_out_length,
+ const int16_t* __restrict coefficients,
+ int coefficients_length,
+ int factor,
+ int delay);
+#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
+int WebRtcSpl_DownsampleFastNeon(const int16_t* data_in,
+ int data_in_length,
+ int16_t* data_out,
+ int data_out_length,
+ const int16_t* __restrict coefficients,
+ int coefficients_length,
+ int factor,
+ int delay);
+#endif
+
+// End: Filter operations.
+
+// FFT operations
+
+int WebRtcSpl_ComplexFFT(WebRtc_Word16 vector[], int stages, int mode);
+int WebRtcSpl_ComplexIFFT(WebRtc_Word16 vector[], int stages, int mode);
+
+// Treat a 16-bit complex data buffer |complex_data| as an array of 32-bit
+// values, and swap elements whose indexes are bit-reverses of each other.
+//
+// Input:
+// - complex_data : Complex data buffer containing 2^|stages| real
+// elements interleaved with 2^|stages| imaginary
+// elements: [Re Im Re Im Re Im....]
+// - stages : Number of FFT stages. Must be at least 3 and at most
+// 10, since the table WebRtcSpl_kSinTable1024[] is 1024
+// elements long.
+//
+// Output:
+// - complex_data : The complex data buffer.
+
+void WebRtcSpl_ComplexBitReverse(int16_t* __restrict complex_data, int stages);
+
+// End: FFT operations
+
+/************************************************************
+ *
+ * RESAMPLING FUNCTIONS AND THEIR STRUCTS ARE DEFINED BELOW
+ *
+ ************************************************************/
+
+/*******************************************************************
+ * resample.c
+ *
+ * Includes the following resampling combinations
+ * 22 kHz -> 16 kHz
+ * 16 kHz -> 22 kHz
+ * 22 kHz -> 8 kHz
+ * 8 kHz -> 22 kHz
+ *
+ ******************************************************************/
+
+// state structure for 22 -> 16 resampler
+typedef struct
+{
+ WebRtc_Word32 S_22_44[8];
+ WebRtc_Word32 S_44_32[8];
+ WebRtc_Word32 S_32_16[8];
+} WebRtcSpl_State22khzTo16khz;
+
+void WebRtcSpl_Resample22khzTo16khz(const WebRtc_Word16* in,
+ WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo16khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample22khzTo16khz(WebRtcSpl_State22khzTo16khz* state);
+
+// state structure for 16 -> 22 resampler
+typedef struct
+{
+ WebRtc_Word32 S_16_32[8];
+ WebRtc_Word32 S_32_22[8];
+} WebRtcSpl_State16khzTo22khz;
+
+void WebRtcSpl_Resample16khzTo22khz(const WebRtc_Word16* in,
+ WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo22khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample16khzTo22khz(WebRtcSpl_State16khzTo22khz* state);
+
+// state structure for 22 -> 8 resampler
+typedef struct
+{
+ WebRtc_Word32 S_22_22[16];
+ WebRtc_Word32 S_22_16[8];
+ WebRtc_Word32 S_16_8[8];
+} WebRtcSpl_State22khzTo8khz;
+
+void WebRtcSpl_Resample22khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo8khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample22khzTo8khz(WebRtcSpl_State22khzTo8khz* state);
+
+// state structure for 8 -> 22 resampler
+typedef struct
+{
+ WebRtc_Word32 S_8_16[8];
+ WebRtc_Word32 S_16_11[8];
+ WebRtc_Word32 S_11_22[8];
+} WebRtcSpl_State8khzTo22khz;
+
+void WebRtcSpl_Resample8khzTo22khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo22khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample8khzTo22khz(WebRtcSpl_State8khzTo22khz* state);
+
+/*******************************************************************
+ * resample_fractional.c
+ * Functions for internal use in the other resample functions
+ *
+ * Includes the following resampling combinations
+ * 48 kHz -> 32 kHz
+ * 32 kHz -> 24 kHz
+ * 44 kHz -> 32 kHz
+ *
+ ******************************************************************/
+
+void WebRtcSpl_Resample48khzTo32khz(const WebRtc_Word32* In, WebRtc_Word32* Out,
+ const WebRtc_Word32 K);
+
+void WebRtcSpl_Resample32khzTo24khz(const WebRtc_Word32* In, WebRtc_Word32* Out,
+ const WebRtc_Word32 K);
+
+void WebRtcSpl_Resample44khzTo32khz(const WebRtc_Word32* In, WebRtc_Word32* Out,
+ const WebRtc_Word32 K);
+
+/*******************************************************************
+ * resample_48khz.c
+ *
+ * Includes the following resampling combinations
+ * 48 kHz -> 16 kHz
+ * 16 kHz -> 48 kHz
+ * 48 kHz -> 8 kHz
+ * 8 kHz -> 48 kHz
+ *
+ ******************************************************************/
+
+typedef struct
+{
+ WebRtc_Word32 S_48_48[16];
+ WebRtc_Word32 S_48_32[8];
+ WebRtc_Word32 S_32_16[8];
+} WebRtcSpl_State48khzTo16khz;
+
+void WebRtcSpl_Resample48khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo16khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state);
+
+typedef struct
+{
+ WebRtc_Word32 S_16_32[8];
+ WebRtc_Word32 S_32_24[8];
+ WebRtc_Word32 S_24_48[8];
+} WebRtcSpl_State16khzTo48khz;
+
+void WebRtcSpl_Resample16khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo48khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state);
+
+typedef struct
+{
+ WebRtc_Word32 S_48_24[8];
+ WebRtc_Word32 S_24_24[16];
+ WebRtc_Word32 S_24_16[8];
+ WebRtc_Word32 S_16_8[8];
+} WebRtcSpl_State48khzTo8khz;
+
+void WebRtcSpl_Resample48khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo8khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state);
+
+typedef struct
+{
+ WebRtc_Word32 S_8_16[8];
+ WebRtc_Word32 S_16_12[8];
+ WebRtc_Word32 S_12_24[8];
+ WebRtc_Word32 S_24_48[8];
+} WebRtcSpl_State8khzTo48khz;
+
+void WebRtcSpl_Resample8khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo48khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state);
+
+/*******************************************************************
+ * resample_by_2.c
+ *
+ * Includes down and up sampling by a factor of two.
+ *
+ ******************************************************************/
+
+void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len,
+ WebRtc_Word16* out, WebRtc_Word32* filtState);
+
+void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, WebRtc_Word16* out,
+ WebRtc_Word32* filtState);
+
+/************************************************************
+ * END OF RESAMPLING FUNCTIONS
+ ************************************************************/
+void WebRtcSpl_AnalysisQMF(const WebRtc_Word16* in_data,
+ WebRtc_Word16* low_band,
+ WebRtc_Word16* high_band,
+ WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2);
+void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band,
+ const WebRtc_Word16* high_band,
+ WebRtc_Word16* out_data,
+ WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif // WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
+
+//
+// WebRtcSpl_AddSatW16(...)
+// WebRtcSpl_AddSatW32(...)
+//
+// Returns the result of a saturated 16-bit, respectively 32-bit, addition of
+// the numbers specified by the |var1| and |var2| parameters.
+//
+// Input:
+// - var1 : Input variable 1
+// - var2 : Input variable 2
+//
+// Return value : Added and saturated value
+//
+
+//
+// WebRtcSpl_SubSatW16(...)
+// WebRtcSpl_SubSatW32(...)
+//
+// Returns the result of a saturated 16-bit, respectively 32-bit, subtraction
+// of the numbers specified by the |var1| and |var2| parameters.
+//
+// Input:
+// - var1 : Input variable 1
+// - var2 : Input variable 2
+//
+// Returned value : Subtracted and saturated value
+//
+
+//
+// WebRtcSpl_GetSizeInBits(...)
+//
+// Returns the # of bits that are needed at the most to represent the number
+// specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bits needed to represent |value|
+//
+
+//
+// WebRtcSpl_NormW32(...)
+//
+// Norm returns the # of left shifts required to 32-bit normalize the 32-bit
+// signed number specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bit shifts needed to 32-bit normalize |value|
+//
+
+//
+// WebRtcSpl_NormW16(...)
+//
+// Norm returns the # of left shifts required to 16-bit normalize the 16-bit
+// signed number specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bit shifts needed to 32-bit normalize |value|
+//
+
+//
+// WebRtcSpl_NormU32(...)
+//
+// Norm returns the # of left shifts required to 32-bit normalize the unsigned
+// 32-bit number specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bit shifts needed to 32-bit normalize |value|
+//
+
+//
+// WebRtcSpl_GetScalingSquare(...)
+//
+// Returns the # of bits required to scale the samples specified in the
+// |in_vector| parameter so that, if the squares of the samples are added the
+// # of times specified by the |times| parameter, the 32-bit addition will not
+// overflow (result in WebRtc_Word32).
+//
+// Input:
+// - in_vector : Input vector to check scaling on
+// - in_vector_length : Samples in |in_vector|
+// - times : Number of additions to be performed
+//
+// Return value : Number of right bit shifts needed to avoid
+// overflow in the addition calculation
+//
+
+//
+// WebRtcSpl_MemSetW16(...)
+//
+// Sets all the values in the WebRtc_Word16 vector |vector| of length
+// |vector_length| to the specified value |set_value|
+//
+// Input:
+// - vector : Pointer to the WebRtc_Word16 vector
+// - set_value : Value specified
+// - vector_length : Length of vector
+//
+
+//
+// WebRtcSpl_MemSetW32(...)
+//
+// Sets all the values in the WebRtc_Word32 vector |vector| of length
+// |vector_length| to the specified value |set_value|
+//
+// Input:
+// - vector : Pointer to the WebRtc_Word16 vector
+// - set_value : Value specified
+// - vector_length : Length of vector
+//
+
+//
+// WebRtcSpl_MemCpyReversedOrder(...)
+//
+// Copies all the values from the source WebRtc_Word16 vector |in_vector| to a
+// destination WebRtc_Word16 vector |out_vector|. It is done in reversed order,
+// meaning that the first sample of |in_vector| is copied to the last sample of
+// the |out_vector|. The procedure continues until the last sample of
+// |in_vector| has been copied to the first sample of |out_vector|. This
+// creates a reversed vector. Used in e.g. prediction in iLBC.
+//
+// Input:
+// - in_vector : Pointer to the first sample in a WebRtc_Word16 vector
+// of length |length|
+// - vector_length : Number of elements to copy
+//
+// Output:
+// - out_vector : Pointer to the last sample in a WebRtc_Word16 vector
+// of length |length|
+//
+
+//
+// WebRtcSpl_CopyFromEndW16(...)
+//
+// Copies the rightmost |samples| of |in_vector| (of length |in_vector_length|)
+// to the vector |out_vector|.
+//
+// Input:
+// - in_vector : Input vector
+// - in_vector_length : Number of samples in |in_vector|
+// - samples : Number of samples to extract (from right side)
+// from |in_vector|
+//
+// Output:
+// - out_vector : Vector with the requested samples
+//
+// Return value : Number of copied samples in |out_vector|
+//
+
+//
+// WebRtcSpl_ZerosArrayW16(...)
+// WebRtcSpl_ZerosArrayW32(...)
+//
+// Inserts the value "zero" in all positions of a w16 and a w32 vector
+// respectively.
+//
+// Input:
+// - vector_length : Number of samples in vector
+//
+// Output:
+// - vector : Vector containing all zeros
+//
+// Return value : Number of samples in vector
+//
+
+//
+// WebRtcSpl_OnesArrayW16(...)
+// WebRtcSpl_OnesArrayW32(...)
+//
+// Inserts the value "one" in all positions of a w16 and a w32 vector
+// respectively.
+//
+// Input:
+// - vector_length : Number of samples in vector
+//
+// Output:
+// - vector : Vector containing all ones
+//
+// Return value : Number of samples in vector
+//
+
+//
+// WebRtcSpl_VectorBitShiftW16(...)
+// WebRtcSpl_VectorBitShiftW32(...)
+//
+// Bit shifts all the values in a vector up or downwards. Different calls for
+// WebRtc_Word16 and WebRtc_Word32 vectors respectively.
+//
+// Input:
+// - vector_length : Length of vector
+// - in_vector : Pointer to the vector that should be bit shifted
+// - right_shifts : Number of right bit shifts (negative value gives left
+// shifts)
+//
+// Output:
+// - out_vector : Pointer to the result vector (can be the same as
+// |in_vector|)
+//
+
+//
+// WebRtcSpl_VectorBitShiftW32ToW16(...)
+//
+// Bit shifts all the values in a WebRtc_Word32 vector up or downwards and
+// stores the result as a WebRtc_Word16 vector
+//
+// Input:
+// - vector_length : Length of vector
+// - in_vector : Pointer to the vector that should be bit shifted
+// - right_shifts : Number of right bit shifts (negative value gives left
+// shifts)
+//
+// Output:
+// - out_vector : Pointer to the result vector (can be the same as
+// |in_vector|)
+//
+
+//
+// WebRtcSpl_ScaleVector(...)
+//
+// Performs the vector operation:
+// out_vector[k] = (gain*in_vector[k])>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Scaling gain
+// - vector_length : Elements in the |in_vector|
+// - right_shifts : Number of right bit shifts applied
+//
+// Output:
+// - out_vector : Output vector (can be the same as |in_vector|)
+//
+
+//
+// WebRtcSpl_ScaleVectorWithSat(...)
+//
+// Performs the vector operation:
+// out_vector[k] = SATURATE( (gain*in_vector[k])>>right_shifts )
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Scaling gain
+// - vector_length : Elements in the |in_vector|
+// - right_shifts : Number of right bit shifts applied
+//
+// Output:
+// - out_vector : Output vector (can be the same as |in_vector|)
+//
+
+//
+// WebRtcSpl_ScaleAndAddVectors(...)
+//
+// Performs the vector operation:
+// out_vector[k] = (gain1*in_vector1[k])>>right_shifts1
+// + (gain2*in_vector2[k])>>right_shifts2
+//
+// Input:
+// - in_vector1 : Input vector 1
+// - gain1 : Gain to be used for vector 1
+// - right_shifts1 : Right bit shift to be used for vector 1
+// - in_vector2 : Input vector 2
+// - gain2 : Gain to be used for vector 2
+// - right_shifts2 : Right bit shift to be used for vector 2
+// - vector_length : Elements in the input vectors
+//
+// Output:
+// - out_vector : Output vector
+//
+
+//
+// WebRtcSpl_ReverseOrderMultArrayElements(...)
+//
+// Performs the vector operation:
+// out_vector[n] = (in_vector[n]*window[-n])>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - window : Window vector (should be reversed). The pointer
+// should be set to the last value in the vector
+// - right_shifts : Number of right bit shift to be applied after the
+// multiplication
+// - vector_length : Number of elements in |in_vector|
+//
+// Output:
+// - out_vector : Output vector (can be same as |in_vector|)
+//
+
+//
+// WebRtcSpl_ElementwiseVectorMult(...)
+//
+// Performs the vector operation:
+// out_vector[n] = (in_vector[n]*window[n])>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - window : Window vector.
+// - right_shifts : Number of right bit shift to be applied after the
+// multiplication
+// - vector_length : Number of elements in |in_vector|
+//
+// Output:
+// - out_vector : Output vector (can be same as |in_vector|)
+//
+
+//
+// WebRtcSpl_AddVectorsAndShift(...)
+//
+// Performs the vector operation:
+// out_vector[k] = (in_vector1[k] + in_vector2[k])>>right_shifts
+//
+// Input:
+// - in_vector1 : Input vector 1
+// - in_vector2 : Input vector 2
+// - right_shifts : Number of right bit shift to be applied after the
+// multiplication
+// - vector_length : Number of elements in |in_vector1| and |in_vector2|
+//
+// Output:
+// - out_vector : Output vector (can be same as |in_vector1|)
+//
+
+//
+// WebRtcSpl_AddAffineVectorToVector(...)
+//
+// Adds an affine transformed vector to another vector |out_vector|, i.e,
+// performs
+// out_vector[k] += (in_vector[k]*gain+add_constant)>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Gain value, used to multiply the in vector with
+// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
+// but others can be used as well
+// - right_shifts : Number of right bit shifts (0-16)
+// - vector_length : Number of samples in |in_vector| and |out_vector|
+//
+// Output:
+// - out_vector : Vector with the output
+//
+
+//
+// WebRtcSpl_AffineTransformVector(...)
+//
+// Affine transforms a vector, i.e, performs
+// out_vector[k] = (in_vector[k]*gain+add_constant)>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Gain value, used to multiply the in vector with
+// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
+// but others can be used as well
+// - right_shifts : Number of right bit shifts (0-16)
+// - vector_length : Number of samples in |in_vector| and |out_vector|
+//
+// Output:
+// - out_vector : Vector with the output
+//
+
+//
+// WebRtcSpl_IncreaseSeed(...)
+//
+// Increases the seed (and returns the new value)
+//
+// Input:
+// - seed : Seed for random calculation
+//
+// Output:
+// - seed : Updated seed value
+//
+// Return value : The new seed value
+//
+
+//
+// WebRtcSpl_RandU(...)
+//
+// Produces a uniformly distributed value in the WebRtc_Word16 range
+//
+// Input:
+// - seed : Seed for random calculation
+//
+// Output:
+// - seed : Updated seed value
+//
+// Return value : Uniformly distributed value in the range
+// [Word16_MIN...Word16_MAX]
+//
+
+//
+// WebRtcSpl_RandN(...)
+//
+// Produces a normal distributed value in the WebRtc_Word16 range
+//
+// Input:
+// - seed : Seed for random calculation
+//
+// Output:
+// - seed : Updated seed value
+//
+// Return value : N(0,1) value in the Q13 domain
+//
+
+//
+// WebRtcSpl_RandUArray(...)
+//
+// Produces a uniformly distributed vector with elements in the WebRtc_Word16
+// range
+//
+// Input:
+// - vector_length : Samples wanted in the vector
+// - seed : Seed for random calculation
+//
+// Output:
+// - vector : Vector with the uniform values
+// - seed : Updated seed value
+//
+// Return value : Number of samples in vector, i.e., |vector_length|
+//
+
+//
+// WebRtcSpl_Sqrt(...)
+//
+// Returns the square root of the input value |value|. The precision of this
+// function is integer precision, i.e., sqrt(8) gives 2 as answer.
+// If |value| is a negative number then 0 is returned.
+//
+// Algorithm:
+//
+// A sixth order Taylor Series expansion is used here to compute the square
+// root of a number y^0.5 = (1+x)^0.5
+// where
+// x = y-1
+// = 1+(x/2)-0.5*((x/2)^2+0.5*((x/2)^3-0.625*((x/2)^4+0.875*((x/2)^5)
+// 0.5 <= x < 1
+//
+// Input:
+// - value : Value to calculate sqrt of
+//
+// Return value : Result of the sqrt calculation
+//
+
+//
+// WebRtcSpl_SqrtFloor(...)
+//
+// Returns the square root of the input value |value|. The precision of this
+// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
+// If |value| is a negative number then 0 is returned.
+//
+// Algorithm:
+//
+// An iterative 4 cylce/bit routine
+//
+// Input:
+// - value : Value to calculate sqrt of
+//
+// Return value : Result of the sqrt calculation
+//
+
+//
+// WebRtcSpl_DivU32U16(...)
+//
+// Divides a WebRtc_UWord32 |num| by a WebRtc_UWord16 |den|.
+//
+// If |den|==0, (WebRtc_UWord32)0xFFFFFFFF is returned.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division (as a WebRtc_UWord32), i.e., the
+// integer part of num/den.
+//
+
+//
+// WebRtcSpl_DivW32W16(...)
+//
+// Divides a WebRtc_Word32 |num| by a WebRtc_Word16 |den|.
+//
+// If |den|==0, (WebRtc_Word32)0x7FFFFFFF is returned.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division (as a WebRtc_Word32), i.e., the
+// integer part of num/den.
+//
+
+//
+// WebRtcSpl_DivW32W16ResW16(...)
+//
+// Divides a WebRtc_Word32 |num| by a WebRtc_Word16 |den|, assuming that the
+// result is less than 32768, otherwise an unpredictable result will occur.
+//
+// If |den|==0, (WebRtc_Word16)0x7FFF is returned.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division (as a WebRtc_Word16), i.e., the
+// integer part of num/den.
+//
+
+//
+// WebRtcSpl_DivResultInQ31(...)
+//
+// Divides a WebRtc_Word32 |num| by a WebRtc_Word16 |den|, assuming that the
+// absolute value of the denominator is larger than the numerator, otherwise
+// an unpredictable result will occur.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division in Q31.
+//
+
+//
+// WebRtcSpl_DivW32HiLow(...)
+//
+// Divides a WebRtc_Word32 |num| by a denominator in hi, low format. The
+// absolute value of the denominator has to be larger (or equal to) the
+// numerator.
+//
+// Input:
+// - num : Numerator
+// - den_hi : High part of denominator
+// - den_low : Low part of denominator
+//
+// Return value : Divided value in Q31
+//
+
+//
+// WebRtcSpl_Energy(...)
+//
+// Calculates the energy of a vector
+//
+// Input:
+// - vector : Vector which the energy should be calculated on
+// - vector_length : Number of samples in vector
+//
+// Output:
+// - scale_factor : Number of left bit shifts needed to get the physical
+// energy value, i.e, to get the Q0 value
+//
+// Return value : Energy value in Q(-|scale_factor|)
+//
+
+//
+// WebRtcSpl_FilterAR(...)
+//
+// Performs a 32-bit AR filtering on a vector in Q12
+//
+// Input:
+// - ar_coef : AR-coefficient vector (values in Q12),
+// ar_coef[0] must be 4096.
+// - ar_coef_length : Number of coefficients in |ar_coef|.
+// - in_vector : Vector to be filtered.
+// - in_vector_length : Number of samples in |in_vector|.
+// - filter_state : Current state (higher part) of the filter.
+// - filter_state_length : Length (in samples) of |filter_state|.
+// - filter_state_low : Current state (lower part) of the filter.
+// - filter_state_low_length : Length (in samples) of |filter_state_low|.
+// - out_vector_low_length : Maximum length (in samples) of
+// |out_vector_low|.
+//
+// Output:
+// - filter_state : Updated state (upper part) vector.
+// - filter_state_low : Updated state (lower part) vector.
+// - out_vector : Vector containing the upper part of the
+// filtered values.
+// - out_vector_low : Vector containing the lower part of the
+// filtered values.
+//
+// Return value : Number of samples in the |out_vector|.
+//
+
+//
+// WebRtcSpl_FilterMAFastQ12(...)
+//
+// Performs a MA filtering on a vector in Q12
+//
+// Input:
+// - in_vector : Input samples (state in positions
+// in_vector[-order] .. in_vector[-1])
+// - ma_coef : Filter coefficients (in Q12)
+// - ma_coef_length : Number of B coefficients (order+1)
+// - vector_length : Number of samples to be filtered
+//
+// Output:
+// - out_vector : Filtered samples
+//
+
+//
+// WebRtcSpl_ComplexIFFT(...)
+//
+// Complex Inverse FFT
+//
+// Computes an inverse complex 2^|stages|-point FFT on the input vector, which
+// is in bit-reversed order. The original content of the vector is destroyed in
+// the process, since the input is overwritten by the output, normal-ordered,
+// FFT vector. With X as the input complex vector, y as the output complex
+// vector and with M = 2^|stages|, the following is computed:
+//
+// M-1
+// y(k) = sum[X(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
+// i=0
+//
+// The implementations are optimized for speed, not for code size. It uses the
+// decimation-in-time algorithm with radix-2 butterfly technique.
+//
+// Input:
+// - vector : In pointer to complex vector containing 2^|stages|
+// real elements interleaved with 2^|stages| imaginary
+// elements.
+// [ReImReImReIm....]
+// The elements are in Q(-scale) domain, see more on Return
+// Value below.
+//
+// - stages : Number of FFT stages. Must be at least 3 and at most 10,
+// since the table WebRtcSpl_kSinTable1024[] is 1024
+// elements long.
+//
+// - mode : This parameter gives the user to choose how the FFT
+// should work.
+// mode==0: Low-complexity and Low-accuracy mode
+// mode==1: High-complexity and High-accuracy mode
+//
+// Output:
+// - vector : Out pointer to the FFT vector (the same as input).
+//
+// Return Value : The scale value that tells the number of left bit shifts
+// that the elements in the |vector| should be shifted with
+// in order to get Q0 values, i.e. the physically correct
+// values. The scale parameter is always 0 or positive,
+// except if N>1024 (|stages|>10), which returns a scale
+// value of -1, indicating error.
+//
+
+//
+// WebRtcSpl_ComplexFFT(...)
+//
+// Complex FFT
+//
+// Computes a complex 2^|stages|-point FFT on the input vector, which is in
+// bit-reversed order. The original content of the vector is destroyed in
+// the process, since the input is overwritten by the output, normal-ordered,
+// FFT vector. With x as the input complex vector, Y as the output complex
+// vector and with M = 2^|stages|, the following is computed:
+//
+// M-1
+// Y(k) = 1/M * sum[x(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
+// i=0
+//
+// The implementations are optimized for speed, not for code size. It uses the
+// decimation-in-time algorithm with radix-2 butterfly technique.
+//
+// This routine prevents overflow by scaling by 2 before each FFT stage. This is
+// a fixed scaling, for proper normalization - there will be log2(n) passes, so
+// this results in an overall factor of 1/n, distributed to maximize arithmetic
+// accuracy.
+//
+// Input:
+// - vector : In pointer to complex vector containing 2^|stages| real
+// elements interleaved with 2^|stages| imaginary elements.
+// [ReImReImReIm....]
+// The output is in the Q0 domain.
+//
+// - stages : Number of FFT stages. Must be at least 3 and at most 10,
+// since the table WebRtcSpl_kSinTable1024[] is 1024
+// elements long.
+//
+// - mode : This parameter gives the user to choose how the FFT
+// should work.
+// mode==0: Low-complexity and Low-accuracy mode
+// mode==1: High-complexity and High-accuracy mode
+//
+// Output:
+// - vector : The output FFT vector is in the Q0 domain.
+//
+// Return value : The scale parameter is always 0, except if N>1024,
+// which returns a scale value of -1, indicating error.
+//
+
+//
+// WebRtcSpl_AnalysisQMF(...)
+//
+// Splits a 0-2*F Hz signal into two sub bands: 0-F Hz and F-2*F Hz. The
+// current version has F = 8000, therefore, a super-wideband audio signal is
+// split to lower-band 0-8 kHz and upper-band 8-16 kHz.
+//
+// Input:
+// - in_data : Wide band speech signal, 320 samples (10 ms)
+//
+// Input & Output:
+// - filter_state1 : Filter state for first All-pass filter
+// - filter_state2 : Filter state for second All-pass filter
+//
+// Output:
+// - low_band : Lower-band signal 0-8 kHz band, 160 samples (10 ms)
+// - high_band : Upper-band signal 8-16 kHz band (flipped in frequency
+// domain), 160 samples (10 ms)
+//
+
+//
+// WebRtcSpl_SynthesisQMF(...)
+//
+// Combines the two sub bands (0-F and F-2*F Hz) into a signal of 0-2*F
+// Hz, (current version has F = 8000 Hz). So the filter combines lower-band
+// (0-8 kHz) and upper-band (8-16 kHz) channels to obtain super-wideband 0-16
+// kHz audio.
+//
+// Input:
+// - low_band : The signal with the 0-8 kHz band, 160 samples (10 ms)
+// - high_band : The signal with the 8-16 kHz band, 160 samples (10 ms)
+//
+// Input & Output:
+// - filter_state1 : Filter state for first All-pass filter
+// - filter_state2 : Filter state for second All-pass filter
+//
+// Output:
+// - out_data : Super-wideband speech signal, 0-16 kHz
+//
+
+// WebRtc_Word16 WebRtcSpl_SatW32ToW16(...)
+//
+// This function saturates a 32-bit word into a 16-bit word.
+//
+// Input:
+// - value32 : The value of a 32-bit word.
+//
+// Output:
+// - out16 : the saturated 16-bit word.
+//
+
+// int32_t WebRtc_MulAccumW16(...)
+//
+// This function multiply a 16-bit word by a 16-bit word, and accumulate this
+// value to a 32-bit integer.
+//
+// Input:
+// - a : The value of the first 16-bit word.
+// - b : The value of the second 16-bit word.
+// - c : The value of an 32-bit integer.
+//
+// Return Value: The value of a * b + c.
+//
+
+// WebRtc_Word16 WebRtcSpl_get_version(...)
+//
+// This function gives the version string of the Signal Processing Library.
+//
+// Input:
+// - length_in_bytes : The size of Allocated space (in Bytes) where
+// the version number is written to (in string format).
+//
+// Output:
+// - version : Pointer to a buffer where the version number is written to.
+//
diff --git a/common_audio/signal_processing/include/spl_inl.h b/common_audio/signal_processing/include/spl_inl.h
new file mode 100644
index 0000000..1cde181
--- /dev/null
+++ b/common_audio/signal_processing/include/spl_inl.h
@@ -0,0 +1,163 @@
+/*
+ * 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 header file includes the inline functions in
+// the fix point signal processing library.
+
+#ifndef WEBRTC_SPL_SPL_INL_H_
+#define WEBRTC_SPL_SPL_INL_H_
+
+#ifdef WEBRTC_ARCH_ARM_V7
+#include "spl_inl_armv7.h"
+#else
+
+static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) {
+ WebRtc_Word16 out16 = (WebRtc_Word16) value32;
+
+ if (value32 > 32767)
+ out16 = 32767;
+ else if (value32 < -32768)
+ out16 = -32768;
+
+ return out16;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a,
+ WebRtc_Word16 b) {
+ return WebRtcSpl_SatW32ToW16((WebRtc_Word32) a + (WebRtc_Word32) b);
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1,
+ WebRtc_Word16 var2) {
+ return WebRtcSpl_SatW32ToW16((WebRtc_Word32) var1 - (WebRtc_Word32) var2);
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
+ int bits;
+
+ if (0xFFFF0000 & n) {
+ bits = 16;
+ } else {
+ bits = 0;
+ }
+ if (0x0000FF00 & (n >> bits)) bits += 8;
+ if (0x000000F0 & (n >> bits)) bits += 4;
+ if (0x0000000C & (n >> bits)) bits += 2;
+ if (0x00000002 & (n >> bits)) bits += 1;
+ if (0x00000001 & (n >> bits)) bits += 1;
+
+ return bits;
+}
+
+static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
+ int zeros;
+
+ if (a <= 0) a ^= 0xFFFFFFFF;
+
+ if (!(0xFFFF8000 & a)) {
+ zeros = 16;
+ } else {
+ zeros = 0;
+ }
+ if (!(0xFF800000 & (a << zeros))) zeros += 8;
+ if (!(0xF8000000 & (a << zeros))) zeros += 4;
+ if (!(0xE0000000 & (a << zeros))) zeros += 2;
+ if (!(0xC0000000 & (a << zeros))) zeros += 1;
+
+ return zeros;
+}
+
+static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
+ int zeros;
+
+ if (a == 0) return 0;
+
+ if (!(0xFFFF0000 & a)) {
+ zeros = 16;
+ } else {
+ zeros = 0;
+ }
+ if (!(0xFF000000 & (a << zeros))) zeros += 8;
+ if (!(0xF0000000 & (a << zeros))) zeros += 4;
+ if (!(0xC0000000 & (a << zeros))) zeros += 2;
+ if (!(0x80000000 & (a << zeros))) zeros += 1;
+
+ return zeros;
+}
+
+static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
+ int zeros;
+
+ if (a <= 0) a ^= 0xFFFF;
+
+ if (!(0xFF80 & a)) {
+ zeros = 8;
+ } else {
+ zeros = 0;
+ }
+ if (!(0xF800 & (a << zeros))) zeros += 4;
+ if (!(0xE000 & (a << zeros))) zeros += 2;
+ if (!(0xC000 & (a << zeros))) zeros += 1;
+
+ return zeros;
+}
+
+static __inline int32_t WebRtc_MulAccumW16(int16_t a,
+ int16_t b,
+ int32_t c) {
+ return (a * b + c);
+}
+
+#endif // WEBRTC_ARCH_ARM_V7
+
+// The following functions have no optimized versions.
+// TODO(kma): Consider saturating add/sub instructions in X86 platform.
+static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_sum;
+
+ // Perform long addition
+ l_sum = l_var1 + l_var2;
+
+ if (l_var1 < 0) { // Check for underflow.
+ if ((l_var2 < 0) && (l_sum >= 0)) {
+ l_sum = (WebRtc_Word32)0x80000000;
+ }
+ } else { // Check for overflow.
+ if ((l_var2 > 0) && (l_sum < 0)) {
+ l_sum = (WebRtc_Word32)0x7FFFFFFF;
+ }
+ }
+
+ return l_sum;
+}
+
+static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_diff;
+
+ // Perform subtraction.
+ l_diff = l_var1 - l_var2;
+
+ if (l_var1 < 0) { // Check for underflow.
+ if ((l_var2 > 0) && (l_diff > 0)) {
+ l_diff = (WebRtc_Word32)0x80000000;
+ }
+ } else { // Check for overflow.
+ if ((l_var2 < 0) && (l_diff < 0)) {
+ l_diff = (WebRtc_Word32)0x7FFFFFFF;
+ }
+ }
+
+ return l_diff;
+}
+
+#endif // WEBRTC_SPL_SPL_INL_H_
diff --git a/common_audio/signal_processing/include/spl_inl_armv7.h b/common_audio/signal_processing/include/spl_inl_armv7.h
new file mode 100644
index 0000000..8461474
--- /dev/null
+++ b/common_audio/signal_processing/include/spl_inl_armv7.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2012 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 header file includes the inline functions for ARM processors in
+ * the fix point signal processing library.
+ */
+
+#ifndef WEBRTC_SPL_SPL_INL_ARMV7_H_
+#define WEBRTC_SPL_SPL_INL_ARMV7_H_
+
+/* TODO(kma): Replace some assembly code with GCC intrinsics
+ * (e.g. __builtin_clz).
+ */
+
+/* This function produces result that is not bit exact with that by the generic
+ * C version in some cases, although the former is at least as accurate as the
+ * later.
+ */
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_32_RSFT16(WebRtc_Word16 a,
+ WebRtc_Word32 b) {
+ WebRtc_Word32 tmp = 0;
+ __asm __volatile ("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a));
+ return tmp;
+}
+
+/* This function produces result that is not bit exact with that by the generic
+ * C version in some cases, although the former is at least as accurate as the
+ * later.
+ */
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32(WebRtc_Word16 a,
+ WebRtc_Word16 b,
+ WebRtc_Word32 c) {
+ WebRtc_Word32 tmp = 0;
+ __asm __volatile (
+ "pkhbt %[tmp], %[b], %[a], lsl #16\n\t"
+ "smmulr %[tmp], %[tmp], %[c]\n\t"
+ :[tmp]"+r"(tmp)
+ :[a]"r"(a),
+ [b]"r"(b),
+ [c]"r"(c)
+ );
+ return tmp;
+}
+
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32BI(WebRtc_Word32 a,
+ WebRtc_Word32 b) {
+ WebRtc_Word32 tmp = 0;
+ __asm volatile ("smmulr %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
+ return tmp;
+}
+
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_16(WebRtc_Word16 a,
+ WebRtc_Word16 b) {
+ WebRtc_Word32 tmp = 0;
+ __asm __volatile ("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
+ return tmp;
+}
+
+// TODO(kma): add unit test.
+static __inline int32_t WebRtc_MulAccumW16(int16_t a,
+ int16_t b,
+ int32_t c) {
+ int32_t tmp = 0;
+ __asm __volatile ("smlabb %0, %1, %2, %3":"=r"(tmp):"r"(a), "r"(b), "r"(c));
+ return tmp;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a,
+ WebRtc_Word16 b) {
+ WebRtc_Word32 s_sum = 0;
+
+ __asm __volatile ("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b));
+
+ return (WebRtc_Word16) s_sum;
+}
+
+/* TODO(kma): find the cause of unittest errors by the next two functions:
+ * http://code.google.com/p/webrtc/issues/detail?id=740.
+ */
+#if 0
+static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_sum = 0;
+
+ __asm __volatile ("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2));
+
+ return l_sum;
+}
+
+static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_sub = 0;
+
+ __asm __volatile ("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2));
+
+ return l_sub;
+}
+#endif
+
+static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1,
+ WebRtc_Word16 var2) {
+ WebRtc_Word32 s_sub = 0;
+
+ __asm __volatile ("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2));
+
+ return (WebRtc_Word16)s_sub;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
+ WebRtc_Word32 tmp = 0;
+
+ __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(n));
+
+ return (WebRtc_Word16)(32 - tmp);
+}
+
+static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
+ WebRtc_Word32 tmp = 0;
+
+ if (a == 0) {
+ return 0;
+ }
+ else if (a < 0) {
+ a ^= 0xFFFFFFFF;
+ }
+
+ __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
+
+ return tmp - 1;
+}
+
+static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
+ int tmp = 0;
+
+ if (a == 0) return 0;
+
+ __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
+
+ return tmp;
+}
+
+static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
+ WebRtc_Word32 tmp = 0;
+
+ if (a == 0) {
+ return 0;
+ }
+ else if (a < 0) {
+ a ^= 0xFFFFFFFF;
+ }
+
+ __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
+
+ return tmp - 17;
+}
+
+// TODO(kma): add unit test.
+static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) {
+ WebRtc_Word16 out16 = 0;
+
+ __asm __volatile ("ssat %r0, #16, %r1" : "=r"(out16) : "r"(value32));
+
+ return out16;
+}
+
+#endif // WEBRTC_SPL_SPL_INL_ARMV7_H_
diff --git a/common_audio/signal_processing/levinson_durbin.c b/common_audio/signal_processing/levinson_durbin.c
new file mode 100644
index 0000000..4e11cdb
--- /dev/null
+++ b/common_audio/signal_processing/levinson_durbin.c
@@ -0,0 +1,259 @@
+/*
+ * 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 function WebRtcSpl_LevinsonDurbin().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#define SPL_LEVINSON_MAXORDER 20
+
+WebRtc_Word16 WebRtcSpl_LevinsonDurbin(WebRtc_Word32 *R, WebRtc_Word16 *A, WebRtc_Word16 *K,
+ WebRtc_Word16 order)
+{
+ WebRtc_Word16 i, j;
+ // Auto-correlation coefficients in high precision
+ WebRtc_Word16 R_hi[SPL_LEVINSON_MAXORDER + 1], R_low[SPL_LEVINSON_MAXORDER + 1];
+ // LPC coefficients in high precision
+ WebRtc_Word16 A_hi[SPL_LEVINSON_MAXORDER + 1], A_low[SPL_LEVINSON_MAXORDER + 1];
+ // LPC coefficients for next iteration
+ WebRtc_Word16 A_upd_hi[SPL_LEVINSON_MAXORDER + 1], A_upd_low[SPL_LEVINSON_MAXORDER + 1];
+ // Reflection coefficient in high precision
+ WebRtc_Word16 K_hi, K_low;
+ // Prediction gain Alpha in high precision and with scale factor
+ WebRtc_Word16 Alpha_hi, Alpha_low, Alpha_exp;
+ WebRtc_Word16 tmp_hi, tmp_low;
+ WebRtc_Word32 temp1W32, temp2W32, temp3W32;
+ WebRtc_Word16 norm;
+
+ // Normalize the autocorrelation R[0]...R[order+1]
+
+ norm = WebRtcSpl_NormW32(R[0]);
+
+ for (i = order; i >= 0; i--)
+ {
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm);
+ // Put R in hi and low format
+ R_hi[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ R_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)), 1);
+ }
+
+ // K = A[1] = -R[1] / R[0]
+
+ temp2W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[1],16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[1],1); // R[1] in Q31
+ temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); // abs R[1]
+ temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); // abs(R[1])/R[0] in Q31
+ // Put back the sign on R[1]
+ if (temp2W32 > 0)
+ {
+ temp1W32 = -temp1W32;
+ }
+
+ // Put K in hi and low format
+ K_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1);
+
+ // Store first reflection coefficient
+ K[0] = K_hi;
+
+ temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4); // A[1] in Q27
+
+ // Put A[1] in hi and low format
+ A_hi[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ A_low[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[1], 16)), 1);
+
+ // Alpha = R[0] * (1-K^2)
+
+ temp1W32 = (((WEBRTC_SPL_MUL_16_16(K_hi, K_low) >> 14) + WEBRTC_SPL_MUL_16_16(K_hi, K_hi))
+ << 1); // temp1W32 = k^2 in Q31
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
+ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; // temp1W32 = (1 - K[0]*K[0]) in Q31
+
+ // Store temp1W32 = 1 - K[0]*K[0] on hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // Calculate Alpha in Q31
+ temp1W32 = ((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi)
+ + (WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi) >> 15)) << 1);
+
+ // Normalize Alpha and put it in hi and low format
+
+ Alpha_exp = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp);
+ Alpha_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1);
+
+ // Perform the iterative calculations in the Levinson-Durbin algorithm
+
+ for (i = 2; i <= order; i++)
+ {
+ /* ----
+ temp1W32 = R[i] + > R[j]*A[i-j]
+ /
+ ----
+ j=1..i-1
+ */
+
+ temp1W32 = 0;
+
+ for (j = 1; j < i; j++)
+ {
+ // temp1W32 is in Q31
+ temp1W32 += ((WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]) << 1)
+ + (((WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]) >> 15)) << 1));
+ }
+
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4);
+ temp1W32 += (WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[i], 1));
+
+ // K = -temp1W32 / Alpha
+ temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); // abs(temp1W32)
+ temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); // abs(temp1W32)/Alpha
+
+ // Put the sign of temp1W32 back again
+ if (temp1W32 > 0)
+ {
+ temp3W32 = -temp3W32;
+ }
+
+ // Use the Alpha shifts from earlier to de-normalize
+ norm = WebRtcSpl_NormW32(temp3W32);
+ if ((Alpha_exp <= norm) || (temp3W32 == 0))
+ {
+ temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp);
+ } else
+ {
+ if (temp3W32 > 0)
+ {
+ temp3W32 = (WebRtc_Word32)0x7fffffffL;
+ } else
+ {
+ temp3W32 = (WebRtc_Word32)0x80000000L;
+ }
+ }
+
+ // Put K on hi and low format
+ K_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
+ K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1);
+
+ // Store Reflection coefficient in Q15
+ K[i - 1] = K_hi;
+
+ // Test for unstable filter.
+ // If unstable return 0 and let the user decide what to do in that case
+
+ if ((WebRtc_Word32)WEBRTC_SPL_ABS_W16(K_hi) > (WebRtc_Word32)32750)
+ {
+ return 0; // Unstable filter
+ }
+
+ /*
+ Compute updated LPC coefficient: Anew[i]
+ Anew[j]= A[j] + K*A[i-j] for j=1..i-1
+ Anew[i]= K
+ */
+
+ for (j = 1; j < i; j++)
+ {
+ // temp1W32 = A[j] in Q27
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[j],16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[j],1);
+
+ // temp1W32 += K*A[i-j] in Q27
+ temp1W32 += ((WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j])
+ + (WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]) >> 15)) << 1);
+
+ // Put Anew in hi and low format
+ A_upd_hi[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ A_upd_low[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[j], 16)), 1);
+ }
+
+ // temp3W32 = K in Q27 (Convert from Q31 to Q27)
+ temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4);
+
+ // Store Anew in hi and low format
+ A_upd_hi[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
+ A_upd_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[i], 16)), 1);
+
+ // Alpha = Alpha * (1-K^2)
+
+ temp1W32 = (((WEBRTC_SPL_MUL_16_16(K_hi, K_low) >> 14)
+ + WEBRTC_SPL_MUL_16_16(K_hi, K_hi)) << 1); // K*K in Q31
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
+ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; // 1 - K*K in Q31
+
+ // Convert 1- K^2 in hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // Calculate Alpha = Alpha * (1-K^2) in Q31
+ temp1W32 = ((WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi)
+ + (WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi) >> 15)) << 1);
+
+ // Normalize Alpha and store it on hi and low format
+
+ norm = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm);
+
+ Alpha_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1);
+
+ // Update the total normalization of Alpha
+ Alpha_exp = Alpha_exp + norm;
+
+ // Update A[]
+
+ for (j = 1; j <= i; j++)
+ {
+ A_hi[j] = A_upd_hi[j];
+ A_low[j] = A_upd_low[j];
+ }
+ }
+
+ /*
+ Set A[0] to 1.0 and store the A[i] i=1...order in Q12
+ (Convert from Q27 and use rounding)
+ */
+
+ A[0] = 4096;
+
+ for (i = 1; i <= order; i++)
+ {
+ // temp1W32 in Q27
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[i], 16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[i], 1);
+ // Round and store upper word
+ A[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32<<1)+(WebRtc_Word32)32768, 16);
+ }
+ return 1; // Stable filters
+}
diff --git a/common_audio/signal_processing/lpc_to_refl_coef.c b/common_audio/signal_processing/lpc_to_refl_coef.c
new file mode 100644
index 0000000..2cb83c2
--- /dev/null
+++ b/common_audio/signal_processing/lpc_to_refl_coef.c
@@ -0,0 +1,57 @@
+/*
+ * 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 function WebRtcSpl_LpcToReflCoef().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#define SPL_LPC_TO_REFL_COEF_MAX_AR_MODEL_ORDER 50
+
+void WebRtcSpl_LpcToReflCoef(WebRtc_Word16* a16, int use_order, WebRtc_Word16* k16)
+{
+ int m, k;
+ WebRtc_Word32 tmp32[SPL_LPC_TO_REFL_COEF_MAX_AR_MODEL_ORDER];
+ WebRtc_Word32 tmp_inv_denom32;
+ WebRtc_Word16 tmp_inv_denom16;
+
+ k16[use_order - 1] = WEBRTC_SPL_LSHIFT_W16(a16[use_order], 3); //Q12<<3 => Q15
+ for (m = use_order - 1; m > 0; m--)
+ {
+ // (1 - k^2) in Q30
+ tmp_inv_denom32 = ((WebRtc_Word32)1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]);
+ // (1 - k^2) in Q15
+ tmp_inv_denom16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp_inv_denom32, 15);
+
+ for (k = 1; k <= m; k++)
+ {
+ // tmp[k] = (a[k] - RC[m] * a[m-k+1]) / (1.0 - RC[m]*RC[m]);
+
+ // [Q12<<16 - (Q15*Q12)<<1] = [Q28 - Q28] = Q28
+ tmp32[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)a16[k], 16)
+ - WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(k16[m], a16[m-k+1]), 1);
+
+ tmp32[k] = WebRtcSpl_DivW32W16(tmp32[k], tmp_inv_denom16); //Q28/Q15 = Q13
+ }
+
+ for (k = 1; k < m; k++)
+ {
+ a16[k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32[k], 1); //Q13>>1 => Q12
+ }
+
+ tmp32[m] = WEBRTC_SPL_SAT(8191, tmp32[m], -8191);
+ k16[m - 1] = (WebRtc_Word16)WEBRTC_SPL_LSHIFT_W32(tmp32[m], 2); //Q13<<2 => Q15
+ }
+ return;
+}
diff --git a/common_audio/signal_processing/min_max_operations.c b/common_audio/signal_processing/min_max_operations.c
new file mode 100644
index 0000000..63a8a99
--- /dev/null
+++ b/common_audio/signal_processing/min_max_operations.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2012 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 implementation of functions
+ * WebRtcSpl_MaxAbsValueW16C()
+ * WebRtcSpl_MaxAbsValueW32C()
+ * WebRtcSpl_MaxValueW16C()
+ * WebRtcSpl_MaxValueW32C()
+ * WebRtcSpl_MinValueW16C()
+ * WebRtcSpl_MinValueW32C()
+ * WebRtcSpl_MaxAbsIndexW16()
+ * WebRtcSpl_MaxIndexW16()
+ * WebRtcSpl_MaxIndexW32()
+ * WebRtcSpl_MinIndexW16()
+ * WebRtcSpl_MinIndexW32()
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#include <stdlib.h>
+
+// TODO(bjorn/kma): Consolidate function pairs (e.g. combine
+// WebRtcSpl_MaxAbsValueW16C and WebRtcSpl_MaxAbsIndexW16 into a single one.)
+// TODO(kma): Move the next six functions into min_max_operations_c.c.
+
+// Maximum absolute value of word16 vector. C version for generic platforms.
+int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, int length) {
+ int i = 0, absolute = 0, maximum = 0;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ absolute = abs((int)vector[i]);
+
+ if (absolute > maximum) {
+ maximum = absolute;
+ }
+ }
+
+ // Guard the case for abs(-32768).
+ if (maximum > WEBRTC_SPL_WORD16_MAX) {
+ maximum = WEBRTC_SPL_WORD16_MAX;
+ }
+
+ return (int16_t)maximum;
+}
+
+// Maximum absolute value of word32 vector. C version for generic platforms.
+int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, int length) {
+ // Use uint32_t for the local variables, to accommodate the return value
+ // of abs(0x80000000), which is 0x80000000.
+
+ uint32_t absolute = 0, maximum = 0;
+ int i = 0;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ absolute = abs((int)vector[i]);
+ if (absolute > maximum) {
+ maximum = absolute;
+ }
+ }
+
+ maximum = WEBRTC_SPL_MIN(maximum, WEBRTC_SPL_WORD32_MAX);
+
+ return (int32_t)maximum;
+}
+
+// Maximum value of word16 vector. C version for generic platforms.
+int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, int length) {
+ int16_t maximum = WEBRTC_SPL_WORD16_MIN;
+ int i = 0;
+
+ if (vector == NULL || length <= 0) {
+ return maximum;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] > maximum)
+ maximum = vector[i];
+ }
+ return maximum;
+}
+
+// Maximum value of word32 vector. C version for generic platforms.
+int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, int length) {
+ int32_t maximum = WEBRTC_SPL_WORD32_MIN;
+ int i = 0;
+
+ if (vector == NULL || length <= 0) {
+ return maximum;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] > maximum)
+ maximum = vector[i];
+ }
+ return maximum;
+}
+
+// Minimum value of word16 vector. C version for generic platforms.
+int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, int length) {
+ int16_t minimum = WEBRTC_SPL_WORD16_MAX;
+ int i = 0;
+
+ if (vector == NULL || length <= 0) {
+ return minimum;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] < minimum)
+ minimum = vector[i];
+ }
+ return minimum;
+}
+
+// Minimum value of word32 vector. C version for generic platforms.
+int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, int length) {
+ int32_t minimum = WEBRTC_SPL_WORD32_MAX;
+ int i = 0;
+
+ if (vector == NULL || length <= 0) {
+ return minimum;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] < minimum)
+ minimum = vector[i];
+ }
+ return minimum;
+}
+
+// Index of maximum absolute value in a word16 vector.
+int WebRtcSpl_MaxAbsIndexW16(const int16_t* vector, int length) {
+ // Use type int for local variables, to accomodate the value of abs(-32768).
+
+ int i = 0, absolute = 0, maximum = 0, index = 0;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ absolute = abs((int)vector[i]);
+
+ if (absolute > maximum) {
+ maximum = absolute;
+ index = i;
+ }
+ }
+
+ return index;
+}
+
+// Index of maximum value in a word16 vector.
+int WebRtcSpl_MaxIndexW16(const int16_t* vector, int length) {
+ int i = 0, index = 0;
+ int16_t maximum = WEBRTC_SPL_WORD16_MIN;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] > maximum) {
+ maximum = vector[i];
+ index = i;
+ }
+ }
+
+ return index;
+}
+
+// Index of maximum value in a word32 vector.
+int WebRtcSpl_MaxIndexW32(const int32_t* vector, int length) {
+ int i = 0, index = 0;
+ int32_t maximum = WEBRTC_SPL_WORD32_MIN;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] > maximum) {
+ maximum = vector[i];
+ index = i;
+ }
+ }
+
+ return index;
+}
+
+// Index of minimum value in a word16 vector.
+int WebRtcSpl_MinIndexW16(const int16_t* vector, int length) {
+ int i = 0, index = 0;
+ int16_t minimum = WEBRTC_SPL_WORD16_MAX;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] < minimum) {
+ minimum = vector[i];
+ index = i;
+ }
+ }
+
+ return index;
+}
+
+// Index of minimum value in a word32 vector.
+int WebRtcSpl_MinIndexW32(const int32_t* vector, int length) {
+ int i = 0, index = 0;
+ int32_t minimum = WEBRTC_SPL_WORD32_MAX;
+
+ if (vector == NULL || length <= 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (vector[i] < minimum) {
+ minimum = vector[i];
+ index = i;
+ }
+ }
+
+ return index;
+}
diff --git a/common_audio/signal_processing/min_max_operations_neon.s b/common_audio/signal_processing/min_max_operations_neon.s
new file mode 100644
index 0000000..85dd2fb
--- /dev/null
+++ b/common_audio/signal_processing/min_max_operations_neon.s
@@ -0,0 +1,305 @@
+@
+@ Copyright (c) 2012 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 some minimum and maximum functions, optimized for
+@ ARM Neon platform. The description header can be found in
+@ signal_processing_library.h
+@
+@ The reference C code is in file min_max_operations.c. Code here is basically
+@ a loop unrolling by 8 with Neon instructions. Bit-exact.
+
+.arch armv7-a
+.fpu neon
+.global WebRtcSpl_MaxAbsValueW16Neon
+.global WebRtcSpl_MaxAbsValueW32Neon
+.global WebRtcSpl_MaxValueW16Neon
+.global WebRtcSpl_MaxValueW32Neon
+.global WebRtcSpl_MinValueW16Neon
+.global WebRtcSpl_MinValueW32Neon
+.align 2
+
+@ int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, int length);
+WebRtcSpl_MaxAbsValueW16Neon:
+.fnstart
+
+ mov r2, #-1 @ Initialize the return value.
+ cmp r0, #0
+ beq END_MAX_ABS_VALUE_W16
+ cmp r1, #0
+ ble END_MAX_ABS_VALUE_W16
+
+ cmp r1, #8
+ blt LOOP_MAX_ABS_VALUE_W16
+
+ vmov.i16 q12, #0
+ sub r1, #8 @ Counter for loops
+
+LOOP_UNROLLED_BY_8_MAX_ABS_VALUE_W16:
+ vld1.16 {q13}, [r0]!
+ subs r1, #8
+ vabs.s16 q13, q13 @ Note vabs doesn't change the value of -32768.
+ vmax.u16 q12, q13 @ Use u16 so we don't lose the value -32768.
+ bge LOOP_UNROLLED_BY_8_MAX_ABS_VALUE_W16
+
+ @ Find the maximum value in the Neon registers and move it to r2.
+ vmax.u16 d24, d25
+ vpmax.u16 d24, d24
+ vpmax.u16 d24, d24
+ adds r1, #8
+ vmov.u16 r2, d24[0]
+ beq END_MAX_ABS_VALUE_W16
+
+LOOP_MAX_ABS_VALUE_W16:
+ ldrsh r3, [r0], #2
+ eor r12, r3, r3, asr #31 @ eor and then sub, to get absolute value.
+ sub r12, r12, r3, asr #31
+ cmp r2, r12
+ movlt r2, r12
+ subs r1, #1
+ bne LOOP_MAX_ABS_VALUE_W16
+
+END_MAX_ABS_VALUE_W16:
+ cmp r2, #0x8000 @ Guard against the case for -32768.
+ subeq r2, #1
+ mov r0, r2
+ bx lr
+
+.fnend
+
+@ int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, int length);
+WebRtcSpl_MaxAbsValueW32Neon:
+.fnstart
+
+ cmp r0, #0
+ moveq r0, #-1
+ beq EXIT @ Return -1 for a NULL pointer.
+ cmp r1, #0 @ length
+ movle r0, #-1
+ ble EXIT @ Return -1 if length <= 0.
+
+ vmov.i32 q11, #0
+ vmov.i32 q12, #0
+ cmp r1, #8
+ blt LOOP_MAX_ABS_VALUE_W32
+
+ sub r1, #8 @ Counter for loops
+
+LOOP_UNROLLED_BY_8_MAX_ABS_VALUE_W32:
+ vld1.32 {q13, q14}, [r0]!
+ subs r1, #8 @ Counter for loops
+ vabs.s32 q13, q13 @ vabs doesn't change the value of 0x80000000.
+ vabs.s32 q14, q14
+ vmax.u32 q11, q13 @ Use u32 so we don't lose the value 0x80000000.
+ vmax.u32 q12, q14
+ bge LOOP_UNROLLED_BY_8_MAX_ABS_VALUE_W32
+
+ @ Find the maximum value in the Neon registers and move it to r2.
+ vmax.u32 q12, q11
+ vmax.u32 d24, d25
+ vpmax.u32 d24, d24
+ adds r1, #8
+ vmov.u32 r2, d24[0]
+ beq END_MAX_ABS_VALUE_W32
+
+LOOP_MAX_ABS_VALUE_W32:
+ ldr r3, [r0], #4
+ eor r12, r3, r3, asr #31 @ eor and then sub, to get absolute value.
+ sub r12, r12, r3, asr #31
+ cmp r2, r12
+ movcc r2, r12
+ subs r1, #1
+ bne LOOP_MAX_ABS_VALUE_W32
+
+END_MAX_ABS_VALUE_W32:
+ mvn r0, #0x80000000 @ Guard against the case for 0x80000000.
+ cmp r2, r0
+ movcc r0, r2
+
+EXIT:
+ bx lr
+
+.fnend
+
+@ int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, int length);
+WebRtcSpl_MaxValueW16Neon:
+.fnstart
+
+ mov r2, #0x8000 @ Initialize the return value.
+ cmp r0, #0
+ beq END_MAX_VALUE_W16
+ cmp r1, #0
+ ble END_MAX_VALUE_W16
+
+ vmov.i16 q12, #0x8000
+ cmp r1, #8
+ blt LOOP_MAX_VALUE_W16
+
+ sub r1, #8 @ Counter for loops
+
+LOOP_UNROLLED_BY_8_MAX_VALUE_W16:
+ vld1.16 {q13}, [r0]!
+ subs r1, #8
+ vmax.s16 q12, q13
+ bge LOOP_UNROLLED_BY_8_MAX_VALUE_W16
+
+ @ Find the maximum value in the Neon registers and move it to r2.
+ vmax.s16 d24, d25
+ vpmax.s16 d24, d24
+ vpmax.s16 d24, d24
+ adds r1, #8
+ vmov.u16 r2, d24[0]
+ beq END_MAX_VALUE_W16
+
+LOOP_MAX_VALUE_W16:
+ ldrsh r3, [r0], #2
+ cmp r2, r3
+ movlt r2, r3
+ subs r1, #1
+ bne LOOP_MAX_VALUE_W16
+
+END_MAX_VALUE_W16:
+ mov r0, r2
+ bx lr
+
+.fnend
+
+@ int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, int length);
+WebRtcSpl_MaxValueW32Neon:
+.fnstart
+
+ mov r2, #0x80000000 @ Initialize the return value.
+ cmp r0, #0
+ beq END_MAX_VALUE_W32
+ cmp r1, #0
+ ble END_MAX_VALUE_W32
+
+ vmov.i32 q11, #0x80000000
+ vmov.i32 q12, #0x80000000
+ cmp r1, #8
+ blt LOOP_MAX_VALUE_W32
+
+ sub r1, #8 @ Counter for loops
+
+LOOP_UNROLLED_BY_8_MAX_VALUE_W32:
+ vld1.32 {q13, q14}, [r0]!
+ subs r1, #8
+ vmax.s32 q11, q13
+ vmax.s32 q12, q14
+ bge LOOP_UNROLLED_BY_8_MAX_VALUE_W32
+
+ @ Find the maximum value in the Neon registers and move it to r2.
+ vmax.s32 q12, q11
+ vpmax.s32 d24, d25
+ vpmax.s32 d24, d24
+ adds r1, #8
+ vmov.s32 r2, d24[0]
+ beq END_MAX_VALUE_W32
+
+LOOP_MAX_VALUE_W32:
+ ldr r3, [r0], #4
+ cmp r2, r3
+ movlt r2, r3
+ subs r1, #1
+ bne LOOP_MAX_VALUE_W32
+
+END_MAX_VALUE_W32:
+ mov r0, r2
+ bx lr
+
+.fnend
+
+@ int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, int length);
+WebRtcSpl_MinValueW16Neon:
+.fnstart
+
+ movw r2, #0x7FFF @ Initialize the return value.
+ cmp r0, #0
+ beq END_MIN_VALUE_W16
+ cmp r1, #0
+ ble END_MIN_VALUE_W16
+
+ vmov.i16 q12, #0x7FFF
+ cmp r1, #8
+ blt LOOP_MIN_VALUE_W16
+
+ sub r1, #8 @ Counter for loops
+
+LOOP_UNROLLED_BY_8_MIN_VALUE_W16:
+ vld1.16 {q13}, [r0]!
+ subs r1, #8
+ vmin.s16 q12, q13
+ bge LOOP_UNROLLED_BY_8_MIN_VALUE_W16
+
+ @ Find the maximum value in the Neon registers and move it to r2.
+ vmin.s16 d24, d25
+ vpmin.s16 d24, d24
+ vpmin.s16 d24, d24
+ adds r1, #8
+ vmov.s16 r2, d24[0]
+ sxth r2, r2
+ beq END_MIN_VALUE_W16
+
+LOOP_MIN_VALUE_W16:
+ ldrsh r3, [r0], #2
+ cmp r2, r3
+ movge r2, r3
+ subs r1, #1
+ bne LOOP_MIN_VALUE_W16
+
+END_MIN_VALUE_W16:
+ mov r0, r2
+ bx lr
+
+.fnend
+
+@ int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, int length);
+WebRtcSpl_MinValueW32Neon:
+.fnstart
+
+ mov r2, #0x7FFFFFFF @ Initialize the return value.
+ cmp r0, #0
+ beq END_MIN_VALUE_W32
+ cmp r1, #0
+ ble END_MIN_VALUE_W32
+
+ vdup.32 q11, r2
+ vdup.32 q12, r2
+ cmp r1, #8
+ blt LOOP_MIN_VALUE_W32
+
+ sub r1, #8 @ Counter for loops
+
+LOOP_UNROLLED_BY_8_MIN_VALUE_W32:
+ vld1.32 {q13, q14}, [r0]!
+ subs r1, #8
+ vmin.s32 q11, q13
+ vmin.s32 q12, q14
+ bge LOOP_UNROLLED_BY_8_MIN_VALUE_W32
+
+ @ Find the maximum value in the Neon registers and move it to r2.
+ vmin.s32 q12, q11
+ vpmin.s32 d24, d25
+ vpmin.s32 d24, d24
+ adds r1, #8
+ vmov.s32 r2, d24[0]
+ beq END_MIN_VALUE_W32
+
+LOOP_MIN_VALUE_W32:
+ ldr r3, [r0], #4
+ cmp r2, r3
+ movge r2, r3
+ subs r1, #1
+ bne LOOP_MIN_VALUE_W32
+
+END_MIN_VALUE_W32:
+ mov r0, r2
+ bx lr
+
+.fnend
diff --git a/common_audio/signal_processing/randomization_functions.c b/common_audio/signal_processing/randomization_functions.c
new file mode 100644
index 0000000..04271ad
--- /dev/null
+++ b/common_audio/signal_processing/randomization_functions.c
@@ -0,0 +1,119 @@
+/*
+ * 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 implementations of the randomization functions
+ * WebRtcSpl_IncreaseSeed()
+ * WebRtcSpl_RandU()
+ * WebRtcSpl_RandN()
+ * WebRtcSpl_RandUArray()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+static const WebRtc_Word16 kRandNTable[] = {
+ 9178, -7260, 40, 10189, 4894, -3531, -13779, 14764,
+ -4008, -8884, -8990, 1008, 7368, 5184, 3251, -5817,
+ -9786, 5963, 1770, 8066, -7135, 10772, -2298, 1361,
+ 6484, 2241, -8633, 792, 199, -3344, 6553, -10079,
+ -15040, 95, 11608, -12469, 14161, -4176, 2476, 6403,
+ 13685, -16005, 6646, 2239, 10916, -3004, -602, -3141,
+ 2142, 14144, -5829, 5305, 8209, 4713, 2697, -5112,
+ 16092, -1210, -2891, -6631, -5360, -11878, -6781, -2739,
+ -6392, 536, 10923, 10872, 5059, -4748, -7770, 5477,
+ 38, -1025, -2892, 1638, 6304, 14375, -11028, 1553,
+ -1565, 10762, -393, 4040, 5257, 12310, 6554, -4799,
+ 4899, -6354, 1603, -1048, -2220, 8247, -186, -8944,
+ -12004, 2332, 4801, -4933, 6371, 131, 8614, -5927,
+ -8287, -22760, 4033, -15162, 3385, 3246, 3153, -5250,
+ 3766, 784, 6494, -62, 3531, -1582, 15572, 662,
+ -3952, -330, -3196, 669, 7236, -2678, -6569, 23319,
+ -8645, -741, 14830, -15976, 4903, 315, -11342, 10311,
+ 1858, -7777, 2145, 5436, 5677, -113, -10033, 826,
+ -1353, 17210, 7768, 986, -1471, 8291, -4982, 8207,
+ -14911, -6255, -2449, -11881, -7059, -11703, -4338, 8025,
+ 7538, -2823, -12490, 9470, -1613, -2529, -10092, -7807,
+ 9480, 6970, -12844, 5123, 3532, 4816, 4803, -8455,
+ -5045, 14032, -4378, -1643, 5756, -11041, -2732, -16618,
+ -6430, -18375, -3320, 6098, 5131, -4269, -8840, 2482,
+ -7048, 1547, -21890, -6505, -7414, -424, -11722, 7955,
+ 1653, -17299, 1823, 473, -9232, 3337, 1111, 873,
+ 4018, -8982, 9889, 3531, -11763, -3799, 7373, -4539,
+ 3231, 7054, -8537, 7616, 6244, 16635, 447, -2915,
+ 13967, 705, -2669, -1520, -1771, -16188, 5956, 5117,
+ 6371, -9936, -1448, 2480, 5128, 7550, -8130, 5236,
+ 8213, -6443, 7707, -1950, -13811, 7218, 7031, -3883,
+ 67, 5731, -2874, 13480, -3743, 9298, -3280, 3552,
+ -4425, -18, -3785, -9988, -5357, 5477, -11794, 2117,
+ 1416, -9935, 3376, 802, -5079, -8243, 12652, 66,
+ 3653, -2368, 6781, -21895, -7227, 2487, 7839, -385,
+ 6646, -7016, -4658, 5531, -1705, 834, 129, 3694,
+ -1343, 2238, -22640, -6417, -11139, 11301, -2945, -3494,
+ -5626, 185, -3615, -2041, -7972, -3106, -60, -23497,
+ -1566, 17064, 3519, 2518, 304, -6805, -10269, 2105,
+ 1936, -426, -736, -8122, -1467, 4238, -6939, -13309,
+ 360, 7402, -7970, 12576, 3287, 12194, -6289, -16006,
+ 9171, 4042, -9193, 9123, -2512, 6388, -4734, -8739,
+ 1028, -5406, -1696, 5889, -666, -4736, 4971, 3565,
+ 9362, -6292, 3876, -3652, -19666, 7523, -4061, 391,
+ -11773, 7502, -3763, 4929, -9478, 13278, 2805, 4496,
+ 7814, 16419, 12455, -14773, 2127, -2746, 3763, 4847,
+ 3698, 6978, 4751, -6957, -3581, -45, 6252, 1513,
+ -4797, -7925, 11270, 16188, -2359, -5269, 9376, -10777,
+ 7262, 20031, -6515, -2208, -5353, 8085, -1341, -1303,
+ 7333, 5576, 3625, 5763, -7931, 9833, -3371, -10305,
+ 6534, -13539, -9971, 997, 8464, -4064, -1495, 1857,
+ 13624, 5458, 9490, -11086, -4524, 12022, -550, -198,
+ 408, -8455, -7068, 10289, 9712, -3366, 9028, -7621,
+ -5243, 2362, 6909, 4672, -4933, -1799, 4709, -4563,
+ -62, -566, 1624, -7010, 14730, -17791, -3697, -2344,
+ -1741, 7099, -9509, -6855, -1989, 3495, -2289, 2031,
+ 12784, 891, 14189, -3963, -5683, 421, -12575, 1724,
+ -12682, -5970, -8169, 3143, -1824, -5488, -5130, 8536,
+ 12799, 794, 5738, 3459, -11689, -258, -3738, -3775,
+ -8742, 2333, 8312, -9383, 10331, 13119, 8398, 10644,
+ -19433, -6446, -16277, -11793, 16284, 9345, 15222, 15834,
+ 2009, -7349, 130, -14547, 338, -5998, 3337, 21492,
+ 2406, 7703, -951, 11196, -564, 3406, 2217, 4806,
+ 2374, -5797, 11839, 8940, -11874, 18213, 2855, 10492
+};
+
+WebRtc_UWord32 WebRtcSpl_IncreaseSeed(WebRtc_UWord32 *seed)
+{
+ seed[0] = (seed[0] * ((WebRtc_Word32)69069) + 1) & (WEBRTC_SPL_MAX_SEED_USED - 1);
+ return seed[0];
+}
+
+WebRtc_Word16 WebRtcSpl_RandU(WebRtc_UWord32 *seed)
+{
+ return (WebRtc_Word16)(WebRtcSpl_IncreaseSeed(seed) >> 16);
+}
+
+WebRtc_Word16 WebRtcSpl_RandN(WebRtc_UWord32 *seed)
+{
+ return kRandNTable[WebRtcSpl_IncreaseSeed(seed) >> 23];
+}
+
+// Creates an array of uniformly distributed variables
+WebRtc_Word16 WebRtcSpl_RandUArray(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length,
+ WebRtc_UWord32* seed)
+{
+ int i;
+ for (i = 0; i < vector_length; i++)
+ {
+ vector[i] = WebRtcSpl_RandU(seed);
+ }
+ return vector_length;
+}
diff --git a/common_audio/signal_processing/real_fft.c b/common_audio/signal_processing/real_fft.c
new file mode 100644
index 0000000..8f32418
--- /dev/null
+++ b/common_audio/signal_processing/real_fft.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "common_audio/signal_processing/include/real_fft.h"
+
+#include <stdlib.h>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+
+struct RealFFT {
+ int order;
+};
+
+struct RealFFT* WebRtcSpl_CreateRealFFT(int order) {
+ struct RealFFT* self = NULL;
+
+ // This constraint comes from ComplexFFT().
+ if (order > 10 || order < 0) {
+ return NULL;
+ }
+
+ self = malloc(sizeof(struct RealFFT));
+ self->order = order;
+
+ return self;
+}
+
+void WebRtcSpl_FreeRealFFT(struct RealFFT* self) {
+ free(self);
+}
+
+// WebRtcSpl_ComplexFFT and WebRtcSpl_ComplexIFFT use in-place algorithm,
+// so copy data from data_in to data_out in the next two functions.
+
+int WebRtcSpl_RealForwardFFTC(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out) {
+ memcpy(data_out, data_in, sizeof(int16_t) * (1 << (self->order + 1)));
+ WebRtcSpl_ComplexBitReverse(data_out, self->order);
+ return WebRtcSpl_ComplexFFT(data_out, self->order, 1);
+}
+
+int WebRtcSpl_RealInverseFFTC(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out) {
+ memcpy(data_out, data_in, sizeof(int16_t) * (1 << (self->order + 1)));
+ WebRtcSpl_ComplexBitReverse(data_out, self->order);
+ return WebRtcSpl_ComplexIFFT(data_out, self->order, 1);
+}
+
+#if defined(WEBRTC_DETECT_ARM_NEON) || defined(WEBRTC_ARCH_ARM_NEON)
+// TODO(kma): Replace the following function bodies into optimized functions
+// for ARM Neon.
+int WebRtcSpl_RealForwardFFTNeon(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out) {
+ return WebRtcSpl_RealForwardFFTC(self, data_in, data_out);
+}
+
+int WebRtcSpl_RealInverseFFTNeon(struct RealFFT* self,
+ const int16_t* data_in,
+ int16_t* data_out) {
+ return WebRtcSpl_RealInverseFFTC(self, data_in, data_out);
+}
+#endif
diff --git a/common_audio/signal_processing/real_fft_unittest.cc b/common_audio/signal_processing/real_fft_unittest.cc
new file mode 100644
index 0000000..a37e732
--- /dev/null
+++ b/common_audio/signal_processing/real_fft_unittest.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "common_audio/signal_processing/include/real_fft.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "typedefs.h"
+
+#include "gtest/gtest.h"
+
+namespace webrtc {
+namespace {
+
+const int kOrder = 4;
+const int kLength = 1 << (kOrder + 1); // +1 to hold complex data.
+const int16_t kRefData[kLength] = {
+ 11739, 6848, -8688, 31980, -30295, 25242, 27085, 19410,
+ -26299, 15607, -10791, 11778, -23819, 14498, -25772, 10076,
+ 1173, 6848, -8688, 31980, -30295, 2522, 27085, 19410,
+ -2629, 5607, -3, 1178, -23819, 1498, -25772, 10076
+};
+
+class RealFFTTest : public ::testing::Test {
+ protected:
+ RealFFTTest() {
+ WebRtcSpl_Init();
+ }
+};
+
+TEST_F(RealFFTTest, CreateFailsOnBadInput) {
+ RealFFT* fft = WebRtcSpl_CreateRealFFT(11);
+ EXPECT_TRUE(fft == NULL);
+ fft = WebRtcSpl_CreateRealFFT(-1);
+ EXPECT_TRUE(fft == NULL);
+}
+
+// TODO(andrew): This won't always be the case, but verifies the current code
+// at least.
+TEST_F(RealFFTTest, RealAndComplexAreIdentical) {
+ int16_t real_data[kLength] = {0};
+ int16_t real_data_out[kLength] = {0};
+ int16_t complex_data[kLength] = {0};
+ memcpy(real_data, kRefData, sizeof(kRefData));
+ memcpy(complex_data, kRefData, sizeof(kRefData));
+
+ RealFFT* fft = WebRtcSpl_CreateRealFFT(kOrder);
+ EXPECT_TRUE(fft != NULL);
+
+ EXPECT_EQ(0, WebRtcSpl_RealForwardFFT(fft, real_data, real_data_out));
+ WebRtcSpl_ComplexBitReverse(complex_data, kOrder);
+ EXPECT_EQ(0, WebRtcSpl_ComplexFFT(complex_data, kOrder, 1));
+
+ for (int i = 0; i < kLength; i++) {
+ EXPECT_EQ(real_data_out[i], complex_data[i]);
+ }
+
+ memcpy(complex_data, kRefData, sizeof(kRefData));
+
+ int real_scale = WebRtcSpl_RealInverseFFT(fft, real_data, real_data_out);
+ EXPECT_GE(real_scale, 0);
+ WebRtcSpl_ComplexBitReverse(complex_data, kOrder);
+ int complex_scale = WebRtcSpl_ComplexIFFT(complex_data, kOrder, 1);
+ EXPECT_EQ(real_scale, complex_scale);
+ for (int i = 0; i < kLength; i++) {
+ EXPECT_EQ(real_data_out[i], complex_data[i]);
+ }
+ WebRtcSpl_FreeRealFFT(fft);
+}
+
+} // namespace
+} // namespace webrtc
diff --git a/common_audio/signal_processing/refl_coef_to_lpc.c b/common_audio/signal_processing/refl_coef_to_lpc.c
new file mode 100644
index 0000000..d07804d
--- /dev/null
+++ b/common_audio/signal_processing/refl_coef_to_lpc.c
@@ -0,0 +1,60 @@
+/*
+ * 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 function WebRtcSpl_ReflCoefToLpc().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_ReflCoefToLpc(G_CONST WebRtc_Word16 *k, int use_order, WebRtc_Word16 *a)
+{
+ WebRtc_Word16 any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
+ WebRtc_Word16 *aptr, *aptr2, *anyptr;
+ G_CONST WebRtc_Word16 *kptr;
+ int m, i;
+
+ kptr = k;
+ *a = 4096; // i.e., (Word16_MAX >> 3)+1.
+ *any = *a;
+ a[1] = WEBRTC_SPL_RSHIFT_W16((*k), 3);
+
+ for (m = 1; m < use_order; m++)
+ {
+ kptr++;
+ aptr = a;
+ aptr++;
+ aptr2 = &a[m];
+ anyptr = any;
+ anyptr++;
+
+ any[m + 1] = WEBRTC_SPL_RSHIFT_W16((*kptr), 3);
+ for (i = 0; i < m; i++)
+ {
+ *anyptr = (*aptr)
+ + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((*aptr2), (*kptr), 15);
+ anyptr++;
+ aptr++;
+ aptr2--;
+ }
+
+ aptr = a;
+ anyptr = any;
+ for (i = 0; i < (m + 2); i++)
+ {
+ *aptr = *anyptr;
+ aptr++;
+ anyptr++;
+ }
+ }
+}
diff --git a/common_audio/signal_processing/resample.c b/common_audio/signal_processing/resample.c
new file mode 100644
index 0000000..19d1778
--- /dev/null
+++ b/common_audio/signal_processing/resample.c
@@ -0,0 +1,505 @@
+/*
+ * 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 functions for 22 kHz.
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+#include "resample_by_2_internal.h"
+
+// Declaration of internally used functions
+static void WebRtcSpl_32khzTo22khzIntToShort(const WebRtc_Word32 *In, WebRtc_Word16 *Out,
+ const WebRtc_Word32 K);
+
+void WebRtcSpl_32khzTo22khzIntToInt(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K);
+
+// interpolation coefficients
+static const WebRtc_Word16 kCoefficients32To22[5][9] = {
+ {127, -712, 2359, -6333, 23456, 16775, -3695, 945, -154},
+ {-39, 230, -830, 2785, 32366, -2324, 760, -218, 38},
+ {117, -663, 2222, -6133, 26634, 13070, -3174, 831, -137},
+ {-77, 457, -1677, 5958, 31175, -4136, 1405, -408, 71},
+ { 98, -560, 1900, -5406, 29240, 9423, -2480, 663, -110}
+};
+
+//////////////////////
+// 22 kHz -> 16 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 4, 5, 10
+#define SUB_BLOCKS_22_16 5
+
+// 22 -> 16 resampler
+void WebRtcSpl_Resample22khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo16khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_22_16 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_22_16; k++)
+ {
+ ///// 22 --> 44 /////
+ // WebRtc_Word16 in[220/SUB_BLOCKS_22_16]
+ // WebRtc_Word32 out[440/SUB_BLOCKS_22_16]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 220 / SUB_BLOCKS_22_16, tmpmem + 16, state->S_22_44);
+
+ ///// 44 --> 32 /////
+ // WebRtc_Word32 in[440/SUB_BLOCKS_22_16]
+ // WebRtc_Word32 out[320/SUB_BLOCKS_22_16]
+ /////
+ // copy state to and from input array
+ tmpmem[8] = state->S_44_32[0];
+ tmpmem[9] = state->S_44_32[1];
+ tmpmem[10] = state->S_44_32[2];
+ tmpmem[11] = state->S_44_32[3];
+ tmpmem[12] = state->S_44_32[4];
+ tmpmem[13] = state->S_44_32[5];
+ tmpmem[14] = state->S_44_32[6];
+ tmpmem[15] = state->S_44_32[7];
+ state->S_44_32[0] = tmpmem[440 / SUB_BLOCKS_22_16 + 8];
+ state->S_44_32[1] = tmpmem[440 / SUB_BLOCKS_22_16 + 9];
+ state->S_44_32[2] = tmpmem[440 / SUB_BLOCKS_22_16 + 10];
+ state->S_44_32[3] = tmpmem[440 / SUB_BLOCKS_22_16 + 11];
+ state->S_44_32[4] = tmpmem[440 / SUB_BLOCKS_22_16 + 12];
+ state->S_44_32[5] = tmpmem[440 / SUB_BLOCKS_22_16 + 13];
+ state->S_44_32[6] = tmpmem[440 / SUB_BLOCKS_22_16 + 14];
+ state->S_44_32[7] = tmpmem[440 / SUB_BLOCKS_22_16 + 15];
+
+ WebRtcSpl_Resample44khzTo32khz(tmpmem + 8, tmpmem, 40 / SUB_BLOCKS_22_16);
+
+ ///// 32 --> 16 /////
+ // WebRtc_Word32 in[320/SUB_BLOCKS_22_16]
+ // WebRtc_Word32 out[160/SUB_BLOCKS_22_16]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 320 / SUB_BLOCKS_22_16, out, state->S_32_16);
+
+ // move input/output pointers 10/SUB_BLOCKS_22_16 ms seconds ahead
+ in += 220 / SUB_BLOCKS_22_16;
+ out += 160 / SUB_BLOCKS_22_16;
+ }
+}
+
+// initialize state of 22 -> 16 resampler
+void WebRtcSpl_ResetResample22khzTo16khz(WebRtcSpl_State22khzTo16khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_22_44[k] = 0;
+ state->S_44_32[k] = 0;
+ state->S_32_16[k] = 0;
+ }
+}
+
+//////////////////////
+// 16 kHz -> 22 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 4, 5, 10
+#define SUB_BLOCKS_16_22 4
+
+// 16 -> 22 resampler
+void WebRtcSpl_Resample16khzTo22khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo22khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_16_22 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_16_22; k++)
+ {
+ ///// 16 --> 32 /////
+ // WebRtc_Word16 in[160/SUB_BLOCKS_16_22]
+ // WebRtc_Word32 out[320/SUB_BLOCKS_16_22]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 160 / SUB_BLOCKS_16_22, tmpmem + 8, state->S_16_32);
+
+ ///// 32 --> 22 /////
+ // WebRtc_Word32 in[320/SUB_BLOCKS_16_22]
+ // WebRtc_Word32 out[220/SUB_BLOCKS_16_22]
+ /////
+ // copy state to and from input array
+ tmpmem[0] = state->S_32_22[0];
+ tmpmem[1] = state->S_32_22[1];
+ tmpmem[2] = state->S_32_22[2];
+ tmpmem[3] = state->S_32_22[3];
+ tmpmem[4] = state->S_32_22[4];
+ tmpmem[5] = state->S_32_22[5];
+ tmpmem[6] = state->S_32_22[6];
+ tmpmem[7] = state->S_32_22[7];
+ state->S_32_22[0] = tmpmem[320 / SUB_BLOCKS_16_22];
+ state->S_32_22[1] = tmpmem[320 / SUB_BLOCKS_16_22 + 1];
+ state->S_32_22[2] = tmpmem[320 / SUB_BLOCKS_16_22 + 2];
+ state->S_32_22[3] = tmpmem[320 / SUB_BLOCKS_16_22 + 3];
+ state->S_32_22[4] = tmpmem[320 / SUB_BLOCKS_16_22 + 4];
+ state->S_32_22[5] = tmpmem[320 / SUB_BLOCKS_16_22 + 5];
+ state->S_32_22[6] = tmpmem[320 / SUB_BLOCKS_16_22 + 6];
+ state->S_32_22[7] = tmpmem[320 / SUB_BLOCKS_16_22 + 7];
+
+ WebRtcSpl_32khzTo22khzIntToShort(tmpmem, out, 20 / SUB_BLOCKS_16_22);
+
+ // move input/output pointers 10/SUB_BLOCKS_16_22 ms seconds ahead
+ in += 160 / SUB_BLOCKS_16_22;
+ out += 220 / SUB_BLOCKS_16_22;
+ }
+}
+
+// initialize state of 16 -> 22 resampler
+void WebRtcSpl_ResetResample16khzTo22khz(WebRtcSpl_State16khzTo22khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_16_32[k] = 0;
+ state->S_32_22[k] = 0;
+ }
+}
+
+//////////////////////
+// 22 kHz -> 8 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 5, 10
+#define SUB_BLOCKS_22_8 2
+
+// 22 -> 8 resampler
+void WebRtcSpl_Resample22khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo8khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_22_8 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_22_8; k++)
+ {
+ ///// 22 --> 22 lowpass /////
+ // WebRtc_Word16 in[220/SUB_BLOCKS_22_8]
+ // WebRtc_Word32 out[220/SUB_BLOCKS_22_8]
+ /////
+ WebRtcSpl_LPBy2ShortToInt(in, 220 / SUB_BLOCKS_22_8, tmpmem + 16, state->S_22_22);
+
+ ///// 22 --> 16 /////
+ // WebRtc_Word32 in[220/SUB_BLOCKS_22_8]
+ // WebRtc_Word32 out[160/SUB_BLOCKS_22_8]
+ /////
+ // copy state to and from input array
+ tmpmem[8] = state->S_22_16[0];
+ tmpmem[9] = state->S_22_16[1];
+ tmpmem[10] = state->S_22_16[2];
+ tmpmem[11] = state->S_22_16[3];
+ tmpmem[12] = state->S_22_16[4];
+ tmpmem[13] = state->S_22_16[5];
+ tmpmem[14] = state->S_22_16[6];
+ tmpmem[15] = state->S_22_16[7];
+ state->S_22_16[0] = tmpmem[220 / SUB_BLOCKS_22_8 + 8];
+ state->S_22_16[1] = tmpmem[220 / SUB_BLOCKS_22_8 + 9];
+ state->S_22_16[2] = tmpmem[220 / SUB_BLOCKS_22_8 + 10];
+ state->S_22_16[3] = tmpmem[220 / SUB_BLOCKS_22_8 + 11];
+ state->S_22_16[4] = tmpmem[220 / SUB_BLOCKS_22_8 + 12];
+ state->S_22_16[5] = tmpmem[220 / SUB_BLOCKS_22_8 + 13];
+ state->S_22_16[6] = tmpmem[220 / SUB_BLOCKS_22_8 + 14];
+ state->S_22_16[7] = tmpmem[220 / SUB_BLOCKS_22_8 + 15];
+
+ WebRtcSpl_Resample44khzTo32khz(tmpmem + 8, tmpmem, 20 / SUB_BLOCKS_22_8);
+
+ ///// 16 --> 8 /////
+ // WebRtc_Word32 in[160/SUB_BLOCKS_22_8]
+ // WebRtc_Word32 out[80/SUB_BLOCKS_22_8]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 160 / SUB_BLOCKS_22_8, out, state->S_16_8);
+
+ // move input/output pointers 10/SUB_BLOCKS_22_8 ms seconds ahead
+ in += 220 / SUB_BLOCKS_22_8;
+ out += 80 / SUB_BLOCKS_22_8;
+ }
+}
+
+// initialize state of 22 -> 8 resampler
+void WebRtcSpl_ResetResample22khzTo8khz(WebRtcSpl_State22khzTo8khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_22_22[k] = 0;
+ state->S_22_22[k + 8] = 0;
+ state->S_22_16[k] = 0;
+ state->S_16_8[k] = 0;
+ }
+}
+
+//////////////////////
+// 8 kHz -> 22 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 5, 10
+#define SUB_BLOCKS_8_22 2
+
+// 8 -> 22 resampler
+void WebRtcSpl_Resample8khzTo22khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo22khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_8_22 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_8_22; k++)
+ {
+ ///// 8 --> 16 /////
+ // WebRtc_Word16 in[80/SUB_BLOCKS_8_22]
+ // WebRtc_Word32 out[160/SUB_BLOCKS_8_22]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 80 / SUB_BLOCKS_8_22, tmpmem + 18, state->S_8_16);
+
+ ///// 16 --> 11 /////
+ // WebRtc_Word32 in[160/SUB_BLOCKS_8_22]
+ // WebRtc_Word32 out[110/SUB_BLOCKS_8_22]
+ /////
+ // copy state to and from input array
+ tmpmem[10] = state->S_16_11[0];
+ tmpmem[11] = state->S_16_11[1];
+ tmpmem[12] = state->S_16_11[2];
+ tmpmem[13] = state->S_16_11[3];
+ tmpmem[14] = state->S_16_11[4];
+ tmpmem[15] = state->S_16_11[5];
+ tmpmem[16] = state->S_16_11[6];
+ tmpmem[17] = state->S_16_11[7];
+ state->S_16_11[0] = tmpmem[160 / SUB_BLOCKS_8_22 + 10];
+ state->S_16_11[1] = tmpmem[160 / SUB_BLOCKS_8_22 + 11];
+ state->S_16_11[2] = tmpmem[160 / SUB_BLOCKS_8_22 + 12];
+ state->S_16_11[3] = tmpmem[160 / SUB_BLOCKS_8_22 + 13];
+ state->S_16_11[4] = tmpmem[160 / SUB_BLOCKS_8_22 + 14];
+ state->S_16_11[5] = tmpmem[160 / SUB_BLOCKS_8_22 + 15];
+ state->S_16_11[6] = tmpmem[160 / SUB_BLOCKS_8_22 + 16];
+ state->S_16_11[7] = tmpmem[160 / SUB_BLOCKS_8_22 + 17];
+
+ WebRtcSpl_32khzTo22khzIntToInt(tmpmem + 10, tmpmem, 10 / SUB_BLOCKS_8_22);
+
+ ///// 11 --> 22 /////
+ // WebRtc_Word32 in[110/SUB_BLOCKS_8_22]
+ // WebRtc_Word16 out[220/SUB_BLOCKS_8_22]
+ /////
+ WebRtcSpl_UpBy2IntToShort(tmpmem, 110 / SUB_BLOCKS_8_22, out, state->S_11_22);
+
+ // move input/output pointers 10/SUB_BLOCKS_8_22 ms seconds ahead
+ in += 80 / SUB_BLOCKS_8_22;
+ out += 220 / SUB_BLOCKS_8_22;
+ }
+}
+
+// initialize state of 8 -> 22 resampler
+void WebRtcSpl_ResetResample8khzTo22khz(WebRtcSpl_State8khzTo22khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_8_16[k] = 0;
+ state->S_16_11[k] = 0;
+ state->S_11_22[k] = 0;
+ }
+}
+
+// compute two inner-products and store them to output array
+static void WebRtcSpl_DotProdIntToInt(const WebRtc_Word32* in1, const WebRtc_Word32* in2,
+ const WebRtc_Word16* coef_ptr, WebRtc_Word32* out1,
+ WebRtc_Word32* out2)
+{
+ WebRtc_Word32 tmp1 = 16384;
+ WebRtc_Word32 tmp2 = 16384;
+ WebRtc_Word16 coef;
+
+ coef = coef_ptr[0];
+ tmp1 += coef * in1[0];
+ tmp2 += coef * in2[-0];
+
+ coef = coef_ptr[1];
+ tmp1 += coef * in1[1];
+ tmp2 += coef * in2[-1];
+
+ coef = coef_ptr[2];
+ tmp1 += coef * in1[2];
+ tmp2 += coef * in2[-2];
+
+ coef = coef_ptr[3];
+ tmp1 += coef * in1[3];
+ tmp2 += coef * in2[-3];
+
+ coef = coef_ptr[4];
+ tmp1 += coef * in1[4];
+ tmp2 += coef * in2[-4];
+
+ coef = coef_ptr[5];
+ tmp1 += coef * in1[5];
+ tmp2 += coef * in2[-5];
+
+ coef = coef_ptr[6];
+ tmp1 += coef * in1[6];
+ tmp2 += coef * in2[-6];
+
+ coef = coef_ptr[7];
+ tmp1 += coef * in1[7];
+ tmp2 += coef * in2[-7];
+
+ coef = coef_ptr[8];
+ *out1 = tmp1 + coef * in1[8];
+ *out2 = tmp2 + coef * in2[-8];
+}
+
+// compute two inner-products and store them to output array
+static void WebRtcSpl_DotProdIntToShort(const WebRtc_Word32* in1, const WebRtc_Word32* in2,
+ const WebRtc_Word16* coef_ptr, WebRtc_Word16* out1,
+ WebRtc_Word16* out2)
+{
+ WebRtc_Word32 tmp1 = 16384;
+ WebRtc_Word32 tmp2 = 16384;
+ WebRtc_Word16 coef;
+
+ coef = coef_ptr[0];
+ tmp1 += coef * in1[0];
+ tmp2 += coef * in2[-0];
+
+ coef = coef_ptr[1];
+ tmp1 += coef * in1[1];
+ tmp2 += coef * in2[-1];
+
+ coef = coef_ptr[2];
+ tmp1 += coef * in1[2];
+ tmp2 += coef * in2[-2];
+
+ coef = coef_ptr[3];
+ tmp1 += coef * in1[3];
+ tmp2 += coef * in2[-3];
+
+ coef = coef_ptr[4];
+ tmp1 += coef * in1[4];
+ tmp2 += coef * in2[-4];
+
+ coef = coef_ptr[5];
+ tmp1 += coef * in1[5];
+ tmp2 += coef * in2[-5];
+
+ coef = coef_ptr[6];
+ tmp1 += coef * in1[6];
+ tmp2 += coef * in2[-6];
+
+ coef = coef_ptr[7];
+ tmp1 += coef * in1[7];
+ tmp2 += coef * in2[-7];
+
+ coef = coef_ptr[8];
+ tmp1 += coef * in1[8];
+ tmp2 += coef * in2[-8];
+
+ // scale down, round and saturate
+ tmp1 >>= 15;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ tmp2 >>= 15;
+ if (tmp2 > (WebRtc_Word32)0x00007FFF)
+ tmp2 = 0x00007FFF;
+ if (tmp2 < (WebRtc_Word32)0xFFFF8000)
+ tmp2 = 0xFFFF8000;
+ *out1 = (WebRtc_Word16)tmp1;
+ *out2 = (WebRtc_Word16)tmp2;
+}
+
+// Resampling ratio: 11/16
+// input: WebRtc_Word32 (normalized, not saturated) :: size 16 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 11 * K
+// K: Number of blocks
+
+void WebRtcSpl_32khzTo22khzIntToInt(const WebRtc_Word32* In,
+ WebRtc_Word32* Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (16 input samples -> 11 output samples);
+ // process in sub blocks of size 16 samples.
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ // first output sample
+ Out[0] = ((WebRtc_Word32)In[3] << 15) + (1 << 14);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[0], &In[22], kCoefficients32To22[0], &Out[1], &Out[10]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[2], &In[20], kCoefficients32To22[1], &Out[2], &Out[9]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[3], &In[19], kCoefficients32To22[2], &Out[3], &Out[8]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[5], &In[17], kCoefficients32To22[3], &Out[4], &Out[7]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[6], &In[16], kCoefficients32To22[4], &Out[5], &Out[6]);
+
+ // update pointers
+ In += 16;
+ Out += 11;
+ }
+}
+
+// Resampling ratio: 11/16
+// input: WebRtc_Word32 (normalized, not saturated) :: size 16 * K
+// output: WebRtc_Word16 (saturated) :: size 11 * K
+// K: Number of blocks
+
+void WebRtcSpl_32khzTo22khzIntToShort(const WebRtc_Word32 *In,
+ WebRtc_Word16 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (16 input samples -> 11 output samples);
+ // process in sub blocks of size 16 samples.
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ // first output sample
+ tmp = In[3];
+ if (tmp > (WebRtc_Word32)0x00007FFF)
+ tmp = 0x00007FFF;
+ if (tmp < (WebRtc_Word32)0xFFFF8000)
+ tmp = 0xFFFF8000;
+ Out[0] = (WebRtc_Word16)tmp;
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[0], &In[22], kCoefficients32To22[0], &Out[1], &Out[10]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[2], &In[20], kCoefficients32To22[1], &Out[2], &Out[9]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[3], &In[19], kCoefficients32To22[2], &Out[3], &Out[8]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[5], &In[17], kCoefficients32To22[3], &Out[4], &Out[7]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[6], &In[16], kCoefficients32To22[4], &Out[5], &Out[6]);
+
+ // update pointers
+ In += 16;
+ Out += 11;
+ }
+}
diff --git a/common_audio/signal_processing/resample_48khz.c b/common_audio/signal_processing/resample_48khz.c
new file mode 100644
index 0000000..31cbe6b
--- /dev/null
+++ b/common_audio/signal_processing/resample_48khz.c
@@ -0,0 +1,186 @@
+/*
+ * 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 resampling functions between 48 kHz and nb/wb.
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include <string.h>
+#include "signal_processing_library.h"
+#include "resample_by_2_internal.h"
+
+////////////////////////////
+///// 48 kHz -> 16 kHz /////
+////////////////////////////
+
+// 48 -> 16 resampler
+void WebRtcSpl_Resample48khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo16khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 48 --> 48(LP) /////
+ // WebRtc_Word16 in[480]
+ // WebRtc_Word32 out[480]
+ /////
+ WebRtcSpl_LPBy2ShortToInt(in, 480, tmpmem + 16, state->S_48_48);
+
+ ///// 48 --> 32 /////
+ // WebRtc_Word32 in[480]
+ // WebRtc_Word32 out[320]
+ /////
+ // copy state to and from input array
+ memcpy(tmpmem + 8, state->S_48_32, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_48_32, tmpmem + 488, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 160);
+
+ ///// 32 --> 16 /////
+ // WebRtc_Word32 in[320]
+ // WebRtc_Word16 out[160]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 320, out, state->S_32_16);
+}
+
+// initialize state of 48 -> 16 resampler
+void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state)
+{
+ memset(state->S_48_48, 0, 16 * sizeof(WebRtc_Word32));
+ memset(state->S_48_32, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_32_16, 0, 8 * sizeof(WebRtc_Word32));
+}
+
+////////////////////////////
+///// 16 kHz -> 48 kHz /////
+////////////////////////////
+
+// 16 -> 48 resampler
+void WebRtcSpl_Resample16khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo48khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 16 --> 32 /////
+ // WebRtc_Word16 in[160]
+ // WebRtc_Word32 out[320]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 160, tmpmem + 16, state->S_16_32);
+
+ ///// 32 --> 24 /////
+ // WebRtc_Word32 in[320]
+ // WebRtc_Word32 out[240]
+ // copy state to and from input array
+ /////
+ memcpy(tmpmem + 8, state->S_32_24, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_32_24, tmpmem + 328, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample32khzTo24khz(tmpmem + 8, tmpmem, 80);
+
+ ///// 24 --> 48 /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word16 out[480]
+ /////
+ WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
+}
+
+// initialize state of 16 -> 48 resampler
+void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state)
+{
+ memset(state->S_16_32, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_32_24, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_24_48, 0, 8 * sizeof(WebRtc_Word32));
+}
+
+////////////////////////////
+///// 48 kHz -> 8 kHz /////
+////////////////////////////
+
+// 48 -> 8 resampler
+void WebRtcSpl_Resample48khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo8khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 48 --> 24 /////
+ // WebRtc_Word16 in[480]
+ // WebRtc_Word32 out[240]
+ /////
+ WebRtcSpl_DownBy2ShortToInt(in, 480, tmpmem + 256, state->S_48_24);
+
+ ///// 24 --> 24(LP) /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word32 out[240]
+ /////
+ WebRtcSpl_LPBy2IntToInt(tmpmem + 256, 240, tmpmem + 16, state->S_24_24);
+
+ ///// 24 --> 16 /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word32 out[160]
+ /////
+ // copy state to and from input array
+ memcpy(tmpmem + 8, state->S_24_16, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_24_16, tmpmem + 248, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 80);
+
+ ///// 16 --> 8 /////
+ // WebRtc_Word32 in[160]
+ // WebRtc_Word16 out[80]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 160, out, state->S_16_8);
+}
+
+// initialize state of 48 -> 8 resampler
+void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state)
+{
+ memset(state->S_48_24, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_24_24, 0, 16 * sizeof(WebRtc_Word32));
+ memset(state->S_24_16, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_16_8, 0, 8 * sizeof(WebRtc_Word32));
+}
+
+////////////////////////////
+///// 8 kHz -> 48 kHz /////
+////////////////////////////
+
+// 8 -> 48 resampler
+void WebRtcSpl_Resample8khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo48khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 8 --> 16 /////
+ // WebRtc_Word16 in[80]
+ // WebRtc_Word32 out[160]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 80, tmpmem + 264, state->S_8_16);
+
+ ///// 16 --> 12 /////
+ // WebRtc_Word32 in[160]
+ // WebRtc_Word32 out[120]
+ /////
+ // copy state to and from input array
+ memcpy(tmpmem + 256, state->S_16_12, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_16_12, tmpmem + 416, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample32khzTo24khz(tmpmem + 256, tmpmem + 240, 40);
+
+ ///// 12 --> 24 /////
+ // WebRtc_Word32 in[120]
+ // WebRtc_Word16 out[240]
+ /////
+ WebRtcSpl_UpBy2IntToInt(tmpmem + 240, 120, tmpmem, state->S_12_24);
+
+ ///// 24 --> 48 /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word16 out[480]
+ /////
+ WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
+}
+
+// initialize state of 8 -> 48 resampler
+void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state)
+{
+ memset(state->S_8_16, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_16_12, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_12_24, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_24_48, 0, 8 * sizeof(WebRtc_Word32));
+}
diff --git a/common_audio/signal_processing/resample_by_2.c b/common_audio/signal_processing/resample_by_2.c
new file mode 100644
index 0000000..c1d8b37
--- /dev/null
+++ b/common_audio/signal_processing/resample_by_2.c
@@ -0,0 +1,181 @@
+/*
+ * 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 "signal_processing_library.h"
+
+#ifdef WEBRTC_ARCH_ARM_V7
+
+// allpass filter coefficients.
+static const WebRtc_UWord32 kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
+static const WebRtc_UWord32 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 WebRtc_Word32 MUL_ACCUM_1(WebRtc_Word32 tbl_value,
+ WebRtc_Word32 diff,
+ WebRtc_Word32 state) {
+ WebRtc_Word32 result;
+ __asm__("smlawb %r0, %r1, %r2, %r3": "=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 WebRtc_Word32 MUL_ACCUM_2(WebRtc_Word32 tbl_value,
+ WebRtc_Word32 diff,
+ WebRtc_Word32 state) {
+ WebRtc_Word32 result;
+ __asm__("smmla %r0, %r1, %r2, %r3": "=r"(result): "r"(diff << 1),
+ "r"(tbl_value), "r"(state));
+ return result;
+}
+
+#else
+
+// allpass filter coefficients.
+static const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528};
+static const WebRtc_UWord16 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
+void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len,
+ WebRtc_Word16* out, WebRtc_Word32* filtState) {
+ WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
+ WebRtc_Word16 i;
+
+ register WebRtc_Word32 state0 = filtState[0];
+ register WebRtc_Word32 state1 = filtState[1];
+ register WebRtc_Word32 state2 = filtState[2];
+ register WebRtc_Word32 state3 = filtState[3];
+ register WebRtc_Word32 state4 = filtState[4];
+ register WebRtc_Word32 state5 = filtState[5];
+ register WebRtc_Word32 state6 = filtState[6];
+ register WebRtc_Word32 state7 = filtState[7];
+
+ for (i = (len >> 1); i > 0; i--) {
+ // lower allpass filter
+ in32 = (WebRtc_Word32)(*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 = (WebRtc_Word32)(*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;
+}
+
+
+void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len,
+ WebRtc_Word16* out, WebRtc_Word32* filtState) {
+ WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
+ WebRtc_Word16 i;
+
+ register WebRtc_Word32 state0 = filtState[0];
+ register WebRtc_Word32 state1 = filtState[1];
+ register WebRtc_Word32 state2 = filtState[2];
+ register WebRtc_Word32 state3 = filtState[3];
+ register WebRtc_Word32 state4 = filtState[4];
+ register WebRtc_Word32 state5 = filtState[5];
+ register WebRtc_Word32 state6 = filtState[6];
+ register WebRtc_Word32 state7 = filtState[7];
+
+ for (i = len; i > 0; i--) {
+ // lower allpass filter
+ in32 = (WebRtc_Word32)(*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;
+}
diff --git a/common_audio/signal_processing/resample_by_2_internal.c b/common_audio/signal_processing/resample_by_2_internal.c
new file mode 100644
index 0000000..cbd2395
--- /dev/null
+++ b/common_audio/signal_processing/resample_by_2_internal.c
@@ -0,0 +1,679 @@
+/*
+ * 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 header file contains some internal resampling functions.
+ *
+ */
+
+#include "resample_by_2_internal.h"
+
+// allpass filter coefficients.
+static const WebRtc_Word16 kResampleAllpass[2][3] = {
+ {821, 6110, 12382},
+ {3050, 9368, 15063}
+};
+
+//
+// decimator
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) OVERWRITTEN!
+// output: WebRtc_Word16 (saturated) (of length len/2)
+// state: filter state array; length = 8
+
+void WebRtcSpl_DownBy2IntToShort(WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word16 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter (operates on even input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // divide by two and store temporarily
+ in[i << 1] = (state[3] >> 1);
+ }
+
+ in++;
+
+ // upper allpass filter (operates on odd input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // divide by two and store temporarily
+ in[i << 1] = (state[7] >> 1);
+ }
+
+ in--;
+
+ // combine allpass outputs
+ for (i = 0; i < len; i += 2)
+ {
+ // divide by two, add both allpass outputs and round
+ tmp0 = (in[i << 1] + in[(i << 1) + 1]) >> 15;
+ tmp1 = (in[(i << 1) + 2] + in[(i << 1) + 3]) >> 15;
+ if (tmp0 > (WebRtc_Word32)0x00007FFF)
+ tmp0 = 0x00007FFF;
+ if (tmp0 < (WebRtc_Word32)0xFFFF8000)
+ tmp0 = 0xFFFF8000;
+ out[i] = (WebRtc_Word16)tmp0;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ out[i + 1] = (WebRtc_Word16)tmp1;
+ }
+}
+
+//
+// decimator
+// input: WebRtc_Word16
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) (of length len/2)
+// state: filter state array; length = 8
+
+void WebRtcSpl_DownBy2ShortToInt(const WebRtc_Word16 *in,
+ WebRtc_Word32 len,
+ WebRtc_Word32 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter (operates on even input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // divide by two and store temporarily
+ out[i] = (state[3] >> 1);
+ }
+
+ in++;
+
+ // upper allpass filter (operates on odd input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // divide by two and store temporarily
+ out[i] += (state[7] >> 1);
+ }
+
+ in--;
+}
+
+//
+// interpolator
+// input: WebRtc_Word16
+// output: WebRtc_Word32 (normalized, not saturated) (of length len*2)
+// state: filter state array; length = 8
+void WebRtcSpl_UpBy2ShortToInt(const WebRtc_Word16 *in, WebRtc_Word32 len, WebRtc_Word32 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ // upper allpass filter (generates odd output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i] << 15) + (1 << 14);
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[7] >> 15;
+ }
+
+ out++;
+
+ // lower allpass filter (generates even output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i] << 15) + (1 << 14);
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3] >> 15;
+ }
+}
+
+//
+// interpolator
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384)
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) (of length len*2)
+// state: filter state array; length = 8
+void WebRtcSpl_UpBy2IntToInt(const WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word32 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ // upper allpass filter (generates odd output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[7];
+ }
+
+ out++;
+
+ // lower allpass filter (generates even output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3];
+ }
+}
+
+//
+// interpolator
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384)
+// output: WebRtc_Word16 (saturated) (of length len*2)
+// state: filter state array; length = 8
+void WebRtcSpl_UpBy2IntToShort(const WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word16 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ // upper allpass filter (generates odd output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // scale down, saturate and store
+ tmp1 = state[7] >> 15;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ out[i << 1] = (WebRtc_Word16)tmp1;
+ }
+
+ out++;
+
+ // lower allpass filter (generates even output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, saturate and store
+ tmp1 = state[3] >> 15;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ out[i << 1] = (WebRtc_Word16)tmp1;
+ }
+}
+
+// lowpass filter
+// input: WebRtc_Word16
+// output: WebRtc_Word32 (normalized, not saturated)
+// state: filter state array; length = 8
+void WebRtcSpl_LPBy2ShortToInt(const WebRtc_Word16* in, WebRtc_Word32 len, WebRtc_Word32* out,
+ WebRtc_Word32* state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter: odd input -> even output samples
+ in++;
+ // initial state of polyphase delay element
+ tmp0 = state[12];
+ for (i = 0; i < len; i++)
+ {
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3] >> 1;
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ }
+ in--;
+
+ // upper allpass filter: even input -> even output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
+ }
+
+ // switch to odd output samples
+ out++;
+
+ // lower allpass filter: even input -> odd output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[9];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[8] + diff * kResampleAllpass[1][0];
+ state[8] = tmp0;
+ diff = tmp1 - state[10];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[9] + diff * kResampleAllpass[1][1];
+ state[9] = tmp1;
+ diff = tmp0 - state[11];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[11] = state[10] + diff * kResampleAllpass[1][2];
+ state[10] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[11] >> 1;
+ }
+
+ // upper allpass filter: odd input -> odd output samples
+ in++;
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[13];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[12] + diff * kResampleAllpass[0][0];
+ state[12] = tmp0;
+ diff = tmp1 - state[14];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[13] + diff * kResampleAllpass[0][1];
+ state[13] = tmp1;
+ diff = tmp0 - state[15];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[15] = state[14] + diff * kResampleAllpass[0][2];
+ state[14] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
+ }
+}
+
+// lowpass filter
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384)
+// output: WebRtc_Word32 (normalized, not saturated)
+// state: filter state array; length = 8
+void WebRtcSpl_LPBy2IntToInt(const WebRtc_Word32* in, WebRtc_Word32 len, WebRtc_Word32* out,
+ WebRtc_Word32* state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter: odd input -> even output samples
+ in++;
+ // initial state of polyphase delay element
+ tmp0 = state[12];
+ for (i = 0; i < len; i++)
+ {
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3] >> 1;
+ tmp0 = in[i << 1];
+ }
+ in--;
+
+ // upper allpass filter: even input -> even output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
+ }
+
+ // switch to odd output samples
+ out++;
+
+ // lower allpass filter: even input -> odd output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[9];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[8] + diff * kResampleAllpass[1][0];
+ state[8] = tmp0;
+ diff = tmp1 - state[10];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[9] + diff * kResampleAllpass[1][1];
+ state[9] = tmp1;
+ diff = tmp0 - state[11];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[11] = state[10] + diff * kResampleAllpass[1][2];
+ state[10] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[11] >> 1;
+ }
+
+ // upper allpass filter: odd input -> odd output samples
+ in++;
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[13];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[12] + diff * kResampleAllpass[0][0];
+ state[12] = tmp0;
+ diff = tmp1 - state[14];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[13] + diff * kResampleAllpass[0][1];
+ state[13] = tmp1;
+ diff = tmp0 - state[15];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[15] = state[14] + diff * kResampleAllpass[0][2];
+ state[14] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
+ }
+}
diff --git a/common_audio/signal_processing/resample_by_2_internal.h b/common_audio/signal_processing/resample_by_2_internal.h
new file mode 100644
index 0000000..b6ac9f0
--- /dev/null
+++ b/common_audio/signal_processing/resample_by_2_internal.h
@@ -0,0 +1,47 @@
+/*
+ * 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 header file contains some internal resampling functions.
+ *
+ */
+
+#ifndef WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
+#define WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
+
+#include "typedefs.h"
+
+/*******************************************************************
+ * resample_by_2_fast.c
+ * Functions for internal use in the other resample functions
+ ******************************************************************/
+void WebRtcSpl_DownBy2IntToShort(WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word16 *out,
+ WebRtc_Word32 *state);
+
+void WebRtcSpl_DownBy2ShortToInt(const WebRtc_Word16 *in, WebRtc_Word32 len,
+ WebRtc_Word32 *out, WebRtc_Word32 *state);
+
+void WebRtcSpl_UpBy2ShortToInt(const WebRtc_Word16 *in, WebRtc_Word32 len,
+ WebRtc_Word32 *out, WebRtc_Word32 *state);
+
+void WebRtcSpl_UpBy2IntToInt(const WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word32 *out,
+ WebRtc_Word32 *state);
+
+void WebRtcSpl_UpBy2IntToShort(const WebRtc_Word32 *in, WebRtc_Word32 len,
+ WebRtc_Word16 *out, WebRtc_Word32 *state);
+
+void WebRtcSpl_LPBy2ShortToInt(const WebRtc_Word16* in, WebRtc_Word32 len,
+ WebRtc_Word32* out, WebRtc_Word32* state);
+
+void WebRtcSpl_LPBy2IntToInt(const WebRtc_Word32* in, WebRtc_Word32 len, WebRtc_Word32* out,
+ WebRtc_Word32* state);
+
+#endif // WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
diff --git a/common_audio/signal_processing/resample_fractional.c b/common_audio/signal_processing/resample_fractional.c
new file mode 100644
index 0000000..51003d4
--- /dev/null
+++ b/common_audio/signal_processing/resample_fractional.c
@@ -0,0 +1,242 @@
+/*
+ * 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 functions between 48, 44, 32 and 24 kHz.
+ * The description headers can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+// interpolation coefficients
+static const WebRtc_Word16 kCoefficients48To32[2][8] = {
+ {778, -2050, 1087, 23285, 12903, -3783, 441, 222},
+ {222, 441, -3783, 12903, 23285, 1087, -2050, 778}
+};
+
+static const WebRtc_Word16 kCoefficients32To24[3][8] = {
+ {767, -2362, 2434, 24406, 10620, -3838, 721, 90},
+ {386, -381, -2646, 19062, 19062, -2646, -381, 386},
+ {90, 721, -3838, 10620, 24406, 2434, -2362, 767}
+};
+
+static const WebRtc_Word16 kCoefficients44To32[4][9] = {
+ {117, -669, 2245, -6183, 26267, 13529, -3245, 845, -138},
+ {-101, 612, -2283, 8532, 29790, -5138, 1789, -524, 91},
+ {50, -292, 1016, -3064, 32010, 3933, -1147, 315, -53},
+ {-156, 974, -3863, 18603, 21691, -6246, 2353, -712, 126}
+};
+
+// Resampling ratio: 2/3
+// input: WebRtc_Word32 (normalized, not saturated) :: size 3 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 2 * K
+// K: number of blocks
+
+void WebRtcSpl_Resample48khzTo32khz(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (3 input samples -> 2 output samples);
+ // process in sub blocks of size 3 samples.
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ tmp = 1 << 14;
+ tmp += kCoefficients48To32[0][0] * In[0];
+ tmp += kCoefficients48To32[0][1] * In[1];
+ tmp += kCoefficients48To32[0][2] * In[2];
+ tmp += kCoefficients48To32[0][3] * In[3];
+ tmp += kCoefficients48To32[0][4] * In[4];
+ tmp += kCoefficients48To32[0][5] * In[5];
+ tmp += kCoefficients48To32[0][6] * In[6];
+ tmp += kCoefficients48To32[0][7] * In[7];
+ Out[0] = tmp;
+
+ tmp = 1 << 14;
+ tmp += kCoefficients48To32[1][0] * In[1];
+ tmp += kCoefficients48To32[1][1] * In[2];
+ tmp += kCoefficients48To32[1][2] * In[3];
+ tmp += kCoefficients48To32[1][3] * In[4];
+ tmp += kCoefficients48To32[1][4] * In[5];
+ tmp += kCoefficients48To32[1][5] * In[6];
+ tmp += kCoefficients48To32[1][6] * In[7];
+ tmp += kCoefficients48To32[1][7] * In[8];
+ Out[1] = tmp;
+
+ // update pointers
+ In += 3;
+ Out += 2;
+ }
+}
+
+// Resampling ratio: 3/4
+// input: WebRtc_Word32 (normalized, not saturated) :: size 4 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 3 * K
+// K: number of blocks
+
+void WebRtcSpl_Resample32khzTo24khz(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (4 input samples -> 3 output samples);
+ // process in sub blocks of size 4 samples.
+ WebRtc_Word32 m;
+ WebRtc_Word32 tmp;
+
+ for (m = 0; m < K; m++)
+ {
+ tmp = 1 << 14;
+ tmp += kCoefficients32To24[0][0] * In[0];
+ tmp += kCoefficients32To24[0][1] * In[1];
+ tmp += kCoefficients32To24[0][2] * In[2];
+ tmp += kCoefficients32To24[0][3] * In[3];
+ tmp += kCoefficients32To24[0][4] * In[4];
+ tmp += kCoefficients32To24[0][5] * In[5];
+ tmp += kCoefficients32To24[0][6] * In[6];
+ tmp += kCoefficients32To24[0][7] * In[7];
+ Out[0] = tmp;
+
+ tmp = 1 << 14;
+ tmp += kCoefficients32To24[1][0] * In[1];
+ tmp += kCoefficients32To24[1][1] * In[2];
+ tmp += kCoefficients32To24[1][2] * In[3];
+ tmp += kCoefficients32To24[1][3] * In[4];
+ tmp += kCoefficients32To24[1][4] * In[5];
+ tmp += kCoefficients32To24[1][5] * In[6];
+ tmp += kCoefficients32To24[1][6] * In[7];
+ tmp += kCoefficients32To24[1][7] * In[8];
+ Out[1] = tmp;
+
+ tmp = 1 << 14;
+ tmp += kCoefficients32To24[2][0] * In[2];
+ tmp += kCoefficients32To24[2][1] * In[3];
+ tmp += kCoefficients32To24[2][2] * In[4];
+ tmp += kCoefficients32To24[2][3] * In[5];
+ tmp += kCoefficients32To24[2][4] * In[6];
+ tmp += kCoefficients32To24[2][5] * In[7];
+ tmp += kCoefficients32To24[2][6] * In[8];
+ tmp += kCoefficients32To24[2][7] * In[9];
+ Out[2] = tmp;
+
+ // update pointers
+ In += 4;
+ Out += 3;
+ }
+}
+
+//
+// fractional resampling filters
+// Fout = 11/16 * Fin
+// Fout = 8/11 * Fin
+//
+
+// compute two inner-products and store them to output array
+static void WebRtcSpl_ResampDotProduct(const WebRtc_Word32 *in1, const WebRtc_Word32 *in2,
+ const WebRtc_Word16 *coef_ptr, WebRtc_Word32 *out1,
+ WebRtc_Word32 *out2)
+{
+ WebRtc_Word32 tmp1 = 16384;
+ WebRtc_Word32 tmp2 = 16384;
+ WebRtc_Word16 coef;
+
+ coef = coef_ptr[0];
+ tmp1 += coef * in1[0];
+ tmp2 += coef * in2[-0];
+
+ coef = coef_ptr[1];
+ tmp1 += coef * in1[1];
+ tmp2 += coef * in2[-1];
+
+ coef = coef_ptr[2];
+ tmp1 += coef * in1[2];
+ tmp2 += coef * in2[-2];
+
+ coef = coef_ptr[3];
+ tmp1 += coef * in1[3];
+ tmp2 += coef * in2[-3];
+
+ coef = coef_ptr[4];
+ tmp1 += coef * in1[4];
+ tmp2 += coef * in2[-4];
+
+ coef = coef_ptr[5];
+ tmp1 += coef * in1[5];
+ tmp2 += coef * in2[-5];
+
+ coef = coef_ptr[6];
+ tmp1 += coef * in1[6];
+ tmp2 += coef * in2[-6];
+
+ coef = coef_ptr[7];
+ tmp1 += coef * in1[7];
+ tmp2 += coef * in2[-7];
+
+ coef = coef_ptr[8];
+ *out1 = tmp1 + coef * in1[8];
+ *out2 = tmp2 + coef * in2[-8];
+}
+
+// Resampling ratio: 8/11
+// input: WebRtc_Word32 (normalized, not saturated) :: size 11 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 8 * K
+// K: number of blocks
+
+void WebRtcSpl_Resample44khzTo32khz(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (11 input samples -> 8 output samples);
+ // process in sub blocks of size 11 samples.
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ tmp = 1 << 14;
+
+ // first output sample
+ Out[0] = ((WebRtc_Word32)In[3] << 15) + tmp;
+
+ // sum and accumulate filter coefficients and input samples
+ tmp += kCoefficients44To32[3][0] * In[5];
+ tmp += kCoefficients44To32[3][1] * In[6];
+ tmp += kCoefficients44To32[3][2] * In[7];
+ tmp += kCoefficients44To32[3][3] * In[8];
+ tmp += kCoefficients44To32[3][4] * In[9];
+ tmp += kCoefficients44To32[3][5] * In[10];
+ tmp += kCoefficients44To32[3][6] * In[11];
+ tmp += kCoefficients44To32[3][7] * In[12];
+ tmp += kCoefficients44To32[3][8] * In[13];
+ Out[4] = tmp;
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_ResampDotProduct(&In[0], &In[17], kCoefficients44To32[0], &Out[1], &Out[7]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_ResampDotProduct(&In[2], &In[15], kCoefficients44To32[1], &Out[2], &Out[6]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_ResampDotProduct(&In[3], &In[14], kCoefficients44To32[2], &Out[3], &Out[5]);
+
+ // update pointers
+ In += 11;
+ Out += 8;
+ }
+}
diff --git a/common_audio/signal_processing/signal_processing.gypi b/common_audio/signal_processing/signal_processing.gypi
new file mode 100644
index 0000000..b09c767
--- /dev/null
+++ b/common_audio/signal_processing/signal_processing.gypi
@@ -0,0 +1,124 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'signal_processing',
+ 'type': '<(library)',
+ 'include_dirs': [
+ 'include',
+ ],
+ 'dependencies': [
+ '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ 'include',
+ ],
+ },
+ 'sources': [
+ 'include/real_fft.h',
+ 'include/signal_processing_library.h',
+ 'include/spl_inl.h',
+ 'auto_corr_to_refl_coef.c',
+ 'auto_correlation.c',
+ 'complex_fft.c',
+ 'complex_bit_reverse.c',
+ 'copy_set_operations.c',
+ 'cross_correlation.c',
+ 'division_operations.c',
+ 'dot_product_with_scale.c',
+ 'downsample_fast.c',
+ 'energy.c',
+ 'filter_ar.c',
+ 'filter_ar_fast_q12.c',
+ 'filter_ma_fast_q12.c',
+ 'get_hanning_window.c',
+ 'get_scaling_square.c',
+ 'ilbc_specific_functions.c',
+ 'levinson_durbin.c',
+ 'lpc_to_refl_coef.c',
+ 'min_max_operations.c',
+ 'randomization_functions.c',
+ 'refl_coef_to_lpc.c',
+ 'real_fft.c',
+ 'resample.c',
+ 'resample_48khz.c',
+ 'resample_by_2.c',
+ 'resample_by_2_internal.c',
+ 'resample_by_2_internal.h',
+ 'resample_fractional.c',
+ 'spl_init.c',
+ 'spl_sqrt.c',
+ 'spl_sqrt_floor.c',
+ 'spl_version.c',
+ 'splitting_filter.c',
+ 'sqrt_of_one_minus_x_squared.c',
+ 'vector_scaling_operations.c',
+ ],
+ 'conditions': [
+ ['target_arch=="arm"', {
+ 'sources': [
+ 'complex_bit_reverse_arm.s',
+ 'spl_sqrt_floor_arm.s',
+ ],
+ 'sources!': [
+ 'complex_bit_reverse.c',
+ 'spl_sqrt_floor.c',
+ ],
+ 'conditions': [
+ ['armv7==1', {
+ 'dependencies': ['signal_processing_neon',],
+ 'sources': [
+ 'filter_ar_fast_q12_armv7.s',
+ ],
+ 'sources!': [
+ 'filter_ar_fast_q12.c',
+ ],
+ }],
+ ],
+ }],
+ ],
+ }, # spl
+ ], # targets
+ 'conditions': [
+ ['include_tests==1', {
+ 'targets': [
+ {
+ 'target_name': 'signal_processing_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'signal_processing',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ '<(webrtc_root)/test/test.gyp:test_support_main',
+ ],
+ 'sources': [
+ 'real_fft_unittest.cc',
+ 'signal_processing_unittest.cc',
+ ],
+ }, # spl_unittests
+ ], # targets
+ }], # include_tests
+ ['target_arch=="arm" and armv7==1', {
+ 'targets': [
+ {
+ 'target_name': 'signal_processing_neon',
+ 'type': '<(library)',
+ 'includes': ['../../build/arm_neon.gypi',],
+ 'sources': [
+ 'cross_correlation_neon.s',
+ 'downsample_fast_neon.s',
+ 'min_max_operations_neon.s',
+ 'vector_scaling_operations_neon.s',
+ ],
+ },
+ ],
+ }], # 'target_arch=="arm" and armv7==1'
+ ], # conditions
+}
diff --git a/common_audio/signal_processing/signal_processing_unittest.cc b/common_audio/signal_processing/signal_processing_unittest.cc
new file mode 100644
index 0000000..d5026fb
--- /dev/null
+++ b/common_audio/signal_processing/signal_processing_unittest.cc
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "signal_processing_library.h"
+#include "gtest/gtest.h"
+
+static const int kVector16Size = 9;
+static const int16_t vector16[kVector16Size] = {1, -15511, 4323, 1963,
+ WEBRTC_SPL_WORD16_MAX, 0, WEBRTC_SPL_WORD16_MIN + 5, -3333, 345};
+
+class SplTest : public testing::Test {
+ protected:
+ SplTest() {
+ WebRtcSpl_Init();
+ }
+ virtual ~SplTest() {
+ }
+};
+
+TEST_F(SplTest, MacroTest) {
+ // Macros with inputs.
+ int A = 10;
+ int B = 21;
+ int a = -3;
+ int b = WEBRTC_SPL_WORD32_MAX;
+ int nr = 2;
+ int d_ptr2 = 0;
+
+ EXPECT_EQ(10, WEBRTC_SPL_MIN(A, B));
+ EXPECT_EQ(21, WEBRTC_SPL_MAX(A, B));
+
+ EXPECT_EQ(3, WEBRTC_SPL_ABS_W16(a));
+ EXPECT_EQ(3, WEBRTC_SPL_ABS_W32(a));
+ EXPECT_EQ(0, WEBRTC_SPL_GET_BYTE(&B, nr));
+ WEBRTC_SPL_SET_BYTE(&d_ptr2, 1, nr);
+ EXPECT_EQ(65536, d_ptr2);
+
+ EXPECT_EQ(-63, WEBRTC_SPL_MUL(a, B));
+ EXPECT_EQ(-2147483645, WEBRTC_SPL_MUL(a, b));
+ EXPECT_EQ(2147483651u, WEBRTC_SPL_UMUL(a, b));
+ b = WEBRTC_SPL_WORD16_MAX >> 1;
+ EXPECT_EQ(65535u, WEBRTC_SPL_UMUL_RSFT16(a, b));
+ EXPECT_EQ(1073627139u, WEBRTC_SPL_UMUL_16_16(a, b));
+ EXPECT_EQ(16382u, WEBRTC_SPL_UMUL_16_16_RSFT16(a, b));
+ EXPECT_EQ(4294918147u, WEBRTC_SPL_UMUL_32_16(a, b));
+ EXPECT_EQ(65535u, WEBRTC_SPL_UMUL_32_16_RSFT16(a, b));
+ EXPECT_EQ(-49149, WEBRTC_SPL_MUL_16_U16(a, b));
+
+ a = b;
+ b = -3;
+ EXPECT_EQ(-5461, WEBRTC_SPL_DIV(a, b));
+ EXPECT_EQ(0u, WEBRTC_SPL_UDIV(a, b));
+
+ EXPECT_EQ(-1, WEBRTC_SPL_MUL_16_32_RSFT16(a, b));
+ EXPECT_EQ(-1, WEBRTC_SPL_MUL_16_32_RSFT15(a, b));
+ EXPECT_EQ(-3, WEBRTC_SPL_MUL_16_32_RSFT14(a, b));
+ EXPECT_EQ(-24, WEBRTC_SPL_MUL_16_32_RSFT11(a, b));
+
+ int a32 = WEBRTC_SPL_WORD32_MAX;
+ int a32a = (WEBRTC_SPL_WORD32_MAX >> 16);
+ int a32b = (WEBRTC_SPL_WORD32_MAX & 0x0000ffff);
+ EXPECT_EQ(5, WEBRTC_SPL_MUL_32_32_RSFT32(a32a, a32b, A));
+ EXPECT_EQ(5, WEBRTC_SPL_MUL_32_32_RSFT32BI(a32, A));
+
+ EXPECT_EQ(-12288, WEBRTC_SPL_MUL_16_16_RSFT(a, b, 2));
+ EXPECT_EQ(-12287, WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(a, b, 2));
+ EXPECT_EQ(-1, WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(a, b));
+
+ EXPECT_EQ(16380, WEBRTC_SPL_ADD_SAT_W32(a, b));
+ EXPECT_EQ(21, WEBRTC_SPL_SAT(a, A, B));
+ EXPECT_EQ(21, WEBRTC_SPL_SAT(a, B, A));
+ EXPECT_EQ(-49149, WEBRTC_SPL_MUL_32_16(a, b));
+
+ EXPECT_EQ(16386, WEBRTC_SPL_SUB_SAT_W32(a, b));
+ EXPECT_EQ(16380, WEBRTC_SPL_ADD_SAT_W16(a, b));
+ EXPECT_EQ(16386, WEBRTC_SPL_SUB_SAT_W16(a, b));
+
+ EXPECT_TRUE(WEBRTC_SPL_IS_NEG(b));
+
+ // Shifting with negative numbers allowed
+ int shift_amount = 1; // Workaround compiler warning using variable here.
+ // Positive means left shift
+ EXPECT_EQ(32766, WEBRTC_SPL_SHIFT_W16(a, shift_amount));
+ EXPECT_EQ(32766, WEBRTC_SPL_SHIFT_W32(a, shift_amount));
+
+ // Shifting with negative numbers not allowed
+ // We cannot do casting here due to signed/unsigned problem
+ EXPECT_EQ(8191, WEBRTC_SPL_RSHIFT_W16(a, 1));
+ EXPECT_EQ(32766, WEBRTC_SPL_LSHIFT_W16(a, 1));
+ EXPECT_EQ(8191, WEBRTC_SPL_RSHIFT_W32(a, 1));
+ EXPECT_EQ(32766, WEBRTC_SPL_LSHIFT_W32(a, 1));
+
+ EXPECT_EQ(8191, WEBRTC_SPL_RSHIFT_U16(a, 1));
+ EXPECT_EQ(32766, WEBRTC_SPL_LSHIFT_U16(a, 1));
+ EXPECT_EQ(8191u, WEBRTC_SPL_RSHIFT_U32(a, 1));
+ EXPECT_EQ(32766u, WEBRTC_SPL_LSHIFT_U32(a, 1));
+
+ EXPECT_EQ(1470, WEBRTC_SPL_RAND(A));
+
+ EXPECT_EQ(-49149, WEBRTC_SPL_MUL_16_16(a, b));
+ EXPECT_EQ(1073676289, WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_WORD16_MAX,
+ WEBRTC_SPL_WORD16_MAX));
+ EXPECT_EQ(1073709055, WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MAX,
+ WEBRTC_SPL_WORD32_MAX));
+ EXPECT_EQ(1073741824, WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MIN,
+ WEBRTC_SPL_WORD32_MIN));
+#ifdef WEBRTC_ARCH_ARM_V7
+ EXPECT_EQ(-1073741824,
+ WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MIN,
+ WEBRTC_SPL_WORD32_MAX));
+ EXPECT_EQ(0x3fffffff, WEBRTC_SPL_MUL_32_32_RSFT32(WEBRTC_SPL_WORD16_MAX,
+ 0xffff, WEBRTC_SPL_WORD32_MAX));
+ EXPECT_EQ(0x3fffffff, WEBRTC_SPL_MUL_32_32_RSFT32BI(WEBRTC_SPL_WORD32_MAX,
+ WEBRTC_SPL_WORD32_MAX));
+#else
+ EXPECT_EQ(-1073741823,
+ WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MIN,
+ WEBRTC_SPL_WORD32_MAX));
+ EXPECT_EQ(0x3fff7ffe, WEBRTC_SPL_MUL_32_32_RSFT32(WEBRTC_SPL_WORD16_MAX,
+ 0xffff, WEBRTC_SPL_WORD32_MAX));
+ EXPECT_EQ(0x3ffffffd, WEBRTC_SPL_MUL_32_32_RSFT32BI(WEBRTC_SPL_WORD32_MAX,
+ WEBRTC_SPL_WORD32_MAX));
+#endif
+}
+
+TEST_F(SplTest, InlineTest) {
+ WebRtc_Word16 a16 = 121;
+ WebRtc_Word16 b16 = -17;
+ WebRtc_Word32 a32 = 111121;
+ WebRtc_Word32 b32 = -1711;
+ char bVersion[8];
+
+ EXPECT_EQ(17, WebRtcSpl_GetSizeInBits(a32));
+
+ EXPECT_EQ(0, WebRtcSpl_NormW32(0));
+ EXPECT_EQ(31, WebRtcSpl_NormW32(-1));
+ EXPECT_EQ(0, WebRtcSpl_NormW32(WEBRTC_SPL_WORD32_MIN));
+ EXPECT_EQ(14, WebRtcSpl_NormW32(a32));
+
+ EXPECT_EQ(0, WebRtcSpl_NormW16(0));
+ EXPECT_EQ(15, WebRtcSpl_NormW16(-1));
+ EXPECT_EQ(0, WebRtcSpl_NormW16(WEBRTC_SPL_WORD16_MIN));
+ EXPECT_EQ(4, WebRtcSpl_NormW16(b32));
+
+ EXPECT_EQ(0, WebRtcSpl_NormU32(0));
+ EXPECT_EQ(0, WebRtcSpl_NormU32(-1));
+ EXPECT_EQ(0, WebRtcSpl_NormU32(WEBRTC_SPL_WORD32_MIN));
+ EXPECT_EQ(15, WebRtcSpl_NormU32(a32));
+
+ EXPECT_EQ(104, WebRtcSpl_AddSatW16(a16, b16));
+ EXPECT_EQ(138, WebRtcSpl_SubSatW16(a16, b16));
+
+ EXPECT_EQ(109410, WebRtcSpl_AddSatW32(a32, b32));
+ EXPECT_EQ(112832, WebRtcSpl_SubSatW32(a32, b32));
+
+ a32 = 0x80000000;
+ b32 = 0x80000000;
+ // Cast to signed int to avoid compiler complaint on gtest.h.
+ EXPECT_EQ(static_cast<int>(0x80000000), WebRtcSpl_AddSatW32(a32, b32));
+ a32 = 0x7fffffff;
+ b32 = 0x7fffffff;
+ EXPECT_EQ(0x7fffffff, WebRtcSpl_AddSatW32(a32, b32));
+ a32 = 0;
+ b32 = 0x80000000;
+ EXPECT_EQ(0x7fffffff, WebRtcSpl_SubSatW32(a32, b32));
+ a32 = 0x7fffffff;
+ b32 = 0x80000000;
+ EXPECT_EQ(0x7fffffff, WebRtcSpl_SubSatW32(a32, b32));
+ a32 = 0x80000000;
+ b32 = 0x7fffffff;
+ EXPECT_EQ(static_cast<int>(0x80000000), WebRtcSpl_SubSatW32(a32, b32));
+
+ EXPECT_EQ(0, WebRtcSpl_get_version(bVersion, 8));
+}
+
+TEST_F(SplTest, MathOperationsTest) {
+ int A = 1134567892;
+ WebRtc_Word32 num = 117;
+ WebRtc_Word32 den = -5;
+ WebRtc_UWord16 denU = 5;
+ EXPECT_EQ(33700, WebRtcSpl_Sqrt(A));
+ EXPECT_EQ(33683, WebRtcSpl_SqrtFloor(A));
+
+
+ EXPECT_EQ(-91772805, WebRtcSpl_DivResultInQ31(den, num));
+ EXPECT_EQ(-23, WebRtcSpl_DivW32W16ResW16(num, (WebRtc_Word16)den));
+ EXPECT_EQ(-23, WebRtcSpl_DivW32W16(num, (WebRtc_Word16)den));
+ EXPECT_EQ(23u, WebRtcSpl_DivU32U16(num, denU));
+ EXPECT_EQ(0, WebRtcSpl_DivW32HiLow(128, 0, 256));
+}
+
+TEST_F(SplTest, BasicArrayOperationsTest) {
+ const int kVectorSize = 4;
+ int B[] = {4, 12, 133, 1100};
+ WebRtc_UWord8 b8[kVectorSize];
+ WebRtc_Word16 b16[kVectorSize];
+ WebRtc_Word32 b32[kVectorSize];
+
+ WebRtc_UWord8 bTmp8[kVectorSize];
+ WebRtc_Word16 bTmp16[kVectorSize];
+ WebRtc_Word32 bTmp32[kVectorSize];
+
+ WebRtcSpl_MemSetW16(b16, 3, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(3, b16[kk]);
+ }
+ EXPECT_EQ(kVectorSize, WebRtcSpl_ZerosArrayW16(b16, kVectorSize));
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(0, b16[kk]);
+ }
+ EXPECT_EQ(kVectorSize, WebRtcSpl_OnesArrayW16(b16, kVectorSize));
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(1, b16[kk]);
+ }
+ WebRtcSpl_MemSetW32(b32, 3, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(3, b32[kk]);
+ }
+ EXPECT_EQ(kVectorSize, WebRtcSpl_ZerosArrayW32(b32, kVectorSize));
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(0, b32[kk]);
+ }
+ EXPECT_EQ(kVectorSize, WebRtcSpl_OnesArrayW32(b32, kVectorSize));
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(1, b32[kk]);
+ }
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ bTmp8[kk] = (WebRtc_Word8)kk;
+ bTmp16[kk] = (WebRtc_Word16)kk;
+ bTmp32[kk] = (WebRtc_Word32)kk;
+ }
+ WEBRTC_SPL_MEMCPY_W8(b8, bTmp8, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(b8[kk], bTmp8[kk]);
+ }
+ WEBRTC_SPL_MEMCPY_W16(b16, bTmp16, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(b16[kk], bTmp16[kk]);
+ }
+// WEBRTC_SPL_MEMCPY_W32(b32, bTmp32, kVectorSize);
+// for (int kk = 0; kk < kVectorSize; ++kk) {
+// EXPECT_EQ(b32[kk], bTmp32[kk]);
+// }
+ EXPECT_EQ(2, WebRtcSpl_CopyFromEndW16(b16, kVectorSize, 2, bTmp16));
+ for (int kk = 0; kk < 2; ++kk) {
+ EXPECT_EQ(kk+2, bTmp16[kk]);
+ }
+
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ b32[kk] = B[kk];
+ b16[kk] = (WebRtc_Word16)B[kk];
+ }
+ WebRtcSpl_VectorBitShiftW32ToW16(bTmp16, kVectorSize, b32, 1);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((B[kk]>>1), bTmp16[kk]);
+ }
+ WebRtcSpl_VectorBitShiftW16(bTmp16, kVectorSize, b16, 1);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((B[kk]>>1), bTmp16[kk]);
+ }
+ WebRtcSpl_VectorBitShiftW32(bTmp32, kVectorSize, b32, 1);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((B[kk]>>1), bTmp32[kk]);
+ }
+
+ WebRtcSpl_MemCpyReversedOrder(&bTmp16[3], b16, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(b16[3-kk], bTmp16[kk]);
+ }
+}
+
+TEST_F(SplTest, ExeptionsHandlingMinMaxOperationsTest) {
+ // Test how the functions handle exceptional cases.
+ const int kVectorSize = 2;
+ int16_t vector16[kVectorSize] = {0};
+ int32_t vector32[kVectorSize] = {0};
+
+ EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW16(vector16, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW16(NULL, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MIN, WebRtcSpl_MaxValueW16(vector16, 0));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MIN, WebRtcSpl_MaxValueW16(NULL, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, WebRtcSpl_MinValueW16(vector16, 0));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, WebRtcSpl_MinValueW16(NULL, kVectorSize));
+ EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW32(vector32, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW32(NULL, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MIN, WebRtcSpl_MaxValueW32(vector32, 0));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MIN, WebRtcSpl_MaxValueW32(NULL, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, WebRtcSpl_MinValueW32(vector32, 0));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, WebRtcSpl_MinValueW32(NULL, kVectorSize));
+ EXPECT_EQ(-1, WebRtcSpl_MaxAbsIndexW16(vector16, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MaxAbsIndexW16(NULL, kVectorSize));
+ EXPECT_EQ(-1, WebRtcSpl_MaxIndexW16(vector16, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MaxIndexW16(NULL, kVectorSize));
+ EXPECT_EQ(-1, WebRtcSpl_MaxIndexW32(vector32, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MaxIndexW32(NULL, kVectorSize));
+ EXPECT_EQ(-1, WebRtcSpl_MinIndexW16(vector16, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MinIndexW16(NULL, kVectorSize));
+ EXPECT_EQ(-1, WebRtcSpl_MinIndexW32(vector32, 0));
+ EXPECT_EQ(-1, WebRtcSpl_MinIndexW32(NULL, kVectorSize));
+}
+
+TEST_F(SplTest, MinMaxOperationsTest) {
+ const int kVectorSize = 17;
+
+ // Vectors to test the cases where minimum values have to be caught
+ // outside of the unrolled loops in ARM-Neon.
+ int16_t vector16[kVectorSize] = {-1, 7485, 0, 3333,
+ -18283, 0, 12334, -29871, 988, -3333,
+ 345, -456, 222, 999, 888, 8774, WEBRTC_SPL_WORD16_MIN};
+ int32_t vector32[kVectorSize] = {-1, 0, 283211, 3333,
+ 8712345, 0, -3333, 89345, -374585456, 222, 999, 122345334,
+ -12389756, -987329871, 888, -2, WEBRTC_SPL_WORD32_MIN};
+
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MIN,
+ WebRtcSpl_MinValueW16(vector16, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MIN,
+ WebRtcSpl_MinValueW32(vector32, kVectorSize));
+ EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MinIndexW16(vector16, kVectorSize));
+ EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MinIndexW32(vector32, kVectorSize));
+
+ // Test the cases where maximum values have to be caught
+ // outside of the unrolled loops in ARM-Neon.
+ vector16[kVectorSize - 1] = WEBRTC_SPL_WORD16_MAX;
+ vector32[kVectorSize - 1] = WEBRTC_SPL_WORD32_MAX;
+
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MAX,
+ WebRtcSpl_MaxAbsValueW16(vector16, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MAX,
+ WebRtcSpl_MaxValueW16(vector16, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MAX,
+ WebRtcSpl_MaxAbsValueW32(vector32, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MAX,
+ WebRtcSpl_MaxValueW32(vector32, kVectorSize));
+ EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MaxAbsIndexW16(vector16, kVectorSize));
+ EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MaxIndexW16(vector16, kVectorSize));
+ EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MaxIndexW32(vector32, kVectorSize));
+
+ // Test the cases where multiple maximum and minimum values are present.
+ vector16[1] = WEBRTC_SPL_WORD16_MAX;
+ vector16[6] = WEBRTC_SPL_WORD16_MIN;
+ vector16[11] = WEBRTC_SPL_WORD16_MIN;
+ vector32[1] = WEBRTC_SPL_WORD32_MAX;
+ vector32[6] = WEBRTC_SPL_WORD32_MIN;
+ vector32[11] = WEBRTC_SPL_WORD32_MIN;
+
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MAX,
+ WebRtcSpl_MaxAbsValueW16(vector16, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MAX,
+ WebRtcSpl_MaxValueW16(vector16, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD16_MIN,
+ WebRtcSpl_MinValueW16(vector16, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MAX,
+ WebRtcSpl_MaxAbsValueW32(vector32, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MAX,
+ WebRtcSpl_MaxValueW32(vector32, kVectorSize));
+ EXPECT_EQ(WEBRTC_SPL_WORD32_MIN,
+ WebRtcSpl_MinValueW32(vector32, kVectorSize));
+ EXPECT_EQ(6, WebRtcSpl_MaxAbsIndexW16(vector16, kVectorSize));
+ EXPECT_EQ(1, WebRtcSpl_MaxIndexW16(vector16, kVectorSize));
+ EXPECT_EQ(1, WebRtcSpl_MaxIndexW32(vector32, kVectorSize));
+ EXPECT_EQ(6, WebRtcSpl_MinIndexW16(vector16, kVectorSize));
+ EXPECT_EQ(6, WebRtcSpl_MinIndexW32(vector32, kVectorSize));
+}
+
+TEST_F(SplTest, VectorOperationsTest) {
+ const int kVectorSize = 4;
+ int B[] = {4, 12, 133, 1100};
+ WebRtc_Word16 a16[kVectorSize];
+ WebRtc_Word16 b16[kVectorSize];
+ WebRtc_Word16 bTmp16[kVectorSize];
+
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ a16[kk] = B[kk];
+ b16[kk] = B[kk];
+ }
+
+ WebRtcSpl_AffineTransformVector(bTmp16, b16, 3, 7, 2, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((B[kk]*3+7)>>2, bTmp16[kk]);
+ }
+ WebRtcSpl_ScaleAndAddVectorsWithRound(b16, 3, b16, 2, 2, bTmp16, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((B[kk]*3+B[kk]*2+2)>>2, bTmp16[kk]);
+ }
+
+ WebRtcSpl_AddAffineVectorToVector(bTmp16, b16, 3, 7, 2, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(((B[kk]*3+B[kk]*2+2)>>2)+((b16[kk]*3+7)>>2), bTmp16[kk]);
+ }
+
+ WebRtcSpl_ScaleVector(b16, bTmp16, 13, kVectorSize, 2);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]);
+ }
+ WebRtcSpl_ScaleVectorWithSat(b16, bTmp16, 13, kVectorSize, 2);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]);
+ }
+ WebRtcSpl_ScaleAndAddVectors(a16, 13, 2, b16, 7, 2, bTmp16, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(((a16[kk]*13)>>2)+((b16[kk]*7)>>2), bTmp16[kk]);
+ }
+
+ WebRtcSpl_AddVectorsAndShift(bTmp16, a16, b16, kVectorSize, 2);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(B[kk] >> 1, bTmp16[kk]);
+ }
+ WebRtcSpl_ReverseOrderMultArrayElements(bTmp16, a16, &b16[3], kVectorSize, 2);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((a16[kk]*b16[3-kk])>>2, bTmp16[kk]);
+ }
+ WebRtcSpl_ElementwiseVectorMult(bTmp16, a16, b16, kVectorSize, 6);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ((a16[kk]*b16[kk])>>6, bTmp16[kk]);
+ }
+
+ WebRtcSpl_SqrtOfOneMinusXSquared(b16, kVectorSize, bTmp16);
+ for (int kk = 0; kk < kVectorSize - 1; ++kk) {
+ EXPECT_EQ(32767, bTmp16[kk]);
+ }
+ EXPECT_EQ(32749, bTmp16[kVectorSize - 1]);
+
+ EXPECT_EQ(0, WebRtcSpl_GetScalingSquare(b16, kVectorSize, 1));
+}
+
+TEST_F(SplTest, EstimatorsTest) {
+ const int kVectorSize = 4;
+ int B[] = {4, 12, 133, 1100};
+ WebRtc_Word16 b16[kVectorSize];
+ WebRtc_Word32 b32[kVectorSize];
+ WebRtc_Word16 bTmp16[kVectorSize];
+
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ b16[kk] = B[kk];
+ b32[kk] = B[kk];
+ }
+
+ EXPECT_EQ(0, WebRtcSpl_LevinsonDurbin(b32, b16, bTmp16, 2));
+}
+
+TEST_F(SplTest, FilterTest) {
+ const int kVectorSize = 4;
+ const int kFilterOrder = 3;
+ WebRtc_Word16 A[] = {1, 2, 33, 100};
+ WebRtc_Word16 A5[] = {1, 2, 33, 100, -5};
+ WebRtc_Word16 B[] = {4, 12, 133, 110};
+ WebRtc_Word16 data_in[kVectorSize];
+ WebRtc_Word16 data_out[kVectorSize];
+ WebRtc_Word16 bTmp16Low[kVectorSize];
+ WebRtc_Word16 bState[kVectorSize];
+ WebRtc_Word16 bStateLow[kVectorSize];
+
+ WebRtcSpl_ZerosArrayW16(bState, kVectorSize);
+ WebRtcSpl_ZerosArrayW16(bStateLow, kVectorSize);
+
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ data_in[kk] = A[kk];
+ data_out[kk] = 0;
+ }
+
+ // MA filters.
+ // Note that the input data has |kFilterOrder| states before the actual
+ // data (one sample).
+ WebRtcSpl_FilterMAFastQ12(&data_in[kFilterOrder], data_out, B,
+ kFilterOrder + 1, 1);
+ EXPECT_EQ(0, data_out[0]);
+ // AR filters.
+ // Note that the output data has |kFilterOrder| states before the actual
+ // data (one sample).
+ WebRtcSpl_FilterARFastQ12(data_in, &data_out[kFilterOrder], A,
+ kFilterOrder + 1, 1);
+ EXPECT_EQ(0, data_out[kFilterOrder]);
+
+ EXPECT_EQ(kVectorSize, WebRtcSpl_FilterAR(A5,
+ 5,
+ data_in,
+ kVectorSize,
+ bState,
+ kVectorSize,
+ bStateLow,
+ kVectorSize,
+ data_out,
+ bTmp16Low,
+ kVectorSize));
+}
+
+TEST_F(SplTest, RandTest) {
+ const int kVectorSize = 4;
+ WebRtc_Word16 BU[] = {3653, 12446, 8525, 30691};
+ WebRtc_Word16 b16[kVectorSize];
+ WebRtc_UWord32 bSeed = 100000;
+
+ EXPECT_EQ(464449057u, WebRtcSpl_IncreaseSeed(&bSeed));
+ EXPECT_EQ(31565, WebRtcSpl_RandU(&bSeed));
+ EXPECT_EQ(-9786, WebRtcSpl_RandN(&bSeed));
+ EXPECT_EQ(kVectorSize, WebRtcSpl_RandUArray(b16, kVectorSize, &bSeed));
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(BU[kk], b16[kk]);
+ }
+}
+
+TEST_F(SplTest, DotProductWithScaleTest) {
+ EXPECT_EQ(605362796, WebRtcSpl_DotProductWithScale(vector16,
+ vector16, kVector16Size, 2));
+}
+
+TEST_F(SplTest, CrossCorrelationTest) {
+ // Note the function arguments relation specificed by API.
+ const int kCrossCorrelationDimension = 3;
+ const int kShift = 2;
+ const int kStep = 1;
+ const int kSeqDimension = 6;
+
+ const int16_t kVector16[kVector16Size] = {1, 4323, 1963,
+ WEBRTC_SPL_WORD16_MAX, WEBRTC_SPL_WORD16_MIN + 5, -3333, -876, 8483, 142};
+ int32_t vector32[kCrossCorrelationDimension] = {0};
+
+ WebRtcSpl_CrossCorrelation(vector32, vector16, kVector16, kSeqDimension,
+ kCrossCorrelationDimension, kShift, kStep);
+
+ // WebRtcSpl_CrossCorrelationC() and WebRtcSpl_CrossCorrelationNeon()
+ // are not bit-exact.
+ const int32_t kExpected[kCrossCorrelationDimension] =
+ {-266947903, -15579555, -171282001};
+ const int32_t kExpectedNeon[kCrossCorrelationDimension] =
+ {-266947901, -15579553, -171281999};
+ const int32_t* expected = kExpected;
+ if (WebRtcSpl_CrossCorrelation != WebRtcSpl_CrossCorrelationC) {
+ expected = kExpectedNeon;
+ }
+ for (int i = 0; i < kCrossCorrelationDimension; ++i) {
+ EXPECT_EQ(expected[i], vector32[i]);
+ }
+}
+
+TEST_F(SplTest, AutoCorrelationTest) {
+ int scale = 0;
+ int32_t vector32[kVector16Size];
+ const int32_t expected[kVector16Size] = {302681398, 14223410, -121705063,
+ -85221647, -17104971, 61806945, 6644603, -669329, 43};
+
+ EXPECT_EQ(-1, WebRtcSpl_AutoCorrelation(vector16,
+ kVector16Size, kVector16Size + 1, vector32, &scale));
+ EXPECT_EQ(kVector16Size, WebRtcSpl_AutoCorrelation(vector16,
+ kVector16Size, kVector16Size - 1, vector32, &scale));
+ EXPECT_EQ(3, scale);
+ for (int i = 0; i < kVector16Size; ++i) {
+ EXPECT_EQ(expected[i], vector32[i]);
+ }
+}
+
+TEST_F(SplTest, SignalProcessingTest) {
+ const int kVectorSize = 4;
+ int A[] = {1, 2, 33, 100};
+ const WebRtc_Word16 kHanning[4] = { 2399, 8192, 13985, 16384 };
+ WebRtc_Word16 b16[kVectorSize];
+
+ WebRtc_Word16 bTmp16[kVectorSize];
+
+ int bScale = 0;
+
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ b16[kk] = A[kk];
+ }
+
+ // TODO(bjornv): Activate the Reflection Coefficient tests when refactoring.
+// WebRtcSpl_ReflCoefToLpc(b16, kVectorSize, bTmp16);
+//// for (int kk = 0; kk < kVectorSize; ++kk) {
+//// EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
+//// }
+// WebRtcSpl_LpcToReflCoef(bTmp16, kVectorSize, b16);
+//// for (int kk = 0; kk < kVectorSize; ++kk) {
+//// EXPECT_EQ(a16[kk], b16[kk]);
+//// }
+// WebRtcSpl_AutoCorrToReflCoef(b32, kVectorSize, bTmp16);
+//// for (int kk = 0; kk < kVectorSize; ++kk) {
+//// EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
+//// }
+
+ WebRtcSpl_GetHanningWindow(bTmp16, kVectorSize);
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ EXPECT_EQ(kHanning[kk], bTmp16[kk]);
+ }
+
+ for (int kk = 0; kk < kVectorSize; ++kk) {
+ b16[kk] = A[kk];
+ }
+ EXPECT_EQ(11094 , WebRtcSpl_Energy(b16, kVectorSize, &bScale));
+ EXPECT_EQ(0, bScale);
+}
+
+TEST_F(SplTest, FFTTest) {
+ WebRtc_Word16 B[] = {1, 2, 33, 100,
+ 2, 3, 34, 101,
+ 3, 4, 35, 102,
+ 4, 5, 36, 103};
+
+ EXPECT_EQ(0, WebRtcSpl_ComplexFFT(B, 3, 1));
+// for (int kk = 0; kk < 16; ++kk) {
+// EXPECT_EQ(A[kk], B[kk]);
+// }
+ EXPECT_EQ(0, WebRtcSpl_ComplexIFFT(B, 3, 1));
+// for (int kk = 0; kk < 16; ++kk) {
+// EXPECT_EQ(A[kk], B[kk]);
+// }
+ WebRtcSpl_ComplexBitReverse(B, 3);
+ for (int kk = 0; kk < 16; ++kk) {
+ //EXPECT_EQ(A[kk], B[kk]);
+ }
+}
diff --git a/common_audio/signal_processing/spl_init.c b/common_audio/signal_processing/spl_init.c
new file mode 100644
index 0000000..db21e40
--- /dev/null
+++ b/common_audio/signal_processing/spl_init.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+/* The global function contained in this file initializes SPL function
+ * pointers, currently only for ARM platforms.
+ *
+ * Some code came from common/rtcd.c in the WebM project.
+ */
+
+#include "common_audio/signal_processing/include/real_fft.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "system_wrappers/interface/cpu_features_wrapper.h"
+
+/* Declare function pointers. */
+MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16;
+MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32;
+MaxValueW16 WebRtcSpl_MaxValueW16;
+MaxValueW32 WebRtcSpl_MaxValueW32;
+MinValueW16 WebRtcSpl_MinValueW16;
+MinValueW32 WebRtcSpl_MinValueW32;
+CrossCorrelation WebRtcSpl_CrossCorrelation;
+DownsampleFast WebRtcSpl_DownsampleFast;
+ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound;
+RealForwardFFT WebRtcSpl_RealForwardFFT;
+RealInverseFFT WebRtcSpl_RealInverseFFT;
+
+#if defined(WEBRTC_DETECT_ARM_NEON) || !defined(WEBRTC_ARCH_ARM_NEON)
+/* Initialize function pointers to the generic C version. */
+static void InitPointersToC() {
+ WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C;
+ WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C;
+ WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C;
+ WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C;
+ WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C;
+ WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C;
+ WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC;
+ WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC;
+ WebRtcSpl_ScaleAndAddVectorsWithRound =
+ WebRtcSpl_ScaleAndAddVectorsWithRoundC;
+ WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTC;
+ WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTC;
+}
+#endif
+
+#if defined(WEBRTC_DETECT_ARM_NEON) || defined(WEBRTC_ARCH_ARM_NEON)
+/* Initialize function pointers to the Neon version. */
+static void InitPointersToNeon() {
+ WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon;
+ WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon;
+ WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon;
+ WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon;
+ WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon;
+ WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon;
+ WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon;
+ WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon;
+ WebRtcSpl_ScaleAndAddVectorsWithRound =
+ WebRtcSpl_ScaleAndAddVectorsWithRoundNeon;
+ WebRtcSpl_RealForwardFFT = WebRtcSpl_RealForwardFFTNeon;
+ WebRtcSpl_RealInverseFFT = WebRtcSpl_RealInverseFFTNeon;
+}
+#endif
+
+static void InitFunctionPointers(void) {
+#if defined(WEBRTC_DETECT_ARM_NEON)
+ if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
+ InitPointersToNeon();
+ } else {
+ InitPointersToC();
+ }
+#elif defined(WEBRTC_ARCH_ARM_NEON)
+ InitPointersToNeon();
+#else
+ InitPointersToC();
+#endif /* WEBRTC_DETECT_ARM_NEON */
+}
+
+#if defined(WEBRTC_POSIX)
+#include <pthread.h>
+
+static void once(void (*func)(void)) {
+ static pthread_once_t lock = PTHREAD_ONCE_INIT;
+ pthread_once(&lock, func);
+}
+
+#elif defined(_WIN32)
+#include <windows.h>
+
+static void once(void (*func)(void)) {
+ /* Didn't use InitializeCriticalSection() since there's no race-free context
+ * in which to execute it.
+ *
+ * TODO(kma): Change to different implementation (e.g.
+ * InterlockedCompareExchangePointer) to avoid issues similar to
+ * http://code.google.com/p/webm/issues/detail?id=467.
+ */
+ static CRITICAL_SECTION lock = {(void *)-1, -1, 0, 0, 0, 0};
+ static int done = 0;
+
+ EnterCriticalSection(&lock);
+ if (!done) {
+ func();
+ done = 1;
+ }
+ LeaveCriticalSection(&lock);
+}
+
+/* There's no fallback version as an #else block here to ensure thread safety.
+ * In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build
+ * system should pick it up.
+ */
+#endif /* WEBRTC_POSIX */
+
+void WebRtcSpl_Init() {
+ once(InitFunctionPointers);
+}
diff --git a/common_audio/signal_processing/spl_sqrt.c b/common_audio/signal_processing/spl_sqrt.c
new file mode 100644
index 0000000..cfe2cd3
--- /dev/null
+++ b/common_audio/signal_processing/spl_sqrt.c
@@ -0,0 +1,184 @@
+/*
+ * 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 function WebRtcSpl_Sqrt().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_Word32 WebRtcSpl_SqrtLocal(WebRtc_Word32 in);
+
+WebRtc_Word32 WebRtcSpl_SqrtLocal(WebRtc_Word32 in)
+{
+
+ WebRtc_Word16 x_half, t16;
+ WebRtc_Word32 A, B, x2;
+
+ /* The following block performs:
+ y=in/2
+ x=y-2^30
+ x_half=x/2^31
+ t = 1 + (x_half) - 0.5*((x_half)^2) + 0.5*((x_half)^3) - 0.625*((x_half)^4)
+ + 0.875*((x_half)^5)
+ */
+
+ B = in;
+
+ B = WEBRTC_SPL_RSHIFT_W32(B, 1); // B = in/2
+ B = B - ((WebRtc_Word32)0x40000000); // B = in/2 - 1/2
+ x_half = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(B, 16);// x_half = x/2 = (in-1)/2
+ B = B + ((WebRtc_Word32)0x40000000); // B = 1 + x/2
+ B = B + ((WebRtc_Word32)0x40000000); // Add 0.5 twice (since 1.0 does not exist in Q31)
+
+ x2 = ((WebRtc_Word32)x_half) * ((WebRtc_Word32)x_half) * 2; // A = (x/2)^2
+ A = -x2; // A = -(x/2)^2
+ B = B + (A >> 1); // B = 1 + x/2 - 0.5*(x/2)^2
+
+ A = WEBRTC_SPL_RSHIFT_W32(A, 16);
+ A = A * A * 2; // A = (x/2)^4
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16);
+ B = B + WEBRTC_SPL_MUL_16_16(-20480, t16) * 2; // B = B - 0.625*A
+ // After this, B = 1 + x/2 - 0.5*(x/2)^2 - 0.625*(x/2)^4
+
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16);
+ A = WEBRTC_SPL_MUL_16_16(x_half, t16) * 2; // A = (x/2)^5
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16);
+ B = B + WEBRTC_SPL_MUL_16_16(28672, t16) * 2; // B = B + 0.875*A
+ // After this, B = 1 + x/2 - 0.5*(x/2)^2 - 0.625*(x/2)^4 + 0.875*(x/2)^5
+
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(x2, 16);
+ A = WEBRTC_SPL_MUL_16_16(x_half, t16) * 2; // A = x/2^3
+
+ B = B + (A >> 1); // B = B + 0.5*A
+ // After this, B = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 - 0.625*(x/2)^4 + 0.875*(x/2)^5
+
+ B = B + ((WebRtc_Word32)32768); // Round off bit
+
+ return B;
+}
+
+WebRtc_Word32 WebRtcSpl_Sqrt(WebRtc_Word32 value)
+{
+ /*
+ Algorithm:
+
+ Six term Taylor Series is used here to compute the square root of a number
+ y^0.5 = (1+x)^0.5 where x = y-1
+ = 1+(x/2)-0.5*((x/2)^2+0.5*((x/2)^3-0.625*((x/2)^4+0.875*((x/2)^5)
+ 0.5 <= x < 1
+
+ Example of how the algorithm works, with ut=sqrt(in), and
+ with in=73632 and ut=271 (even shift value case):
+
+ in=73632
+ y= in/131072
+ x=y-1
+ t = 1 + (x/2) - 0.5*((x/2)^2) + 0.5*((x/2)^3) - 0.625*((x/2)^4) + 0.875*((x/2)^5)
+ ut=t*(1/sqrt(2))*512
+
+ or:
+
+ in=73632
+ in2=73632*2^14
+ y= in2/2^31
+ x=y-1
+ t = 1 + (x/2) - 0.5*((x/2)^2) + 0.5*((x/2)^3) - 0.625*((x/2)^4) + 0.875*((x/2)^5)
+ ut=t*(1/sqrt(2))
+ ut2=ut*2^9
+
+ which gives:
+
+ in = 73632
+ in2 = 1206386688
+ y = 0.56176757812500
+ x = -0.43823242187500
+ t = 0.74973506527313
+ ut = 0.53014274874797
+ ut2 = 2.714330873589594e+002
+
+ or:
+
+ in=73632
+ in2=73632*2^14
+ y=in2/2
+ x=y-2^30
+ x_half=x/2^31
+ t = 1 + (x_half) - 0.5*((x_half)^2) + 0.5*((x_half)^3) - 0.625*((x_half)^4)
+ + 0.875*((x_half)^5)
+ ut=t*(1/sqrt(2))
+ ut2=ut*2^9
+
+ which gives:
+
+ in = 73632
+ in2 = 1206386688
+ y = 603193344
+ x = -470548480
+ x_half = -0.21911621093750
+ t = 0.74973506527313
+ ut = 0.53014274874797
+ ut2 = 2.714330873589594e+002
+
+ */
+
+ WebRtc_Word16 x_norm, nshift, t16, sh;
+ WebRtc_Word32 A;
+
+ WebRtc_Word16 k_sqrt_2 = 23170; // 1/sqrt2 (==5a82)
+
+ A = value;
+
+ if (A == 0)
+ return (WebRtc_Word32)0; // sqrt(0) = 0
+
+ sh = WebRtcSpl_NormW32(A); // # shifts to normalize A
+ A = WEBRTC_SPL_LSHIFT_W32(A, sh); // Normalize A
+ if (A < (WEBRTC_SPL_WORD32_MAX - 32767))
+ {
+ A = A + ((WebRtc_Word32)32768); // Round off bit
+ } else
+ {
+ A = WEBRTC_SPL_WORD32_MAX;
+ }
+
+ x_norm = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16); // x_norm = AH
+
+ nshift = WEBRTC_SPL_RSHIFT_W16(sh, 1); // nshift = sh>>1
+ nshift = -nshift; // Negate the power for later de-normalization
+
+ A = (WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)x_norm, 16);
+ A = WEBRTC_SPL_ABS_W32(A); // A = abs(x_norm<<16)
+ A = WebRtcSpl_SqrtLocal(A); // A = sqrt(A)
+
+ if ((-2 * nshift) == sh)
+ { // Even shift value case
+
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16); // t16 = AH
+
+ A = WEBRTC_SPL_MUL_16_16(k_sqrt_2, t16) * 2; // A = 1/sqrt(2)*t16
+ A = A + ((WebRtc_Word32)32768); // Round off
+ A = A & ((WebRtc_Word32)0x7fff0000); // Round off
+
+ A = WEBRTC_SPL_RSHIFT_W32(A, 15); // A = A>>16
+
+ } else
+ {
+ A = WEBRTC_SPL_RSHIFT_W32(A, 16); // A = A>>16
+ }
+
+ A = A & ((WebRtc_Word32)0x0000ffff);
+ A = (WebRtc_Word32)WEBRTC_SPL_SHIFT_W32(A, nshift); // De-normalize the result
+
+ return A;
+}
diff --git a/common_audio/signal_processing/spl_sqrt_floor.c b/common_audio/signal_processing/spl_sqrt_floor.c
new file mode 100644
index 0000000..f0e8ae2
--- /dev/null
+++ b/common_audio/signal_processing/spl_sqrt_floor.c
@@ -0,0 +1,54 @@
+/*
+ * Written by Wilco Dijkstra, 1996. Refer to file LICENSE under
+ * trunk/third_party_mods/sqrt_floor.
+ *
+ * Minor modifications in code style for WebRTC, 2012.
+ */
+
+#include "signal_processing_library.h"
+
+/*
+ * Algorithm:
+ * Successive approximation of the equation (root + delta) ^ 2 = N
+ * until delta < 1. If delta < 1 we have the integer part of SQRT (N).
+ * Use delta = 2^i for i = 15 .. 0.
+ *
+ * Output precision is 16 bits. Note for large input values (close to
+ * 0x7FFFFFFF), bit 15 (the highest bit of the low 16-bit half word)
+ * contains the MSB information (a non-sign value). Do with caution
+ * if you need to cast the output to int16_t type.
+ *
+ * If the input value is negative, it returns 0.
+ */
+
+#define WEBRTC_SPL_SQRT_ITER(N) \
+ try1 = root + (1 << (N)); \
+ if (value >= try1 << (N)) \
+ { \
+ value -= try1 << (N); \
+ root |= 2 << (N); \
+ }
+
+int32_t WebRtcSpl_SqrtFloor(int32_t value)
+{
+ int32_t root = 0, try1;
+
+ WEBRTC_SPL_SQRT_ITER (15);
+ WEBRTC_SPL_SQRT_ITER (14);
+ WEBRTC_SPL_SQRT_ITER (13);
+ WEBRTC_SPL_SQRT_ITER (12);
+ WEBRTC_SPL_SQRT_ITER (11);
+ WEBRTC_SPL_SQRT_ITER (10);
+ WEBRTC_SPL_SQRT_ITER ( 9);
+ WEBRTC_SPL_SQRT_ITER ( 8);
+ WEBRTC_SPL_SQRT_ITER ( 7);
+ WEBRTC_SPL_SQRT_ITER ( 6);
+ WEBRTC_SPL_SQRT_ITER ( 5);
+ WEBRTC_SPL_SQRT_ITER ( 4);
+ WEBRTC_SPL_SQRT_ITER ( 3);
+ WEBRTC_SPL_SQRT_ITER ( 2);
+ WEBRTC_SPL_SQRT_ITER ( 1);
+ WEBRTC_SPL_SQRT_ITER ( 0);
+
+ return root >> 1;
+}
diff --git a/common_audio/signal_processing/spl_sqrt_floor_arm.s b/common_audio/signal_processing/spl_sqrt_floor_arm.s
new file mode 100644
index 0000000..a2c5b7d
--- /dev/null
+++ b/common_audio/signal_processing/spl_sqrt_floor_arm.s
@@ -0,0 +1,86 @@
+@ Written by Wilco Dijkstra, 1996. Refer to file LICENSE under
+@ trunk/third_party_mods/sqrt_floor.
+@
+@ Minor modifications in code style for WebRTC, 2012.
+@ Output is bit-exact with the reference C code in spl_sqrt_floor.c.
+
+@ Input : r0 32 bit unsigned integer
+@ Output: r0 = INT (SQRT (r0)), precision is 16 bits
+@ Registers touched: r1, r2
+
+.global WebRtcSpl_SqrtFloor
+
+.align 2
+WebRtcSpl_SqrtFloor:
+ mov r1, #3 << 30
+ mov r2, #1 << 30
+
+ @ unroll for i = 0 .. 15
+
+ cmp r0, r2, ror #2 * 0
+ subhs r0, r0, r2, ror #2 * 0
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 1
+ subhs r0, r0, r2, ror #2 * 1
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 2
+ subhs r0, r0, r2, ror #2 * 2
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 3
+ subhs r0, r0, r2, ror #2 * 3
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 4
+ subhs r0, r0, r2, ror #2 * 4
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 5
+ subhs r0, r0, r2, ror #2 * 5
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 6
+ subhs r0, r0, r2, ror #2 * 6
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 7
+ subhs r0, r0, r2, ror #2 * 7
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 8
+ subhs r0, r0, r2, ror #2 * 8
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 9
+ subhs r0, r0, r2, ror #2 * 9
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 10
+ subhs r0, r0, r2, ror #2 * 10
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 11
+ subhs r0, r0, r2, ror #2 * 11
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 12
+ subhs r0, r0, r2, ror #2 * 12
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 13
+ subhs r0, r0, r2, ror #2 * 13
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 14
+ subhs r0, r0, r2, ror #2 * 14
+ adc r2, r1, r2, lsl #1
+
+ cmp r0, r2, ror #2 * 15
+ subhs r0, r0, r2, ror #2 * 15
+ adc r2, r1, r2, lsl #1
+
+ bic r0, r2, #3 << 30 @ for rounding add: cmp r0, r2 adc r2, #1
+ bx lr
+
diff --git a/common_audio/signal_processing/spl_version.c b/common_audio/signal_processing/spl_version.c
new file mode 100644
index 0000000..936925e
--- /dev/null
+++ b/common_audio/signal_processing/spl_version.c
@@ -0,0 +1,25 @@
+/*
+ * 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 function WebRtcSpl_get_version().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include <string.h>
+#include "signal_processing_library.h"
+
+WebRtc_Word16 WebRtcSpl_get_version(char* version, WebRtc_Word16 length_in_bytes)
+{
+ strncpy(version, "1.2.0", length_in_bytes);
+ return 0;
+}
diff --git a/common_audio/signal_processing/splitting_filter.c b/common_audio/signal_processing/splitting_filter.c
new file mode 100644
index 0000000..f1acf67
--- /dev/null
+++ b/common_audio/signal_processing/splitting_filter.c
@@ -0,0 +1,198 @@
+/*
+ * 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 splitting filter functions.
+ *
+ */
+
+#include "signal_processing_library.h"
+
+// Number of samples in a low/high-band frame.
+enum
+{
+ kBandFrameLength = 160
+};
+
+// QMF filter coefficients in Q16.
+static const WebRtc_UWord16 WebRtcSpl_kAllPassFilter1[3] = {6418, 36982, 57261};
+static const WebRtc_UWord16 WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// WebRtcSpl_AllPassQMF(...)
+//
+// Allpass filter used by the analysis and synthesis parts of the QMF filter.
+//
+// Input:
+// - in_data : Input data sequence (Q10)
+// - data_length : Length of data sequence (>2)
+// - filter_coefficients : Filter coefficients (length 3, Q16)
+//
+// Input & Output:
+// - filter_state : Filter state (length 6, Q10).
+//
+// Output:
+// - out_data : Output data sequence (Q10), length equal to
+// |data_length|
+//
+
+void WebRtcSpl_AllPassQMF(WebRtc_Word32* in_data, const WebRtc_Word16 data_length,
+ WebRtc_Word32* out_data, const WebRtc_UWord16* filter_coefficients,
+ WebRtc_Word32* filter_state)
+{
+ // The procedure is to filter the input with three first order all pass filters
+ // (cascade operations).
+ //
+ // a_3 + q^-1 a_2 + q^-1 a_1 + q^-1
+ // y[n] = ----------- ----------- ----------- x[n]
+ // 1 + a_3q^-1 1 + a_2q^-1 1 + a_1q^-1
+ //
+ // The input vector |filter_coefficients| includes these three filter coefficients.
+ // The filter state contains the in_data state, in_data[-1], followed by
+ // the out_data state, out_data[-1]. This is repeated for each cascade.
+ // The first cascade filter will filter the |in_data| and store the output in
+ // |out_data|. The second will the take the |out_data| as input and make an
+ // intermediate storage in |in_data|, to save memory. The third, and final, cascade
+ // filter operation takes the |in_data| (which is the output from the previous cascade
+ // filter) and store the output in |out_data|.
+ // Note that the input vector values are changed during the process.
+ WebRtc_Word16 k;
+ WebRtc_Word32 diff;
+ // First all-pass cascade; filter from in_data to out_data.
+
+ // Let y_i[n] indicate the output of cascade filter i (with filter coefficient a_i) at
+ // vector position n. Then the final output will be y[n] = y_3[n]
+
+ // First loop, use the states stored in memory.
+ // "diff" should be safe from wrap around since max values are 2^25
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[0], filter_state[1]); // = (x[0] - y_1[-1])
+ // y_1[0] = x[-1] + a_1 * (x[0] - y_1[-1])
+ out_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, filter_state[0]);
+
+ // For the remaining loops, use previous values.
+ for (k = 1; k < data_length; k++)
+ {
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[k], out_data[k - 1]); // = (x[n] - y_1[n-1])
+ // y_1[n] = x[n-1] + a_1 * (x[n] - y_1[n-1])
+ out_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, in_data[k - 1]);
+ }
+
+ // Update states.
+ filter_state[0] = in_data[data_length - 1]; // x[N-1], becomes x[-1] next time
+ filter_state[1] = out_data[data_length - 1]; // y_1[N-1], becomes y_1[-1] next time
+
+ // Second all-pass cascade; filter from out_data to in_data.
+ diff = WEBRTC_SPL_SUB_SAT_W32(out_data[0], filter_state[3]); // = (y_1[0] - y_2[-1])
+ // y_2[0] = y_1[-1] + a_2 * (y_1[0] - y_2[-1])
+ in_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, filter_state[2]);
+ for (k = 1; k < data_length; k++)
+ {
+ diff = WEBRTC_SPL_SUB_SAT_W32(out_data[k], in_data[k - 1]); // =(y_1[n] - y_2[n-1])
+ // y_2[0] = y_1[-1] + a_2 * (y_1[0] - y_2[-1])
+ in_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, out_data[k-1]);
+ }
+
+ filter_state[2] = out_data[data_length - 1]; // y_1[N-1], becomes y_1[-1] next time
+ filter_state[3] = in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
+
+ // Third all-pass cascade; filter from in_data to out_data.
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[0], filter_state[5]); // = (y_2[0] - y[-1])
+ // y[0] = y_2[-1] + a_3 * (y_2[0] - y[-1])
+ out_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, filter_state[4]);
+ for (k = 1; k < data_length; k++)
+ {
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[k], out_data[k - 1]); // = (y_2[n] - y[n-1])
+ // y[n] = y_2[n-1] + a_3 * (y_2[n] - y[n-1])
+ out_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, in_data[k-1]);
+ }
+ filter_state[4] = in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
+ filter_state[5] = out_data[data_length - 1]; // y[N-1], becomes y[-1] next time
+}
+
+void WebRtcSpl_AnalysisQMF(const WebRtc_Word16* in_data, WebRtc_Word16* low_band,
+ WebRtc_Word16* high_band, WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2)
+{
+ WebRtc_Word16 i;
+ WebRtc_Word16 k;
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 half_in1[kBandFrameLength];
+ WebRtc_Word32 half_in2[kBandFrameLength];
+ WebRtc_Word32 filter1[kBandFrameLength];
+ WebRtc_Word32 filter2[kBandFrameLength];
+
+ // Split even and odd samples. Also shift them to Q10.
+ for (i = 0, k = 0; i < kBandFrameLength; i++, k += 2)
+ {
+ half_in2[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)in_data[k], 10);
+ half_in1[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)in_data[k + 1], 10);
+ }
+
+ // All pass filter even and odd samples, independently.
+ WebRtcSpl_AllPassQMF(half_in1, kBandFrameLength, filter1, WebRtcSpl_kAllPassFilter1,
+ filter_state1);
+ WebRtcSpl_AllPassQMF(half_in2, kBandFrameLength, filter2, WebRtcSpl_kAllPassFilter2,
+ filter_state2);
+
+ // Take the sum and difference of filtered version of odd and even
+ // branches to get upper & lower band.
+ for (i = 0; i < kBandFrameLength; i++)
+ {
+ tmp = filter1[i] + filter2[i] + 1024;
+ tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11);
+ low_band[i] = WebRtcSpl_SatW32ToW16(tmp);
+
+ tmp = filter1[i] - filter2[i] + 1024;
+ tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11);
+ high_band[i] = WebRtcSpl_SatW32ToW16(tmp);
+ }
+}
+
+void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band, const WebRtc_Word16* high_band,
+ WebRtc_Word16* out_data, WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2)
+{
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 half_in1[kBandFrameLength];
+ WebRtc_Word32 half_in2[kBandFrameLength];
+ WebRtc_Word32 filter1[kBandFrameLength];
+ WebRtc_Word32 filter2[kBandFrameLength];
+ WebRtc_Word16 i;
+ WebRtc_Word16 k;
+
+ // Obtain the sum and difference channels out of upper and lower-band channels.
+ // Also shift to Q10 domain.
+ for (i = 0; i < kBandFrameLength; i++)
+ {
+ tmp = (WebRtc_Word32)low_band[i] + (WebRtc_Word32)high_band[i];
+ half_in1[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
+ tmp = (WebRtc_Word32)low_band[i] - (WebRtc_Word32)high_band[i];
+ half_in2[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
+ }
+
+ // all-pass filter the sum and difference channels
+ WebRtcSpl_AllPassQMF(half_in1, kBandFrameLength, filter1, WebRtcSpl_kAllPassFilter2,
+ filter_state1);
+ WebRtcSpl_AllPassQMF(half_in2, kBandFrameLength, filter2, WebRtcSpl_kAllPassFilter1,
+ filter_state2);
+
+ // The filtered signals are even and odd samples of the output. Combine
+ // them. The signals are Q10 should shift them back to Q0 and take care of
+ // saturation.
+ for (i = 0, k = 0; i < kBandFrameLength; i++)
+ {
+ tmp = WEBRTC_SPL_RSHIFT_W32(filter2[i] + 512, 10);
+ out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
+
+ tmp = WEBRTC_SPL_RSHIFT_W32(filter1[i] + 512, 10);
+ out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
+ }
+
+}
diff --git a/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c b/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c
new file mode 100644
index 0000000..9fb2c73
--- /dev/null
+++ b/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c
@@ -0,0 +1,35 @@
+/*
+ * 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 function WebRtcSpl_SqrtOfOneMinusXSquared().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_SqrtOfOneMinusXSquared(WebRtc_Word16 *xQ15, int vector_length,
+ WebRtc_Word16 *yQ15)
+{
+ WebRtc_Word32 sq;
+ int m;
+ WebRtc_Word16 tmp;
+
+ for (m = 0; m < vector_length; m++)
+ {
+ tmp = xQ15[m];
+ sq = WEBRTC_SPL_MUL_16_16(tmp, tmp); // x^2 in Q30
+ sq = 1073741823 - sq; // 1-x^2, where 1 ~= 0.99999999906 is 1073741823 in Q30
+ sq = WebRtcSpl_Sqrt(sq); // sqrt(1-x^2) in Q15
+ yQ15[m] = (WebRtc_Word16)sq;
+ }
+}
diff --git a/common_audio/signal_processing/vector_scaling_operations.c b/common_audio/signal_processing/vector_scaling_operations.c
new file mode 100644
index 0000000..242955c
--- /dev/null
+++ b/common_audio/signal_processing/vector_scaling_operations.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2012 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 implementations of the functions
+ * WebRtcSpl_VectorBitShiftW16()
+ * WebRtcSpl_VectorBitShiftW32()
+ * WebRtcSpl_VectorBitShiftW32ToW16()
+ * WebRtcSpl_ScaleVector()
+ * WebRtcSpl_ScaleVectorWithSat()
+ * WebRtcSpl_ScaleAndAddVectors()
+ * WebRtcSpl_ScaleAndAddVectorsWithRoundC()
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_VectorBitShiftW16(WebRtc_Word16 *res,
+ WebRtc_Word16 length,
+ G_CONST WebRtc_Word16 *in,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+
+ if (right_shifts > 0)
+ {
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = ((*in++) >> right_shifts);
+ }
+ } else
+ {
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = ((*in++) << (-right_shifts));
+ }
+ }
+}
+
+void WebRtcSpl_VectorBitShiftW32(WebRtc_Word32 *out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word32 *in_vector,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+
+ if (right_shifts > 0)
+ {
+ for (i = vector_length; i > 0; i--)
+ {
+ (*out_vector++) = ((*in_vector++) >> right_shifts);
+ }
+ } else
+ {
+ for (i = vector_length; i > 0; i--)
+ {
+ (*out_vector++) = ((*in_vector++) << (-right_shifts));
+ }
+ }
+}
+
+void WebRtcSpl_VectorBitShiftW32ToW16(WebRtc_Word16 *res,
+ WebRtc_Word16 length,
+ G_CONST WebRtc_Word32 *in,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+
+ if (right_shifts >= 0)
+ {
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = (WebRtc_Word16)((*in++) >> right_shifts);
+ }
+ } else
+ {
+ WebRtc_Word16 left_shifts = -right_shifts;
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = (WebRtc_Word16)((*in++) << left_shifts);
+ }
+ }
+}
+
+void WebRtcSpl_ScaleVector(G_CONST WebRtc_Word16 *in_vector, WebRtc_Word16 *out_vector,
+ WebRtc_Word16 gain, WebRtc_Word16 in_vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts
+ int i;
+ G_CONST WebRtc_Word16 *inptr;
+ WebRtc_Word16 *outptr;
+
+ inptr = in_vector;
+ outptr = out_vector;
+
+ for (i = 0; i < in_vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++, gain, right_shifts);
+ }
+}
+
+void WebRtcSpl_ScaleVectorWithSat(G_CONST WebRtc_Word16 *in_vector, WebRtc_Word16 *out_vector,
+ WebRtc_Word16 gain, WebRtc_Word16 in_vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts
+ int i;
+ WebRtc_Word32 tmpW32;
+ G_CONST WebRtc_Word16 *inptr;
+ WebRtc_Word16 *outptr;
+
+ inptr = in_vector;
+ outptr = out_vector;
+
+ for (i = 0; i < in_vector_length; i++)
+ {
+ tmpW32 = WEBRTC_SPL_MUL_16_16_RSFT(*inptr++, gain, right_shifts);
+ (*outptr++) = WebRtcSpl_SatW32ToW16(tmpW32);
+ }
+}
+
+void WebRtcSpl_ScaleAndAddVectors(G_CONST WebRtc_Word16 *in1, WebRtc_Word16 gain1, int shift1,
+ G_CONST WebRtc_Word16 *in2, WebRtc_Word16 gain2, int shift2,
+ WebRtc_Word16 *out, int vector_length)
+{
+ // Performs vector operation: out = (gain1*in1)>>shift1 + (gain2*in2)>>shift2
+ int i;
+ G_CONST WebRtc_Word16 *in1ptr;
+ G_CONST WebRtc_Word16 *in2ptr;
+ WebRtc_Word16 *outptr;
+
+ in1ptr = in1;
+ in2ptr = in2;
+ outptr = out;
+
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(gain1, *in1ptr++, shift1)
+ + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(gain2, *in2ptr++, shift2);
+ }
+}
+
+// C version of WebRtcSpl_ScaleAndAddVectorsWithRound() for generic platforms.
+int WebRtcSpl_ScaleAndAddVectorsWithRoundC(const int16_t* in_vector1,
+ int16_t in_vector1_scale,
+ const int16_t* in_vector2,
+ int16_t in_vector2_scale,
+ int right_shifts,
+ int16_t* out_vector,
+ int length) {
+ int i = 0;
+ int round_value = (1 << right_shifts) >> 1;
+
+ if (in_vector1 == NULL || in_vector2 == NULL || out_vector == NULL ||
+ length <= 0 || right_shifts < 0) {
+ return -1;
+ }
+
+ for (i = 0; i < length; i++) {
+ out_vector[i] = (int16_t)((
+ WEBRTC_SPL_MUL_16_16(in_vector1[i], in_vector1_scale)
+ + WEBRTC_SPL_MUL_16_16(in_vector2[i], in_vector2_scale)
+ + round_value) >> right_shifts);
+ }
+
+ return 0;
+}
diff --git a/common_audio/signal_processing/vector_scaling_operations_neon.s b/common_audio/signal_processing/vector_scaling_operations_neon.s
new file mode 100644
index 0000000..562425b
--- /dev/null
+++ b/common_audio/signal_processing/vector_scaling_operations_neon.s
@@ -0,0 +1,88 @@
+@
+@ Copyright (c) 2012 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.
+@
+
+@ vector_scaling_operations_neon.s
+@ This file contains the function WebRtcSpl_ScaleAndAddVectorsWithRoundNeon(),
+@ optimized for ARM Neon platform. Output is bit-exact with the reference
+@ C code in vector_scaling_operations.c.
+
+.arch armv7-a
+.fpu neon
+
+.align 2
+.global WebRtcSpl_ScaleAndAddVectorsWithRoundNeon
+
+WebRtcSpl_ScaleAndAddVectorsWithRoundNeon:
+.fnstart
+
+ push {r4-r9}
+
+ ldr r4, [sp, #32] @ length
+ ldr r5, [sp, #28] @ out_vector
+ ldrsh r6, [sp, #24] @ right_shifts
+
+ cmp r4, #0
+ ble END @ Return if length <= 0.
+
+ cmp r4, #8
+ blt SET_ROUND_VALUE
+
+ vdup.16 d26, r1 @ in_vector1_scale
+ vdup.16 d27, r3 @ in_vector2_scale
+
+ @ Neon instructions can only right shift by an immediate value. To shift right
+ @ by a register value, we have to do a left shift left by the negative value.
+ rsb r7, r6, #0
+ vdup.16 q12, r7 @ -right_shifts
+
+ bic r7, r4, #7 @ Counter for LOOP_UNROLLED_BY_8: length / 8 * 8.
+
+LOOP_UNROLLED_BY_8:
+ vld1.16 {d28, d29}, [r0]! @ in_vector1[]
+ vld1.16 {d30, d31}, [r2]! @ in_vector2[]
+ vmull.s16 q0, d28, d26
+ vmull.s16 q1, d29, d26
+ vmull.s16 q2, d30, d27
+ vmull.s16 q3, d31, d27
+ vadd.s32 q0, q2
+ vadd.s32 q1, q3
+ vrshl.s32 q0, q12 @ Round shift right by right_shifts.
+ vrshl.s32 q1, q12
+ vmovn.i32 d0, q0 @ Cast to 16 bit values.
+ vmovn.i32 d1, q1
+ subs r7, #8
+ vst1.16 {d0, d1}, [r5]!
+ bgt LOOP_UNROLLED_BY_8
+
+ ands r4, #0xFF @ Counter for LOOP_NO_UNROLLING: length % 8.
+ beq END
+
+SET_ROUND_VALUE:
+ mov r9, #1
+ lsl r9, r6
+ lsr r9, #1
+
+LOOP_NO_UNROLLING:
+ ldrh r7, [r0], #2
+ ldrh r8, [r2], #2
+ smulbb r7, r7, r1
+ smulbb r8, r8, r3
+ subs r4, #1
+ add r7, r9
+ add r7, r8
+ asr r7, r6
+ strh r7, [r5], #2
+ bne LOOP_NO_UNROLLING
+
+END:
+ pop {r4-r9}
+ bx lr
+
+.fnend
diff --git a/common_audio/signal_processing/webrtc_fft_t_1024_8.c b/common_audio/signal_processing/webrtc_fft_t_1024_8.c
new file mode 100644
index 0000000..b587380
--- /dev/null
+++ b/common_audio/signal_processing/webrtc_fft_t_1024_8.c
@@ -0,0 +1,704 @@
+/*
+ * 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 Q14 radix-8 tables used in ARM9e optimizations.
+ *
+ */
+
+extern const int s_Q14S_8;
+const int s_Q14S_8 = 1024;
+extern const unsigned short t_Q14S_8[2032];
+const unsigned short t_Q14S_8[2032] = {
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x22a3,0x187e ,0x3249,0x0c7c ,0x11a8,0x238e ,
+ 0x0000,0x2d41 ,0x22a3,0x187e ,0xdd5d,0x3b21 ,
+ 0xdd5d,0x3b21 ,0x11a8,0x238e ,0xb4be,0x3ec5 ,
+ 0xc000,0x4000 ,0x0000,0x2d41 ,0xa57e,0x2d41 ,
+ 0xac61,0x3b21 ,0xee58,0x3537 ,0xb4be,0x0c7c ,
+ 0xa57e,0x2d41 ,0xdd5d,0x3b21 ,0xdd5d,0xe782 ,
+ 0xac61,0x187e ,0xcdb7,0x3ec5 ,0x11a8,0xcac9 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x396b,0x0646 ,0x3cc8,0x0324 ,0x35eb,0x0964 ,
+ 0x3249,0x0c7c ,0x396b,0x0646 ,0x2aaa,0x1294 ,
+ 0x2aaa,0x1294 ,0x35eb,0x0964 ,0x1e7e,0x1b5d ,
+ 0x22a3,0x187e ,0x3249,0x0c7c ,0x11a8,0x238e ,
+ 0x1a46,0x1e2b ,0x2e88,0x0f8d ,0x0471,0x2afb ,
+ 0x11a8,0x238e ,0x2aaa,0x1294 ,0xf721,0x3179 ,
+ 0x08df,0x289a ,0x26b3,0x1590 ,0xea02,0x36e5 ,
+ 0x0000,0x2d41 ,0x22a3,0x187e ,0xdd5d,0x3b21 ,
+ 0xf721,0x3179 ,0x1e7e,0x1b5d ,0xd178,0x3e15 ,
+ 0xee58,0x3537 ,0x1a46,0x1e2b ,0xc695,0x3fb1 ,
+ 0xe5ba,0x3871 ,0x15fe,0x20e7 ,0xbcf0,0x3fec ,
+ 0xdd5d,0x3b21 ,0x11a8,0x238e ,0xb4be,0x3ec5 ,
+ 0xd556,0x3d3f ,0x0d48,0x2620 ,0xae2e,0x3c42 ,
+ 0xcdb7,0x3ec5 ,0x08df,0x289a ,0xa963,0x3871 ,
+ 0xc695,0x3fb1 ,0x0471,0x2afb ,0xa678,0x3368 ,
+ 0xc000,0x4000 ,0x0000,0x2d41 ,0xa57e,0x2d41 ,
+ 0xba09,0x3fb1 ,0xfb8f,0x2f6c ,0xa678,0x2620 ,
+ 0xb4be,0x3ec5 ,0xf721,0x3179 ,0xa963,0x1e2b ,
+ 0xb02d,0x3d3f ,0xf2b8,0x3368 ,0xae2e,0x1590 ,
+ 0xac61,0x3b21 ,0xee58,0x3537 ,0xb4be,0x0c7c ,
+ 0xa963,0x3871 ,0xea02,0x36e5 ,0xbcf0,0x0324 ,
+ 0xa73b,0x3537 ,0xe5ba,0x3871 ,0xc695,0xf9ba ,
+ 0xa5ed,0x3179 ,0xe182,0x39db ,0xd178,0xf073 ,
+ 0xa57e,0x2d41 ,0xdd5d,0x3b21 ,0xdd5d,0xe782 ,
+ 0xa5ed,0x289a ,0xd94d,0x3c42 ,0xea02,0xdf19 ,
+ 0xa73b,0x238e ,0xd556,0x3d3f ,0xf721,0xd766 ,
+ 0xa963,0x1e2b ,0xd178,0x3e15 ,0x0471,0xd094 ,
+ 0xac61,0x187e ,0xcdb7,0x3ec5 ,0x11a8,0xcac9 ,
+ 0xb02d,0x1294 ,0xca15,0x3f4f ,0x1e7e,0xc625 ,
+ 0xb4be,0x0c7c ,0xc695,0x3fb1 ,0x2aaa,0xc2c1 ,
+ 0xba09,0x0646 ,0xc338,0x3fec ,0x35eb,0xc0b1 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3e69,0x0192 ,0x3f36,0x00c9 ,0x3d9a,0x025b ,
+ 0x3cc8,0x0324 ,0x3e69,0x0192 ,0x3b1e,0x04b5 ,
+ 0x3b1e,0x04b5 ,0x3d9a,0x025b ,0x388e,0x070e ,
+ 0x396b,0x0646 ,0x3cc8,0x0324 ,0x35eb,0x0964 ,
+ 0x37af,0x07d6 ,0x3bf4,0x03ed ,0x3334,0x0bb7 ,
+ 0x35eb,0x0964 ,0x3b1e,0x04b5 ,0x306c,0x0e06 ,
+ 0x341e,0x0af1 ,0x3a46,0x057e ,0x2d93,0x1050 ,
+ 0x3249,0x0c7c ,0x396b,0x0646 ,0x2aaa,0x1294 ,
+ 0x306c,0x0e06 ,0x388e,0x070e ,0x27b3,0x14d2 ,
+ 0x2e88,0x0f8d ,0x37af,0x07d6 ,0x24ae,0x1709 ,
+ 0x2c9d,0x1112 ,0x36ce,0x089d ,0x219c,0x1937 ,
+ 0x2aaa,0x1294 ,0x35eb,0x0964 ,0x1e7e,0x1b5d ,
+ 0x28b2,0x1413 ,0x3505,0x0a2b ,0x1b56,0x1d79 ,
+ 0x26b3,0x1590 ,0x341e,0x0af1 ,0x1824,0x1f8c ,
+ 0x24ae,0x1709 ,0x3334,0x0bb7 ,0x14ea,0x2193 ,
+ 0x22a3,0x187e ,0x3249,0x0c7c ,0x11a8,0x238e ,
+ 0x2093,0x19ef ,0x315b,0x0d41 ,0x0e61,0x257e ,
+ 0x1e7e,0x1b5d ,0x306c,0x0e06 ,0x0b14,0x2760 ,
+ 0x1c64,0x1cc6 ,0x2f7b,0x0eca ,0x07c4,0x2935 ,
+ 0x1a46,0x1e2b ,0x2e88,0x0f8d ,0x0471,0x2afb ,
+ 0x1824,0x1f8c ,0x2d93,0x1050 ,0x011c,0x2cb2 ,
+ 0x15fe,0x20e7 ,0x2c9d,0x1112 ,0xfdc7,0x2e5a ,
+ 0x13d5,0x223d ,0x2ba4,0x11d3 ,0xfa73,0x2ff2 ,
+ 0x11a8,0x238e ,0x2aaa,0x1294 ,0xf721,0x3179 ,
+ 0x0f79,0x24da ,0x29af,0x1354 ,0xf3d2,0x32ef ,
+ 0x0d48,0x2620 ,0x28b2,0x1413 ,0xf087,0x3453 ,
+ 0x0b14,0x2760 ,0x27b3,0x14d2 ,0xed41,0x35a5 ,
+ 0x08df,0x289a ,0x26b3,0x1590 ,0xea02,0x36e5 ,
+ 0x06a9,0x29ce ,0x25b1,0x164c ,0xe6cb,0x3812 ,
+ 0x0471,0x2afb ,0x24ae,0x1709 ,0xe39c,0x392b ,
+ 0x0239,0x2c21 ,0x23a9,0x17c4 ,0xe077,0x3a30 ,
+ 0x0000,0x2d41 ,0x22a3,0x187e ,0xdd5d,0x3b21 ,
+ 0xfdc7,0x2e5a ,0x219c,0x1937 ,0xda4f,0x3bfd ,
+ 0xfb8f,0x2f6c ,0x2093,0x19ef ,0xd74e,0x3cc5 ,
+ 0xf957,0x3076 ,0x1f89,0x1aa7 ,0xd45c,0x3d78 ,
+ 0xf721,0x3179 ,0x1e7e,0x1b5d ,0xd178,0x3e15 ,
+ 0xf4ec,0x3274 ,0x1d72,0x1c12 ,0xcea5,0x3e9d ,
+ 0xf2b8,0x3368 ,0x1c64,0x1cc6 ,0xcbe2,0x3f0f ,
+ 0xf087,0x3453 ,0x1b56,0x1d79 ,0xc932,0x3f6b ,
+ 0xee58,0x3537 ,0x1a46,0x1e2b ,0xc695,0x3fb1 ,
+ 0xec2b,0x3612 ,0x1935,0x1edc ,0xc40c,0x3fe1 ,
+ 0xea02,0x36e5 ,0x1824,0x1f8c ,0xc197,0x3ffb ,
+ 0xe7dc,0x37b0 ,0x1711,0x203a ,0xbf38,0x3fff ,
+ 0xe5ba,0x3871 ,0x15fe,0x20e7 ,0xbcf0,0x3fec ,
+ 0xe39c,0x392b ,0x14ea,0x2193 ,0xbabf,0x3fc4 ,
+ 0xe182,0x39db ,0x13d5,0x223d ,0xb8a6,0x3f85 ,
+ 0xdf6d,0x3a82 ,0x12bf,0x22e7 ,0xb6a5,0x3f30 ,
+ 0xdd5d,0x3b21 ,0x11a8,0x238e ,0xb4be,0x3ec5 ,
+ 0xdb52,0x3bb6 ,0x1091,0x2435 ,0xb2f2,0x3e45 ,
+ 0xd94d,0x3c42 ,0x0f79,0x24da ,0xb140,0x3daf ,
+ 0xd74e,0x3cc5 ,0x0e61,0x257e ,0xafa9,0x3d03 ,
+ 0xd556,0x3d3f ,0x0d48,0x2620 ,0xae2e,0x3c42 ,
+ 0xd363,0x3daf ,0x0c2e,0x26c1 ,0xacd0,0x3b6d ,
+ 0xd178,0x3e15 ,0x0b14,0x2760 ,0xab8e,0x3a82 ,
+ 0xcf94,0x3e72 ,0x09fa,0x27fe ,0xaa6a,0x3984 ,
+ 0xcdb7,0x3ec5 ,0x08df,0x289a ,0xa963,0x3871 ,
+ 0xcbe2,0x3f0f ,0x07c4,0x2935 ,0xa87b,0x374b ,
+ 0xca15,0x3f4f ,0x06a9,0x29ce ,0xa7b1,0x3612 ,
+ 0xc851,0x3f85 ,0x058d,0x2a65 ,0xa705,0x34c6 ,
+ 0xc695,0x3fb1 ,0x0471,0x2afb ,0xa678,0x3368 ,
+ 0xc4e2,0x3fd4 ,0x0355,0x2b8f ,0xa60b,0x31f8 ,
+ 0xc338,0x3fec ,0x0239,0x2c21 ,0xa5bc,0x3076 ,
+ 0xc197,0x3ffb ,0x011c,0x2cb2 ,0xa58d,0x2ee4 ,
+ 0xc000,0x4000 ,0x0000,0x2d41 ,0xa57e,0x2d41 ,
+ 0xbe73,0x3ffb ,0xfee4,0x2dcf ,0xa58d,0x2b8f ,
+ 0xbcf0,0x3fec ,0xfdc7,0x2e5a ,0xa5bc,0x29ce ,
+ 0xbb77,0x3fd4 ,0xfcab,0x2ee4 ,0xa60b,0x27fe ,
+ 0xba09,0x3fb1 ,0xfb8f,0x2f6c ,0xa678,0x2620 ,
+ 0xb8a6,0x3f85 ,0xfa73,0x2ff2 ,0xa705,0x2435 ,
+ 0xb74d,0x3f4f ,0xf957,0x3076 ,0xa7b1,0x223d ,
+ 0xb600,0x3f0f ,0xf83c,0x30f9 ,0xa87b,0x203a ,
+ 0xb4be,0x3ec5 ,0xf721,0x3179 ,0xa963,0x1e2b ,
+ 0xb388,0x3e72 ,0xf606,0x31f8 ,0xaa6a,0x1c12 ,
+ 0xb25e,0x3e15 ,0xf4ec,0x3274 ,0xab8e,0x19ef ,
+ 0xb140,0x3daf ,0xf3d2,0x32ef ,0xacd0,0x17c4 ,
+ 0xb02d,0x3d3f ,0xf2b8,0x3368 ,0xae2e,0x1590 ,
+ 0xaf28,0x3cc5 ,0xf19f,0x33df ,0xafa9,0x1354 ,
+ 0xae2e,0x3c42 ,0xf087,0x3453 ,0xb140,0x1112 ,
+ 0xad41,0x3bb6 ,0xef6f,0x34c6 ,0xb2f2,0x0eca ,
+ 0xac61,0x3b21 ,0xee58,0x3537 ,0xb4be,0x0c7c ,
+ 0xab8e,0x3a82 ,0xed41,0x35a5 ,0xb6a5,0x0a2b ,
+ 0xaac8,0x39db ,0xec2b,0x3612 ,0xb8a6,0x07d6 ,
+ 0xaa0f,0x392b ,0xeb16,0x367d ,0xbabf,0x057e ,
+ 0xa963,0x3871 ,0xea02,0x36e5 ,0xbcf0,0x0324 ,
+ 0xa8c5,0x37b0 ,0xe8ef,0x374b ,0xbf38,0x00c9 ,
+ 0xa834,0x36e5 ,0xe7dc,0x37b0 ,0xc197,0xfe6e ,
+ 0xa7b1,0x3612 ,0xe6cb,0x3812 ,0xc40c,0xfc13 ,
+ 0xa73b,0x3537 ,0xe5ba,0x3871 ,0xc695,0xf9ba ,
+ 0xa6d3,0x3453 ,0xe4aa,0x38cf ,0xc932,0xf763 ,
+ 0xa678,0x3368 ,0xe39c,0x392b ,0xcbe2,0xf50f ,
+ 0xa62c,0x3274 ,0xe28e,0x3984 ,0xcea5,0xf2bf ,
+ 0xa5ed,0x3179 ,0xe182,0x39db ,0xd178,0xf073 ,
+ 0xa5bc,0x3076 ,0xe077,0x3a30 ,0xd45c,0xee2d ,
+ 0xa599,0x2f6c ,0xdf6d,0x3a82 ,0xd74e,0xebed ,
+ 0xa585,0x2e5a ,0xde64,0x3ad3 ,0xda4f,0xe9b4 ,
+ 0xa57e,0x2d41 ,0xdd5d,0x3b21 ,0xdd5d,0xe782 ,
+ 0xa585,0x2c21 ,0xdc57,0x3b6d ,0xe077,0xe559 ,
+ 0xa599,0x2afb ,0xdb52,0x3bb6 ,0xe39c,0xe33a ,
+ 0xa5bc,0x29ce ,0xda4f,0x3bfd ,0xe6cb,0xe124 ,
+ 0xa5ed,0x289a ,0xd94d,0x3c42 ,0xea02,0xdf19 ,
+ 0xa62c,0x2760 ,0xd84d,0x3c85 ,0xed41,0xdd19 ,
+ 0xa678,0x2620 ,0xd74e,0x3cc5 ,0xf087,0xdb26 ,
+ 0xa6d3,0x24da ,0xd651,0x3d03 ,0xf3d2,0xd93f ,
+ 0xa73b,0x238e ,0xd556,0x3d3f ,0xf721,0xd766 ,
+ 0xa7b1,0x223d ,0xd45c,0x3d78 ,0xfa73,0xd59b ,
+ 0xa834,0x20e7 ,0xd363,0x3daf ,0xfdc7,0xd3df ,
+ 0xa8c5,0x1f8c ,0xd26d,0x3de3 ,0x011c,0xd231 ,
+ 0xa963,0x1e2b ,0xd178,0x3e15 ,0x0471,0xd094 ,
+ 0xaa0f,0x1cc6 ,0xd085,0x3e45 ,0x07c4,0xcf07 ,
+ 0xaac8,0x1b5d ,0xcf94,0x3e72 ,0x0b14,0xcd8c ,
+ 0xab8e,0x19ef ,0xcea5,0x3e9d ,0x0e61,0xcc21 ,
+ 0xac61,0x187e ,0xcdb7,0x3ec5 ,0x11a8,0xcac9 ,
+ 0xad41,0x1709 ,0xcccc,0x3eeb ,0x14ea,0xc983 ,
+ 0xae2e,0x1590 ,0xcbe2,0x3f0f ,0x1824,0xc850 ,
+ 0xaf28,0x1413 ,0xcafb,0x3f30 ,0x1b56,0xc731 ,
+ 0xb02d,0x1294 ,0xca15,0x3f4f ,0x1e7e,0xc625 ,
+ 0xb140,0x1112 ,0xc932,0x3f6b ,0x219c,0xc52d ,
+ 0xb25e,0x0f8d ,0xc851,0x3f85 ,0x24ae,0xc44a ,
+ 0xb388,0x0e06 ,0xc772,0x3f9c ,0x27b3,0xc37b ,
+ 0xb4be,0x0c7c ,0xc695,0x3fb1 ,0x2aaa,0xc2c1 ,
+ 0xb600,0x0af1 ,0xc5ba,0x3fc4 ,0x2d93,0xc21d ,
+ 0xb74d,0x0964 ,0xc4e2,0x3fd4 ,0x306c,0xc18e ,
+ 0xb8a6,0x07d6 ,0xc40c,0x3fe1 ,0x3334,0xc115 ,
+ 0xba09,0x0646 ,0xc338,0x3fec ,0x35eb,0xc0b1 ,
+ 0xbb77,0x04b5 ,0xc266,0x3ff5 ,0x388e,0xc064 ,
+ 0xbcf0,0x0324 ,0xc197,0x3ffb ,0x3b1e,0xc02c ,
+ 0xbe73,0x0192 ,0xc0ca,0x3fff ,0x3d9a,0xc00b ,
+ 0x4000,0x0000 ,0x3f9b,0x0065 ,0x3f36,0x00c9 ,
+ 0x3ed0,0x012e ,0x3e69,0x0192 ,0x3e02,0x01f7 ,
+ 0x3d9a,0x025b ,0x3d31,0x02c0 ,0x3cc8,0x0324 ,
+ 0x3c5f,0x0388 ,0x3bf4,0x03ed ,0x3b8a,0x0451 ,
+ 0x3b1e,0x04b5 ,0x3ab2,0x051a ,0x3a46,0x057e ,
+ 0x39d9,0x05e2 ,0x396b,0x0646 ,0x38fd,0x06aa ,
+ 0x388e,0x070e ,0x381f,0x0772 ,0x37af,0x07d6 ,
+ 0x373f,0x0839 ,0x36ce,0x089d ,0x365d,0x0901 ,
+ 0x35eb,0x0964 ,0x3578,0x09c7 ,0x3505,0x0a2b ,
+ 0x3492,0x0a8e ,0x341e,0x0af1 ,0x33a9,0x0b54 ,
+ 0x3334,0x0bb7 ,0x32bf,0x0c1a ,0x3249,0x0c7c ,
+ 0x31d2,0x0cdf ,0x315b,0x0d41 ,0x30e4,0x0da4 ,
+ 0x306c,0x0e06 ,0x2ff4,0x0e68 ,0x2f7b,0x0eca ,
+ 0x2f02,0x0f2b ,0x2e88,0x0f8d ,0x2e0e,0x0fee ,
+ 0x2d93,0x1050 ,0x2d18,0x10b1 ,0x2c9d,0x1112 ,
+ 0x2c21,0x1173 ,0x2ba4,0x11d3 ,0x2b28,0x1234 ,
+ 0x2aaa,0x1294 ,0x2a2d,0x12f4 ,0x29af,0x1354 ,
+ 0x2931,0x13b4 ,0x28b2,0x1413 ,0x2833,0x1473 ,
+ 0x27b3,0x14d2 ,0x2733,0x1531 ,0x26b3,0x1590 ,
+ 0x2632,0x15ee ,0x25b1,0x164c ,0x252f,0x16ab ,
+ 0x24ae,0x1709 ,0x242b,0x1766 ,0x23a9,0x17c4 ,
+ 0x2326,0x1821 ,0x22a3,0x187e ,0x221f,0x18db ,
+ 0x219c,0x1937 ,0x2117,0x1993 ,0x2093,0x19ef ,
+ 0x200e,0x1a4b ,0x1f89,0x1aa7 ,0x1f04,0x1b02 ,
+ 0x1e7e,0x1b5d ,0x1df8,0x1bb8 ,0x1d72,0x1c12 ,
+ 0x1ceb,0x1c6c ,0x1c64,0x1cc6 ,0x1bdd,0x1d20 ,
+ 0x1b56,0x1d79 ,0x1ace,0x1dd3 ,0x1a46,0x1e2b ,
+ 0x19be,0x1e84 ,0x1935,0x1edc ,0x18ad,0x1f34 ,
+ 0x1824,0x1f8c ,0x179b,0x1fe3 ,0x1711,0x203a ,
+ 0x1688,0x2091 ,0x15fe,0x20e7 ,0x1574,0x213d ,
+ 0x14ea,0x2193 ,0x145f,0x21e8 ,0x13d5,0x223d ,
+ 0x134a,0x2292 ,0x12bf,0x22e7 ,0x1234,0x233b ,
+ 0x11a8,0x238e ,0x111d,0x23e2 ,0x1091,0x2435 ,
+ 0x1005,0x2488 ,0x0f79,0x24da ,0x0eed,0x252c ,
+ 0x0e61,0x257e ,0x0dd4,0x25cf ,0x0d48,0x2620 ,
+ 0x0cbb,0x2671 ,0x0c2e,0x26c1 ,0x0ba1,0x2711 ,
+ 0x0b14,0x2760 ,0x0a87,0x27af ,0x09fa,0x27fe ,
+ 0x096d,0x284c ,0x08df,0x289a ,0x0852,0x28e7 ,
+ 0x07c4,0x2935 ,0x0736,0x2981 ,0x06a9,0x29ce ,
+ 0x061b,0x2a1a ,0x058d,0x2a65 ,0x04ff,0x2ab0 ,
+ 0x0471,0x2afb ,0x03e3,0x2b45 ,0x0355,0x2b8f ,
+ 0x02c7,0x2bd8 ,0x0239,0x2c21 ,0x01aa,0x2c6a ,
+ 0x011c,0x2cb2 ,0x008e,0x2cfa ,0x0000,0x2d41 ,
+ 0xff72,0x2d88 ,0xfee4,0x2dcf ,0xfe56,0x2e15 ,
+ 0xfdc7,0x2e5a ,0xfd39,0x2e9f ,0xfcab,0x2ee4 ,
+ 0xfc1d,0x2f28 ,0xfb8f,0x2f6c ,0xfb01,0x2faf ,
+ 0xfa73,0x2ff2 ,0xf9e5,0x3034 ,0xf957,0x3076 ,
+ 0xf8ca,0x30b8 ,0xf83c,0x30f9 ,0xf7ae,0x3139 ,
+ 0xf721,0x3179 ,0xf693,0x31b9 ,0xf606,0x31f8 ,
+ 0xf579,0x3236 ,0xf4ec,0x3274 ,0xf45f,0x32b2 ,
+ 0xf3d2,0x32ef ,0xf345,0x332c ,0xf2b8,0x3368 ,
+ 0xf22c,0x33a3 ,0xf19f,0x33df ,0xf113,0x3419 ,
+ 0xf087,0x3453 ,0xeffb,0x348d ,0xef6f,0x34c6 ,
+ 0xeee3,0x34ff ,0xee58,0x3537 ,0xedcc,0x356e ,
+ 0xed41,0x35a5 ,0xecb6,0x35dc ,0xec2b,0x3612 ,
+ 0xeba1,0x3648 ,0xeb16,0x367d ,0xea8c,0x36b1 ,
+ 0xea02,0x36e5 ,0xe978,0x3718 ,0xe8ef,0x374b ,
+ 0xe865,0x377e ,0xe7dc,0x37b0 ,0xe753,0x37e1 ,
+ 0xe6cb,0x3812 ,0xe642,0x3842 ,0xe5ba,0x3871 ,
+ 0xe532,0x38a1 ,0xe4aa,0x38cf ,0xe423,0x38fd ,
+ 0xe39c,0x392b ,0xe315,0x3958 ,0xe28e,0x3984 ,
+ 0xe208,0x39b0 ,0xe182,0x39db ,0xe0fc,0x3a06 ,
+ 0xe077,0x3a30 ,0xdff2,0x3a59 ,0xdf6d,0x3a82 ,
+ 0xdee9,0x3aab ,0xde64,0x3ad3 ,0xdde1,0x3afa ,
+ 0xdd5d,0x3b21 ,0xdcda,0x3b47 ,0xdc57,0x3b6d ,
+ 0xdbd5,0x3b92 ,0xdb52,0x3bb6 ,0xdad1,0x3bda ,
+ 0xda4f,0x3bfd ,0xd9ce,0x3c20 ,0xd94d,0x3c42 ,
+ 0xd8cd,0x3c64 ,0xd84d,0x3c85 ,0xd7cd,0x3ca5 ,
+ 0xd74e,0x3cc5 ,0xd6cf,0x3ce4 ,0xd651,0x3d03 ,
+ 0xd5d3,0x3d21 ,0xd556,0x3d3f ,0xd4d8,0x3d5b ,
+ 0xd45c,0x3d78 ,0xd3df,0x3d93 ,0xd363,0x3daf ,
+ 0xd2e8,0x3dc9 ,0xd26d,0x3de3 ,0xd1f2,0x3dfc ,
+ 0xd178,0x3e15 ,0xd0fe,0x3e2d ,0xd085,0x3e45 ,
+ 0xd00c,0x3e5c ,0xcf94,0x3e72 ,0xcf1c,0x3e88 ,
+ 0xcea5,0x3e9d ,0xce2e,0x3eb1 ,0xcdb7,0x3ec5 ,
+ 0xcd41,0x3ed8 ,0xcccc,0x3eeb ,0xcc57,0x3efd ,
+ 0xcbe2,0x3f0f ,0xcb6e,0x3f20 ,0xcafb,0x3f30 ,
+ 0xca88,0x3f40 ,0xca15,0x3f4f ,0xc9a3,0x3f5d ,
+ 0xc932,0x3f6b ,0xc8c1,0x3f78 ,0xc851,0x3f85 ,
+ 0xc7e1,0x3f91 ,0xc772,0x3f9c ,0xc703,0x3fa7 ,
+ 0xc695,0x3fb1 ,0xc627,0x3fbb ,0xc5ba,0x3fc4 ,
+ 0xc54e,0x3fcc ,0xc4e2,0x3fd4 ,0xc476,0x3fdb ,
+ 0xc40c,0x3fe1 ,0xc3a1,0x3fe7 ,0xc338,0x3fec ,
+ 0xc2cf,0x3ff1 ,0xc266,0x3ff5 ,0xc1fe,0x3ff8 ,
+ 0xc197,0x3ffb ,0xc130,0x3ffd ,0xc0ca,0x3fff ,
+ 0xc065,0x4000 ,0xc000,0x4000 ,0xbf9c,0x4000 ,
+ 0xbf38,0x3fff ,0xbed5,0x3ffd ,0xbe73,0x3ffb ,
+ 0xbe11,0x3ff8 ,0xbdb0,0x3ff5 ,0xbd50,0x3ff1 ,
+ 0xbcf0,0x3fec ,0xbc91,0x3fe7 ,0xbc32,0x3fe1 ,
+ 0xbbd4,0x3fdb ,0xbb77,0x3fd4 ,0xbb1b,0x3fcc ,
+ 0xbabf,0x3fc4 ,0xba64,0x3fbb ,0xba09,0x3fb1 ,
+ 0xb9af,0x3fa7 ,0xb956,0x3f9c ,0xb8fd,0x3f91 ,
+ 0xb8a6,0x3f85 ,0xb84f,0x3f78 ,0xb7f8,0x3f6b ,
+ 0xb7a2,0x3f5d ,0xb74d,0x3f4f ,0xb6f9,0x3f40 ,
+ 0xb6a5,0x3f30 ,0xb652,0x3f20 ,0xb600,0x3f0f ,
+ 0xb5af,0x3efd ,0xb55e,0x3eeb ,0xb50e,0x3ed8 ,
+ 0xb4be,0x3ec5 ,0xb470,0x3eb1 ,0xb422,0x3e9d ,
+ 0xb3d5,0x3e88 ,0xb388,0x3e72 ,0xb33d,0x3e5c ,
+ 0xb2f2,0x3e45 ,0xb2a7,0x3e2d ,0xb25e,0x3e15 ,
+ 0xb215,0x3dfc ,0xb1cd,0x3de3 ,0xb186,0x3dc9 ,
+ 0xb140,0x3daf ,0xb0fa,0x3d93 ,0xb0b5,0x3d78 ,
+ 0xb071,0x3d5b ,0xb02d,0x3d3f ,0xafeb,0x3d21 ,
+ 0xafa9,0x3d03 ,0xaf68,0x3ce4 ,0xaf28,0x3cc5 ,
+ 0xaee8,0x3ca5 ,0xaea9,0x3c85 ,0xae6b,0x3c64 ,
+ 0xae2e,0x3c42 ,0xadf2,0x3c20 ,0xadb6,0x3bfd ,
+ 0xad7b,0x3bda ,0xad41,0x3bb6 ,0xad08,0x3b92 ,
+ 0xacd0,0x3b6d ,0xac98,0x3b47 ,0xac61,0x3b21 ,
+ 0xac2b,0x3afa ,0xabf6,0x3ad3 ,0xabc2,0x3aab ,
+ 0xab8e,0x3a82 ,0xab5b,0x3a59 ,0xab29,0x3a30 ,
+ 0xaaf8,0x3a06 ,0xaac8,0x39db ,0xaa98,0x39b0 ,
+ 0xaa6a,0x3984 ,0xaa3c,0x3958 ,0xaa0f,0x392b ,
+ 0xa9e3,0x38fd ,0xa9b7,0x38cf ,0xa98d,0x38a1 ,
+ 0xa963,0x3871 ,0xa93a,0x3842 ,0xa912,0x3812 ,
+ 0xa8eb,0x37e1 ,0xa8c5,0x37b0 ,0xa89f,0x377e ,
+ 0xa87b,0x374b ,0xa857,0x3718 ,0xa834,0x36e5 ,
+ 0xa812,0x36b1 ,0xa7f1,0x367d ,0xa7d0,0x3648 ,
+ 0xa7b1,0x3612 ,0xa792,0x35dc ,0xa774,0x35a5 ,
+ 0xa757,0x356e ,0xa73b,0x3537 ,0xa71f,0x34ff ,
+ 0xa705,0x34c6 ,0xa6eb,0x348d ,0xa6d3,0x3453 ,
+ 0xa6bb,0x3419 ,0xa6a4,0x33df ,0xa68e,0x33a3 ,
+ 0xa678,0x3368 ,0xa664,0x332c ,0xa650,0x32ef ,
+ 0xa63e,0x32b2 ,0xa62c,0x3274 ,0xa61b,0x3236 ,
+ 0xa60b,0x31f8 ,0xa5fb,0x31b9 ,0xa5ed,0x3179 ,
+ 0xa5e0,0x3139 ,0xa5d3,0x30f9 ,0xa5c7,0x30b8 ,
+ 0xa5bc,0x3076 ,0xa5b2,0x3034 ,0xa5a9,0x2ff2 ,
+ 0xa5a1,0x2faf ,0xa599,0x2f6c ,0xa593,0x2f28 ,
+ 0xa58d,0x2ee4 ,0xa588,0x2e9f ,0xa585,0x2e5a ,
+ 0xa581,0x2e15 ,0xa57f,0x2dcf ,0xa57e,0x2d88 ,
+ 0xa57e,0x2d41 ,0xa57e,0x2cfa ,0xa57f,0x2cb2 ,
+ 0xa581,0x2c6a ,0xa585,0x2c21 ,0xa588,0x2bd8 ,
+ 0xa58d,0x2b8f ,0xa593,0x2b45 ,0xa599,0x2afb ,
+ 0xa5a1,0x2ab0 ,0xa5a9,0x2a65 ,0xa5b2,0x2a1a ,
+ 0xa5bc,0x29ce ,0xa5c7,0x2981 ,0xa5d3,0x2935 ,
+ 0xa5e0,0x28e7 ,0xa5ed,0x289a ,0xa5fb,0x284c ,
+ 0xa60b,0x27fe ,0xa61b,0x27af ,0xa62c,0x2760 ,
+ 0xa63e,0x2711 ,0xa650,0x26c1 ,0xa664,0x2671 ,
+ 0xa678,0x2620 ,0xa68e,0x25cf ,0xa6a4,0x257e ,
+ 0xa6bb,0x252c ,0xa6d3,0x24da ,0xa6eb,0x2488 ,
+ 0xa705,0x2435 ,0xa71f,0x23e2 ,0xa73b,0x238e ,
+ 0xa757,0x233b ,0xa774,0x22e7 ,0xa792,0x2292 ,
+ 0xa7b1,0x223d ,0xa7d0,0x21e8 ,0xa7f1,0x2193 ,
+ 0xa812,0x213d ,0xa834,0x20e7 ,0xa857,0x2091 ,
+ 0xa87b,0x203a ,0xa89f,0x1fe3 ,0xa8c5,0x1f8c ,
+ 0xa8eb,0x1f34 ,0xa912,0x1edc ,0xa93a,0x1e84 ,
+ 0xa963,0x1e2b ,0xa98d,0x1dd3 ,0xa9b7,0x1d79 ,
+ 0xa9e3,0x1d20 ,0xaa0f,0x1cc6 ,0xaa3c,0x1c6c ,
+ 0xaa6a,0x1c12 ,0xaa98,0x1bb8 ,0xaac8,0x1b5d ,
+ 0xaaf8,0x1b02 ,0xab29,0x1aa7 ,0xab5b,0x1a4b ,
+ 0xab8e,0x19ef ,0xabc2,0x1993 ,0xabf6,0x1937 ,
+ 0xac2b,0x18db ,0xac61,0x187e ,0xac98,0x1821 ,
+ 0xacd0,0x17c4 ,0xad08,0x1766 ,0xad41,0x1709 ,
+ 0xad7b,0x16ab ,0xadb6,0x164c ,0xadf2,0x15ee ,
+ 0xae2e,0x1590 ,0xae6b,0x1531 ,0xaea9,0x14d2 ,
+ 0xaee8,0x1473 ,0xaf28,0x1413 ,0xaf68,0x13b4 ,
+ 0xafa9,0x1354 ,0xafeb,0x12f4 ,0xb02d,0x1294 ,
+ 0xb071,0x1234 ,0xb0b5,0x11d3 ,0xb0fa,0x1173 ,
+ 0xb140,0x1112 ,0xb186,0x10b1 ,0xb1cd,0x1050 ,
+ 0xb215,0x0fee ,0xb25e,0x0f8d ,0xb2a7,0x0f2b ,
+ 0xb2f2,0x0eca ,0xb33d,0x0e68 ,0xb388,0x0e06 ,
+ 0xb3d5,0x0da4 ,0xb422,0x0d41 ,0xb470,0x0cdf ,
+ 0xb4be,0x0c7c ,0xb50e,0x0c1a ,0xb55e,0x0bb7 ,
+ 0xb5af,0x0b54 ,0xb600,0x0af1 ,0xb652,0x0a8e ,
+ 0xb6a5,0x0a2b ,0xb6f9,0x09c7 ,0xb74d,0x0964 ,
+ 0xb7a2,0x0901 ,0xb7f8,0x089d ,0xb84f,0x0839 ,
+ 0xb8a6,0x07d6 ,0xb8fd,0x0772 ,0xb956,0x070e ,
+ 0xb9af,0x06aa ,0xba09,0x0646 ,0xba64,0x05e2 ,
+ 0xbabf,0x057e ,0xbb1b,0x051a ,0xbb77,0x04b5 ,
+ 0xbbd4,0x0451 ,0xbc32,0x03ed ,0xbc91,0x0388 ,
+ 0xbcf0,0x0324 ,0xbd50,0x02c0 ,0xbdb0,0x025b ,
+ 0xbe11,0x01f7 ,0xbe73,0x0192 ,0xbed5,0x012e ,
+ 0xbf38,0x00c9 ,0xbf9c,0x0065 };
+
+
+extern const int s_Q14R_8;
+const int s_Q14R_8 = 1024;
+extern const unsigned short t_Q14R_8[2032];
+const unsigned short t_Q14R_8[2032] = {
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3b21,0x187e ,0x3ec5,0x0c7c ,0x3537,0x238e ,
+ 0x2d41,0x2d41 ,0x3b21,0x187e ,0x187e,0x3b21 ,
+ 0x187e,0x3b21 ,0x3537,0x238e ,0xf384,0x3ec5 ,
+ 0x0000,0x4000 ,0x2d41,0x2d41 ,0xd2bf,0x2d41 ,
+ 0xe782,0x3b21 ,0x238e,0x3537 ,0xc13b,0x0c7c ,
+ 0xd2bf,0x2d41 ,0x187e,0x3b21 ,0xc4df,0xe782 ,
+ 0xc4df,0x187e ,0x0c7c,0x3ec5 ,0xdc72,0xcac9 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3fb1,0x0646 ,0x3fec,0x0324 ,0x3f4f,0x0964 ,
+ 0x3ec5,0x0c7c ,0x3fb1,0x0646 ,0x3d3f,0x1294 ,
+ 0x3d3f,0x1294 ,0x3f4f,0x0964 ,0x39db,0x1b5d ,
+ 0x3b21,0x187e ,0x3ec5,0x0c7c ,0x3537,0x238e ,
+ 0x3871,0x1e2b ,0x3e15,0x0f8d ,0x2f6c,0x2afb ,
+ 0x3537,0x238e ,0x3d3f,0x1294 ,0x289a,0x3179 ,
+ 0x3179,0x289a ,0x3c42,0x1590 ,0x20e7,0x36e5 ,
+ 0x2d41,0x2d41 ,0x3b21,0x187e ,0x187e,0x3b21 ,
+ 0x289a,0x3179 ,0x39db,0x1b5d ,0x0f8d,0x3e15 ,
+ 0x238e,0x3537 ,0x3871,0x1e2b ,0x0646,0x3fb1 ,
+ 0x1e2b,0x3871 ,0x36e5,0x20e7 ,0xfcdc,0x3fec ,
+ 0x187e,0x3b21 ,0x3537,0x238e ,0xf384,0x3ec5 ,
+ 0x1294,0x3d3f ,0x3368,0x2620 ,0xea70,0x3c42 ,
+ 0x0c7c,0x3ec5 ,0x3179,0x289a ,0xe1d5,0x3871 ,
+ 0x0646,0x3fb1 ,0x2f6c,0x2afb ,0xd9e0,0x3368 ,
+ 0x0000,0x4000 ,0x2d41,0x2d41 ,0xd2bf,0x2d41 ,
+ 0xf9ba,0x3fb1 ,0x2afb,0x2f6c ,0xcc98,0x2620 ,
+ 0xf384,0x3ec5 ,0x289a,0x3179 ,0xc78f,0x1e2b ,
+ 0xed6c,0x3d3f ,0x2620,0x3368 ,0xc3be,0x1590 ,
+ 0xe782,0x3b21 ,0x238e,0x3537 ,0xc13b,0x0c7c ,
+ 0xe1d5,0x3871 ,0x20e7,0x36e5 ,0xc014,0x0324 ,
+ 0xdc72,0x3537 ,0x1e2b,0x3871 ,0xc04f,0xf9ba ,
+ 0xd766,0x3179 ,0x1b5d,0x39db ,0xc1eb,0xf073 ,
+ 0xd2bf,0x2d41 ,0x187e,0x3b21 ,0xc4df,0xe782 ,
+ 0xce87,0x289a ,0x1590,0x3c42 ,0xc91b,0xdf19 ,
+ 0xcac9,0x238e ,0x1294,0x3d3f ,0xce87,0xd766 ,
+ 0xc78f,0x1e2b ,0x0f8d,0x3e15 ,0xd505,0xd094 ,
+ 0xc4df,0x187e ,0x0c7c,0x3ec5 ,0xdc72,0xcac9 ,
+ 0xc2c1,0x1294 ,0x0964,0x3f4f ,0xe4a3,0xc625 ,
+ 0xc13b,0x0c7c ,0x0646,0x3fb1 ,0xed6c,0xc2c1 ,
+ 0xc04f,0x0646 ,0x0324,0x3fec ,0xf69c,0xc0b1 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3ffb,0x0192 ,0x3fff,0x00c9 ,0x3ff5,0x025b ,
+ 0x3fec,0x0324 ,0x3ffb,0x0192 ,0x3fd4,0x04b5 ,
+ 0x3fd4,0x04b5 ,0x3ff5,0x025b ,0x3f9c,0x070e ,
+ 0x3fb1,0x0646 ,0x3fec,0x0324 ,0x3f4f,0x0964 ,
+ 0x3f85,0x07d6 ,0x3fe1,0x03ed ,0x3eeb,0x0bb7 ,
+ 0x3f4f,0x0964 ,0x3fd4,0x04b5 ,0x3e72,0x0e06 ,
+ 0x3f0f,0x0af1 ,0x3fc4,0x057e ,0x3de3,0x1050 ,
+ 0x3ec5,0x0c7c ,0x3fb1,0x0646 ,0x3d3f,0x1294 ,
+ 0x3e72,0x0e06 ,0x3f9c,0x070e ,0x3c85,0x14d2 ,
+ 0x3e15,0x0f8d ,0x3f85,0x07d6 ,0x3bb6,0x1709 ,
+ 0x3daf,0x1112 ,0x3f6b,0x089d ,0x3ad3,0x1937 ,
+ 0x3d3f,0x1294 ,0x3f4f,0x0964 ,0x39db,0x1b5d ,
+ 0x3cc5,0x1413 ,0x3f30,0x0a2b ,0x38cf,0x1d79 ,
+ 0x3c42,0x1590 ,0x3f0f,0x0af1 ,0x37b0,0x1f8c ,
+ 0x3bb6,0x1709 ,0x3eeb,0x0bb7 ,0x367d,0x2193 ,
+ 0x3b21,0x187e ,0x3ec5,0x0c7c ,0x3537,0x238e ,
+ 0x3a82,0x19ef ,0x3e9d,0x0d41 ,0x33df,0x257e ,
+ 0x39db,0x1b5d ,0x3e72,0x0e06 ,0x3274,0x2760 ,
+ 0x392b,0x1cc6 ,0x3e45,0x0eca ,0x30f9,0x2935 ,
+ 0x3871,0x1e2b ,0x3e15,0x0f8d ,0x2f6c,0x2afb ,
+ 0x37b0,0x1f8c ,0x3de3,0x1050 ,0x2dcf,0x2cb2 ,
+ 0x36e5,0x20e7 ,0x3daf,0x1112 ,0x2c21,0x2e5a ,
+ 0x3612,0x223d ,0x3d78,0x11d3 ,0x2a65,0x2ff2 ,
+ 0x3537,0x238e ,0x3d3f,0x1294 ,0x289a,0x3179 ,
+ 0x3453,0x24da ,0x3d03,0x1354 ,0x26c1,0x32ef ,
+ 0x3368,0x2620 ,0x3cc5,0x1413 ,0x24da,0x3453 ,
+ 0x3274,0x2760 ,0x3c85,0x14d2 ,0x22e7,0x35a5 ,
+ 0x3179,0x289a ,0x3c42,0x1590 ,0x20e7,0x36e5 ,
+ 0x3076,0x29ce ,0x3bfd,0x164c ,0x1edc,0x3812 ,
+ 0x2f6c,0x2afb ,0x3bb6,0x1709 ,0x1cc6,0x392b ,
+ 0x2e5a,0x2c21 ,0x3b6d,0x17c4 ,0x1aa7,0x3a30 ,
+ 0x2d41,0x2d41 ,0x3b21,0x187e ,0x187e,0x3b21 ,
+ 0x2c21,0x2e5a ,0x3ad3,0x1937 ,0x164c,0x3bfd ,
+ 0x2afb,0x2f6c ,0x3a82,0x19ef ,0x1413,0x3cc5 ,
+ 0x29ce,0x3076 ,0x3a30,0x1aa7 ,0x11d3,0x3d78 ,
+ 0x289a,0x3179 ,0x39db,0x1b5d ,0x0f8d,0x3e15 ,
+ 0x2760,0x3274 ,0x3984,0x1c12 ,0x0d41,0x3e9d ,
+ 0x2620,0x3368 ,0x392b,0x1cc6 ,0x0af1,0x3f0f ,
+ 0x24da,0x3453 ,0x38cf,0x1d79 ,0x089d,0x3f6b ,
+ 0x238e,0x3537 ,0x3871,0x1e2b ,0x0646,0x3fb1 ,
+ 0x223d,0x3612 ,0x3812,0x1edc ,0x03ed,0x3fe1 ,
+ 0x20e7,0x36e5 ,0x37b0,0x1f8c ,0x0192,0x3ffb ,
+ 0x1f8c,0x37b0 ,0x374b,0x203a ,0xff37,0x3fff ,
+ 0x1e2b,0x3871 ,0x36e5,0x20e7 ,0xfcdc,0x3fec ,
+ 0x1cc6,0x392b ,0x367d,0x2193 ,0xfa82,0x3fc4 ,
+ 0x1b5d,0x39db ,0x3612,0x223d ,0xf82a,0x3f85 ,
+ 0x19ef,0x3a82 ,0x35a5,0x22e7 ,0xf5d5,0x3f30 ,
+ 0x187e,0x3b21 ,0x3537,0x238e ,0xf384,0x3ec5 ,
+ 0x1709,0x3bb6 ,0x34c6,0x2435 ,0xf136,0x3e45 ,
+ 0x1590,0x3c42 ,0x3453,0x24da ,0xeeee,0x3daf ,
+ 0x1413,0x3cc5 ,0x33df,0x257e ,0xecac,0x3d03 ,
+ 0x1294,0x3d3f ,0x3368,0x2620 ,0xea70,0x3c42 ,
+ 0x1112,0x3daf ,0x32ef,0x26c1 ,0xe83c,0x3b6d ,
+ 0x0f8d,0x3e15 ,0x3274,0x2760 ,0xe611,0x3a82 ,
+ 0x0e06,0x3e72 ,0x31f8,0x27fe ,0xe3ee,0x3984 ,
+ 0x0c7c,0x3ec5 ,0x3179,0x289a ,0xe1d5,0x3871 ,
+ 0x0af1,0x3f0f ,0x30f9,0x2935 ,0xdfc6,0x374b ,
+ 0x0964,0x3f4f ,0x3076,0x29ce ,0xddc3,0x3612 ,
+ 0x07d6,0x3f85 ,0x2ff2,0x2a65 ,0xdbcb,0x34c6 ,
+ 0x0646,0x3fb1 ,0x2f6c,0x2afb ,0xd9e0,0x3368 ,
+ 0x04b5,0x3fd4 ,0x2ee4,0x2b8f ,0xd802,0x31f8 ,
+ 0x0324,0x3fec ,0x2e5a,0x2c21 ,0xd632,0x3076 ,
+ 0x0192,0x3ffb ,0x2dcf,0x2cb2 ,0xd471,0x2ee4 ,
+ 0x0000,0x4000 ,0x2d41,0x2d41 ,0xd2bf,0x2d41 ,
+ 0xfe6e,0x3ffb ,0x2cb2,0x2dcf ,0xd11c,0x2b8f ,
+ 0xfcdc,0x3fec ,0x2c21,0x2e5a ,0xcf8a,0x29ce ,
+ 0xfb4b,0x3fd4 ,0x2b8f,0x2ee4 ,0xce08,0x27fe ,
+ 0xf9ba,0x3fb1 ,0x2afb,0x2f6c ,0xcc98,0x2620 ,
+ 0xf82a,0x3f85 ,0x2a65,0x2ff2 ,0xcb3a,0x2435 ,
+ 0xf69c,0x3f4f ,0x29ce,0x3076 ,0xc9ee,0x223d ,
+ 0xf50f,0x3f0f ,0x2935,0x30f9 ,0xc8b5,0x203a ,
+ 0xf384,0x3ec5 ,0x289a,0x3179 ,0xc78f,0x1e2b ,
+ 0xf1fa,0x3e72 ,0x27fe,0x31f8 ,0xc67c,0x1c12 ,
+ 0xf073,0x3e15 ,0x2760,0x3274 ,0xc57e,0x19ef ,
+ 0xeeee,0x3daf ,0x26c1,0x32ef ,0xc493,0x17c4 ,
+ 0xed6c,0x3d3f ,0x2620,0x3368 ,0xc3be,0x1590 ,
+ 0xebed,0x3cc5 ,0x257e,0x33df ,0xc2fd,0x1354 ,
+ 0xea70,0x3c42 ,0x24da,0x3453 ,0xc251,0x1112 ,
+ 0xe8f7,0x3bb6 ,0x2435,0x34c6 ,0xc1bb,0x0eca ,
+ 0xe782,0x3b21 ,0x238e,0x3537 ,0xc13b,0x0c7c ,
+ 0xe611,0x3a82 ,0x22e7,0x35a5 ,0xc0d0,0x0a2b ,
+ 0xe4a3,0x39db ,0x223d,0x3612 ,0xc07b,0x07d6 ,
+ 0xe33a,0x392b ,0x2193,0x367d ,0xc03c,0x057e ,
+ 0xe1d5,0x3871 ,0x20e7,0x36e5 ,0xc014,0x0324 ,
+ 0xe074,0x37b0 ,0x203a,0x374b ,0xc001,0x00c9 ,
+ 0xdf19,0x36e5 ,0x1f8c,0x37b0 ,0xc005,0xfe6e ,
+ 0xddc3,0x3612 ,0x1edc,0x3812 ,0xc01f,0xfc13 ,
+ 0xdc72,0x3537 ,0x1e2b,0x3871 ,0xc04f,0xf9ba ,
+ 0xdb26,0x3453 ,0x1d79,0x38cf ,0xc095,0xf763 ,
+ 0xd9e0,0x3368 ,0x1cc6,0x392b ,0xc0f1,0xf50f ,
+ 0xd8a0,0x3274 ,0x1c12,0x3984 ,0xc163,0xf2bf ,
+ 0xd766,0x3179 ,0x1b5d,0x39db ,0xc1eb,0xf073 ,
+ 0xd632,0x3076 ,0x1aa7,0x3a30 ,0xc288,0xee2d ,
+ 0xd505,0x2f6c ,0x19ef,0x3a82 ,0xc33b,0xebed ,
+ 0xd3df,0x2e5a ,0x1937,0x3ad3 ,0xc403,0xe9b4 ,
+ 0xd2bf,0x2d41 ,0x187e,0x3b21 ,0xc4df,0xe782 ,
+ 0xd1a6,0x2c21 ,0x17c4,0x3b6d ,0xc5d0,0xe559 ,
+ 0xd094,0x2afb ,0x1709,0x3bb6 ,0xc6d5,0xe33a ,
+ 0xcf8a,0x29ce ,0x164c,0x3bfd ,0xc7ee,0xe124 ,
+ 0xce87,0x289a ,0x1590,0x3c42 ,0xc91b,0xdf19 ,
+ 0xcd8c,0x2760 ,0x14d2,0x3c85 ,0xca5b,0xdd19 ,
+ 0xcc98,0x2620 ,0x1413,0x3cc5 ,0xcbad,0xdb26 ,
+ 0xcbad,0x24da ,0x1354,0x3d03 ,0xcd11,0xd93f ,
+ 0xcac9,0x238e ,0x1294,0x3d3f ,0xce87,0xd766 ,
+ 0xc9ee,0x223d ,0x11d3,0x3d78 ,0xd00e,0xd59b ,
+ 0xc91b,0x20e7 ,0x1112,0x3daf ,0xd1a6,0xd3df ,
+ 0xc850,0x1f8c ,0x1050,0x3de3 ,0xd34e,0xd231 ,
+ 0xc78f,0x1e2b ,0x0f8d,0x3e15 ,0xd505,0xd094 ,
+ 0xc6d5,0x1cc6 ,0x0eca,0x3e45 ,0xd6cb,0xcf07 ,
+ 0xc625,0x1b5d ,0x0e06,0x3e72 ,0xd8a0,0xcd8c ,
+ 0xc57e,0x19ef ,0x0d41,0x3e9d ,0xda82,0xcc21 ,
+ 0xc4df,0x187e ,0x0c7c,0x3ec5 ,0xdc72,0xcac9 ,
+ 0xc44a,0x1709 ,0x0bb7,0x3eeb ,0xde6d,0xc983 ,
+ 0xc3be,0x1590 ,0x0af1,0x3f0f ,0xe074,0xc850 ,
+ 0xc33b,0x1413 ,0x0a2b,0x3f30 ,0xe287,0xc731 ,
+ 0xc2c1,0x1294 ,0x0964,0x3f4f ,0xe4a3,0xc625 ,
+ 0xc251,0x1112 ,0x089d,0x3f6b ,0xe6c9,0xc52d ,
+ 0xc1eb,0x0f8d ,0x07d6,0x3f85 ,0xe8f7,0xc44a ,
+ 0xc18e,0x0e06 ,0x070e,0x3f9c ,0xeb2e,0xc37b ,
+ 0xc13b,0x0c7c ,0x0646,0x3fb1 ,0xed6c,0xc2c1 ,
+ 0xc0f1,0x0af1 ,0x057e,0x3fc4 ,0xefb0,0xc21d ,
+ 0xc0b1,0x0964 ,0x04b5,0x3fd4 ,0xf1fa,0xc18e ,
+ 0xc07b,0x07d6 ,0x03ed,0x3fe1 ,0xf449,0xc115 ,
+ 0xc04f,0x0646 ,0x0324,0x3fec ,0xf69c,0xc0b1 ,
+ 0xc02c,0x04b5 ,0x025b,0x3ff5 ,0xf8f2,0xc064 ,
+ 0xc014,0x0324 ,0x0192,0x3ffb ,0xfb4b,0xc02c ,
+ 0xc005,0x0192 ,0x00c9,0x3fff ,0xfda5,0xc00b ,
+ 0x4000,0x0000 ,0x4000,0x0065 ,0x3fff,0x00c9 ,
+ 0x3ffd,0x012e ,0x3ffb,0x0192 ,0x3ff8,0x01f7 ,
+ 0x3ff5,0x025b ,0x3ff1,0x02c0 ,0x3fec,0x0324 ,
+ 0x3fe7,0x0388 ,0x3fe1,0x03ed ,0x3fdb,0x0451 ,
+ 0x3fd4,0x04b5 ,0x3fcc,0x051a ,0x3fc4,0x057e ,
+ 0x3fbb,0x05e2 ,0x3fb1,0x0646 ,0x3fa7,0x06aa ,
+ 0x3f9c,0x070e ,0x3f91,0x0772 ,0x3f85,0x07d6 ,
+ 0x3f78,0x0839 ,0x3f6b,0x089d ,0x3f5d,0x0901 ,
+ 0x3f4f,0x0964 ,0x3f40,0x09c7 ,0x3f30,0x0a2b ,
+ 0x3f20,0x0a8e ,0x3f0f,0x0af1 ,0x3efd,0x0b54 ,
+ 0x3eeb,0x0bb7 ,0x3ed8,0x0c1a ,0x3ec5,0x0c7c ,
+ 0x3eb1,0x0cdf ,0x3e9d,0x0d41 ,0x3e88,0x0da4 ,
+ 0x3e72,0x0e06 ,0x3e5c,0x0e68 ,0x3e45,0x0eca ,
+ 0x3e2d,0x0f2b ,0x3e15,0x0f8d ,0x3dfc,0x0fee ,
+ 0x3de3,0x1050 ,0x3dc9,0x10b1 ,0x3daf,0x1112 ,
+ 0x3d93,0x1173 ,0x3d78,0x11d3 ,0x3d5b,0x1234 ,
+ 0x3d3f,0x1294 ,0x3d21,0x12f4 ,0x3d03,0x1354 ,
+ 0x3ce4,0x13b4 ,0x3cc5,0x1413 ,0x3ca5,0x1473 ,
+ 0x3c85,0x14d2 ,0x3c64,0x1531 ,0x3c42,0x1590 ,
+ 0x3c20,0x15ee ,0x3bfd,0x164c ,0x3bda,0x16ab ,
+ 0x3bb6,0x1709 ,0x3b92,0x1766 ,0x3b6d,0x17c4 ,
+ 0x3b47,0x1821 ,0x3b21,0x187e ,0x3afa,0x18db ,
+ 0x3ad3,0x1937 ,0x3aab,0x1993 ,0x3a82,0x19ef ,
+ 0x3a59,0x1a4b ,0x3a30,0x1aa7 ,0x3a06,0x1b02 ,
+ 0x39db,0x1b5d ,0x39b0,0x1bb8 ,0x3984,0x1c12 ,
+ 0x3958,0x1c6c ,0x392b,0x1cc6 ,0x38fd,0x1d20 ,
+ 0x38cf,0x1d79 ,0x38a1,0x1dd3 ,0x3871,0x1e2b ,
+ 0x3842,0x1e84 ,0x3812,0x1edc ,0x37e1,0x1f34 ,
+ 0x37b0,0x1f8c ,0x377e,0x1fe3 ,0x374b,0x203a ,
+ 0x3718,0x2091 ,0x36e5,0x20e7 ,0x36b1,0x213d ,
+ 0x367d,0x2193 ,0x3648,0x21e8 ,0x3612,0x223d ,
+ 0x35dc,0x2292 ,0x35a5,0x22e7 ,0x356e,0x233b ,
+ 0x3537,0x238e ,0x34ff,0x23e2 ,0x34c6,0x2435 ,
+ 0x348d,0x2488 ,0x3453,0x24da ,0x3419,0x252c ,
+ 0x33df,0x257e ,0x33a3,0x25cf ,0x3368,0x2620 ,
+ 0x332c,0x2671 ,0x32ef,0x26c1 ,0x32b2,0x2711 ,
+ 0x3274,0x2760 ,0x3236,0x27af ,0x31f8,0x27fe ,
+ 0x31b9,0x284c ,0x3179,0x289a ,0x3139,0x28e7 ,
+ 0x30f9,0x2935 ,0x30b8,0x2981 ,0x3076,0x29ce ,
+ 0x3034,0x2a1a ,0x2ff2,0x2a65 ,0x2faf,0x2ab0 ,
+ 0x2f6c,0x2afb ,0x2f28,0x2b45 ,0x2ee4,0x2b8f ,
+ 0x2e9f,0x2bd8 ,0x2e5a,0x2c21 ,0x2e15,0x2c6a ,
+ 0x2dcf,0x2cb2 ,0x2d88,0x2cfa ,0x2d41,0x2d41 ,
+ 0x2cfa,0x2d88 ,0x2cb2,0x2dcf ,0x2c6a,0x2e15 ,
+ 0x2c21,0x2e5a ,0x2bd8,0x2e9f ,0x2b8f,0x2ee4 ,
+ 0x2b45,0x2f28 ,0x2afb,0x2f6c ,0x2ab0,0x2faf ,
+ 0x2a65,0x2ff2 ,0x2a1a,0x3034 ,0x29ce,0x3076 ,
+ 0x2981,0x30b8 ,0x2935,0x30f9 ,0x28e7,0x3139 ,
+ 0x289a,0x3179 ,0x284c,0x31b9 ,0x27fe,0x31f8 ,
+ 0x27af,0x3236 ,0x2760,0x3274 ,0x2711,0x32b2 ,
+ 0x26c1,0x32ef ,0x2671,0x332c ,0x2620,0x3368 ,
+ 0x25cf,0x33a3 ,0x257e,0x33df ,0x252c,0x3419 ,
+ 0x24da,0x3453 ,0x2488,0x348d ,0x2435,0x34c6 ,
+ 0x23e2,0x34ff ,0x238e,0x3537 ,0x233b,0x356e ,
+ 0x22e7,0x35a5 ,0x2292,0x35dc ,0x223d,0x3612 ,
+ 0x21e8,0x3648 ,0x2193,0x367d ,0x213d,0x36b1 ,
+ 0x20e7,0x36e5 ,0x2091,0x3718 ,0x203a,0x374b ,
+ 0x1fe3,0x377e ,0x1f8c,0x37b0 ,0x1f34,0x37e1 ,
+ 0x1edc,0x3812 ,0x1e84,0x3842 ,0x1e2b,0x3871 ,
+ 0x1dd3,0x38a1 ,0x1d79,0x38cf ,0x1d20,0x38fd ,
+ 0x1cc6,0x392b ,0x1c6c,0x3958 ,0x1c12,0x3984 ,
+ 0x1bb8,0x39b0 ,0x1b5d,0x39db ,0x1b02,0x3a06 ,
+ 0x1aa7,0x3a30 ,0x1a4b,0x3a59 ,0x19ef,0x3a82 ,
+ 0x1993,0x3aab ,0x1937,0x3ad3 ,0x18db,0x3afa ,
+ 0x187e,0x3b21 ,0x1821,0x3b47 ,0x17c4,0x3b6d ,
+ 0x1766,0x3b92 ,0x1709,0x3bb6 ,0x16ab,0x3bda ,
+ 0x164c,0x3bfd ,0x15ee,0x3c20 ,0x1590,0x3c42 ,
+ 0x1531,0x3c64 ,0x14d2,0x3c85 ,0x1473,0x3ca5 ,
+ 0x1413,0x3cc5 ,0x13b4,0x3ce4 ,0x1354,0x3d03 ,
+ 0x12f4,0x3d21 ,0x1294,0x3d3f ,0x1234,0x3d5b ,
+ 0x11d3,0x3d78 ,0x1173,0x3d93 ,0x1112,0x3daf ,
+ 0x10b1,0x3dc9 ,0x1050,0x3de3 ,0x0fee,0x3dfc ,
+ 0x0f8d,0x3e15 ,0x0f2b,0x3e2d ,0x0eca,0x3e45 ,
+ 0x0e68,0x3e5c ,0x0e06,0x3e72 ,0x0da4,0x3e88 ,
+ 0x0d41,0x3e9d ,0x0cdf,0x3eb1 ,0x0c7c,0x3ec5 ,
+ 0x0c1a,0x3ed8 ,0x0bb7,0x3eeb ,0x0b54,0x3efd ,
+ 0x0af1,0x3f0f ,0x0a8e,0x3f20 ,0x0a2b,0x3f30 ,
+ 0x09c7,0x3f40 ,0x0964,0x3f4f ,0x0901,0x3f5d ,
+ 0x089d,0x3f6b ,0x0839,0x3f78 ,0x07d6,0x3f85 ,
+ 0x0772,0x3f91 ,0x070e,0x3f9c ,0x06aa,0x3fa7 ,
+ 0x0646,0x3fb1 ,0x05e2,0x3fbb ,0x057e,0x3fc4 ,
+ 0x051a,0x3fcc ,0x04b5,0x3fd4 ,0x0451,0x3fdb ,
+ 0x03ed,0x3fe1 ,0x0388,0x3fe7 ,0x0324,0x3fec ,
+ 0x02c0,0x3ff1 ,0x025b,0x3ff5 ,0x01f7,0x3ff8 ,
+ 0x0192,0x3ffb ,0x012e,0x3ffd ,0x00c9,0x3fff ,
+ 0x0065,0x4000 ,0x0000,0x4000 ,0xff9b,0x4000 ,
+ 0xff37,0x3fff ,0xfed2,0x3ffd ,0xfe6e,0x3ffb ,
+ 0xfe09,0x3ff8 ,0xfda5,0x3ff5 ,0xfd40,0x3ff1 ,
+ 0xfcdc,0x3fec ,0xfc78,0x3fe7 ,0xfc13,0x3fe1 ,
+ 0xfbaf,0x3fdb ,0xfb4b,0x3fd4 ,0xfae6,0x3fcc ,
+ 0xfa82,0x3fc4 ,0xfa1e,0x3fbb ,0xf9ba,0x3fb1 ,
+ 0xf956,0x3fa7 ,0xf8f2,0x3f9c ,0xf88e,0x3f91 ,
+ 0xf82a,0x3f85 ,0xf7c7,0x3f78 ,0xf763,0x3f6b ,
+ 0xf6ff,0x3f5d ,0xf69c,0x3f4f ,0xf639,0x3f40 ,
+ 0xf5d5,0x3f30 ,0xf572,0x3f20 ,0xf50f,0x3f0f ,
+ 0xf4ac,0x3efd ,0xf449,0x3eeb ,0xf3e6,0x3ed8 ,
+ 0xf384,0x3ec5 ,0xf321,0x3eb1 ,0xf2bf,0x3e9d ,
+ 0xf25c,0x3e88 ,0xf1fa,0x3e72 ,0xf198,0x3e5c ,
+ 0xf136,0x3e45 ,0xf0d5,0x3e2d ,0xf073,0x3e15 ,
+ 0xf012,0x3dfc ,0xefb0,0x3de3 ,0xef4f,0x3dc9 ,
+ 0xeeee,0x3daf ,0xee8d,0x3d93 ,0xee2d,0x3d78 ,
+ 0xedcc,0x3d5b ,0xed6c,0x3d3f ,0xed0c,0x3d21 ,
+ 0xecac,0x3d03 ,0xec4c,0x3ce4 ,0xebed,0x3cc5 ,
+ 0xeb8d,0x3ca5 ,0xeb2e,0x3c85 ,0xeacf,0x3c64 ,
+ 0xea70,0x3c42 ,0xea12,0x3c20 ,0xe9b4,0x3bfd ,
+ 0xe955,0x3bda ,0xe8f7,0x3bb6 ,0xe89a,0x3b92 ,
+ 0xe83c,0x3b6d ,0xe7df,0x3b47 ,0xe782,0x3b21 ,
+ 0xe725,0x3afa ,0xe6c9,0x3ad3 ,0xe66d,0x3aab ,
+ 0xe611,0x3a82 ,0xe5b5,0x3a59 ,0xe559,0x3a30 ,
+ 0xe4fe,0x3a06 ,0xe4a3,0x39db ,0xe448,0x39b0 ,
+ 0xe3ee,0x3984 ,0xe394,0x3958 ,0xe33a,0x392b ,
+ 0xe2e0,0x38fd ,0xe287,0x38cf ,0xe22d,0x38a1 ,
+ 0xe1d5,0x3871 ,0xe17c,0x3842 ,0xe124,0x3812 ,
+ 0xe0cc,0x37e1 ,0xe074,0x37b0 ,0xe01d,0x377e ,
+ 0xdfc6,0x374b ,0xdf6f,0x3718 ,0xdf19,0x36e5 ,
+ 0xdec3,0x36b1 ,0xde6d,0x367d ,0xde18,0x3648 ,
+ 0xddc3,0x3612 ,0xdd6e,0x35dc ,0xdd19,0x35a5 ,
+ 0xdcc5,0x356e ,0xdc72,0x3537 ,0xdc1e,0x34ff ,
+ 0xdbcb,0x34c6 ,0xdb78,0x348d ,0xdb26,0x3453 ,
+ 0xdad4,0x3419 ,0xda82,0x33df ,0xda31,0x33a3 ,
+ 0xd9e0,0x3368 ,0xd98f,0x332c ,0xd93f,0x32ef ,
+ 0xd8ef,0x32b2 ,0xd8a0,0x3274 ,0xd851,0x3236 ,
+ 0xd802,0x31f8 ,0xd7b4,0x31b9 ,0xd766,0x3179 ,
+ 0xd719,0x3139 ,0xd6cb,0x30f9 ,0xd67f,0x30b8 ,
+ 0xd632,0x3076 ,0xd5e6,0x3034 ,0xd59b,0x2ff2 ,
+ 0xd550,0x2faf ,0xd505,0x2f6c ,0xd4bb,0x2f28 ,
+ 0xd471,0x2ee4 ,0xd428,0x2e9f ,0xd3df,0x2e5a ,
+ 0xd396,0x2e15 ,0xd34e,0x2dcf ,0xd306,0x2d88 ,
+ 0xd2bf,0x2d41 ,0xd278,0x2cfa ,0xd231,0x2cb2 ,
+ 0xd1eb,0x2c6a ,0xd1a6,0x2c21 ,0xd161,0x2bd8 ,
+ 0xd11c,0x2b8f ,0xd0d8,0x2b45 ,0xd094,0x2afb ,
+ 0xd051,0x2ab0 ,0xd00e,0x2a65 ,0xcfcc,0x2a1a ,
+ 0xcf8a,0x29ce ,0xcf48,0x2981 ,0xcf07,0x2935 ,
+ 0xcec7,0x28e7 ,0xce87,0x289a ,0xce47,0x284c ,
+ 0xce08,0x27fe ,0xcdca,0x27af ,0xcd8c,0x2760 ,
+ 0xcd4e,0x2711 ,0xcd11,0x26c1 ,0xccd4,0x2671 ,
+ 0xcc98,0x2620 ,0xcc5d,0x25cf ,0xcc21,0x257e ,
+ 0xcbe7,0x252c ,0xcbad,0x24da ,0xcb73,0x2488 ,
+ 0xcb3a,0x2435 ,0xcb01,0x23e2 ,0xcac9,0x238e ,
+ 0xca92,0x233b ,0xca5b,0x22e7 ,0xca24,0x2292 ,
+ 0xc9ee,0x223d ,0xc9b8,0x21e8 ,0xc983,0x2193 ,
+ 0xc94f,0x213d ,0xc91b,0x20e7 ,0xc8e8,0x2091 ,
+ 0xc8b5,0x203a ,0xc882,0x1fe3 ,0xc850,0x1f8c ,
+ 0xc81f,0x1f34 ,0xc7ee,0x1edc ,0xc7be,0x1e84 ,
+ 0xc78f,0x1e2b ,0xc75f,0x1dd3 ,0xc731,0x1d79 ,
+ 0xc703,0x1d20 ,0xc6d5,0x1cc6 ,0xc6a8,0x1c6c ,
+ 0xc67c,0x1c12 ,0xc650,0x1bb8 ,0xc625,0x1b5d ,
+ 0xc5fa,0x1b02 ,0xc5d0,0x1aa7 ,0xc5a7,0x1a4b ,
+ 0xc57e,0x19ef ,0xc555,0x1993 ,0xc52d,0x1937 ,
+ 0xc506,0x18db ,0xc4df,0x187e ,0xc4b9,0x1821 ,
+ 0xc493,0x17c4 ,0xc46e,0x1766 ,0xc44a,0x1709 ,
+ 0xc426,0x16ab ,0xc403,0x164c ,0xc3e0,0x15ee ,
+ 0xc3be,0x1590 ,0xc39c,0x1531 ,0xc37b,0x14d2 ,
+ 0xc35b,0x1473 ,0xc33b,0x1413 ,0xc31c,0x13b4 ,
+ 0xc2fd,0x1354 ,0xc2df,0x12f4 ,0xc2c1,0x1294 ,
+ 0xc2a5,0x1234 ,0xc288,0x11d3 ,0xc26d,0x1173 ,
+ 0xc251,0x1112 ,0xc237,0x10b1 ,0xc21d,0x1050 ,
+ 0xc204,0x0fee ,0xc1eb,0x0f8d ,0xc1d3,0x0f2b ,
+ 0xc1bb,0x0eca ,0xc1a4,0x0e68 ,0xc18e,0x0e06 ,
+ 0xc178,0x0da4 ,0xc163,0x0d41 ,0xc14f,0x0cdf ,
+ 0xc13b,0x0c7c ,0xc128,0x0c1a ,0xc115,0x0bb7 ,
+ 0xc103,0x0b54 ,0xc0f1,0x0af1 ,0xc0e0,0x0a8e ,
+ 0xc0d0,0x0a2b ,0xc0c0,0x09c7 ,0xc0b1,0x0964 ,
+ 0xc0a3,0x0901 ,0xc095,0x089d ,0xc088,0x0839 ,
+ 0xc07b,0x07d6 ,0xc06f,0x0772 ,0xc064,0x070e ,
+ 0xc059,0x06aa ,0xc04f,0x0646 ,0xc045,0x05e2 ,
+ 0xc03c,0x057e ,0xc034,0x051a ,0xc02c,0x04b5 ,
+ 0xc025,0x0451 ,0xc01f,0x03ed ,0xc019,0x0388 ,
+ 0xc014,0x0324 ,0xc00f,0x02c0 ,0xc00b,0x025b ,
+ 0xc008,0x01f7 ,0xc005,0x0192 ,0xc003,0x012e ,
+ 0xc001,0x00c9 ,0xc000,0x0065 };
diff --git a/common_audio/signal_processing/webrtc_fft_t_rad.c b/common_audio/signal_processing/webrtc_fft_t_rad.c
new file mode 100644
index 0000000..13fbd9f
--- /dev/null
+++ b/common_audio/signal_processing/webrtc_fft_t_rad.c
@@ -0,0 +1,27 @@
+/*
+ * 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 Q14 radix-2 tables used in ARM9E optimization routines.
+ *
+ */
+
+extern const unsigned short t_Q14S_rad8[2];
+const unsigned short t_Q14S_rad8[2] = { 0x0000,0x2d41 };
+
+//extern const int t_Q30S_rad8[2];
+//const int t_Q30S_rad8[2] = { 0x00000000,0x2d413ccd };
+
+extern const unsigned short t_Q14R_rad8[2];
+const unsigned short t_Q14R_rad8[2] = { 0x2d41,0x2d41 };
+
+//extern const int t_Q30R_rad8[2];
+//const int t_Q30R_rad8[2] = { 0x2d413ccd,0x2d413ccd };
diff --git a/common_audio/vad/Android.mk b/common_audio/vad/Android.mk
new file mode 100644
index 0000000..b7be3f0
--- /dev/null
+++ b/common_audio/vad/Android.mk
@@ -0,0 +1,50 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/../../../android-webrtc.mk
+
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libwebrtc_vad
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+ webrtc_vad.c \
+ vad_core.c \
+ vad_filterbank.c \
+ vad_gmm.c \
+ vad_sp.c
+
+# Flags passed to both C and C++ files.
+LOCAL_CFLAGS := \
+ $(MY_WEBRTC_COMMON_DEFS)
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../.. \
+ $(LOCAL_PATH)/../signal_processing/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libdl \
+ libstlport
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl -lpthread
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+ifndef NDK_ROOT
+include external/stlport/libstlport.mk
+endif
+include $(BUILD_STATIC_LIBRARY)
diff --git a/common_audio/vad/include/webrtc_vad.h b/common_audio/vad/include/webrtc_vad.h
new file mode 100644
index 0000000..edc7494
--- /dev/null
+++ b/common_audio/vad/include/webrtc_vad.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012 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 header file includes the VAD API calls. Specific function calls are given below.
+ */
+
+#ifndef WEBRTC_COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_ // NOLINT
+#define WEBRTC_COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_
+
+#include "typedefs.h" // NOLINT
+
+typedef struct WebRtcVadInst VadInst;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Creates an instance to the VAD structure.
+//
+// - handle [o] : Pointer to the VAD instance that should be created.
+//
+// returns : 0 - (OK), -1 - (Error)
+int WebRtcVad_Create(VadInst** handle);
+
+// Frees the dynamic memory of a specified VAD instance.
+//
+// - handle [i] : Pointer to VAD instance that should be freed.
+//
+// returns : 0 - (OK), -1 - (NULL pointer in)
+int WebRtcVad_Free(VadInst* handle);
+
+// Initializes a VAD instance.
+//
+// - handle [i/o] : Instance that should be initialized.
+//
+// returns : 0 - (OK),
+// -1 - (NULL pointer or Default mode could not be set).
+int WebRtcVad_Init(VadInst* handle);
+
+// Sets the VAD operating mode. A more aggressive (higher mode) VAD is more
+// restrictive in reporting speech. Put in other words the probability of being
+// speech when the VAD returns 1 is increased with increasing mode. As a
+// consequence also the missed detection rate goes up.
+//
+// - handle [i/o] : VAD instance.
+// - mode [i] : Aggressiveness mode (0, 1, 2, or 3).
+//
+// returns : 0 - (OK),
+// -1 - (NULL pointer, mode could not be set or the VAD instance
+// has not been initialized).
+int WebRtcVad_set_mode(VadInst* handle, int mode);
+
+// Calculates a VAD decision for the |audio_frame|. For valid sampling rates
+// frame lengths, see the description of WebRtcVad_ValidRatesAndFrameLengths().
+//
+// - handle [i/o] : VAD Instance. Needs to be initialized by
+// WebRtcVad_Init() before call.
+// - fs [i] : Sampling frequency (Hz): 8000, 16000, or 32000
+// - audio_frame [i] : Audio frame buffer.
+// - frame_length [i] : Length of audio frame buffer in number of samples.
+//
+// returns : 1 - (Active Voice),
+// 0 - (Non-active Voice),
+// -1 - (Error)
+int WebRtcVad_Process(VadInst* handle, int fs, int16_t* audio_frame,
+ int frame_length);
+
+// Checks for valid combinations of |rate| and |frame_length|. We support 10,
+// 20 and 30 ms frames and the rates 8000, 16000 and 32000 Hz.
+//
+// - rate [i] : Sampling frequency (Hz).
+// - frame_length [i] : Speech frame buffer length in number of samples.
+//
+// returns : 0 - (valid combination), -1 - (invalid combination)
+int WebRtcVad_ValidRateAndFrameLength(int rate, int frame_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WEBRTC_COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_ // NOLINT
diff --git a/common_audio/vad/vad.gypi b/common_audio/vad/vad.gypi
new file mode 100644
index 0000000..5a9466c
--- /dev/null
+++ b/common_audio/vad/vad.gypi
@@ -0,0 +1,68 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'vad',
+ 'type': '<(library)',
+ 'dependencies': [
+ 'signal_processing',
+ ],
+ 'include_dirs': [
+ 'include',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ 'include',
+ ],
+ },
+ 'sources': [
+ 'include/webrtc_vad.h',
+ 'webrtc_vad.c',
+ 'vad_core.c',
+ 'vad_core.h',
+ 'vad_filterbank.c',
+ 'vad_filterbank.h',
+ 'vad_gmm.c',
+ 'vad_gmm.h',
+ 'vad_sp.c',
+ 'vad_sp.h',
+ ],
+ },
+ ], # targets
+ 'conditions': [
+ ['include_tests==1', {
+ 'targets' : [
+ {
+ 'target_name': 'vad_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'vad',
+ '<(webrtc_root)/test/test.gyp:test_support_main',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'vad_core_unittest.cc',
+ 'vad_filterbank_unittest.cc',
+ 'vad_gmm_unittest.cc',
+ 'vad_sp_unittest.cc',
+ 'vad_unittest.cc',
+ 'vad_unittest.h',
+ ],
+ }, # vad_unittests
+ ], # targets
+ }], # include_tests
+ ], # conditions
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/common_audio/vad/vad_core.c b/common_audio/vad/vad_core.c
new file mode 100644
index 0000000..6a36349
--- /dev/null
+++ b/common_audio/vad/vad_core.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "vad_core.h"
+
+#include "signal_processing_library.h"
+#include "typedefs.h"
+#include "vad_filterbank.h"
+#include "vad_gmm.h"
+#include "vad_sp.h"
+
+// Spectrum Weighting
+static const int16_t kSpectrumWeight[kNumChannels] = { 6, 8, 10, 12, 14, 16 };
+static const int16_t kNoiseUpdateConst = 655; // Q15
+static const int16_t kSpeechUpdateConst = 6554; // Q15
+static const int16_t kBackEta = 154; // Q8
+// Minimum difference between the two models, Q5
+static const int16_t kMinimumDifference[kNumChannels] = {
+ 544, 544, 576, 576, 576, 576 };
+// Upper limit of mean value for speech model, Q7
+static const int16_t kMaximumSpeech[kNumChannels] = {
+ 11392, 11392, 11520, 11520, 11520, 11520 };
+// Minimum value for mean value
+static const int16_t kMinimumMean[kNumGaussians] = { 640, 768 };
+// Upper limit of mean value for noise model, Q7
+static const int16_t kMaximumNoise[kNumChannels] = {
+ 9216, 9088, 8960, 8832, 8704, 8576 };
+// Start values for the Gaussian models, Q7
+// Weights for the two Gaussians for the six channels (noise)
+static const int16_t kNoiseDataWeights[kTableSize] = {
+ 34, 62, 72, 66, 53, 25, 94, 66, 56, 62, 75, 103 };
+// Weights for the two Gaussians for the six channels (speech)
+static const int16_t kSpeechDataWeights[kTableSize] = {
+ 48, 82, 45, 87, 50, 47, 80, 46, 83, 41, 78, 81 };
+// Means for the two Gaussians for the six channels (noise)
+static const int16_t kNoiseDataMeans[kTableSize] = {
+ 6738, 4892, 7065, 6715, 6771, 3369, 7646, 3863, 7820, 7266, 5020, 4362 };
+// Means for the two Gaussians for the six channels (speech)
+static const int16_t kSpeechDataMeans[kTableSize] = {
+ 8306, 10085, 10078, 11823, 11843, 6309, 9473, 9571, 10879, 7581, 8180, 7483
+};
+// Stds for the two Gaussians for the six channels (noise)
+static const int16_t kNoiseDataStds[kTableSize] = {
+ 378, 1064, 493, 582, 688, 593, 474, 697, 475, 688, 421, 455 };
+// Stds for the two Gaussians for the six channels (speech)
+static const int16_t kSpeechDataStds[kTableSize] = {
+ 555, 505, 567, 524, 585, 1231, 509, 828, 492, 1540, 1079, 850 };
+
+// Constants used in GmmProbability().
+//
+// Maximum number of counted speech (VAD = 1) frames in a row.
+static const int16_t kMaxSpeechFrames = 6;
+// Minimum standard deviation for both speech and noise.
+static const int16_t kMinStd = 384;
+
+// Constants in WebRtcVad_InitCore().
+// Default aggressiveness mode.
+static const short kDefaultMode = 0;
+static const int kInitCheck = 42;
+
+// Constants used in WebRtcVad_set_mode_core().
+//
+// Thresholds for different frame lengths (10 ms, 20 ms and 30 ms).
+//
+// Mode 0, Quality.
+static const int16_t kOverHangMax1Q[3] = { 8, 4, 3 };
+static const int16_t kOverHangMax2Q[3] = { 14, 7, 5 };
+static const int16_t kLocalThresholdQ[3] = { 24, 21, 24 };
+static const int16_t kGlobalThresholdQ[3] = { 57, 48, 57 };
+// Mode 1, Low bitrate.
+static const int16_t kOverHangMax1LBR[3] = { 8, 4, 3 };
+static const int16_t kOverHangMax2LBR[3] = { 14, 7, 5 };
+static const int16_t kLocalThresholdLBR[3] = { 37, 32, 37 };
+static const int16_t kGlobalThresholdLBR[3] = { 100, 80, 100 };
+// Mode 2, Aggressive.
+static const int16_t kOverHangMax1AGG[3] = { 6, 3, 2 };
+static const int16_t kOverHangMax2AGG[3] = { 9, 5, 3 };
+static const int16_t kLocalThresholdAGG[3] = { 82, 78, 82 };
+static const int16_t kGlobalThresholdAGG[3] = { 285, 260, 285 };
+// Mode 3, Very aggressive.
+static const int16_t kOverHangMax1VAG[3] = { 6, 3, 2 };
+static const int16_t kOverHangMax2VAG[3] = { 9, 5, 3 };
+static const int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };
+static const int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 };
+
+// Calculates the weighted average w.r.t. number of Gaussians. The |data| are
+// updated with an |offset| before averaging.
+//
+// - data [i/o] : Data to average.
+// - offset [i] : An offset added to |data|.
+// - weights [i] : Weights used for averaging.
+//
+// returns : The weighted average.
+static int32_t WeightedAverage(int16_t* data, int16_t offset,
+ const int16_t* weights) {
+ int k;
+ int32_t weighted_average = 0;
+
+ for (k = 0; k < kNumGaussians; k++) {
+ data[k * kNumChannels] += offset;
+ weighted_average += data[k * kNumChannels] * weights[k * kNumChannels];
+ }
+ return weighted_average;
+}
+
+// Calculates the probabilities for both speech and background noise using
+// Gaussian Mixture Models (GMM). A hypothesis-test is performed to decide which
+// type of signal is most probable.
+//
+// - self [i/o] : Pointer to VAD instance
+// - features [i] : Feature vector of length |kNumChannels|
+// = log10(energy in frequency band)
+// - total_power [i] : Total power in audio frame.
+// - frame_length [i] : Number of input samples
+//
+// - returns : the VAD decision (0 - noise, 1 - speech).
+static int16_t GmmProbability(VadInstT* self, int16_t* features,
+ int16_t total_power, int frame_length) {
+ int channel, k;
+ int16_t feature_minimum;
+ int16_t h0, h1;
+ int16_t log_likelihood_ratio;
+ int16_t vadflag = 0;
+ int16_t shifts_h0, shifts_h1;
+ int16_t tmp_s16, tmp1_s16, tmp2_s16;
+ int16_t diff;
+ int gaussian;
+ int16_t nmk, nmk2, nmk3, smk, smk2, nsk, ssk;
+ int16_t delt, ndelt;
+ int16_t maxspe, maxmu;
+ int16_t deltaN[kTableSize], deltaS[kTableSize];
+ int16_t ngprvec[kTableSize] = { 0 }; // Conditional probability = 0.
+ int16_t sgprvec[kTableSize] = { 0 }; // Conditional probability = 0.
+ int32_t h0_test, h1_test;
+ int32_t tmp1_s32, tmp2_s32;
+ int32_t sum_log_likelihood_ratios = 0;
+ int32_t noise_global_mean, speech_global_mean;
+ int32_t noise_probability[kNumGaussians], speech_probability[kNumGaussians];
+ int16_t overhead1, overhead2, individualTest, totalTest;
+
+ // Set various thresholds based on frame lengths (80, 160 or 240 samples).
+ if (frame_length == 80) {
+ overhead1 = self->over_hang_max_1[0];
+ overhead2 = self->over_hang_max_2[0];
+ individualTest = self->individual[0];
+ totalTest = self->total[0];
+ } else if (frame_length == 160) {
+ overhead1 = self->over_hang_max_1[1];
+ overhead2 = self->over_hang_max_2[1];
+ individualTest = self->individual[1];
+ totalTest = self->total[1];
+ } else {
+ overhead1 = self->over_hang_max_1[2];
+ overhead2 = self->over_hang_max_2[2];
+ individualTest = self->individual[2];
+ totalTest = self->total[2];
+ }
+
+ if (total_power > kMinEnergy) {
+ // The signal power of current frame is large enough for processing. The
+ // processing consists of two parts:
+ // 1) Calculating the likelihood of speech and thereby a VAD decision.
+ // 2) Updating the underlying model, w.r.t., the decision made.
+
+ // The detection scheme is an LRT with hypothesis
+ // H0: Noise
+ // H1: Speech
+ //
+ // We combine a global LRT with local tests, for each frequency sub-band,
+ // here defined as |channel|.
+ for (channel = 0; channel < kNumChannels; channel++) {
+ // For each channel we model the probability with a GMM consisting of
+ // |kNumGaussians|, with different means and standard deviations depending
+ // on H0 or H1.
+ h0_test = 0;
+ h1_test = 0;
+ for (k = 0; k < kNumGaussians; k++) {
+ gaussian = channel + k * kNumChannels;
+ // Probability under H0, that is, probability of frame being noise.
+ // Value given in Q27 = Q7 * Q20.
+ tmp1_s32 = WebRtcVad_GaussianProbability(features[channel],
+ self->noise_means[gaussian],
+ self->noise_stds[gaussian],
+ &deltaN[gaussian]);
+ noise_probability[k] = kNoiseDataWeights[gaussian] * tmp1_s32;
+ h0_test += noise_probability[k]; // Q27
+
+ // Probability under H1, that is, probability of frame being speech.
+ // Value given in Q27 = Q7 * Q20.
+ tmp1_s32 = WebRtcVad_GaussianProbability(features[channel],
+ self->speech_means[gaussian],
+ self->speech_stds[gaussian],
+ &deltaS[gaussian]);
+ speech_probability[k] = kSpeechDataWeights[gaussian] * tmp1_s32;
+ h1_test += speech_probability[k]; // Q27
+ }
+
+ // Calculate the log likelihood ratio: log2(Pr{X|H1} / Pr{X|H1}).
+ // Approximation:
+ // log2(Pr{X|H1} / Pr{X|H1}) = log2(Pr{X|H1}*2^Q) - log2(Pr{X|H1}*2^Q)
+ // = log2(h1_test) - log2(h0_test)
+ // = log2(2^(31-shifts_h1)*(1+b1))
+ // - log2(2^(31-shifts_h0)*(1+b0))
+ // = shifts_h0 - shifts_h1
+ // + log2(1+b1) - log2(1+b0)
+ // ~= shifts_h0 - shifts_h1
+ //
+ // Note that b0 and b1 are values less than 1, hence, 0 <= log2(1+b0) < 1.
+ // Further, b0 and b1 are independent and on the average the two terms
+ // cancel.
+ shifts_h0 = WebRtcSpl_NormW32(h0_test);
+ shifts_h1 = WebRtcSpl_NormW32(h1_test);
+ if (h0_test == 0) {
+ shifts_h0 = 31;
+ }
+ if (h1_test == 0) {
+ shifts_h1 = 31;
+ }
+ log_likelihood_ratio = shifts_h0 - shifts_h1;
+
+ // Update |sum_log_likelihood_ratios| with spectrum weighting. This is
+ // used for the global VAD decision.
+ sum_log_likelihood_ratios +=
+ (int32_t) (log_likelihood_ratio * kSpectrumWeight[channel]);
+
+ // Local VAD decision.
+ if ((log_likelihood_ratio << 2) > individualTest) {
+ vadflag = 1;
+ }
+
+ // TODO(bjornv): The conditional probabilities below are applied on the
+ // hard coded number of Gaussians set to two. Find a way to generalize.
+ // Calculate local noise probabilities used later when updating the GMM.
+ h0 = (int16_t) (h0_test >> 12); // Q15
+ if (h0 > 0) {
+ // High probability of noise. Assign conditional probabilities for each
+ // Gaussian in the GMM.
+ tmp1_s32 = (noise_probability[0] & 0xFFFFF000) << 2; // Q29
+ ngprvec[channel] = (int16_t) WebRtcSpl_DivW32W16(tmp1_s32, h0); // Q14
+ ngprvec[channel + kNumChannels] = 16384 - ngprvec[channel];
+ } else {
+ // Low noise probability. Assign conditional probability 1 to the first
+ // Gaussian and 0 to the rest (which is already set at initialization).
+ ngprvec[channel] = 16384;
+ }
+
+ // Calculate local speech probabilities used later when updating the GMM.
+ h1 = (int16_t) (h1_test >> 12); // Q15
+ if (h1 > 0) {
+ // High probability of speech. Assign conditional probabilities for each
+ // Gaussian in the GMM. Otherwise use the initialized values, i.e., 0.
+ tmp1_s32 = (speech_probability[0] & 0xFFFFF000) << 2; // Q29
+ sgprvec[channel] = (int16_t) WebRtcSpl_DivW32W16(tmp1_s32, h1); // Q14
+ sgprvec[channel + kNumChannels] = 16384 - sgprvec[channel];
+ }
+ }
+
+ // Make a global VAD decision.
+ vadflag |= (sum_log_likelihood_ratios >= totalTest);
+
+ // Update the model parameters.
+ maxspe = 12800;
+ for (channel = 0; channel < kNumChannels; channel++) {
+
+ // Get minimum value in past which is used for long term correction in Q4.
+ feature_minimum = WebRtcVad_FindMinimum(self, features[channel], channel);
+
+ // Compute the "global" mean, that is the sum of the two means weighted.
+ noise_global_mean = WeightedAverage(&self->noise_means[channel], 0,
+ &kNoiseDataWeights[channel]);
+ tmp1_s16 = (int16_t) (noise_global_mean >> 6); // Q8
+
+ for (k = 0; k < kNumGaussians; k++) {
+ gaussian = channel + k * kNumChannels;
+
+ nmk = self->noise_means[gaussian];
+ smk = self->speech_means[gaussian];
+ nsk = self->noise_stds[gaussian];
+ ssk = self->speech_stds[gaussian];
+
+ // Update noise mean vector if the frame consists of noise only.
+ nmk2 = nmk;
+ if (!vadflag) {
+ // deltaN = (x-mu)/sigma^2
+ // ngprvec[k] = |noise_probability[k]| /
+ // (|noise_probability[0]| + |noise_probability[1]|)
+
+ // (Q14 * Q11 >> 11) = Q14.
+ delt = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(ngprvec[gaussian],
+ deltaN[gaussian],
+ 11);
+ // Q7 + (Q14 * Q15 >> 22) = Q7.
+ nmk2 = nmk + (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(delt,
+ kNoiseUpdateConst,
+ 22);
+ }
+
+ // Long term correction of the noise mean.
+ // Q8 - Q8 = Q8.
+ ndelt = (feature_minimum << 4) - tmp1_s16;
+ // Q7 + (Q8 * Q8) >> 9 = Q7.
+ nmk3 = nmk2 + (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(ndelt, kBackEta, 9);
+
+ // Control that the noise mean does not drift to much.
+ tmp_s16 = (int16_t) ((k + 5) << 7);
+ if (nmk3 < tmp_s16) {
+ nmk3 = tmp_s16;
+ }
+ tmp_s16 = (int16_t) ((72 + k - channel) << 7);
+ if (nmk3 > tmp_s16) {
+ nmk3 = tmp_s16;
+ }
+ self->noise_means[gaussian] = nmk3;
+
+ if (vadflag) {
+ // Update speech mean vector:
+ // |deltaS| = (x-mu)/sigma^2
+ // sgprvec[k] = |speech_probability[k]| /
+ // (|speech_probability[0]| + |speech_probability[1]|)
+
+ // (Q14 * Q11) >> 11 = Q14.
+ delt = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(sgprvec[gaussian],
+ deltaS[gaussian],
+ 11);
+ // Q14 * Q15 >> 21 = Q8.
+ tmp_s16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(delt,
+ kSpeechUpdateConst,
+ 21);
+ // Q7 + (Q8 >> 1) = Q7. With rounding.
+ smk2 = smk + ((tmp_s16 + 1) >> 1);
+
+ // Control that the speech mean does not drift to much.
+ maxmu = maxspe + 640;
+ if (smk2 < kMinimumMean[k]) {
+ smk2 = kMinimumMean[k];
+ }
+ if (smk2 > maxmu) {
+ smk2 = maxmu;
+ }
+ self->speech_means[gaussian] = smk2; // Q7.
+
+ // (Q7 >> 3) = Q4. With rounding.
+ tmp_s16 = ((smk + 4) >> 3);
+
+ tmp_s16 = features[channel] - tmp_s16; // Q4
+ // (Q11 * Q4 >> 3) = Q12.
+ tmp1_s32 = WEBRTC_SPL_MUL_16_16_RSFT(deltaS[gaussian], tmp_s16, 3);
+ tmp2_s32 = tmp1_s32 - 4096;
+ tmp_s16 = sgprvec[gaussian] >> 2;
+ // (Q14 >> 2) * Q12 = Q24.
+ tmp1_s32 = tmp_s16 * tmp2_s32;
+
+ tmp2_s32 = tmp1_s32 >> 4; // Q20
+
+ // 0.1 * Q20 / Q7 = Q13.
+ if (tmp2_s32 > 0) {
+ tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(tmp2_s32, ssk * 10);
+ } else {
+ tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(-tmp2_s32, ssk * 10);
+ tmp_s16 = -tmp_s16;
+ }
+ // Divide by 4 giving an update factor of 0.025 (= 0.1 / 4).
+ // Note that division by 4 equals shift by 2, hence,
+ // (Q13 >> 8) = (Q13 >> 6) / 4 = Q7.
+ tmp_s16 += 128; // Rounding.
+ ssk += (tmp_s16 >> 8);
+ if (ssk < kMinStd) {
+ ssk = kMinStd;
+ }
+ self->speech_stds[gaussian] = ssk;
+ } else {
+ // Update GMM variance vectors.
+ // deltaN * (features[channel] - nmk) - 1
+ // Q4 - (Q7 >> 3) = Q4.
+ tmp_s16 = features[channel] - (nmk >> 3);
+ // (Q11 * Q4 >> 3) = Q12.
+ tmp1_s32 = WEBRTC_SPL_MUL_16_16_RSFT(deltaN[gaussian], tmp_s16, 3);
+ tmp1_s32 -= 4096;
+
+ // (Q14 >> 2) * Q12 = Q24.
+ tmp_s16 = (ngprvec[gaussian] + 2) >> 2;
+ tmp2_s32 = tmp_s16 * tmp1_s32;
+ // Q20 * approx 0.001 (2^-10=0.0009766), hence,
+ // (Q24 >> 14) = (Q24 >> 4) / 2^10 = Q20.
+ tmp1_s32 = tmp2_s32 >> 14;
+
+ // Q20 / Q7 = Q13.
+ if (tmp1_s32 > 0) {
+ tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(tmp1_s32, nsk);
+ } else {
+ tmp_s16 = (int16_t) WebRtcSpl_DivW32W16(-tmp1_s32, nsk);
+ tmp_s16 = -tmp_s16;
+ }
+ tmp_s16 += 32; // Rounding
+ nsk += tmp_s16 >> 6; // Q13 >> 6 = Q7.
+ if (nsk < kMinStd) {
+ nsk = kMinStd;
+ }
+ self->noise_stds[gaussian] = nsk;
+ }
+ }
+
+ // Separate models if they are too close.
+ // |noise_global_mean| in Q14 (= Q7 * Q7).
+ noise_global_mean = WeightedAverage(&self->noise_means[channel], 0,
+ &kNoiseDataWeights[channel]);
+
+ // |speech_global_mean| in Q14 (= Q7 * Q7).
+ speech_global_mean = WeightedAverage(&self->speech_means[channel], 0,
+ &kSpeechDataWeights[channel]);
+
+ // |diff| = "global" speech mean - "global" noise mean.
+ // (Q14 >> 9) - (Q14 >> 9) = Q5.
+ diff = (int16_t) (speech_global_mean >> 9) -
+ (int16_t) (noise_global_mean >> 9);
+ if (diff < kMinimumDifference[channel]) {
+ tmp_s16 = kMinimumDifference[channel] - diff;
+
+ // |tmp1_s16| = ~0.8 * (kMinimumDifference - diff) in Q7.
+ // |tmp2_s16| = ~0.2 * (kMinimumDifference - diff) in Q7.
+ tmp1_s16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(13, tmp_s16, 2);
+ tmp2_s16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(3, tmp_s16, 2);
+
+ // Move Gaussian means for speech model by |tmp1_s16| and update
+ // |speech_global_mean|. Note that |self->speech_means[channel]| is
+ // changed after the call.
+ speech_global_mean = WeightedAverage(&self->speech_means[channel],
+ tmp1_s16,
+ &kSpeechDataWeights[channel]);
+
+ // Move Gaussian means for noise model by -|tmp2_s16| and update
+ // |noise_global_mean|. Note that |self->noise_means[channel]| is
+ // changed after the call.
+ noise_global_mean = WeightedAverage(&self->noise_means[channel],
+ -tmp2_s16,
+ &kNoiseDataWeights[channel]);
+ }
+
+ // Control that the speech & noise means do not drift to much.
+ maxspe = kMaximumSpeech[channel];
+ tmp2_s16 = (int16_t) (speech_global_mean >> 7);
+ if (tmp2_s16 > maxspe) {
+ // Upper limit of speech model.
+ tmp2_s16 -= maxspe;
+
+ for (k = 0; k < kNumGaussians; k++) {
+ self->speech_means[channel + k * kNumChannels] -= tmp2_s16;
+ }
+ }
+
+ tmp2_s16 = (int16_t) (noise_global_mean >> 7);
+ if (tmp2_s16 > kMaximumNoise[channel]) {
+ tmp2_s16 -= kMaximumNoise[channel];
+
+ for (k = 0; k < kNumGaussians; k++) {
+ self->noise_means[channel + k * kNumChannels] -= tmp2_s16;
+ }
+ }
+ }
+ self->frame_counter++;
+ }
+
+ // Smooth with respect to transition hysteresis.
+ if (!vadflag) {
+ if (self->over_hang > 0) {
+ vadflag = 2 + self->over_hang;
+ self->over_hang--;
+ }
+ self->num_of_speech = 0;
+ } else {
+ self->num_of_speech++;
+ if (self->num_of_speech > kMaxSpeechFrames) {
+ self->num_of_speech = kMaxSpeechFrames;
+ self->over_hang = overhead2;
+ } else {
+ self->over_hang = overhead1;
+ }
+ }
+ return vadflag;
+}
+
+// Initialize the VAD. Set aggressiveness mode to default value.
+int WebRtcVad_InitCore(VadInstT* self) {
+ int i;
+
+ if (self == NULL) {
+ return -1;
+ }
+
+ // Initialization of general struct variables.
+ self->vad = 1; // Speech active (=1).
+ self->frame_counter = 0;
+ self->over_hang = 0;
+ self->num_of_speech = 0;
+
+ // Initialization of downsampling filter state.
+ memset(self->downsampling_filter_states, 0,
+ sizeof(self->downsampling_filter_states));
+
+ // Initialization of 48 to 8 kHz downsampling.
+ WebRtcSpl_ResetResample48khzTo8khz(&self->state_48_to_8);
+
+ // Read initial PDF parameters.
+ for (i = 0; i < kTableSize; i++) {
+ self->noise_means[i] = kNoiseDataMeans[i];
+ self->speech_means[i] = kSpeechDataMeans[i];
+ self->noise_stds[i] = kNoiseDataStds[i];
+ self->speech_stds[i] = kSpeechDataStds[i];
+ }
+
+ // Initialize Index and Minimum value vectors.
+ for (i = 0; i < 16 * kNumChannels; i++) {
+ self->low_value_vector[i] = 10000;
+ self->index_vector[i] = 0;
+ }
+
+ // Initialize splitting filter states.
+ memset(self->upper_state, 0, sizeof(self->upper_state));
+ memset(self->lower_state, 0, sizeof(self->lower_state));
+
+ // Initialize high pass filter states.
+ memset(self->hp_filter_state, 0, sizeof(self->hp_filter_state));
+
+ // Initialize mean value memory, for WebRtcVad_FindMinimum().
+ for (i = 0; i < kNumChannels; i++) {
+ self->mean_value[i] = 1600;
+ }
+
+ // Set aggressiveness mode to default (=|kDefaultMode|).
+ if (WebRtcVad_set_mode_core(self, kDefaultMode) != 0) {
+ return -1;
+ }
+
+ self->init_flag = kInitCheck;
+
+ return 0;
+}
+
+// Set aggressiveness mode
+int WebRtcVad_set_mode_core(VadInstT* self, int mode) {
+ int return_value = 0;
+
+ switch (mode) {
+ case 0:
+ // Quality mode.
+ memcpy(self->over_hang_max_1, kOverHangMax1Q,
+ sizeof(self->over_hang_max_1));
+ memcpy(self->over_hang_max_2, kOverHangMax2Q,
+ sizeof(self->over_hang_max_2));
+ memcpy(self->individual, kLocalThresholdQ,
+ sizeof(self->individual));
+ memcpy(self->total, kGlobalThresholdQ,
+ sizeof(self->total));
+ break;
+ case 1:
+ // Low bitrate mode.
+ memcpy(self->over_hang_max_1, kOverHangMax1LBR,
+ sizeof(self->over_hang_max_1));
+ memcpy(self->over_hang_max_2, kOverHangMax2LBR,
+ sizeof(self->over_hang_max_2));
+ memcpy(self->individual, kLocalThresholdLBR,
+ sizeof(self->individual));
+ memcpy(self->total, kGlobalThresholdLBR,
+ sizeof(self->total));
+ break;
+ case 2:
+ // Aggressive mode.
+ memcpy(self->over_hang_max_1, kOverHangMax1AGG,
+ sizeof(self->over_hang_max_1));
+ memcpy(self->over_hang_max_2, kOverHangMax2AGG,
+ sizeof(self->over_hang_max_2));
+ memcpy(self->individual, kLocalThresholdAGG,
+ sizeof(self->individual));
+ memcpy(self->total, kGlobalThresholdAGG,
+ sizeof(self->total));
+ break;
+ case 3:
+ // Very aggressive mode.
+ memcpy(self->over_hang_max_1, kOverHangMax1VAG,
+ sizeof(self->over_hang_max_1));
+ memcpy(self->over_hang_max_2, kOverHangMax2VAG,
+ sizeof(self->over_hang_max_2));
+ memcpy(self->individual, kLocalThresholdVAG,
+ sizeof(self->individual));
+ memcpy(self->total, kGlobalThresholdVAG,
+ sizeof(self->total));
+ break;
+ default:
+ return_value = -1;
+ break;
+ }
+
+ return return_value;
+}
+
+// Calculate VAD decision by first extracting feature values and then calculate
+// probability for both speech and background noise.
+
+int WebRtcVad_CalcVad48khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length) {
+ int vad;
+ int i;
+ int16_t speech_nb[240]; // 30 ms in 8 kHz.
+ // |tmp_mem| is a temporary memory used by resample function, length is
+ // frame length in 10 ms (480 samples) + 256 extra.
+ int32_t tmp_mem[480 + 256] = { 0 };
+ const int kFrameLen10ms48khz = 480;
+ const int kFrameLen10ms8khz = 80;
+ int num_10ms_frames = frame_length / kFrameLen10ms48khz;
+
+ for (i = 0; i < num_10ms_frames; i++) {
+ WebRtcSpl_Resample48khzTo8khz(speech_frame,
+ &speech_nb[i * kFrameLen10ms8khz],
+ &inst->state_48_to_8,
+ tmp_mem);
+ }
+
+ // Do VAD on an 8 kHz signal
+ vad = WebRtcVad_CalcVad8khz(inst, speech_nb, frame_length / 6);
+
+ return vad;
+}
+
+int WebRtcVad_CalcVad32khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length)
+{
+ int len, vad;
+ int16_t speechWB[480]; // Downsampled speech frame: 960 samples (30ms in SWB)
+ int16_t speechNB[240]; // Downsampled speech frame: 480 samples (30ms in WB)
+
+
+ // Downsample signal 32->16->8 before doing VAD
+ WebRtcVad_Downsampling(speech_frame, speechWB, &(inst->downsampling_filter_states[2]),
+ frame_length);
+ len = WEBRTC_SPL_RSHIFT_W16(frame_length, 1);
+
+ WebRtcVad_Downsampling(speechWB, speechNB, inst->downsampling_filter_states, len);
+ len = WEBRTC_SPL_RSHIFT_W16(len, 1);
+
+ // Do VAD on an 8 kHz signal
+ vad = WebRtcVad_CalcVad8khz(inst, speechNB, len);
+
+ return vad;
+}
+
+int WebRtcVad_CalcVad16khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length)
+{
+ int len, vad;
+ int16_t speechNB[240]; // Downsampled speech frame: 480 samples (30ms in WB)
+
+ // Wideband: Downsample signal before doing VAD
+ WebRtcVad_Downsampling(speech_frame, speechNB, inst->downsampling_filter_states,
+ frame_length);
+
+ len = WEBRTC_SPL_RSHIFT_W16(frame_length, 1);
+ vad = WebRtcVad_CalcVad8khz(inst, speechNB, len);
+
+ return vad;
+}
+
+int WebRtcVad_CalcVad8khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length)
+{
+ int16_t feature_vector[kNumChannels], total_power;
+
+ // Get power in the bands
+ total_power = WebRtcVad_CalculateFeatures(inst, speech_frame, frame_length,
+ feature_vector);
+
+ // Make a VAD
+ inst->vad = GmmProbability(inst, feature_vector, total_power, frame_length);
+
+ return inst->vad;
+}
diff --git a/common_audio/vad/vad_core.h b/common_audio/vad/vad_core.h
new file mode 100644
index 0000000..b89d5df
--- /dev/null
+++ b/common_audio/vad/vad_core.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012 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 header file includes the descriptions of the core VAD calls.
+ */
+
+#ifndef WEBRTC_COMMON_AUDIO_VAD_VAD_CORE_H_
+#define WEBRTC_COMMON_AUDIO_VAD_VAD_CORE_H_
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "typedefs.h"
+
+enum { kNumChannels = 6 }; // Number of frequency bands (named channels).
+enum { kNumGaussians = 2 }; // Number of Gaussians per channel in the GMM.
+enum { kTableSize = kNumChannels * kNumGaussians };
+enum { kMinEnergy = 10 }; // Minimum energy required to trigger audio signal.
+
+typedef struct VadInstT_
+{
+
+ int vad;
+ int32_t downsampling_filter_states[4];
+ WebRtcSpl_State48khzTo8khz state_48_to_8;
+ int16_t noise_means[kTableSize];
+ int16_t speech_means[kTableSize];
+ int16_t noise_stds[kTableSize];
+ int16_t speech_stds[kTableSize];
+ // TODO(bjornv): Change to |frame_count|.
+ int32_t frame_counter;
+ int16_t over_hang; // Over Hang
+ int16_t num_of_speech;
+ // TODO(bjornv): Change to |age_vector|.
+ int16_t index_vector[16 * kNumChannels];
+ int16_t low_value_vector[16 * kNumChannels];
+ // TODO(bjornv): Change to |median|.
+ int16_t mean_value[kNumChannels];
+ int16_t upper_state[5];
+ int16_t lower_state[5];
+ int16_t hp_filter_state[4];
+ int16_t over_hang_max_1[3];
+ int16_t over_hang_max_2[3];
+ int16_t individual[3];
+ int16_t total[3];
+
+ int init_flag;
+
+} VadInstT;
+
+// Initializes the core VAD component. The default aggressiveness mode is
+// controlled by |kDefaultMode| in vad_core.c.
+//
+// - self [i/o] : Instance that should be initialized
+//
+// returns : 0 (OK), -1 (NULL pointer in or if the default mode can't be
+// set)
+int WebRtcVad_InitCore(VadInstT* self);
+
+/****************************************************************************
+ * WebRtcVad_set_mode_core(...)
+ *
+ * This function changes the VAD settings
+ *
+ * Input:
+ * - inst : VAD instance
+ * - mode : Aggressiveness degree
+ * 0 (High quality) - 3 (Highly aggressive)
+ *
+ * Output:
+ * - inst : Changed instance
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+int WebRtcVad_set_mode_core(VadInstT* self, int mode);
+
+/****************************************************************************
+ * WebRtcVad_CalcVad48khz(...)
+ * WebRtcVad_CalcVad32khz(...)
+ * WebRtcVad_CalcVad16khz(...)
+ * WebRtcVad_CalcVad8khz(...)
+ *
+ * Calculate probability for active speech and make VAD decision.
+ *
+ * Input:
+ * - inst : Instance that should be initialized
+ * - speech_frame : Input speech frame
+ * - frame_length : Number of input samples
+ *
+ * Output:
+ * - inst : Updated filter states etc.
+ *
+ * Return value : VAD decision
+ * 0 - No active speech
+ * 1-6 - Active speech
+ */
+int WebRtcVad_CalcVad48khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length);
+int WebRtcVad_CalcVad32khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length);
+int WebRtcVad_CalcVad16khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length);
+int WebRtcVad_CalcVad8khz(VadInstT* inst, int16_t* speech_frame,
+ int frame_length);
+
+#endif // WEBRTC_COMMON_AUDIO_VAD_VAD_CORE_H_
diff --git a/common_audio/vad/vad_core_unittest.cc b/common_audio/vad/vad_core_unittest.cc
new file mode 100644
index 0000000..0c5648f
--- /dev/null
+++ b/common_audio/vad/vad_core_unittest.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+#include "typedefs.h"
+#include "vad_unittest.h"
+
+extern "C" {
+#include "vad_core.h"
+}
+
+namespace {
+
+TEST_F(VadTest, InitCore) {
+ // Test WebRtcVad_InitCore().
+ VadInstT* self = reinterpret_cast<VadInstT*>(malloc(sizeof(VadInstT)));
+
+ // NULL pointer test.
+ EXPECT_EQ(-1, WebRtcVad_InitCore(NULL));
+
+ // Verify return = 0 for non-NULL pointer.
+ EXPECT_EQ(0, WebRtcVad_InitCore(self));
+ // Verify init_flag is set.
+ EXPECT_EQ(42, self->init_flag);
+
+ free(self);
+}
+
+TEST_F(VadTest, set_mode_core) {
+ VadInstT* self = reinterpret_cast<VadInstT*>(malloc(sizeof(VadInstT)));
+
+ // TODO(bjornv): Add NULL pointer check if we take care of it in
+ // vad_core.c
+
+ ASSERT_EQ(0, WebRtcVad_InitCore(self));
+ // Test WebRtcVad_set_mode_core().
+ // Invalid modes should return -1.
+ EXPECT_EQ(-1, WebRtcVad_set_mode_core(self, -1));
+ EXPECT_EQ(-1, WebRtcVad_set_mode_core(self, 1000));
+ // Valid modes should return 0.
+ for (size_t j = 0; j < kModesSize; ++j) {
+ EXPECT_EQ(0, WebRtcVad_set_mode_core(self, kModes[j]));
+ }
+
+ free(self);
+}
+
+TEST_F(VadTest, CalcVad) {
+ VadInstT* self = reinterpret_cast<VadInstT*>(malloc(sizeof(VadInstT)));
+ int16_t speech[kMaxFrameLength];
+
+ // TODO(bjornv): Add NULL pointer check if we take care of it in
+ // vad_core.c
+
+ // Test WebRtcVad_CalcVadXXkhz()
+ // Verify that all zeros in gives VAD = 0 out.
+ memset(speech, 0, sizeof(speech));
+ ASSERT_EQ(0, WebRtcVad_InitCore(self));
+ for (size_t j = 0; j < kFrameLengthsSize; ++j) {
+ if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) {
+ EXPECT_EQ(0, WebRtcVad_CalcVad8khz(self, speech, kFrameLengths[j]));
+ }
+ if (ValidRatesAndFrameLengths(16000, kFrameLengths[j])) {
+ EXPECT_EQ(0, WebRtcVad_CalcVad16khz(self, speech, kFrameLengths[j]));
+ }
+ if (ValidRatesAndFrameLengths(32000, kFrameLengths[j])) {
+ EXPECT_EQ(0, WebRtcVad_CalcVad32khz(self, speech, kFrameLengths[j]));
+ }
+ if (ValidRatesAndFrameLengths(48000, kFrameLengths[j])) {
+ EXPECT_EQ(0, WebRtcVad_CalcVad48khz(self, speech, kFrameLengths[j]));
+ }
+ }
+
+ // Construct a speech signal that will trigger the VAD in all modes. It is
+ // known that (i * i) will wrap around, but that doesn't matter in this case.
+ for (int16_t i = 0; i < kMaxFrameLength; ++i) {
+ speech[i] = (i * i);
+ }
+ for (size_t j = 0; j < kFrameLengthsSize; ++j) {
+ if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) {
+ EXPECT_EQ(1, WebRtcVad_CalcVad8khz(self, speech, kFrameLengths[j]));
+ }
+ if (ValidRatesAndFrameLengths(16000, kFrameLengths[j])) {
+ EXPECT_EQ(1, WebRtcVad_CalcVad16khz(self, speech, kFrameLengths[j]));
+ }
+ if (ValidRatesAndFrameLengths(32000, kFrameLengths[j])) {
+ EXPECT_EQ(1, WebRtcVad_CalcVad32khz(self, speech, kFrameLengths[j]));
+ }
+ if (ValidRatesAndFrameLengths(48000, kFrameLengths[j])) {
+ EXPECT_EQ(1, WebRtcVad_CalcVad48khz(self, speech, kFrameLengths[j]));
+ }
+ }
+
+ free(self);
+}
+} // namespace
diff --git a/common_audio/vad/vad_filterbank.c b/common_audio/vad/vad_filterbank.c
new file mode 100644
index 0000000..b626ad0
--- /dev/null
+++ b/common_audio/vad/vad_filterbank.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "vad_filterbank.h"
+
+#include <assert.h>
+
+#include "signal_processing_library.h"
+#include "typedefs.h"
+
+// Constants used in LogOfEnergy().
+static const int16_t kLogConst = 24660; // 160*log10(2) in Q9.
+static const int16_t kLogEnergyIntPart = 14336; // 14 in Q10
+
+// Coefficients used by HighPassFilter, Q14.
+static const int16_t kHpZeroCoefs[3] = { 6631, -13262, 6631 };
+static const int16_t kHpPoleCoefs[3] = { 16384, -7756, 5620 };
+
+// Allpass filter coefficients, upper and lower, in Q15.
+// Upper: 0.64, Lower: 0.17
+static const int16_t kAllPassCoefsQ15[2] = { 20972, 5571 };
+
+// Adjustment for division with two in SplitFilter.
+static const int16_t kOffsetVector[6] = { 368, 368, 272, 176, 176, 176 };
+
+// High pass filtering, with a cut-off frequency at 80 Hz, if the |data_in| is
+// sampled at 500 Hz.
+//
+// - data_in [i] : Input audio data sampled at 500 Hz.
+// - data_length [i] : Length of input and output data.
+// - filter_state [i/o] : State of the filter.
+// - data_out [o] : Output audio data in the frequency interval
+// 80 - 250 Hz.
+static void HighPassFilter(const int16_t* data_in, int data_length,
+ int16_t* filter_state, int16_t* data_out) {
+ int i;
+ const int16_t* in_ptr = data_in;
+ int16_t* out_ptr = data_out;
+ int32_t tmp32 = 0;
+
+
+ // The sum of the absolute values of the impulse response:
+ // The zero/pole-filter has a max amplification of a single sample of: 1.4546
+ // Impulse response: 0.4047 -0.6179 -0.0266 0.1993 0.1035 -0.0194
+ // The all-zero section has a max amplification of a single sample of: 1.6189
+ // Impulse response: 0.4047 -0.8094 0.4047 0 0 0
+ // The all-pole section has a max amplification of a single sample of: 1.9931
+ // Impulse response: 1.0000 0.4734 -0.1189 -0.2187 -0.0627 0.04532
+
+ for (i = 0; i < data_length; i++) {
+ // All-zero section (filter coefficients in Q14).
+ tmp32 = WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[0], *in_ptr);
+ tmp32 += WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[1], filter_state[0]);
+ tmp32 += WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[2], filter_state[1]);
+ filter_state[1] = filter_state[0];
+ filter_state[0] = *in_ptr++;
+
+ // All-pole section (filter coefficients in Q14).
+ tmp32 -= WEBRTC_SPL_MUL_16_16(kHpPoleCoefs[1], filter_state[2]);
+ tmp32 -= WEBRTC_SPL_MUL_16_16(kHpPoleCoefs[2], filter_state[3]);
+ filter_state[3] = filter_state[2];
+ filter_state[2] = (int16_t) (tmp32 >> 14);
+ *out_ptr++ = filter_state[2];
+ }
+}
+
+// All pass filtering of |data_in|, used before splitting the signal into two
+// frequency bands (low pass vs high pass).
+// Note that |data_in| and |data_out| can NOT correspond to the same address.
+//
+// - data_in [i] : Input audio signal given in Q0.
+// - data_length [i] : Length of input and output data.
+// - filter_coefficient [i] : Given in Q15.
+// - filter_state [i/o] : State of the filter given in Q(-1).
+// - data_out [o] : Output audio signal given in Q(-1).
+static void AllPassFilter(const int16_t* data_in, int data_length,
+ int16_t filter_coefficient, int16_t* filter_state,
+ int16_t* data_out) {
+ // The filter can only cause overflow (in the w16 output variable)
+ // if more than 4 consecutive input numbers are of maximum value and
+ // has the the same sign as the impulse responses first taps.
+ // First 6 taps of the impulse response:
+ // 0.6399 0.5905 -0.3779 0.2418 -0.1547 0.0990
+
+ int i;
+ int16_t tmp16 = 0;
+ int32_t tmp32 = 0;
+ int32_t state32 = ((int32_t) (*filter_state) << 16); // Q15
+
+ for (i = 0; i < data_length; i++) {
+ tmp32 = state32 + WEBRTC_SPL_MUL_16_16(filter_coefficient, *data_in);
+ tmp16 = (int16_t) (tmp32 >> 16); // Q(-1)
+ *data_out++ = tmp16;
+ state32 = (((int32_t) (*data_in)) << 14); // Q14
+ state32 -= WEBRTC_SPL_MUL_16_16(filter_coefficient, tmp16); // Q14
+ state32 <<= 1; // Q15.
+ data_in += 2;
+ }
+
+ *filter_state = (int16_t) (state32 >> 16); // Q(-1)
+}
+
+// Splits |data_in| into |hp_data_out| and |lp_data_out| corresponding to
+// an upper (high pass) part and a lower (low pass) part respectively.
+//
+// - data_in [i] : Input audio data to be split into two frequency bands.
+// - data_length [i] : Length of |data_in|.
+// - upper_state [i/o] : State of the upper filter, given in Q(-1).
+// - lower_state [i/o] : State of the lower filter, given in Q(-1).
+// - hp_data_out [o] : Output audio data of the upper half of the spectrum.
+// The length is |data_length| / 2.
+// - lp_data_out [o] : Output audio data of the lower half of the spectrum.
+// The length is |data_length| / 2.
+static void SplitFilter(const int16_t* data_in, int data_length,
+ int16_t* upper_state, int16_t* lower_state,
+ int16_t* hp_data_out, int16_t* lp_data_out) {
+ int i;
+ int half_length = data_length >> 1; // Downsampling by 2.
+ int16_t tmp_out;
+
+ // All-pass filtering upper branch.
+ AllPassFilter(&data_in[0], half_length, kAllPassCoefsQ15[0], upper_state,
+ hp_data_out);
+
+ // All-pass filtering lower branch.
+ AllPassFilter(&data_in[1], half_length, kAllPassCoefsQ15[1], lower_state,
+ lp_data_out);
+
+ // Make LP and HP signals.
+ for (i = 0; i < half_length; i++) {
+ tmp_out = *hp_data_out;
+ *hp_data_out++ -= *lp_data_out;
+ *lp_data_out++ += tmp_out;
+ }
+}
+
+// Calculates the energy of |data_in| in dB, and also updates an overall
+// |total_energy| if necessary.
+//
+// - data_in [i] : Input audio data for energy calculation.
+// - data_length [i] : Length of input data.
+// - offset [i] : Offset value added to |log_energy|.
+// - total_energy [i/o] : An external energy updated with the energy of
+// |data_in|.
+// NOTE: |total_energy| is only updated if
+// |total_energy| <= |kMinEnergy|.
+// - log_energy [o] : 10 * log10("energy of |data_in|") given in Q4.
+static void LogOfEnergy(const int16_t* data_in, int data_length,
+ int16_t offset, int16_t* total_energy,
+ int16_t* log_energy) {
+ // |tot_rshifts| accumulates the number of right shifts performed on |energy|.
+ int tot_rshifts = 0;
+ // The |energy| will be normalized to 15 bits. We use unsigned integer because
+ // we eventually will mask out the fractional part.
+ uint32_t energy = 0;
+
+ assert(data_in != NULL);
+ assert(data_length > 0);
+
+ energy = (uint32_t) WebRtcSpl_Energy((int16_t*) data_in, data_length,
+ &tot_rshifts);
+
+ if (energy != 0) {
+ // By construction, normalizing to 15 bits is equivalent with 17 leading
+ // zeros of an unsigned 32 bit value.
+ int normalizing_rshifts = 17 - WebRtcSpl_NormU32(energy);
+ // In a 15 bit representation the leading bit is 2^14. log2(2^14) in Q10 is
+ // (14 << 10), which is what we initialize |log2_energy| with. For a more
+ // detailed derivations, see below.
+ int16_t log2_energy = kLogEnergyIntPart;
+
+ tot_rshifts += normalizing_rshifts;
+ // Normalize |energy| to 15 bits.
+ // |tot_rshifts| is now the total number of right shifts performed on
+ // |energy| after normalization. This means that |energy| is in
+ // Q(-tot_rshifts).
+ if (normalizing_rshifts < 0) {
+ energy <<= -normalizing_rshifts;
+ } else {
+ energy >>= normalizing_rshifts;
+ }
+
+ // Calculate the energy of |data_in| in dB, in Q4.
+ //
+ // 10 * log10("true energy") in Q4 = 2^4 * 10 * log10("true energy") =
+ // 160 * log10(|energy| * 2^|tot_rshifts|) =
+ // 160 * log10(2) * log2(|energy| * 2^|tot_rshifts|) =
+ // 160 * log10(2) * (log2(|energy|) + log2(2^|tot_rshifts|)) =
+ // (160 * log10(2)) * (log2(|energy|) + |tot_rshifts|) =
+ // |kLogConst| * (|log2_energy| + |tot_rshifts|)
+ //
+ // We know by construction that |energy| is normalized to 15 bits. Hence,
+ // |energy| = 2^14 + frac_Q15, where frac_Q15 is a fractional part in Q15.
+ // Further, we'd like |log2_energy| in Q10
+ // log2(|energy|) in Q10 = 2^10 * log2(2^14 + frac_Q15) =
+ // 2^10 * log2(2^14 * (1 + frac_Q15 * 2^-14)) =
+ // 2^10 * (14 + log2(1 + frac_Q15 * 2^-14)) ~=
+ // (14 << 10) + 2^10 * (frac_Q15 * 2^-14) =
+ // (14 << 10) + (frac_Q15 * 2^-4) = (14 << 10) + (frac_Q15 >> 4)
+ //
+ // Note that frac_Q15 = (|energy| & 0x00003FFF)
+
+ // Calculate and add the fractional part to |log2_energy|.
+ log2_energy += (int16_t) ((energy & 0x00003FFF) >> 4);
+
+ // |kLogConst| is in Q9, |log2_energy| in Q10 and |tot_rshifts| in Q0.
+ // Note that we in our derivation above have accounted for an output in Q4.
+ *log_energy = (int16_t) (WEBRTC_SPL_MUL_16_16_RSFT(
+ kLogConst, log2_energy, 19) +
+ WEBRTC_SPL_MUL_16_16_RSFT(tot_rshifts, kLogConst, 9));
+
+ if (*log_energy < 0) {
+ *log_energy = 0;
+ }
+ } else {
+ *log_energy = offset;
+ return;
+ }
+
+ *log_energy += offset;
+
+ // Update the approximate |total_energy| with the energy of |data_in|, if
+ // |total_energy| has not exceeded |kMinEnergy|. |total_energy| is used as an
+ // energy indicator in WebRtcVad_GmmProbability() in vad_core.c.
+ if (*total_energy <= kMinEnergy) {
+ if (tot_rshifts >= 0) {
+ // We know by construction that the |energy| > |kMinEnergy| in Q0, so add
+ // an arbitrary value such that |total_energy| exceeds |kMinEnergy|.
+ *total_energy += kMinEnergy + 1;
+ } else {
+ // By construction |energy| is represented by 15 bits, hence any number of
+ // right shifted |energy| will fit in an int16_t. In addition, adding the
+ // value to |total_energy| is wrap around safe as long as
+ // |kMinEnergy| < 8192.
+ *total_energy += (int16_t) (energy >> -tot_rshifts); // Q0.
+ }
+ }
+}
+
+int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
+ int data_length, int16_t* features) {
+ int16_t total_energy = 0;
+ // We expect |data_length| to be 80, 160 or 240 samples, which corresponds to
+ // 10, 20 or 30 ms in 8 kHz. Therefore, the intermediate downsampled data will
+ // have at most 120 samples after the first split and at most 60 samples after
+ // the second split.
+ int16_t hp_120[120], lp_120[120];
+ int16_t hp_60[60], lp_60[60];
+ const int half_data_length = data_length >> 1;
+ int length = half_data_length; // |data_length| / 2, corresponds to
+ // bandwidth = 2000 Hz after downsampling.
+
+ // Initialize variables for the first SplitFilter().
+ int frequency_band = 0;
+ const int16_t* in_ptr = data_in; // [0 - 4000] Hz.
+ int16_t* hp_out_ptr = hp_120; // [2000 - 4000] Hz.
+ int16_t* lp_out_ptr = lp_120; // [0 - 2000] Hz.
+
+ assert(data_length >= 0);
+ assert(data_length <= 240);
+ assert(4 < kNumChannels - 1); // Checking maximum |frequency_band|.
+
+ // Split at 2000 Hz and downsample.
+ SplitFilter(in_ptr, data_length, &self->upper_state[frequency_band],
+ &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
+
+ // For the upper band (2000 Hz - 4000 Hz) split at 3000 Hz and downsample.
+ frequency_band = 1;
+ in_ptr = hp_120; // [2000 - 4000] Hz.
+ hp_out_ptr = hp_60; // [3000 - 4000] Hz.
+ lp_out_ptr = lp_60; // [2000 - 3000] Hz.
+ SplitFilter(in_ptr, length, &self->upper_state[frequency_band],
+ &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
+
+ // Energy in 3000 Hz - 4000 Hz.
+ length >>= 1; // |data_length| / 4 <=> bandwidth = 1000 Hz.
+
+ LogOfEnergy(hp_60, length, kOffsetVector[5], &total_energy, &features[5]);
+
+ // Energy in 2000 Hz - 3000 Hz.
+ LogOfEnergy(lp_60, length, kOffsetVector[4], &total_energy, &features[4]);
+
+ // For the lower band (0 Hz - 2000 Hz) split at 1000 Hz and downsample.
+ frequency_band = 2;
+ in_ptr = lp_120; // [0 - 2000] Hz.
+ hp_out_ptr = hp_60; // [1000 - 2000] Hz.
+ lp_out_ptr = lp_60; // [0 - 1000] Hz.
+ length = half_data_length; // |data_length| / 2 <=> bandwidth = 2000 Hz.
+ SplitFilter(in_ptr, length, &self->upper_state[frequency_band],
+ &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
+
+ // Energy in 1000 Hz - 2000 Hz.
+ length >>= 1; // |data_length| / 4 <=> bandwidth = 1000 Hz.
+ LogOfEnergy(hp_60, length, kOffsetVector[3], &total_energy, &features[3]);
+
+ // For the lower band (0 Hz - 1000 Hz) split at 500 Hz and downsample.
+ frequency_band = 3;
+ in_ptr = lp_60; // [0 - 1000] Hz.
+ hp_out_ptr = hp_120; // [500 - 1000] Hz.
+ lp_out_ptr = lp_120; // [0 - 500] Hz.
+ SplitFilter(in_ptr, length, &self->upper_state[frequency_band],
+ &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
+
+ // Energy in 500 Hz - 1000 Hz.
+ length >>= 1; // |data_length| / 8 <=> bandwidth = 500 Hz.
+ LogOfEnergy(hp_120, length, kOffsetVector[2], &total_energy, &features[2]);
+
+ // For the lower band (0 Hz - 500 Hz) split at 250 Hz and downsample.
+ frequency_band = 4;
+ in_ptr = lp_120; // [0 - 500] Hz.
+ hp_out_ptr = hp_60; // [250 - 500] Hz.
+ lp_out_ptr = lp_60; // [0 - 250] Hz.
+ SplitFilter(in_ptr, length, &self->upper_state[frequency_band],
+ &self->lower_state[frequency_band], hp_out_ptr, lp_out_ptr);
+
+ // Energy in 250 Hz - 500 Hz.
+ length >>= 1; // |data_length| / 16 <=> bandwidth = 250 Hz.
+ LogOfEnergy(hp_60, length, kOffsetVector[1], &total_energy, &features[1]);
+
+ // Remove 0 Hz - 80 Hz, by high pass filtering the lower band.
+ HighPassFilter(lp_60, length, self->hp_filter_state, hp_120);
+
+ // Energy in 80 Hz - 250 Hz.
+ LogOfEnergy(hp_120, length, kOffsetVector[0], &total_energy, &features[0]);
+
+ return total_energy;
+}
diff --git a/common_audio/vad/vad_filterbank.h b/common_audio/vad/vad_filterbank.h
new file mode 100644
index 0000000..b5fd69e
--- /dev/null
+++ b/common_audio/vad/vad_filterbank.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012 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 includes feature calculating functionality used in vad_core.c.
+ */
+
+#ifndef WEBRTC_COMMON_AUDIO_VAD_VAD_FILTERBANK_H_
+#define WEBRTC_COMMON_AUDIO_VAD_VAD_FILTERBANK_H_
+
+#include "typedefs.h"
+#include "vad_core.h"
+
+// Takes |data_length| samples of |data_in| and calculates the logarithm of the
+// energy of each of the |kNumChannels| = 6 frequency bands used by the VAD:
+// 80 Hz - 250 Hz
+// 250 Hz - 500 Hz
+// 500 Hz - 1000 Hz
+// 1000 Hz - 2000 Hz
+// 2000 Hz - 3000 Hz
+// 3000 Hz - 4000 Hz
+//
+// The values are given in Q4 and written to |features|. Further, an approximate
+// overall energy is returned. The return value is used in
+// WebRtcVad_GmmProbability() as a signal indicator, hence it is arbitrary above
+// the threshold |kMinEnergy|.
+//
+// - self [i/o] : State information of the VAD.
+// - data_in [i] : Input audio data, for feature extraction.
+// - data_length [i] : Audio data size, in number of samples.
+// - features [o] : 10 * log10(energy in each frequency band), Q4.
+// - returns : Total energy of the signal (NOTE! This value is not
+// exact. It is only used in a comparison.)
+int16_t WebRtcVad_CalculateFeatures(VadInstT* self, const int16_t* data_in,
+ int data_length, int16_t* features);
+
+#endif // WEBRTC_COMMON_AUDIO_VAD_VAD_FILTERBANK_H_
diff --git a/common_audio/vad/vad_filterbank_unittest.cc b/common_audio/vad/vad_filterbank_unittest.cc
new file mode 100644
index 0000000..ef01146
--- /dev/null
+++ b/common_audio/vad/vad_filterbank_unittest.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+#include "typedefs.h"
+#include "vad_unittest.h"
+
+extern "C" {
+#include "vad_core.h"
+#include "vad_filterbank.h"
+}
+
+namespace {
+
+enum { kNumValidFrameLengths = 3 };
+
+TEST_F(VadTest, vad_filterbank) {
+ VadInstT* self = reinterpret_cast<VadInstT*>(malloc(sizeof(VadInstT)));
+ static const int16_t kReference[kNumValidFrameLengths] = { 48, 11, 11 };
+ static const int16_t kFeatures[kNumValidFrameLengths * kNumChannels] = {
+ 1213, 759, 587, 462, 434, 272,
+ 1479, 1385, 1291, 1200, 1103, 1099,
+ 1732, 1692, 1681, 1629, 1436, 1436
+ };
+ static const int16_t kOffsetVector[kNumChannels] = {
+ 368, 368, 272, 176, 176, 176 };
+ int16_t features[kNumChannels];
+
+ // Construct a speech signal that will trigger the VAD in all modes. It is
+ // known that (i * i) will wrap around, but that doesn't matter in this case.
+ int16_t speech[kMaxFrameLength];
+ for (int16_t i = 0; i < kMaxFrameLength; ++i) {
+ speech[i] = (i * i);
+ }
+
+ int frame_length_index = 0;
+ ASSERT_EQ(0, WebRtcVad_InitCore(self));
+ for (size_t j = 0; j < kFrameLengthsSize; ++j) {
+ if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) {
+ EXPECT_EQ(kReference[frame_length_index],
+ WebRtcVad_CalculateFeatures(self, speech, kFrameLengths[j],
+ features));
+ for (int k = 0; k < kNumChannels; ++k) {
+ EXPECT_EQ(kFeatures[k + frame_length_index * kNumChannels],
+ features[k]);
+ }
+ frame_length_index++;
+ }
+ }
+ EXPECT_EQ(kNumValidFrameLengths, frame_length_index);
+
+ // Verify that all zeros in gives kOffsetVector out.
+ memset(speech, 0, sizeof(speech));
+ ASSERT_EQ(0, WebRtcVad_InitCore(self));
+ for (size_t j = 0; j < kFrameLengthsSize; ++j) {
+ if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) {
+ EXPECT_EQ(0, WebRtcVad_CalculateFeatures(self, speech, kFrameLengths[j],
+ features));
+ for (int k = 0; k < kNumChannels; ++k) {
+ EXPECT_EQ(kOffsetVector[k], features[k]);
+ }
+ }
+ }
+
+ // Verify that all ones in gives kOffsetVector out. Any other constant input
+ // will have a small impact in the sub bands.
+ for (int16_t i = 0; i < kMaxFrameLength; ++i) {
+ speech[i] = 1;
+ }
+ for (size_t j = 0; j < kFrameLengthsSize; ++j) {
+ if (ValidRatesAndFrameLengths(8000, kFrameLengths[j])) {
+ ASSERT_EQ(0, WebRtcVad_InitCore(self));
+ EXPECT_EQ(0, WebRtcVad_CalculateFeatures(self, speech, kFrameLengths[j],
+ features));
+ for (int k = 0; k < kNumChannels; ++k) {
+ EXPECT_EQ(kOffsetVector[k], features[k]);
+ }
+ }
+ }
+
+ free(self);
+}
+} // namespace
diff --git a/common_audio/vad/vad_gmm.c b/common_audio/vad/vad_gmm.c
new file mode 100644
index 0000000..20a703a
--- /dev/null
+++ b/common_audio/vad/vad_gmm.c
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#include "vad_gmm.h"
+
+#include "signal_processing_library.h"
+#include "typedefs.h"
+
+static const int32_t kCompVar = 22005;
+static const int16_t kLog2Exp = 5909; // log2(exp(1)) in Q12.
+
+// For a normal distribution, the probability of |input| is calculated and
+// returned (in Q20). The formula for normal distributed probability is
+//
+// 1 / s * exp(-(x - m)^2 / (2 * s^2))
+//
+// where the parameters are given in the following Q domains:
+// m = |mean| (Q7)
+// s = |std| (Q7)
+// x = |input| (Q4)
+// in addition to the probability we output |delta| (in Q11) used when updating
+// the noise/speech model.
+int32_t WebRtcVad_GaussianProbability(int16_t input,
+ int16_t mean,
+ int16_t std,
+ int16_t* delta) {
+ int16_t tmp16, inv_std, inv_std2, exp_value = 0;
+ int32_t tmp32;
+
+ // Calculate |inv_std| = 1 / s, in Q10.
+ // 131072 = 1 in Q17, and (|std| >> 1) is for rounding instead of truncation.
+ // Q-domain: Q17 / Q7 = Q10.
+ tmp32 = (int32_t) 131072 + (int32_t) (std >> 1);
+ inv_std = (int16_t) WebRtcSpl_DivW32W16(tmp32, std);
+
+ // Calculate |inv_std2| = 1 / s^2, in Q14.
+ tmp16 = (inv_std >> 2); // Q10 -> Q8.
+ // Q-domain: (Q8 * Q8) >> 2 = Q14.
+ inv_std2 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp16, tmp16, 2);
+ // TODO(bjornv): Investigate if changing to
+ // |inv_std2| = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(|inv_std|, |inv_std|, 6);
+ // gives better accuracy.
+
+ tmp16 = (input << 3); // Q4 -> Q7
+ tmp16 = tmp16 - mean; // Q7 - Q7 = Q7
+
+ // To be used later, when updating noise/speech model.
+ // |delta| = (x - m) / s^2, in Q11.
+ // Q-domain: (Q14 * Q7) >> 10 = Q11.
+ *delta = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(inv_std2, tmp16, 10);
+
+ // Calculate the exponent |tmp32| = (x - m)^2 / (2 * s^2), in Q10. Replacing
+ // division by two with one shift.
+ // Q-domain: (Q11 * Q7) >> 8 = Q10.
+ tmp32 = WEBRTC_SPL_MUL_16_16_RSFT(*delta, tmp16, 9);
+
+ // If the exponent is small enough to give a non-zero probability we calculate
+ // |exp_value| ~= exp(-(x - m)^2 / (2 * s^2))
+ // ~= exp2(-log2(exp(1)) * |tmp32|).
+ if (tmp32 < kCompVar) {
+ // Calculate |tmp16| = log2(exp(1)) * |tmp32|, in Q10.
+ // Q-domain: (Q12 * Q10) >> 12 = Q10.
+ tmp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(kLog2Exp, (int16_t) tmp32, 12);
+ tmp16 = -tmp16;
+ exp_value = (0x0400 | (tmp16 & 0x03FF));
+ tmp16 ^= 0xFFFF;
+ tmp16 >>= 10;
+ tmp16 += 1;
+ // Get |exp_value| = exp(-|tmp32|) in Q10.
+ exp_value >>= tmp16;
+ }
+
+ // Calculate and return (1 / s) * exp(-(x - m)^2 / (2 * s^2)), in Q20.
+ // Q-domain: Q10 * Q10 = Q20.
+ return WEBRTC_SPL_MUL_16_16(inv_std, exp_value);
+}
diff --git a/common_audio/vad/vad_gmm.h b/common_audio/vad/vad_gmm.h
new file mode 100644
index 0000000..2333af7
--- /dev/null
+++ b/common_audio/vad/vad_gmm.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+// Gaussian probability calculations internally used in vad_core.c.
+
+#ifndef WEBRTC_COMMON_AUDIO_VAD_VAD_GMM_H_
+#define WEBRTC_COMMON_AUDIO_VAD_VAD_GMM_H_
+
+#include "typedefs.h"
+
+// Calculates the probability for |input|, given that |input| comes from a
+// normal distribution with mean and standard deviation (|mean|, |std|).
+//
+// Inputs:
+// - input : input sample in Q4.
+// - mean : mean input in the statistical model, Q7.
+// - std : standard deviation, Q7.
+//
+// Output:
+//
+// - delta : input used when updating the model, Q11.
+// |delta| = (|input| - |mean|) / |std|^2.
+//
+// Return:
+// (probability for |input|) =
+// 1 / |std| * exp(-(|input| - |mean|)^2 / (2 * |std|^2));
+int32_t WebRtcVad_GaussianProbability(int16_t input,
+ int16_t mean,
+ int16_t std,
+ int16_t* delta);
+
+#endif // WEBRTC_COMMON_AUDIO_VAD_VAD_GMM_H_
diff --git a/common_audio/vad/vad_gmm_unittest.cc b/common_audio/vad/vad_gmm_unittest.cc
new file mode 100644
index 0000000..205435a
--- /dev/null
+++ b/common_audio/vad/vad_gmm_unittest.cc
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include "gtest/gtest.h"
+#include "typedefs.h"
+#include "vad_unittest.h"
+
+extern "C" {
+#include "vad_gmm.h"
+}
+
+namespace {
+
+TEST_F(VadTest, vad_gmm) {
+ int16_t delta = 0;
+ // Input value at mean.
+ EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(0, 0, 128, &delta));
+ EXPECT_EQ(0, delta);
+ EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(16, 128, 128, &delta));
+ EXPECT_EQ(0, delta);
+ EXPECT_EQ(1048576, WebRtcVad_GaussianProbability(-16, -128, 128, &delta));
+ EXPECT_EQ(0, delta);
+
+ // Largest possible input to give non-zero probability.
+ EXPECT_EQ(1024, WebRtcVad_GaussianProbability(59, 0, 128, &delta));
+ EXPECT_EQ(7552, delta);
+ EXPECT_EQ(1024, WebRtcVad_GaussianProbability(75, 128, 128, &delta));
+ EXPECT_EQ(7552, delta);
+ EXPECT_EQ(1024, WebRtcVad_GaussianProbability(-75, -128, 128, &delta));
+ EXPECT_EQ(-7552, delta);
+
+ // Too large input, should give zero probability.
+ EXPECT_EQ(0, WebRtcVad_GaussianProbability(105, 0, 128, &delta));
+ EXPECT_EQ(13440, delta);
+}
+} // namespace
diff --git a/common_audio/vad/vad_sp.c b/common_audio/vad/vad_sp.c
new file mode 100644
index 0000000..9e531c4
--- /dev/null
+++ b/common_audio/vad/vad_sp.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "common_audio/vad/vad_sp.h"
+
+#include <assert.h>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/vad/vad_core.h"
+#include "typedefs.h"
+
+// Allpass filter coefficients, upper and lower, in Q13.
+// Upper: 0.64, Lower: 0.17.
+static const int16_t kAllPassCoefsQ13[2] = { 5243, 1392 }; // Q13.
+static const int16_t kSmoothingDown = 6553; // 0.2 in Q15.
+static const int16_t kSmoothingUp = 32439; // 0.99 in Q15.
+
+// TODO(bjornv): Move this function to vad_filterbank.c.
+// Downsampling filter based on splitting filter and allpass functions.
+void WebRtcVad_Downsampling(int16_t* signal_in,
+ int16_t* signal_out,
+ int32_t* filter_state,
+ int in_length) {
+ int16_t tmp16_1 = 0, tmp16_2 = 0;
+ int32_t tmp32_1 = filter_state[0];
+ int32_t tmp32_2 = filter_state[1];
+ int n = 0;
+ int half_length = (in_length >> 1); // Downsampling by 2 gives half length.
+
+ // Filter coefficients in Q13, filter state in Q0.
+ for (n = 0; n < half_length; n++) {
+ // All-pass filtering upper branch.
+ tmp16_1 = (int16_t) ((tmp32_1 >> 1) +
+ WEBRTC_SPL_MUL_16_16_RSFT(kAllPassCoefsQ13[0], *signal_in, 14));
+ *signal_out = tmp16_1;
+ tmp32_1 = (int32_t) (*signal_in++) -
+ WEBRTC_SPL_MUL_16_16_RSFT(kAllPassCoefsQ13[0], tmp16_1, 12);
+
+ // All-pass filtering lower branch.
+ tmp16_2 = (int16_t) ((tmp32_2 >> 1) +
+ WEBRTC_SPL_MUL_16_16_RSFT(kAllPassCoefsQ13[1], *signal_in, 14));
+ *signal_out++ += tmp16_2;
+ tmp32_2 = (int32_t) (*signal_in++) -
+ WEBRTC_SPL_MUL_16_16_RSFT(kAllPassCoefsQ13[1], tmp16_2, 12);
+ }
+ // Store the filter states.
+ filter_state[0] = tmp32_1;
+ filter_state[1] = tmp32_2;
+}
+
+// Inserts |feature_value| into |low_value_vector|, if it is one of the 16
+// smallest values the last 100 frames. Then calculates and returns the median
+// of the five smallest values.
+int16_t WebRtcVad_FindMinimum(VadInstT* self,
+ int16_t feature_value,
+ int channel) {
+ int i = 0, j = 0;
+ int position = -1;
+ // Offset to beginning of the 16 minimum values in memory.
+ const int offset = (channel << 4);
+ int16_t current_median = 1600;
+ int16_t alpha = 0;
+ int32_t tmp32 = 0;
+ // Pointer to memory for the 16 minimum values and the age of each value of
+ // the |channel|.
+ int16_t* age = &self->index_vector[offset];
+ int16_t* smallest_values = &self->low_value_vector[offset];
+
+ assert(channel < kNumChannels);
+
+ // Each value in |smallest_values| is getting 1 loop older. Update |age|, and
+ // remove old values.
+ for (i = 0; i < 16; i++) {
+ if (age[i] != 100) {
+ age[i]++;
+ } else {
+ // Too old value. Remove from memory and shift larger values downwards.
+ for (j = i; j < 16; j++) {
+ smallest_values[j] = smallest_values[j + 1];
+ age[j] = age[j + 1];
+ }
+ age[15] = 101;
+ smallest_values[15] = 10000;
+ }
+ }
+
+ // Check if |feature_value| is smaller than any of the values in
+ // |smallest_values|. If so, find the |position| where to insert the new value
+ // (|feature_value|).
+ if (feature_value < smallest_values[7]) {
+ if (feature_value < smallest_values[3]) {
+ if (feature_value < smallest_values[1]) {
+ if (feature_value < smallest_values[0]) {
+ position = 0;
+ } else {
+ position = 1;
+ }
+ } else if (feature_value < smallest_values[2]) {
+ position = 2;
+ } else {
+ position = 3;
+ }
+ } else if (feature_value < smallest_values[5]) {
+ if (feature_value < smallest_values[4]) {
+ position = 4;
+ } else {
+ position = 5;
+ }
+ } else if (feature_value < smallest_values[6]) {
+ position = 6;
+ } else {
+ position = 7;
+ }
+ } else if (feature_value < smallest_values[15]) {
+ if (feature_value < smallest_values[11]) {
+ if (feature_value < smallest_values[9]) {
+ if (feature_value < smallest_values[8]) {
+ position = 8;
+ } else {
+ position = 9;
+ }
+ } else if (feature_value < smallest_values[10]) {
+ position = 10;
+ } else {
+ position = 11;
+ }
+ } else if (feature_value < smallest_values[13]) {
+ if (feature_value < smallest_values[12]) {
+ position = 12;
+ } else {
+ position = 13;
+ }
+ } else if (feature_value < smallest_values[14]) {
+ position = 14;
+ } else {
+ position = 15;
+ }
+ }
+
+ // If we have detected a new small value, insert it at the correct position
+ // and shift larger values up.
+ if (position > -1) {
+ for (i = 15; i > position; i--) {
+ smallest_values[i] = smallest_values[i - 1];
+ age[i] = age[i - 1];
+ }
+ smallest_values[position] = feature_value;
+ age[position] = 1;
+ }
+
+ // Get |current_median|.
+ if (self->frame_counter > 2) {
+ current_median = smallest_values[2];
+ } else if (self->frame_counter > 0) {
+ current_median = smallest_values[0];
+ }
+
+ // Smooth the median value.
+ if (self->frame_counter > 0) {
+ if (current_median < self->mean_value[channel]) {
+ alpha = kSmoothingDown; // 0.2 in Q15.
+ } else {
+ alpha = kSmoothingUp; // 0.99 in Q15.
+ }
+ }
+ tmp32 = WEBRTC_SPL_MUL_16_16(alpha + 1, self->mean_value[channel]);
+ tmp32 += WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_WORD16_MAX - alpha, current_median);
+ tmp32 += 16384;
+ self->mean_value[channel] = (int16_t) (tmp32 >> 15);
+
+ return self->mean_value[channel];
+}
diff --git a/common_audio/vad/vad_sp.h b/common_audio/vad/vad_sp.h
new file mode 100644
index 0000000..9e8b204
--- /dev/null
+++ b/common_audio/vad/vad_sp.h
@@ -0,0 +1,56 @@
+/*
+ * 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 includes specific signal processing tools used in vad_core.c.
+
+#ifndef WEBRTC_COMMON_AUDIO_VAD_VAD_SP_H_
+#define WEBRTC_COMMON_AUDIO_VAD_VAD_SP_H_
+
+#include "typedefs.h"
+#include "vad_core.h"
+
+// Downsamples the signal by a factor 2, eg. 32->16 or 16->8.
+//
+// Inputs:
+// - signal_in : Input signal.
+// - in_length : Length of input signal in samples.
+//
+// Input & Output:
+// - filter_state : Current filter states of the two all-pass filters. The
+// |filter_state| is updated after all samples have been
+// processed.
+//
+// Output:
+// - signal_out : Downsampled signal (of length |in_length| / 2).
+void WebRtcVad_Downsampling(int16_t* signal_in,
+ int16_t* signal_out,
+ int32_t* filter_state,
+ int in_length);
+
+// Updates and returns the smoothed feature minimum. As minimum we use the
+// median of the five smallest feature values in a 100 frames long window.
+// As long as |handle->frame_counter| is zero, that is, we haven't received any
+// "valid" data, FindMinimum() outputs the default value of 1600.
+//
+// Inputs:
+// - feature_value : New feature value to update with.
+// - channel : Channel number.
+//
+// Input & Output:
+// - handle : State information of the VAD.
+//
+// Returns:
+// : Smoothed minimum value for a moving window.
+int16_t WebRtcVad_FindMinimum(VadInstT* handle,
+ int16_t feature_value,
+ int channel);
+
+#endif // WEBRTC_COMMON_AUDIO_VAD_VAD_SP_H_
diff --git a/common_audio/vad/vad_sp_unittest.cc b/common_audio/vad/vad_sp_unittest.cc
new file mode 100644
index 0000000..632117f
--- /dev/null
+++ b/common_audio/vad/vad_sp_unittest.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+#include "typedefs.h"
+#include "vad_unittest.h"
+
+extern "C" {
+#include "vad_core.h"
+#include "vad_sp.h"
+}
+
+namespace {
+
+TEST_F(VadTest, vad_sp) {
+ VadInstT* self = reinterpret_cast<VadInstT*>(malloc(sizeof(VadInstT)));
+ const int kMaxFrameLenSp = 960; // Maximum frame length in this unittest.
+ int16_t zeros[kMaxFrameLenSp] = { 0 };
+ int32_t state[2] = { 0 };
+ int16_t data_in[kMaxFrameLenSp];
+ int16_t data_out[kMaxFrameLenSp];
+
+ // We expect the first value to be 1600 as long as |frame_counter| is zero,
+ // which is true for the first iteration.
+ static const int16_t kReferenceMin[32] = {
+ 1600, 720, 509, 512, 532, 552, 570, 588,
+ 606, 624, 642, 659, 675, 691, 707, 723,
+ 1600, 544, 502, 522, 542, 561, 579, 597,
+ 615, 633, 651, 667, 683, 699, 715, 731
+ };
+
+ // Construct a speech signal that will trigger the VAD in all modes. It is
+ // known that (i * i) will wrap around, but that doesn't matter in this case.
+ for (int16_t i = 0; i < kMaxFrameLenSp; ++i) {
+ data_in[i] = (i * i);
+ }
+ // Input values all zeros, expect all zeros out.
+ WebRtcVad_Downsampling(zeros, data_out, state, kMaxFrameLenSp);
+ EXPECT_EQ(0, state[0]);
+ EXPECT_EQ(0, state[1]);
+ for (int16_t i = 0; i < kMaxFrameLenSp / 2; ++i) {
+ EXPECT_EQ(0, data_out[i]);
+ }
+ // Make a simple non-zero data test.
+ WebRtcVad_Downsampling(data_in, data_out, state, kMaxFrameLenSp);
+ EXPECT_EQ(207, state[0]);
+ EXPECT_EQ(2270, state[1]);
+
+ ASSERT_EQ(0, WebRtcVad_InitCore(self));
+ // TODO(bjornv): Replace this part of the test with taking values from an
+ // array and calculate the reference value here. Make sure the values are not
+ // ordered.
+ for (int16_t i = 0; i < 16; ++i) {
+ int16_t value = 500 * (i + 1);
+ for (int j = 0; j < kNumChannels; ++j) {
+ // Use values both above and below initialized value.
+ EXPECT_EQ(kReferenceMin[i], WebRtcVad_FindMinimum(self, value, j));
+ EXPECT_EQ(kReferenceMin[i + 16], WebRtcVad_FindMinimum(self, 12000, j));
+ }
+ self->frame_counter++;
+ }
+
+ free(self);
+}
+} // namespace
diff --git a/common_audio/vad/vad_unittest.cc b/common_audio/vad/vad_unittest.cc
new file mode 100644
index 0000000..3e66853
--- /dev/null
+++ b/common_audio/vad/vad_unittest.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "vad_unittest.h"
+
+#include <stdlib.h>
+
+#include "gtest/gtest.h"
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/vad/include/webrtc_vad.h"
+#include "typedefs.h"
+
+VadTest::VadTest() {}
+
+void VadTest::SetUp() {}
+
+void VadTest::TearDown() {}
+
+// Returns true if the rate and frame length combination is valid.
+bool VadTest::ValidRatesAndFrameLengths(int rate, int frame_length) {
+ if (rate == 8000) {
+ if (frame_length == 80 || frame_length == 160 || frame_length == 240) {
+ return true;
+ }
+ return false;
+ } else if (rate == 16000) {
+ if (frame_length == 160 || frame_length == 320 || frame_length == 480) {
+ return true;
+ }
+ return false;
+ } else if (rate == 32000) {
+ if (frame_length == 320 || frame_length == 640 || frame_length == 960) {
+ return true;
+ }
+ return false;
+ } else if (rate == 48000) {
+ if (frame_length == 480 || frame_length == 960 || frame_length == 1440) {
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
+
+namespace {
+
+TEST_F(VadTest, ApiTest) {
+ // This API test runs through the APIs for all possible valid and invalid
+ // combinations.
+
+ VadInst* handle = NULL;
+ int16_t zeros[kMaxFrameLength] = { 0 };
+
+ // Construct a speech signal that will trigger the VAD in all modes. It is
+ // known that (i * i) will wrap around, but that doesn't matter in this case.
+ int16_t speech[kMaxFrameLength];
+ for (int16_t i = 0; i < kMaxFrameLength; i++) {
+ speech[i] = (i * i);
+ }
+
+ // NULL instance tests
+ EXPECT_EQ(-1, WebRtcVad_Create(NULL));
+ EXPECT_EQ(-1, WebRtcVad_Init(NULL));
+ EXPECT_EQ(-1, WebRtcVad_Free(NULL));
+ EXPECT_EQ(-1, WebRtcVad_set_mode(NULL, kModes[0]));
+ EXPECT_EQ(-1, WebRtcVad_Process(NULL, kRates[0], speech, kFrameLengths[0]));
+
+ // WebRtcVad_Create()
+ ASSERT_EQ(0, WebRtcVad_Create(&handle));
+
+ // Not initialized tests
+ EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[0], speech, kFrameLengths[0]));
+ EXPECT_EQ(-1, WebRtcVad_set_mode(handle, kModes[0]));
+
+ // WebRtcVad_Init() test
+ ASSERT_EQ(0, WebRtcVad_Init(handle));
+
+ // WebRtcVad_set_mode() invalid modes tests. Tries smallest supported value
+ // minus one and largest supported value plus one.
+ EXPECT_EQ(-1, WebRtcVad_set_mode(handle,
+ WebRtcSpl_MinValueW32(kModes,
+ kModesSize) - 1));
+ EXPECT_EQ(-1, WebRtcVad_set_mode(handle,
+ WebRtcSpl_MaxValueW32(kModes,
+ kModesSize) + 1));
+
+ // WebRtcVad_Process() tests
+ // NULL speech pointer
+ EXPECT_EQ(-1, WebRtcVad_Process(handle, kRates[0], NULL, kFrameLengths[0]));
+ // Invalid sampling rate
+ EXPECT_EQ(-1, WebRtcVad_Process(handle, 9999, speech, kFrameLengths[0]));
+ // All zeros as input should work
+ EXPECT_EQ(0, WebRtcVad_Process(handle, kRates[0], zeros, kFrameLengths[0]));
+ for (size_t k = 0; k < kModesSize; k++) {
+ // Test valid modes
+ EXPECT_EQ(0, WebRtcVad_set_mode(handle, kModes[k]));
+ // Loop through sampling rate and frame length combinations
+ for (size_t i = 0; i < kRatesSize; i++) {
+ for (size_t j = 0; j < kFrameLengthsSize; j++) {
+ if (ValidRatesAndFrameLengths(kRates[i], kFrameLengths[j])) {
+ EXPECT_EQ(1, WebRtcVad_Process(handle,
+ kRates[i],
+ speech,
+ kFrameLengths[j]));
+ } else {
+ EXPECT_EQ(-1, WebRtcVad_Process(handle,
+ kRates[i],
+ speech,
+ kFrameLengths[j]));
+ }
+ }
+ }
+ }
+
+ EXPECT_EQ(0, WebRtcVad_Free(handle));
+}
+
+TEST_F(VadTest, ValidRatesFrameLengths) {
+ // This test verifies valid and invalid rate/frame_length combinations. We
+ // loop through some sampling rates and frame lengths from negative values to
+ // values larger than possible.
+ const int kNumRates = 12;
+ const int kRates[kNumRates] = {
+ -8000, -4000, 0, 4000, 8000, 8001, 15999, 16000, 32000, 48000, 48001, 96000
+ };
+
+ const int kNumFrameLengths = 13;
+ const int kFrameLengths[kNumFrameLengths] = {
+ -10, 0, 80, 81, 159, 160, 240, 320, 480, 640, 960, 1440, 2000
+ };
+
+ for (int i = 0; i < kNumRates; i++) {
+ for (int j = 0; j < kNumFrameLengths; j++) {
+ if (ValidRatesAndFrameLengths(kRates[i], kFrameLengths[j])) {
+ EXPECT_EQ(0, WebRtcVad_ValidRateAndFrameLength(kRates[i],
+ kFrameLengths[j]));
+ } else {
+ EXPECT_EQ(-1, WebRtcVad_ValidRateAndFrameLength(kRates[i],
+ kFrameLengths[j]));
+ }
+ }
+ }
+}
+
+// TODO(bjornv): Add a process test, run on file.
+
+} // namespace
diff --git a/common_audio/vad/vad_unittest.h b/common_audio/vad/vad_unittest.h
new file mode 100644
index 0000000..a42e86f
--- /dev/null
+++ b/common_audio/vad/vad_unittest.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#ifndef WEBRTC_COMMON_AUDIO_VAD_VAD_UNITTEST_H
+#define WEBRTC_COMMON_AUDIO_VAD_VAD_UNITTEST_H
+
+#include <stddef.h> // size_t
+
+#include "gtest/gtest.h"
+
+#include "typedefs.h"
+
+namespace {
+
+// Modes we support
+const int kModes[] = { 0, 1, 2, 3 };
+const size_t kModesSize = sizeof(kModes) / sizeof(*kModes);
+
+// Rates we support.
+const int kRates[] = { 8000, 12000, 16000, 24000, 32000, 48000 };
+const size_t kRatesSize = sizeof(kRates) / sizeof(*kRates);
+
+// Frame lengths we support.
+const int kMaxFrameLength = 1440;
+const int kFrameLengths[] = { 80, 120, 160, 240, 320, 480, 640, 960,
+ kMaxFrameLength };
+const size_t kFrameLengthsSize = sizeof(kFrameLengths) / sizeof(*kFrameLengths);
+
+} // namespace
+
+class VadTest : public ::testing::Test {
+ protected:
+ VadTest();
+ virtual void SetUp();
+ virtual void TearDown();
+
+ // Returns true if the rate and frame length combination is valid.
+ bool ValidRatesAndFrameLengths(int rate, int frame_length);
+};
+
+#endif // WEBRTC_COMMON_AUDIO_VAD_VAD_UNITTEST_H
diff --git a/common_audio/vad/webrtc_vad.c b/common_audio/vad/webrtc_vad.c
new file mode 100644
index 0000000..dad9d73
--- /dev/null
+++ b/common_audio/vad/webrtc_vad.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include "common_audio/vad/include/webrtc_vad.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/vad/vad_core.h"
+#include "typedefs.h"
+
+static const int kInitCheck = 42;
+static const int kValidRates[] = { 8000, 16000, 32000, 48000 };
+static const size_t kRatesSize = sizeof(kValidRates) / sizeof(*kValidRates);
+static const int kMaxFrameLengthMs = 30;
+
+int WebRtcVad_Create(VadInst** handle) {
+ VadInstT* self = NULL;
+
+ if (handle == NULL) {
+ return -1;
+ }
+
+ *handle = NULL;
+ self = (VadInstT*) malloc(sizeof(VadInstT));
+ *handle = (VadInst*) self;
+
+ if (self == NULL) {
+ return -1;
+ }
+
+ WebRtcSpl_Init();
+
+ self->init_flag = 0;
+
+ return 0;
+}
+
+int WebRtcVad_Free(VadInst* handle) {
+ if (handle == NULL) {
+ return -1;
+ }
+
+ free(handle);
+
+ return 0;
+}
+
+// TODO(bjornv): Move WebRtcVad_InitCore() code here.
+int WebRtcVad_Init(VadInst* handle) {
+ // Initialize the core VAD component.
+ return WebRtcVad_InitCore((VadInstT*) handle);
+}
+
+// TODO(bjornv): Move WebRtcVad_set_mode_core() code here.
+int WebRtcVad_set_mode(VadInst* handle, int mode) {
+ VadInstT* self = (VadInstT*) handle;
+
+ if (handle == NULL) {
+ return -1;
+ }
+ if (self->init_flag != kInitCheck) {
+ return -1;
+ }
+
+ return WebRtcVad_set_mode_core(self, mode);
+}
+
+int WebRtcVad_Process(VadInst* handle, int fs, int16_t* audio_frame,
+ int frame_length) {
+ int vad = -1;
+ VadInstT* self = (VadInstT*) handle;
+
+ if (handle == NULL) {
+ return -1;
+ }
+
+ if (self->init_flag != kInitCheck) {
+ return -1;
+ }
+ if (audio_frame == NULL) {
+ return -1;
+ }
+ if (WebRtcVad_ValidRateAndFrameLength(fs, frame_length) != 0) {
+ return -1;
+ }
+
+ if (fs == 48000) {
+ vad = WebRtcVad_CalcVad48khz(self, audio_frame, frame_length);
+ } else if (fs == 32000) {
+ vad = WebRtcVad_CalcVad32khz(self, audio_frame, frame_length);
+ } else if (fs == 16000) {
+ vad = WebRtcVad_CalcVad16khz(self, audio_frame, frame_length);
+ } else if (fs == 8000) {
+ vad = WebRtcVad_CalcVad8khz(self, audio_frame, frame_length);
+ }
+
+ if (vad > 0) {
+ vad = 1;
+ }
+ return vad;
+}
+
+int WebRtcVad_ValidRateAndFrameLength(int rate, int frame_length) {
+ int return_value = -1;
+ size_t i;
+ int valid_length_ms;
+ int valid_length;
+
+ // We only allow 10, 20 or 30 ms frames. Loop through valid frame rates and
+ // see if we have a matching pair.
+ for (i = 0; i < kRatesSize; i++) {
+ if (kValidRates[i] == rate) {
+ for (valid_length_ms = 10; valid_length_ms <= kMaxFrameLengthMs;
+ valid_length_ms += 10) {
+ valid_length = (kValidRates[i] / 1000 * valid_length_ms);
+ if (frame_length == valid_length) {
+ return_value = 0;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return return_value;
+}