diff --git a/common_audio/OWNERS b/common_audio/OWNERS new file mode 100644 index 0000000000..0eb967b2f9 --- /dev/null +++ b/common_audio/OWNERS @@ -0,0 +1 @@ +bjornv@google.com diff --git a/common_audio/resampler/OWNERS b/common_audio/resampler/OWNERS new file mode 100644 index 0000000000..cf595df7d8 --- /dev/null +++ b/common_audio/resampler/OWNERS @@ -0,0 +1,3 @@ +bjornv@google.com +tlegrand@google.com +jks@google.com diff --git a/common_audio/resampler/main/interface/resampler.h b/common_audio/resampler/main/interface/resampler.h new file mode 100644 index 0000000000..a03ff18031 --- /dev/null +++ b/common_audio/resampler/main/interface/resampler.h @@ -0,0 +1,110 @@ +/* + * 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 +{ + +enum ResamplerType +{ + // 4 MSB = Number of channels + // 4 LSB = Synchronous or asynchronous + + kResamplerSynchronous = 0x10, + kResamplerAsynchronous = 0x11, + kResamplerSynchronousStereo = 0x20, + kResamplerAsynchronousStereo = 0x21, + kResamplerInvalid = 0xff +}; + +enum ResamplerMode +{ + kResamplerMode1To1, + kResamplerMode1To2, + kResamplerMode1To3, + kResamplerMode1To4, + kResamplerMode1To6, + kResamplerMode2To3, + kResamplerMode2To11, + kResamplerMode4To11, + kResamplerMode8To11, + kResamplerMode11To16, + kResamplerMode11To32, + kResamplerMode2To1, + kResamplerMode3To1, + kResamplerMode4To1, + kResamplerMode6To1, + kResamplerMode3To2, + kResamplerMode11To2, + kResamplerMode11To4, + kResamplerMode11To8 +}; + +class Resampler +{ + +public: + Resampler(); + 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/main/source/resampler.cc b/common_audio/resampler/main/source/resampler.cc new file mode 100644 index 0000000000..f866739752 --- /dev/null +++ b/common_audio/resampler/main/source/resampler.cc @@ -0,0 +1,981 @@ +/* + * 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 +#include + +#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; + + int res = 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 = (ResamplerType)((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; + default: + my_type_ = kResamplerInvalid; + break; + } + } 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; + default: + my_type_ = kResamplerInvalid; + break; + } + } 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 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 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; + } + + // Container for temp samples + WebRtc_Word16* tmp; + // 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 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 (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 kResamplerMode3To2: + if (maxLen < (lengthIn * 2 / 3)) + { + return -1; + } + // 3:6 + tmp = static_cast (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/main/source/resampler.gyp b/common_audio/resampler/main/source/resampler.gyp new file mode 100644 index 0000000000..8baf870ae8 --- /dev/null +++ b/common_audio/resampler/main/source/resampler.gyp @@ -0,0 +1,40 @@ +# 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': [ + '../../../../common_settings.gypi', # Common settings + ], + 'targets': [ + { + 'target_name': 'resampler', + 'type': '<(library)', + 'dependencies': [ + '../../../signal_processing_library/main/source/spl.gyp:spl', + ], + 'include_dirs': [ + '../interface', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../interface', + ], + }, + 'sources': [ + '../interface/resampler.h', + 'resampler.cc', + ], + }, + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/common_audio/signal_processing_library/OWNERS b/common_audio/signal_processing_library/OWNERS new file mode 100644 index 0000000000..cf595df7d8 --- /dev/null +++ b/common_audio/signal_processing_library/OWNERS @@ -0,0 +1,3 @@ +bjornv@google.com +tlegrand@google.com +jks@google.com diff --git a/common_audio/signal_processing_library/main/interface/signal_processing_library.h b/common_audio/signal_processing_library/main/interface/signal_processing_library.h new file mode 100644 index 0000000000..02ad52d39a --- /dev/null +++ b/common_audio/signal_processing_library/main/interface/signal_processing_library.h @@ -0,0 +1,1649 @@ +/* + * 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 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 +#include "typedefs.h" + +#ifdef ARM_WINM +#include // intrinsic file for windows mobile +#endif + +#ifdef ANDROID_ISACOPT +#define WEBRTC_SPL_INLINE_CALLS +#define SPL_NO_DOUBLE_IMPLEMENTATIONS +#endif + +// 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 +#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)) + +#if (defined WEBRTC_TARGET_PC)||(defined __TARGET_XSCALE) +#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)) +#elif defined WEBRTC_BIG_ENDIAN +#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))) +#else +#define WEBRTC_SPL_GET_BYTE(a,nr)\ + ((((WebRtc_Word16 *)(a))[(nr) >> 1]) >> (((nr) & 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) + 1) & 0x1)))) | ((val) << (8 * ((index) & 0x1))) +#endif + +#ifndef ANDROID_ISACOPT +#define WEBRTC_SPL_MUL(a, b) ((WebRtc_Word32) ((WebRtc_Word32)(a) * (WebRtc_Word32)(b))) +#endif + +#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))) + +#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)) + +#ifndef ANDROID_ISACOPT +#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 + +#ifdef ARM_WINM +#define WEBRTC_SPL_MUL_16_16(a, b) _SmulLo_SW_SL((WebRtc_Word16)(a), (WebRtc_Word16)(b)) +#elif !defined (ANDROID_ISACOPT) +#define WEBRTC_SPL_MUL_16_16(a, b)\ + ((WebRtc_Word32) (((WebRtc_Word16)(a)) * ((WebRtc_Word16)(b)))) +#endif + +#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)) + +// Trigonometric tables used for quick lookup +// default declarations +extern WebRtc_Word16 WebRtcSpl_kCosTable[]; +extern WebRtc_Word16 WebRtcSpl_kSinTable[]; +extern WebRtc_Word16 WebRtcSpl_kSinTable1024[]; +// Hanning table +extern WebRtc_Word16 WebRtcSpl_kHanningTable[]; +// Random table +extern WebRtc_Word16 WebRtcSpl_kRandNTable[]; + +#ifndef WEBRTC_SPL_INLINE_CALLS +WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 var1, WebRtc_Word16 var2); +WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1, WebRtc_Word16 var2); +WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 var1, WebRtc_Word32 var2); +WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 var1, WebRtc_Word32 var2); +WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 value); +int WebRtcSpl_NormW32(WebRtc_Word32 value); +int WebRtcSpl_NormW16(WebRtc_Word16 value); +int WebRtcSpl_NormU32(WebRtc_UWord32 value); +#else +#include "spl_inl.h" +#endif + +// 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 operations. Implementation in min_max_operations.c. Descriptions at +// bottom of file. +WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length); +WebRtc_Word32 WebRtcSpl_MaxAbsValueW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length); +WebRtc_Word16 WebRtcSpl_MinValueW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length); +WebRtc_Word32 WebRtcSpl_MinValueW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length); +WebRtc_Word16 WebRtcSpl_MaxValueW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length); + +WebRtc_Word16 WebRtcSpl_MaxAbsIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length); +WebRtc_Word32 WebRtcSpl_MaxValueW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length); +WebRtc_Word16 WebRtcSpl_MinIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length); +WebRtc_Word16 WebRtcSpl_MinIndexW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length); +WebRtc_Word16 WebRtcSpl_MaxIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length); +WebRtc_Word16 WebRtcSpl_MaxIndexW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 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); +// End: Vector scaling operations. + +// iLBC specific functions. Implementations in ilbc_specific_functions.c. Description at +// bottom of file. +void WebRtcSpl_ScaleAndAddVectorsWithRound(WebRtc_Word16* in_vector1, WebRtc_Word16 scale1, + WebRtc_Word16* in_vector2, WebRtc_Word16 scale2, + WebRtc_Word16 right_shifts, WebRtc_Word16* out_vector, + WebRtc_Word16 vector_length); +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. Descriptions at bottom of this file. +int WebRtcSpl_AutoCorrelation(G_CONST WebRtc_Word16* vector, int vector_length, int order, + WebRtc_Word32* result_vector, int* scale); +WebRtc_Word16 WebRtcSpl_LevinsonDurbin(WebRtc_Word32* auto_corr, WebRtc_Word16* lpc_coef, WebRtc_Word16* refl_coef, + WebRtc_Word16 order); +void WebRtcSpl_ReflCoefToLpc(G_CONST WebRtc_Word16* refl_coef, int use_order, WebRtc_Word16* lpc_coef); +void WebRtcSpl_LpcToReflCoef(WebRtc_Word16* lpc_coef, int use_order, WebRtc_Word16* refl_coef); +void WebRtcSpl_AutoCorrToReflCoef(G_CONST WebRtc_Word32* auto_corr, int use_order, WebRtc_Word16* refl_coef); +void WebRtcSpl_CrossCorrelation(WebRtc_Word32* cross_corr, + WebRtc_Word16* vector1, + WebRtc_Word16* vector2, + WebRtc_Word16 dim_vector, + WebRtc_Word16 dim_cross_corr, + WebRtc_Word16 right_shifts, + WebRtc_Word16 step_vector2); +void WebRtcSpl_GetHanningWindow(WebRtc_Word16* window, WebRtc_Word16 size); +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); + +// 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); + +WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16* vector1, WebRtc_Word16* vector2, + int vector_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); +void WebRtcSpl_FilterARFastQ12(WebRtc_Word16* in_vector, WebRtc_Word16* out_vector, WebRtc_Word16* ar_coef, + WebRtc_Word16 ar_coef_length, WebRtc_Word16 vector_length); +int WebRtcSpl_DownsampleFast(WebRtc_Word16* in_vector, WebRtc_Word16 in_vector_length, + WebRtc_Word16* out_vector, WebRtc_Word16 out_vector_length, + WebRtc_Word16* ma_coef, WebRtc_Word16 ma_coef_length, WebRtc_Word16 factor, + WebRtc_Word16 delay); +// 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); +#if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT) +int WebRtcSpl_ComplexFFT2(WebRtc_Word16 in_vector[], WebRtc_Word16 out_vector[], int stages, int mode); +int WebRtcSpl_ComplexIFFT2(WebRtc_Word16 in_vector[], WebRtc_Word16 out_vector[], int stages, int mode); +#endif +void WebRtcSpl_ComplexBitReverse(WebRtc_Word16 vector[], 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_MinValueW16(...) +// WebRtcSpl_MinValueW32(...) +// +// Returns the minimum value of a vector +// +// Input: +// - vector : Input vector +// - vector_length : Number of samples in vector +// +// Return value : Minimum sample value in vector +// + +// +// WebRtcSpl_MaxValueW16(...) +// WebRtcSpl_MaxValueW32(...) +// +// Returns the maximum value of a vector +// +// Input: +// - vector : Input vector +// - vector_length : Number of samples in vector +// +// Return value : Maximum sample value in vector +// + +// +// WebRtcSpl_MaxAbsValueW16(...) +// WebRtcSpl_MaxAbsValueW32(...) +// +// Returns the largest absolute value of a vector +// +// Input: +// - vector : Input vector +// - vector_length : Number of samples in vector +// +// Return value : Maximum absolute value in vector +// + +// +// WebRtcSpl_MaxAbsIndexW16(...) +// +// Returns the vector index to the largest absolute value of a vector +// +// Input: +// - vector : Input vector +// - vector_length : Number of samples in vector +// +// Return value : Index to maximum absolute value in vector +// + +// +// WebRtcSpl_MinIndexW16(...) +// WebRtcSpl_MinIndexW32(...) +// +// Returns the vector index to the minimum sample value of a vector +// +// Input: +// - vector : Input vector +// - vector_length : Number of samples in vector +// +// Return value : Index to minimum sample value in vector +// + +// +// WebRtcSpl_MaxIndexW16(...) +// WebRtcSpl_MaxIndexW32(...) +// +// Returns the vector index to the maximum sample value of a vector +// +// Input: +// - vector : Input vector +// - vector_length : Number of samples in vector +// +// Return value : Index to maximum sample value 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_ScaleAndAddVectorsWithRound(...) +// +// Performs the vector operation: +// +// out_vector[k] = ((scale1*in_vector1[k]) + (scale2*in_vector2[k]) +// + round_value) >> right_shifts +// +// where: +// +// round_value = (1<>1 +// +// Input: +// - in_vector1 : Input vector 1 +// - scale1 : Gain to be used for vector 1 +// - in_vector2 : Input vector 2 +// - scale2 : Gain to be used for vector 2 +// - right_shifts : Number of right bit shifts to be applied +// - vector_length : Number of 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_AutoCorrelation(...) +// +// A 32-bit fix-point implementation of auto-correlation computation +// +// Input: +// - vector : Vector to calculate autocorrelation upon +// - vector_length : Length (in samples) of |vector| +// - order : The order up to which the autocorrelation should be +// calculated +// +// Output: +// - result_vector : 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 : Number of samples in |result_vector|, i.e., (order+1) +// + +// +// WebRtcSpl_LevinsonDurbin(...) +// +// 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 +// + +// +// WebRtcSpl_ReflCoefToLpc(...) +// +// 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 +// + +// +// WebRtcSpl_LpcToReflCoef(...) +// +// 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. +// + +// +// WebRtcSpl_AutoCorrToReflCoef(...) +// +// 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. +// + +// +// WebRtcSpl_CrossCorrelation(...) +// +// Calculates the cross-correlation between two sequences |vector1| and +// |vector2|. |vector1| is fixed and |vector2| slides as the pointer is +// increased with the amount |step_vector2| +// +// Input: +// - vector1 : First sequence (fixed throughout the correlation) +// - vector2 : Second sequence (slides |step_vector2| for each +// new correlation) +// - dim_vector : Number of samples to use in the cross-correlation +// - dim_cross_corr : 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_vector2 : How many (positive or negative) steps the +// |vector2| pointer should be updated for each new +// cross-correlation value. +// +// Output: +// - cross_corr : The cross-correlation in Q(-right_shifts) +// + +// +// WebRtcSpl_GetHanningWindow(...) +// +// 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. +// + +// +// WebRtcSpl_SqrtOfOneMinusXSquared(...) +// +// 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 +// + +// +// 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_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_FilterARFastQ12(...) +// +// Performs a AR filtering on a vector in Q12 +// +// Input: +// - in_vector : Input samples +// - out_vector : State information in positions +// out_vector[-order] .. out_vector[-1] +// - ar_coef : Filter coefficients (in Q12) +// - ar_coef_length : Number of B coefficients (order+1) +// - vector_length : Number of samples to be filtered +// +// Output: +// - out_vector : Filtered samples +// + +// +// WebRtcSpl_DownsampleFast(...) +// +// Performs a MA down sampling filter on a vector +// +// Input: +// - in_vector : Input samples (state in positions +// in_vector[-order] .. in_vector[-1]) +// - in_vector_length : Number of samples in |in_vector| to be filtered. +// This must be at least +// |delay| + |factor|*(|out_vector_length|-1) + 1) +// - out_vector_length : Number of down sampled samples desired +// - ma_coef : Filter coefficients (in Q12) +// - ma_coef_length : Number of B coefficients (order+1) +// - factor : Decimation factor +// - delay : Delay of filter (compensated for in out_vector) +// +// Output: +// - out_vector : Filtered samples +// +// Return value : 0 if OK, -1 if |in_vector| is too short +// + +// +// WebRtcSpl_DotProductWithScale(...) +// +// 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) +// + +// +// 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. +// + +#if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT) +// +// WebRtcSpl_ComplexIFFT2(...) +// +// Complex or Real inverse FFT, for ARM processor only +// +// Computes a 2^|stages|-point FFT on the input vector, which can be or not be +// in bit-reversed order. If it is bit-reversed, the original content of the +// vector could be overwritten by the output by setting the first two arguments +// the same. 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. +// +// Arguments: +// - in_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. +// - out_vector : Output pointer to 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. +// - mode : Dummy input. +// +// Return value : The scale parameter is always 0, except if N>1024, +// which returns a scale value of -1, indicating error. +// +#endif + +// +// 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. +// + +#if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT) +// +// WebRtcSpl_ComplexFFT2(...) +// +// Complex or Real FFT, for ARM processor only +// +// Computes a 2^|stages|-point FFT on the input vector, which can be or not be +// in bit-reversed order. If it is bit-reversed, the original content of the +// vector could be overwritten by the output by setting the first two arguments +// the same. 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. +// +// Arguments: +// - in_vector : In pointer to complex vector containing 2^|stages| +// real elements interleaved with 2^|stages| imaginary +// elements. [ReImReImReIm....] +// - out_vector : Output pointer to 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. +// - mode : Dummy input +// +// Return value : The scale parameter is always 0, except if N>1024, +// which returns a scale value of -1, indicating error. +// +#endif + +// +// WebRtcSpl_ComplexBitReverse(...) +// +// Complex Bit Reverse +// +// This function bit-reverses the position of elements in the complex input +// vector into the output vector. +// +// If you bit-reverse a linear-order array, you obtain a bit-reversed order +// array. If you bit-reverse a bit-reversed order array, you obtain a +// linear-order array. +// +// Input: +// - vector : In pointer to complex vector containing 2^|stages| real +// elements interleaved with 2^|stages| imaginary elements. +// [ReImReImReIm....] +// - stages : Number of FFT stages. Must be at least 3 and at most 10, +// since the table WebRtcSpl_kSinTable1024[] is 1024 +// elements long. +// +// Output: +// - vector : Out pointer to complex vector in bit-reversed order. +// The input vector is over written. +// + +// +// 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_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_library/main/interface/spl_inl.h b/common_audio/signal_processing_library/main/interface/spl_inl.h new file mode 100644 index 0000000000..eb62fbee5a --- /dev/null +++ b/common_audio/signal_processing_library/main/interface/spl_inl.h @@ -0,0 +1,284 @@ +/* + * 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_SPL_INLINE_CALLS + +#ifdef ANDROID_ISACOPT + +WEBRTC_INLINE WebRtc_Word32 WEBRTC_SPL_MUL(WebRtc_Word32 a, WebRtc_Word32 b) +{ + WebRtc_Word32 tmp; + __asm__("mul %0, %1, %2":"=r"(tmp):"r"(a), "r"(b)); + return tmp; +} + +WEBRTC_INLINE WebRtc_Word32 WEBRTC_SPL_MUL_16_32_RSFT16(WebRtc_Word16 a, WebRtc_Word32 b) +{ + WebRtc_Word32 tmp; + __asm__("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a)); + return tmp; +} + +WEBRTC_INLINE WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32(WebRtc_Word16 a, + WebRtc_Word16 b, + WebRtc_Word32 c) +{ + WebRtc_Word32 tmp; + __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(tmp) : "r"(b), "r"(a)); + __asm__("smmul %0, %1, %2":"=r"(tmp):"r"(tmp), "r"(c)); + return tmp; +} + +WEBRTC_INLINE WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32BI( + WebRtc_Word32 a, + WebRtc_Word32 b) +{ + WebRtc_Word32 tmp; + __asm__("smmul %0, %1, %2":"=r"(tmp):"r"(a), "r"(b)); + return tmp; +} + +WEBRTC_INLINE WebRtc_Word32 WEBRTC_SPL_MUL_16_16(WebRtc_Word16 a,WebRtc_Word16 b) +{ + WebRtc_Word32 tmp; + __asm__("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b)); + return tmp; +} + +WEBRTC_INLINE WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a, WebRtc_Word16 b) +{ + WebRtc_Word32 s_sum; + + __asm__("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b)); + + return (WebRtc_Word16) s_sum; +} + +WEBRTC_INLINE WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1, WebRtc_Word32 l_var2) +{ + WebRtc_Word32 l_sum; + + __asm__("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2)); + + return l_sum; +} + +WEBRTC_INLINE WebRtc_Word16 WebRtcSpl_SubSatW32(WebRtc_Word16 var1, WebRtc_Word16 var2) +{ + WebRtc_Word32 s_sub; + + __asm__("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2)); + + return (WebRtc_Word16)s_sub; +} + +WEBRTC_INLINE WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1, WebRtc_Word32 l_var2) +{ + WebRtc_Word32 l_sub; + + __asm__("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2)); + + return l_sub; +} + +WEBRTC_INLINE WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) +{ + WebRtc_Word32 tmp; + + __asm__("clz %0, %1":"=r"(tmp):"r"(n)); + + return (WebRtc_Word16)(32 - tmp); +} + +WEBRTC_INLINE int WebRtcSpl_NormW32(WebRtc_Word32 a) +{ + WebRtc_Word32 tmp; + + if (a <= 0) a ^= 0xFFFFFFFF; + + __asm__("clz %0, %1":"=r"(tmp):"r"(a)); + + return tmp - 1; +} + +WEBRTC_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; +} + +WEBRTC_INLINE int WebRtcSpl_NormU32(WebRtc_UWord32 a) +{ + int tmp; + + if (a == 0) return 0; + + __asm__("clz %0, %1":"=r"(tmp):"r"(a)); + + return tmp; +} + +#else + +WEBRTC_INLINE WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a, WebRtc_Word16 b) +{ + WebRtc_Word32 s_sum = (WebRtc_Word32) a + (WebRtc_Word32) b; + + if (s_sum > WEBRTC_SPL_WORD16_MAX) + s_sum = WEBRTC_SPL_WORD16_MAX; + else if (s_sum < WEBRTC_SPL_WORD16_MIN) + s_sum = WEBRTC_SPL_WORD16_MIN; + + return (WebRtc_Word16)s_sum; +} + +WEBRTC_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; + + // check for under or overflow + if (WEBRTC_SPL_IS_NEG (l_var1)) + { + if (WEBRTC_SPL_IS_NEG (l_var2) && !WEBRTC_SPL_IS_NEG (l_sum)) + { + l_sum = (WebRtc_Word32)0x80000000; + } + } + else + { + if (!WEBRTC_SPL_IS_NEG (l_var2) && WEBRTC_SPL_IS_NEG (l_sum)) + { + l_sum = (WebRtc_Word32)0x7FFFFFFF; + } + } + + return l_sum; +} + +WEBRTC_INLINE WebRtc_Word16 WebRtcSpl_SubSatW16( WebRtc_Word16 var1, WebRtc_Word16 var2) +{ + WebRtc_Word32 l_diff; + WebRtc_Word16 s_diff; + + // perform subtraction + l_diff = (WebRtc_Word32)var1 - (WebRtc_Word32)var2; + + // default setting + s_diff = (WebRtc_Word16) l_diff; + + // check for overflow + if (l_diff > (WebRtc_Word32)32767) + s_diff = (WebRtc_Word16)32767; + + // check for underflow + if (l_diff < (WebRtc_Word32)-32768) + s_diff = (WebRtc_Word16)-32768; + + return s_diff; +} + +WEBRTC_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; + + // check for underflow + if ((l_var1 < 0) && (l_var2 > 0) && (l_diff > 0)) + l_diff = (WebRtc_Word32)0x80000000; + // check for overflow + if ((l_var1 > 0) && (l_var2 < 0) && (l_diff < 0)) + l_diff = (WebRtc_Word32)0x7FFFFFFF; + + return l_diff; +} + +WEBRTC_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; +} + +WEBRTC_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; +} + +WEBRTC_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; +} + +WEBRTC_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; +} + +#endif // ANDROID_ISACOPT +#endif // WEBRTC_SPL_INLINE_CALLS +#endif // WEBRTC_SPL_SPL_INL_H_ diff --git a/common_audio/signal_processing_library/main/source/CMakeLists.txt b/common_audio/signal_processing_library/main/source/CMakeLists.txt new file mode 100644 index 0000000000..1ab03170bd --- /dev/null +++ b/common_audio/signal_processing_library/main/source/CMakeLists.txt @@ -0,0 +1,11 @@ +project(splib) + +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../../applications/buildtools) +include(Macros) + +set(SPLIB_DIR ${PROJECT_SOURCE_DIR}) +include(splib.cmake) +include_directories(../../../released/interface) + +# Include the generic library module +include(Library) diff --git a/common_audio/signal_processing_library/main/source/add_affine_vector_to_vector.c b/common_audio/signal_processing_library/main/source/add_affine_vector_to_vector.c new file mode 100644 index 0000000000..e8649a1f5e --- /dev/null +++ b/common_audio/signal_processing_library/main/source/add_affine_vector_to_vector.c @@ -0,0 +1,26 @@ +/* + * add_affine_vector_to_vector.c + * + * This file contains the function WebRtcSpl_AddAffineVectorToVector(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/add_sat_w16.c b/common_audio/signal_processing_library/main/source/add_sat_w16.c new file mode 100644 index 0000000000..d103999b9b --- /dev/null +++ b/common_audio/signal_processing_library/main/source/add_sat_w16.c @@ -0,0 +1,34 @@ +/* + * 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_AddSatW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 var1, WebRtc_Word16 var2) +{ + WebRtc_Word32 s_sum = (WebRtc_Word32)var1 + (WebRtc_Word32)var2; + + if (s_sum > WEBRTC_SPL_WORD16_MAX) + s_sum = WEBRTC_SPL_WORD16_MAX; + else if (s_sum < WEBRTC_SPL_WORD16_MIN) + s_sum = WEBRTC_SPL_WORD16_MIN; + + return (WebRtc_Word16)s_sum; +} + +#endif diff --git a/common_audio/signal_processing_library/main/source/add_sat_w32.c b/common_audio/signal_processing_library/main/source/add_sat_w32.c new file mode 100644 index 0000000000..6d83e75bfd --- /dev/null +++ b/common_audio/signal_processing_library/main/source/add_sat_w32.c @@ -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 file contains the function WebRtcSpl_AddSatW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 var1, WebRtc_Word32 var2) +{ + WebRtc_Word32 l_sum; + + // perform long addition + l_sum = var1 + var2; + + // check for under or overflow + if (WEBRTC_SPL_IS_NEG(var1)) + { + if (WEBRTC_SPL_IS_NEG(var2) && !WEBRTC_SPL_IS_NEG(l_sum)) + { + l_sum = (WebRtc_Word32)0x80000000; + } + } else + { + if (!WEBRTC_SPL_IS_NEG(var2) && WEBRTC_SPL_IS_NEG(l_sum)) + { + l_sum = (WebRtc_Word32)0x7FFFFFFF; + } + } + + return l_sum; +} + +#endif diff --git a/common_audio/signal_processing_library/main/source/add_vectors_and_shift.c b/common_audio/signal_processing_library/main/source/add_vectors_and_shift.c new file mode 100644 index 0000000000..c895e415e1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/add_vectors_and_shift.c @@ -0,0 +1,23 @@ +/* + * add_vectors_and_shift.c + * + * This file contains the function WebRtcSpl_AddVectorsAndShift(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/affine_transform_vector.c b/common_audio/signal_processing_library/main/source/affine_transform_vector.c new file mode 100644 index 0000000000..b9f07f1972 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/affine_transform_vector.c @@ -0,0 +1,26 @@ +/* + * affine_transform_vector.c + * + * This file contains the function WebRtcSpl_AffineTransformVector(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_AffineTransformVector(WebRtc_Word16 *out, WebRtc_Word16 *in, + WebRtc_Word16 gain, WebRtc_Word32 constAdd, + WebRtc_Word16 Rshifts, int length) +{ + WebRtc_Word16 *inPtr; + WebRtc_Word16 *outPtr; + int i; + + inPtr = in; + outPtr = out; + for (i = 0; i < length; i++) + { + (*outPtr++) = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16((*inPtr++), gain) + + (WebRtc_Word32)constAdd) >> Rshifts); + } +} diff --git a/common_audio/signal_processing_library/main/source/array_shift_w16.c b/common_audio/signal_processing_library/main/source/array_shift_w16.c new file mode 100644 index 0000000000..132cc080f3 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/array_shift_w16.c @@ -0,0 +1,31 @@ +/* + * array_shift_w16.c + * + * This file contains the function WebRtcSpl_ArrayShiftW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ArrayShiftW16(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)); + } + } +} diff --git a/common_audio/signal_processing_library/main/source/array_shift_w32.c b/common_audio/signal_processing_library/main/source/array_shift_w32.c new file mode 100644 index 0000000000..4c562497c8 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/array_shift_w32.c @@ -0,0 +1,31 @@ +/* + * array_shift_w32.c + * + * This file contains the function WebRtcSpl_ArrayShiftW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ArrayShiftW32(WebRtc_Word32 *out_vector, // (o) Output vector + WebRtc_Word16 vector_length, // (i) Number of samples + G_CONST WebRtc_Word32 *in_vector, // (i) Input vector + WebRtc_Word16 right_shifts) // (i) Number of 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)); + } + } +} diff --git a/common_audio/signal_processing_library/main/source/array_shift_w32_to_w16.c b/common_audio/signal_processing_library/main/source/array_shift_w32_to_w16.c new file mode 100644 index 0000000000..2cdc61ff48 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/array_shift_w32_to_w16.c @@ -0,0 +1,32 @@ +/* + * array_shift_w32_to_w16.c + * + * This file contains the function WebRtcSpl_ArrayShiftW32ToW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ArrayShiftW32ToW16(WebRtc_Word16 *res, // (o) Output vector + WebRtc_Word16 length, // (i) Number of samples + G_CONST WebRtc_Word32 *in, // (i) Input vector + WebRtc_Word16 right_shifts) // (i) Number of 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); + } + } +} diff --git a/common_audio/signal_processing_library/main/source/auto_corr_to_k_returns_pred_gain.c b/common_audio/signal_processing_library/main/source/auto_corr_to_k_returns_pred_gain.c new file mode 100644 index 0000000000..ca3897846d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/auto_corr_to_k_returns_pred_gain.c @@ -0,0 +1,111 @@ +/* + * auto_corr_to_k_returns_pred_gain.c + * + * This file contains the function WebRtcSpl_AutoCorrToKReturnsPredGain(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_AutoCorrToKReturnsPredGain(G_CONST WebRtc_Word32 *R, int use_order, + WebRtc_Word16 *K) +{ + int i, n; + WebRtc_Word16 tmp, err, gain; + 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]; + + /* In the special case of R[0]==0, return K[i]=0. */ + /* This should never happen; right? It doesn't */ + /* if called from the LPC... */ + /* + if( *R==0 ) + { + for( i=use_order; i--; *K++ = 0 ); + return; + } + */ + + /* 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 0; + } + + // 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; + } + + /* 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 ); + err = *pptr; + pptr++; + + /* Last iteration; don't do Schur recursion. */ + if (n == use_order) + { + gain = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)ACF[0], err); + tmp = (14 - WebRtcSpl_NormW16(gain)) >> 1; + return tmp; + } + + 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++; + } + } + return 0; +} diff --git a/common_audio/signal_processing_library/main/source/auto_corr_to_refl_coef.c b/common_audio/signal_processing_library/main/source/auto_corr_to_refl_coef.c new file mode 100644 index 0000000000..b7e885898a --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/auto_correlation.c b/common_audio/signal_processing_library/main/source/auto_correlation.c new file mode 100644 index 0000000000..a00fde4bc3 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/auto_correlation.c @@ -0,0 +1,141 @@ +/* + * 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_AutoCorrelation(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +int WebRtcSpl_AutoCorrelation(G_CONST WebRtc_Word16* in_vector, + int in_vector_length, + int order, + WebRtc_Word32* result, + int* scale) +{ + WebRtc_Word32 sum; + int i, j; + WebRtc_Word16 smax; // Sample max + G_CONST WebRtc_Word16* xptr1; + G_CONST WebRtc_Word16* xptr2; + WebRtc_Word32* resultptr; + int scaling = 0; + +#ifdef _ARM_OPT_ +#pragma message("NOTE: _ARM_OPT_ optimizations are used") + WebRtc_Word16 loops4; +#endif + + if (order < 0) + order = in_vector_length; + + // Find the max. sample + 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 + { + int nbits = WebRtcSpl_GetSizeInBits(in_vector_length); // # of bits in the sum loop + int t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax)); // # of bits to normalize smax + + if (t > nbits) + { + scaling = 0; + } else + { + scaling = nbits - t; + } + + } + + resultptr = result; + + // Perform the actual correlation calculation + for (i = 0; i < order + 1; i++) + { + int loops = (in_vector_length - i); + sum = 0; + xptr1 = in_vector; + xptr2 = &in_vector[i]; +#ifndef _ARM_OPT_ + for (j = loops; j > 0; j--) + { + sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1++, *xptr2++, scaling); + } +#else + loops4 = (loops >> 2) << 2; + + if (scaling == 0) + { + for (j = 0; j < loops4; j = j + 4) + { + sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2); + xptr1++; + xptr2++; + sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2); + xptr1++; + xptr2++; + sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2); + xptr1++; + xptr2++; + sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2); + xptr1++; + xptr2++; + } + + for (j = loops4; j < loops; j++) + { + sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2); + xptr1++; + xptr2++; + } + } + else + { + for (j = 0; j < loops4; j = j + 4) + { + sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling); + xptr1++; + xptr2++; + sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling); + xptr1++; + xptr2++; + sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling); + xptr1++; + xptr2++; + sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling); + xptr1++; + xptr2++; + } + + for (j = loops4; j < loops; j++) + { + sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling); + xptr1++; + xptr2++; + } + } + +#endif + *resultptr++ = sum; + } + + *scale = scaling; + + return order + 1; +} diff --git a/common_audio/signal_processing_library/main/source/cat_arrays_u8.c b/common_audio/signal_processing_library/main/source/cat_arrays_u8.c new file mode 100644 index 0000000000..4398212ab1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/cat_arrays_u8.c @@ -0,0 +1,36 @@ +/* + */ +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CatArraysU8(G_CONST unsigned char *vector1, WebRtc_Word16 len1, + G_CONST unsigned char *vector2, WebRtc_Word16 len2, + unsigned char *outvector, WebRtc_Word16 maxlen) +{ +#ifdef _DEBUG + if (maxlen < len1 + len2) + { + printf("chcatarr : out vector is too short\n"); + exit(0); + } + if ((len1 != len2) || (len2 < 0)) + { + printf("chcatarr : input vectors are not of equal length\n"); + exit(0); + } +#endif + /* Unused input variable */ + maxlen = maxlen; + + /* Concat the two vectors */ + /* A unsigned char is bytes long */ + WEBRTC_SPL_MEMCPY_W8(outvector, vector1, len1); + WEBRTC_SPL_MEMCPY_W8(&outvector[len1], vector2, len2); + + return (len1 + len2); +} diff --git a/common_audio/signal_processing_library/main/source/cat_arrays_w16.c b/common_audio/signal_processing_library/main/source/cat_arrays_w16.c new file mode 100644 index 0000000000..89008691a7 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/cat_arrays_w16.c @@ -0,0 +1,36 @@ +/* + */ +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CatArraysW16(G_CONST WebRtc_Word16 *vector1, WebRtc_Word16 len1, + G_CONST WebRtc_Word16 *vector2, WebRtc_Word16 len2, + WebRtc_Word16 *outvector, WebRtc_Word16 maxlen) +{ +#ifdef _DEBUG + if (maxlen < len1 + len2) + { + printf("w16catarr : out vector is too short\n"); + exit(0); + } + if ((len1 != len2) || (len2 < 0)) + { + printf("w16catarr : input vectors are not of equal length\n"); + exit(0); + } +#endif + /* Unused input variable */ + maxlen = maxlen; + + /* Concat the two vectors */ + /* A word16 is 2 bytes long */ + WEBRTC_SPL_MEMCPY_W16(outvector, vector1, len1); + WEBRTC_SPL_MEMCPY_W16(&outvector[len1], vector2, len2); + + return (len1 + len2); +} diff --git a/common_audio/signal_processing_library/main/source/cat_arrays_w32.c b/common_audio/signal_processing_library/main/source/cat_arrays_w32.c new file mode 100644 index 0000000000..6395f9753b --- /dev/null +++ b/common_audio/signal_processing_library/main/source/cat_arrays_w32.c @@ -0,0 +1,38 @@ +/* + */ + +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CatArraysW32(G_CONST WebRtc_Word32 *vector1, WebRtc_Word16 len1, + G_CONST WebRtc_Word32 *vector2, WebRtc_Word16 len2, + WebRtc_Word32 *outvector, WebRtc_Word16 maxlen) +{ +#ifdef _DEBUG + if (maxlen < len1 + len2) + { + printf("w32catarr : out vector is too short\n"); + exit(0); + } + if ((len1 != len2) || (len2 < 0)) + { + printf("w32catarr : input vectors are not of equal length\n"); + exit(0); + } +#endif + + /* Unused input variable */ + maxlen = maxlen; + + /* Concat the two vectors */ + /* A word32 is 4 bytes long */ + WEBRTC_SPL_MEMCPY_W32(outvector, vector1, len1); + WEBRTC_SPL_MEMCPY_W32(&outvector[len1], vector2, len2); + + return (len1 + len2); +} diff --git a/common_audio/signal_processing_library/main/source/complex_bit_reverse.c b/common_audio/signal_processing_library/main/source/complex_bit_reverse.c new file mode 100644 index 0000000000..85c76f8283 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/complex_bit_reverse.c @@ -0,0 +1,51 @@ +/* + * 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_ComplexBitReverse(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ComplexBitReverse(WebRtc_Word16 frfi[], int stages) +{ + int mr, nn, n, l, m; + WebRtc_Word16 tr, ti; + + n = 1 << stages; + + mr = 0; + nn = n - 1; + + // decimation in time - re-order data + for (m = 1; m <= nn; ++m) + { + l = n; + do + { + l >>= 1; + } while (mr + l > nn); + mr = (mr & (l - 1)) + l; + + if (mr <= m) + continue; + + tr = frfi[2 * m]; + frfi[2 * m] = frfi[2 * mr]; + frfi[2 * mr] = tr; + + ti = frfi[2 * m + 1]; + frfi[2 * m + 1] = frfi[2 * mr + 1]; + frfi[2 * mr + 1] = ti; + } +} diff --git a/common_audio/signal_processing_library/main/source/complex_fft.c b/common_audio/signal_processing_library/main/source/complex_fft.c new file mode 100644 index 0000000000..b6f0c4e1bb --- /dev/null +++ b/common_audio/signal_processing_library/main/source/complex_fft.c @@ -0,0 +1,140 @@ +/* + * 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 + +#if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT) +extern "C" int FFT_4OFQ14(void *src, void *dest, int NC, int shift); + +// For detailed description of the fft functions, check the readme files in fft_ARM9E folder. +int WebRtcSpl_ComplexFFT2(WebRtc_Word16 frfi[], WebRtc_Word16 frfiOut[], int stages, int mode) +{ + return FFT_4OFQ14(frfi, frfiOut, 1 << stages, 0); +} +#endif + +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 WebRtcSpl_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 WebRtcSpl_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 + * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input + * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 + */ + wr = WebRtcSpl_kSinTable1024[j + 256]; + wi = -WebRtcSpl_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 + * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input + * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 + */ + wr = WebRtcSpl_kSinTable1024[j + 256]; + wi = -WebRtcSpl_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]) + CFFTRND), + 15 - CFFTSFT); + + ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) + + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND), 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; +} diff --git a/common_audio/signal_processing_library/main/source/complex_ifft.c b/common_audio/signal_processing_library/main/source/complex_ifft.c new file mode 100644 index 0000000000..184b8de5be --- /dev/null +++ b/common_audio/signal_processing_library/main/source/complex_ifft.c @@ -0,0 +1,155 @@ +/* + * 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_ComplexIFFT(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#define CIFFTSFT 14 +#define CIFFTRND 1 + +#if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT) +extern "C" int FFT_4OIQ14(void *src, void *dest, int NC, int shift); + +// For detailed description of the fft functions, check the readme files in fft_ARM9E folder. +int WebRtcSpl_ComplexIFFT2(WebRtc_Word16 frfi[], WebRtc_Word16 frfiOut[], int stages, int mode) +{ + FFT_4OIQ14(frfi, frfiOut, 1 << stages, 0); + return 0; +} +#endif + +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 WebRtcSpl_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 WebRtcSpl_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 + * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input + * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 + */ + wr = WebRtcSpl_kSinTable1024[j + 256]; + wi = WebRtcSpl_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 + * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input + * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 + */ + wr = WebRtcSpl_kSinTable1024[j + 256]; + wi = WebRtcSpl_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) + CIFFTRND), + 15 - CIFFTSFT); + + 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) + + CIFFTRND), 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_library/main/source/copy_from_begin_u8.c b/common_audio/signal_processing_library/main/source/copy_from_begin_u8.c new file mode 100644 index 0000000000..ed2165b5ce --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_begin_u8.c @@ -0,0 +1,45 @@ +/* + * copy_from_begin_u8.c + * + * This file contains the function WebRtcSpl_CopyFromBeginU8(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromBeginU8(G_CONST unsigned char *vector_in, + WebRtc_Word16 length, + WebRtc_Word16 samples, + unsigned char *vector_out, + WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples) + { + printf("CopyFromBeginU8 : vector_in shorter than requested length\n"); + exit(0); + } + if (max_length < samples) + { + printf("CopyFromBeginU8 : vector_out shorter than requested length\n"); + exit(0); + } +#endif + + // Unused input variable + max_length = max_length; + length = length; + + // Copy the first of the input vector to vector_out + // A unsigned char is 1 bytes long + WEBRTC_SPL_MEMCPY_W8(vector_out, vector_in, samples); + + return samples; +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_begin_w16.c b/common_audio/signal_processing_library/main/source/copy_from_begin_w16.c new file mode 100644 index 0000000000..1f3f2f10c1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_begin_w16.c @@ -0,0 +1,44 @@ +/* + * copy_from_begin_w16.c + * + * This file contains the function WebRtcSpl_CopyFromBeginW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromBeginW16(G_CONST WebRtc_Word16 *vector_in, + WebRtc_Word16 length, + WebRtc_Word16 samples, + WebRtc_Word16 *vector_out, + WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples) + { + printf(" CopyFromBeginW16 : vector_in shorter than requested length\n"); + exit(0); + } + if (max_length < samples) + { + printf(" CopyFromBeginW16 : vector_out shorter than requested length\n"); + exit(0); + } +#endif + // Unused input variable + length = length; + max_length = max_length; + + // Copy the first of the input vector to vector_out + // A WebRtc_Word16 is 2 bytes long + WEBRTC_SPL_MEMCPY_W16(vector_out, vector_in, samples); + + return samples; +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_begin_w32.c b/common_audio/signal_processing_library/main/source/copy_from_begin_w32.c new file mode 100644 index 0000000000..68fb5ed5ee --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_begin_w32.c @@ -0,0 +1,45 @@ +/* + * copy_from_begin_w32.c + * + * This file contains the function WebRtcSpl_CopyFromBeginW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromBeginW32(G_CONST WebRtc_Word32 *vector_in, + WebRtc_Word16 length, + WebRtc_Word16 samples, + WebRtc_Word32 *vector_out, + WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples) + { + printf(" CopyFromBeginW32 : invector shorter than requested length\n"); + exit(0); + } + if (max_length < samples) + { + printf(" CopyFromBeginW32 : outvector shorter than requested length\n"); + exit(0); + } +#endif + + // Unused input variable + max_length = max_length; + length = length; + + // Copy the first of the input vector to vector_out + // A WebRtc_Word32 is 4 bytes long + WEBRTC_SPL_MEMCPY_W32(vector_out, vector_in, samples); + + return samples; +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_end_u8.c b/common_audio/signal_processing_library/main/source/copy_from_end_u8.c new file mode 100644 index 0000000000..4a7c0960c9 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_end_u8.c @@ -0,0 +1,45 @@ +/* + * copy_from_end_u8.c + * + * This file contains the function WebRtcSpl_CopyFromEndU8(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +WebRtc_Word16 WebRtcSpl_CopyFromEndU8(G_CONST unsigned char *vector_in, + WebRtc_Word16 length, + WebRtc_Word16 samples, + unsigned char *vector_out, + WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples) + { + printf("CopyFromEndU8 : vector_in shorter than requested length\n"); + exit(0); + } + if (max_length < samples) + { + printf("CopyFromEndU8 : vector_out shorter than requested length\n"); + exit(0); + } +#endif + + // Unused input variable + max_length = max_length; + + // Copy the last of the input vector to vector_out + // An unsigned char is 1 bytes long + WEBRTC_SPL_MEMCPY_W8(vector_out, &vector_in[length - samples], samples); + + return samples; +} + diff --git a/common_audio/signal_processing_library/main/source/copy_from_end_w16.c b/common_audio/signal_processing_library/main/source/copy_from_end_w16.c new file mode 100644 index 0000000000..855883caec --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_end_w16.c @@ -0,0 +1,34 @@ +/* + * 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_CopyFromEndW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromEndW16(G_CONST WebRtc_Word16 *vector_in, + WebRtc_Word16 length, + WebRtc_Word16 samples, + WebRtc_Word16 *vector_out, + WebRtc_Word16 max_length) +{ + // Unused input variable + max_length = max_length; + + // Copy the last of the input vector to vector_out + WEBRTC_SPL_MEMCPY_W16(vector_out, &vector_in[length - samples], samples); + + return samples; +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_end_w32.c b/common_audio/signal_processing_library/main/source/copy_from_end_w32.c new file mode 100644 index 0000000000..a561aa6f7d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_end_w32.c @@ -0,0 +1,44 @@ +/* + * copy_from_end_w32.c + * + * This file contains the function WebRtcSpl_CopyFromEndW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +WebRtc_Word16 WebRtcSpl_CopyFromEndW32(G_CONST WebRtc_Word32 *vector_in, + WebRtc_Word16 length, + WebRtc_Word16 samples, + WebRtc_Word32 *vector_out, + WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples) + { + printf("CopyFromEndW32 : vector_in shorter than requested length\n"); + exit(0); + } + if (max_length < samples) + { + printf("CopyFromEndW32 : vector_out shorter than requested length\n"); + exit(0); + } +#endif + + // Unused input variable + max_length = max_length; + + // Copy the last of the input vector to vector_out + // A WebRtc_Word32 is 4 bytes long + WEBRTC_SPL_MEMCPY_W32(vector_out, &vector_in[length - samples], samples); + + return samples; +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_mid_u8.c b/common_audio/signal_processing_library/main/source/copy_from_mid_u8.c new file mode 100644 index 0000000000..278459cb61 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_mid_u8.c @@ -0,0 +1,42 @@ +/* + * copy_from_mid_u8.c + * + * This file contains the function WebRtcSpl_CopyFromMidU8(). + * The description header can be found in signal_processing_library.h + * + */ + +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromMidU8(unsigned char *vector_in, WebRtc_Word16 length, + WebRtc_Word16 startpos, WebRtc_Word16 samples, + unsigned char *vector_out, WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples + startpos) + { + printf("chmid : invector copy out of bounds\n"); + exit(0); + } + if (max_length < samples) + { + printf("chmid : outvector shorter than requested length\n"); + exit(0); + } +#endif + /* Unused input variable */ + max_length = max_length; + length = length; + + /* Copy the from pos of the input vector to vector_out */ + /* A unsigned char is 1 bytes long */ + WEBRTC_SPL_MEMCPY_W8(vector_out,&vector_in[startpos],samples); + + return (samples); +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_mid_w16.c b/common_audio/signal_processing_library/main/source/copy_from_mid_w16.c new file mode 100644 index 0000000000..45da2da675 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_mid_w16.c @@ -0,0 +1,36 @@ +/* + */ +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromMidW16(G_CONST WebRtc_Word16 *vector_in, WebRtc_Word16 length, + WebRtc_Word16 startpos, WebRtc_Word16 samples, + WebRtc_Word16 *vector_out, WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples + startpos) + { + printf("w16mid : invector copy out of bounds\n"); + exit(0); + } + if (max_length < samples) + { + printf("w16mid : outvector shorter than requested length\n"); + exit(0); + } +#endif + /* Unused input variable */ + length = length; + max_length = max_length; + + /* Copy the from pos of the input vector to vector_out */ + /* A WebRtc_Word16 is 2 bytes long */ + WEBRTC_SPL_MEMCPY_W16(vector_out, &vector_in[startpos], samples); + + return (samples); +} diff --git a/common_audio/signal_processing_library/main/source/copy_from_mid_w32.c b/common_audio/signal_processing_library/main/source/copy_from_mid_w32.c new file mode 100644 index 0000000000..a3a43e9155 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/copy_from_mid_w32.c @@ -0,0 +1,37 @@ +/* + */ +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_CopyFromMidW32(G_CONST WebRtc_Word32 *vector_in, WebRtc_Word16 length, + WebRtc_Word16 startpos, WebRtc_Word16 samples, + WebRtc_Word32 *vector_out, WebRtc_Word16 max_length) +{ +#ifdef _DEBUG + if (length < samples + startpos) + { + printf("w32mid : invector copy out of bounds\n"); + exit(0); + } + if (max_length < samples) + { + printf("w32mid : outvector shorter than requested length\n"); + exit(0); + } +#endif + + /* Unused input variable */ + max_length = max_length; + length = length; + + /* Copy the from pos of the input vector to vector_out */ + /* A WebRtc_Word32 is 4 bytes long */ + WEBRTC_SPL_MEMCPY_W32(vector_out,&vector_in[startpos],samples); + + return (samples); +} diff --git a/common_audio/signal_processing_library/main/source/copy_set_operations.c b/common_audio/signal_processing_library/main/source/copy_set_operations.c new file mode 100644 index 0000000000..8247337754 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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 +#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 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_library/main/source/cos_table.c b/common_audio/signal_processing_library/main/source/cos_table.c new file mode 100644 index 0000000000..7dba4b046b --- /dev/null +++ b/common_audio/signal_processing_library/main/source/cos_table.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 360 degree cos table. + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_kCosTable[] = { + 8192, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112, + 8091, 8067, 8041, 8012, 7982, 7948, 7912, 7874, 7834, + 7791, 7745, 7697, 7647, 7595, 7540, 7483, 7424, 7362, + 7299, 7233, 7164, 7094, 7021, 6947, 6870, 6791, 6710, + 6627, 6542, 6455, 6366, 6275, 6182, 6087, 5991, 5892, + 5792, 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, + 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 3845, + 3719, 3591, 3462, 3331, 3200, 3068, 2935, 2801, 2667, + 2531, 2395, 2258, 2120, 1981, 1842, 1703, 1563, 1422, + 1281, 1140, 998, 856, 713, 571, 428, 285, 142, + 0, -142, -285, -428, -571, -713, -856, -998, -1140, + -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395, + -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591, + -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698, + -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690, + -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542, + -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233, + -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745, + -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067, + -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190, + -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112, + -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834, + -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362, + -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710, + -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892, + -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930, + -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845, + -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667, + -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, + -1281, -1140, -998, -856, -713, -571, -428, -285, -142, + 0, 142, 285, 428, 571, 713, 856, 998, 1140, + 1281, 1422, 1563, 1703, 1842, 1981, 2120, 2258, 2395, + 2531, 2667, 2801, 2935, 3068, 3200, 3331, 3462, 3591, + 3719, 3845, 3971, 4095, 4219, 4341, 4461, 4580, 4698, + 4815, 4930, 5043, 5155, 5265, 5374, 5481, 5586, 5690, + 5792, 5892, 5991, 6087, 6182, 6275, 6366, 6455, 6542, + 6627, 6710, 6791, 6870, 6947, 7021, 7094, 7164, 7233, + 7299, 7362, 7424, 7483, 7540, 7595, 7647, 7697, 7745, + 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 8067, + 8091, 8112, 8130, 8147, 8160, 8172, 8180, 8187, 8190 +}; diff --git a/common_audio/signal_processing_library/main/source/cross_correlation.c b/common_audio/signal_processing_library/main/source/cross_correlation.c new file mode 100644 index 0000000000..1133d0933d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/cross_correlation.c @@ -0,0 +1,267 @@ +/* + * 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_CrossCorrelation(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_CrossCorrelation(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, j; + WebRtc_Word16* seq1Ptr; + WebRtc_Word16* seq2Ptr; + WebRtc_Word32* CrossCorrPtr; + +#ifdef _XSCALE_OPT_ + +#ifdef _WIN32 +#pragma message("NOTE: _XSCALE_OPT_ optimizations are used (overrides _ARM_OPT_ and requires /QRxscale compiler flag)") +#endif + + __int64 macc40; + + int iseq1[250]; + int iseq2[250]; + int iseq3[250]; + int * iseq1Ptr; + int * iseq2Ptr; + int * iseq3Ptr; + int len, i_len; + + seq1Ptr = seq1; + iseq1Ptr = iseq1; + for(i = 0; i < ((dim_seq + 1) >> 1); i++) + { + *iseq1Ptr = (unsigned short)*seq1Ptr++; + *iseq1Ptr++ |= (WebRtc_Word32)*seq1Ptr++ << 16; + + } + + if(dim_seq%2) + { + *(iseq1Ptr-1) &= 0x0000ffff; + } + *iseq1Ptr = 0; + iseq1Ptr++; + *iseq1Ptr = 0; + iseq1Ptr++; + *iseq1Ptr = 0; + + if(step_seq2 < 0) + { + seq2Ptr = seq2 - dim_cross_correlation + 1; + CrossCorrPtr = &cross_correlation[dim_cross_correlation - 1]; + } + else + { + seq2Ptr = seq2; + CrossCorrPtr = cross_correlation; + } + + len = dim_seq + dim_cross_correlation - 1; + i_len = (len + 1) >> 1; + iseq2Ptr = iseq2; + + iseq3Ptr = iseq3; + for(i = 0; i < i_len; i++) + { + *iseq2Ptr = (unsigned short)*seq2Ptr++; + *iseq3Ptr = (unsigned short)*seq2Ptr; + *iseq2Ptr++ |= (WebRtc_Word32)*seq2Ptr++ << 16; + *iseq3Ptr++ |= (WebRtc_Word32)*seq2Ptr << 16; + } + + if(len % 2) + { + iseq2[i_len - 1] &= 0x0000ffff; + iseq3[i_len - 1] = 0; + } + else + iseq3[i_len - 1] &= 0x0000ffff; + + iseq2[i_len] = 0; + iseq3[i_len] = 0; + iseq2[i_len + 1] = 0; + iseq3[i_len + 1] = 0; + iseq2[i_len + 2] = 0; + iseq3[i_len + 2] = 0; + + // Set pointer to start value + iseq2Ptr = iseq2; + iseq3Ptr = iseq3; + + i_len = (dim_seq + 7) >> 3; + for (i = 0; i < dim_cross_correlation; i++) + { + + iseq1Ptr = iseq1; + + macc40 = 0; + + _WriteCoProcessor(macc40, 0); + + if((i & 1)) + { + iseq3Ptr = iseq3 + (i >> 1); + for (j = i_len; j > 0; j--) + { + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++); + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++); + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++); + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++); + } + } + else + { + iseq2Ptr = iseq2 + (i >> 1); + for (j = i_len; j > 0; j--) + { + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++); + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++); + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++); + _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++); + } + + } + + macc40 = _ReadCoProcessor(0); + *CrossCorrPtr = (WebRtc_Word32)(macc40 >> right_shifts); + CrossCorrPtr += step_seq2; + } +#else // #ifdef _XSCALE_OPT_ +#ifdef _ARM_OPT_ + WebRtc_Word16 dim_seq8 = (dim_seq >> 3) << 3; +#endif + + CrossCorrPtr = cross_correlation; + + for (i = 0; i < dim_cross_correlation; i++) + { + // Set the pointer to the static vector, set the pointer to the sliding vector + // and initialize cross_correlation + seq1Ptr = seq1; + seq2Ptr = seq2 + (step_seq2 * i); + (*CrossCorrPtr) = 0; + +#ifndef _ARM_OPT_ +#ifdef _WIN32 +#pragma message("NOTE: default implementation is used") +#endif + // Perform the cross correlation + for (j = 0; j < dim_seq; j++) + { + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), right_shifts); + seq1Ptr++; + seq2Ptr++; + } +#else +#ifdef _WIN32 +#pragma message("NOTE: _ARM_OPT_ optimizations are used") +#endif + if (right_shifts == 0) + { + // Perform the optimized cross correlation + for (j = 0; j < dim_seq8; j = j + 8) + { + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + } + + for (j = dim_seq8; j < dim_seq; j++) + { + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr)); + seq1Ptr++; + seq2Ptr++; + } + } + else // right_shifts != 0 + + { + // Perform the optimized cross correlation + for (j = 0; j < dim_seq8; j = j + 8) + { + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + } + + for (j = dim_seq8; j < dim_seq; j++) + { + (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), + right_shifts); + seq1Ptr++; + seq2Ptr++; + } + } +#endif + CrossCorrPtr++; + } +#endif +} diff --git a/common_audio/signal_processing_library/main/source/div_result_in_q31.c b/common_audio/signal_processing_library/main/source/div_result_in_q31.c new file mode 100644 index 0000000000..04224d6f4c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/div_result_in_q31.c @@ -0,0 +1,48 @@ +/* + * div_result_in_q31.c + * + * This file contains the function WebRtcSpl_DivResultInQ31(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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_den <<= 1; + L_num <<= 1; + if (L_num >= L_den) + { + L_num -= L_den; + div++; + } + } + if (change_sign == 1) + { + div = -div; + } + return div; +} diff --git a/common_audio/signal_processing_library/main/source/div_u32_u16.c b/common_audio/signal_processing_library/main/source/div_u32_u16.c new file mode 100644 index 0000000000..5d03f40132 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/div_u32_u16.c @@ -0,0 +1,21 @@ +/* + * div_u32_u16.c + * + * This file contains the function WebRtcSpl_DivU32U16(). + * 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); + } +} diff --git a/common_audio/signal_processing_library/main/source/div_w32_hi_low.c b/common_audio/signal_processing_library/main/source/div_w32_hi_low.c new file mode 100644 index 0000000000..f2fe277af2 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/div_w32_hi_low.c @@ -0,0 +1,55 @@ +/* + * div_w32_hi_low.c + * + * This file contains the function WebRtcSpl_DivW32HiLow(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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_library/main/source/div_w32_w16.c b/common_audio/signal_processing_library/main/source/div_w32_w16.c new file mode 100644 index 0000000000..3184fa733e --- /dev/null +++ b/common_audio/signal_processing_library/main/source/div_w32_w16.c @@ -0,0 +1,21 @@ +/* + * div_w32_w16.c + * + * This file contains the function WebRtcSpl_DivW32W16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/div_w32_w16_res_w16.c b/common_audio/signal_processing_library/main/source/div_w32_w16_res_w16.c new file mode 100644 index 0000000000..0ec96c1b5d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/div_w32_w16_res_w16.c @@ -0,0 +1,21 @@ +/* + * div_w32_w16_res_w16.c + * + * This file contains the function WebRtcSpl_DivW32W16ResW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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; + } +} diff --git a/common_audio/signal_processing_library/main/source/division_operations.c b/common_audio/signal_processing_library/main/source/division_operations.c new file mode 100644 index 0000000000..b143373a2f --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/dot_product.c b/common_audio/signal_processing_library/main/source/dot_product.c new file mode 100644 index 0000000000..a4da5c069d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/dot_product.c @@ -0,0 +1,23 @@ +/* + * dot_product.c + * + * This file contains the function WebRtcSpl_DotProduct(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word32 WebRtcSpl_DotProduct(WebRtc_Word16 *vector1, WebRtc_Word16 *vector2, int length) +{ + WebRtc_Word32 sum; + int i; + + sum = 0; + for (i = 0; i < length; i++) + { + sum += WEBRTC_SPL_MUL_16_16(*vector1++, *vector2++); + } + return sum; +} + diff --git a/common_audio/signal_processing_library/main/source/dot_product_with_scale.c b/common_audio/signal_processing_library/main/source/dot_product_with_scale.c new file mode 100644 index 0000000000..6e085fdb60 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/dot_product_with_scale.c @@ -0,0 +1,91 @@ +/* + * 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_DotProductWithScale(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16 *vector1, WebRtc_Word16 *vector2, + int length, int scaling) +{ + WebRtc_Word32 sum; + int i; +#ifdef _ARM_OPT_ +#pragma message("NOTE: _ARM_OPT_ optimizations are used") + WebRtc_Word16 len4 = (length >> 2) << 2; +#endif + + sum = 0; + +#ifndef _ARM_OPT_ + for (i = 0; i < length; i++) + { + sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1++, *vector2++, scaling); + } +#else + if (scaling == 0) + { + for (i = 0; i < len4; i = i + 4) + { + sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2); + vector1++; + vector2++; + sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2); + vector1++; + vector2++; + sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2); + vector1++; + vector2++; + sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2); + vector1++; + vector2++; + } + + for (i = len4; i < length; i++) + { + sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2); + vector1++; + vector2++; + } + } + else + { + for (i = 0; i < len4; i = i + 4) + { + sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling); + vector1++; + vector2++; + sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling); + vector1++; + vector2++; + sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling); + vector1++; + vector2++; + sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling); + vector1++; + vector2++; + } + + for (i = len4; i < length; i++) + { + sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling); + vector1++; + vector2++; + } + } +#endif + + return sum; +} diff --git a/common_audio/signal_processing_library/main/source/downsample.c b/common_audio/signal_processing_library/main/source/downsample.c new file mode 100644 index 0000000000..1e7a0632d5 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/downsample.c @@ -0,0 +1,93 @@ +/* + * downsample.c + * + * This file contains the function WebRtcSpl_Downsample(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +int WebRtcSpl_Downsample(G_CONST WebRtc_Word16 *b, int b_length, + G_CONST WebRtc_Word16 *signal_in, int signal_length, + WebRtc_Word16 *state, int state_length, + WebRtc_Word16 *signal_downsampled, int max_length, int factor, + int delay) +{ + WebRtc_Word32 o; + int i, j, stop; + + WebRtc_Word16 *signal_downsampled_ptr = signal_downsampled; + G_CONST WebRtc_Word16 *b_ptr; + G_CONST WebRtc_Word16 *signal_in_ptr; + WebRtc_Word16 *state_ptr; + WebRtc_Word16 inc = 1 << factor; + + // Unused input variable + max_length = max_length; + + for (i = delay; i < signal_length; i += inc) + { + b_ptr = &b[0]; + signal_in_ptr = &signal_in[i]; + state_ptr = &state[state_length - 1]; + + o = (WebRtc_Word32)0; + stop = (i < b_length) ? i + 1 : b_length; + + for (j = 0; j < stop; j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *signal_in_ptr--); + } + for (j = i + 1; j < b_length; j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + } + + // If output is higher than 32768, saturate it. Same with negative side + // 2^27 = 134217728, which corresponds to 32768 + if (o < (WebRtc_Word32)-134217728) + o = (WebRtc_Word32)-134217728; + + if (o > (WebRtc_Word32)(134217727 - 2048)) + o = (WebRtc_Word32)(134217727 - 2048); + + *signal_downsampled_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); //Q12 ops + } + + // Get the last delay part. + for (i = ((signal_length >> factor) << factor) + inc; i < signal_length + delay; i += inc) + { + o = 0; + if (i < signal_length) + { + b_ptr = &b[0]; + signal_in_ptr = &signal_in[i]; + for (j = 0; j < b_length; j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *signal_in_ptr--); + } + } else + { + b_ptr = &b[i - signal_length]; + signal_in_ptr = &signal_in[signal_length - 1]; + for (j = 0; j < b_length - (i - signal_length); j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *signal_in_ptr--); + } + } + + /* If output is higher than 32768, saturate it. Same with negative side + 2^27 = 134217728, which corresponds to 32768 + */ + if (o < (WebRtc_Word32)-134217728) + o = (WebRtc_Word32)-134217728; + + if (o > (WebRtc_Word32)(134217727 - 2048)) + o = (WebRtc_Word32)(134217727 - 2048); + + *signal_downsampled_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); //Q12 ops + } + + return (signal_length >> factor); +} diff --git a/common_audio/signal_processing_library/main/source/downsample_fast.c b/common_audio/signal_processing_library/main/source/downsample_fast.c new file mode 100644 index 0000000000..93382751b3 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/downsample_fast.c @@ -0,0 +1,59 @@ +/* + * 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_DownsampleFast(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +int WebRtcSpl_DownsampleFast(WebRtc_Word16 *in_ptr, WebRtc_Word16 in_length, + WebRtc_Word16 *out_ptr, WebRtc_Word16 out_length, + WebRtc_Word16 *B, WebRtc_Word16 B_length, WebRtc_Word16 factor, + WebRtc_Word16 delay) +{ + WebRtc_Word32 o; + int i, j; + + WebRtc_Word16 *downsampled_ptr = out_ptr; + WebRtc_Word16 *b_ptr; + WebRtc_Word16 *x_ptr; + WebRtc_Word16 endpos = delay + + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(factor, (out_length - 1)) + 1; + + if (in_length < endpos) + { + return -1; + } + + for (i = delay; i < endpos; i += factor) + { + b_ptr = &B[0]; + x_ptr = &in_ptr[i]; + + o = (WebRtc_Word32)2048; // Round val + + for (j = 0; j < B_length; j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + } + + o = WEBRTC_SPL_RSHIFT_W32(o, 12); + + // If output is higher than 32768, saturate it. Same with negative side + + *downsampled_ptr++ = (WebRtc_Word16)WEBRTC_SPL_SAT(32767, o, -32768); + } + + return 0; +} diff --git a/common_audio/signal_processing_library/main/source/elementwise_vector_mult.c b/common_audio/signal_processing_library/main/source/elementwise_vector_mult.c new file mode 100644 index 0000000000..f48bc69f2c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/elementwise_vector_mult.c @@ -0,0 +1,24 @@ +/* + * elementwise_vector_mult.c + * + * This file contains the function WebRtcSpl_ElementwiseVectorMult(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/energy.c b/common_audio/signal_processing_library/main/source/energy.c new file mode 100644 index 0000000000..e8fdf94e03 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/fft_ARM9E/FFT_4OFQ14.s b/common_audio/signal_processing_library/main/source/fft_ARM9E/FFT_4OFQ14.s new file mode 100644 index 0000000000..74b2392864 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/FFT_4OFQ14.s @@ -0,0 +1,51 @@ +;// Optimised ARM assembler multi-radix FFT + INCLUDE fft_main_forward.h + + + MACRO + GENERATE_FFT_FUNCTION $flags + ; first work out a readable function name + ; based on the flags + FFT_OPTIONS_STRING $flags, name + + ; Entry: + ; r0 = input array + ; r1 = output array + ; r2 = number of points in FFT + ; r3 = pre-scale shift + ; + ; Exit: + ; r0 = 0 if successful + ; = 1 if table too small + ; + + EXPORT FFT_$name +FFT_4OFQ14 + STMFD sp!, {r4-r11, r14} + IF "$radix"="4O" +tablename SETS "_8" +tablename SETS "$qname$coeforder$tablename" + ELSE +tablename SETS "_4" +tablename SETS "$qname$coeforder$tablename" + ENDIF + IMPORT s_$tablename + LDR lr, =s_$tablename + LDR lr,[lr] + + CMP N, lr + MOVGT r0, #1 + LDMGTFD sp!, {r4-r11, pc} + GENERATE_FFT $flags + MOV r0, #0 + LDMFD sp!, {r4-r11, pc} + LTORG + MEND + + + AREA FFTCODE, CODE, READONLY + + + GENERATE_FFT_FUNCTION FFT_16bit +FFT_RADIX4_8F +FFT_FORWARD ; +FFT_REVERSED + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/FFT_4OIQ14.s b/common_audio/signal_processing_library/main/source/fft_ARM9E/FFT_4OIQ14.s new file mode 100644 index 0000000000..b3b955c130 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/FFT_4OIQ14.s @@ -0,0 +1,51 @@ +;// Optimised ARM assembler multi-radix FFT + INCLUDE fft_main_inverse.h + + + MACRO + GENERATE_IFFT_FUNCTION $flags + ; first work out a readable function name + ; based on the flags + FFT_OPTIONS_STRING $flags, name + + ; Entry: + ; r0 = input array + ; r1 = output array + ; r2 = number of points in FFT + ; r3 = pre-scale shift + ; + ; Exit: + ; r0 = 0 if successful + ; = 1 if table too small + ; + + + EXPORT FFT_$name +FFT_4OIQ14 + STMFD sp!, {r4-r11, r14} + IF "$radix"="4O" +tablename SETS "_8" +tablename SETS "$qname$coeforder$tablename" + ELSE +tablename SETS "_4" +tablename SETS "$qname$coeforder$tablename" + ENDIF + IMPORT s_$tablename + LDR lr, =s_$tablename + LDR lr,[lr] + + CMP N, lr + MOVGT r0, #1 + LDMGTFD sp!, {r4-r11, pc} + GENERATE_FFT $flags + MOV r0, #0 + LDMFD sp!, {r4-r11, pc} + LTORG + MEND + + AREA FFTCODE, CODE, READONLY + + + GENERATE_IFFT_FUNCTION FFT_16bit +FFT_RADIX4_8F +FFT_INVERSE +FFT_NONORM ; +FFT_REVERSED + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_mac_forward.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_mac_forward.h new file mode 100644 index 0000000000..59f50b1d5c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_mac_forward.h @@ -0,0 +1,774 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: fft_mac.h,v +; Revision: 1.14 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; +; Shared macros and interface definition file. + +; NB: All the algorithms in this code are Decimation in Time. ARM +; is much better at Decimation in Time (as opposed to Decimation +; in Frequency) due to the position of the barrel shifter. Decimation +; in time has the twiddeling at the start of the butterfly, where as +; decimation in frequency has it at the end of the butterfly. The +; post multiply shifts can be hidden for Decimation in Time. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; FIRST STAGE INTERFACE +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; The FIRST STAGE macros "FS_RAD" have the following interface: +; +; ON ENTRY: +; REGISTERS: +; r0 = inptr => points to the input buffer consisting of N complex +; numbers of size (1< points to the output buffer consisting of N complex +; numbers of size (1< is the number of points in the transform +; r3 = pscale => shift to prescale input by (if applicable) +; ASSEMBLER VARIABLES: +; reversed => logical variable, true if input data is already bit reversed +; The data needs to be bit reversed otherwise +; +; ACTION: +; The routine should +; (1) Bit reverse the data as required for the whole FFT (unless +; the reversed flag is set) +; (2) Prescale the input data by +; (3) Perform a radix R first stage on the data +; (4) Place the processed data in the output array pointed to be dptr +; +; ON EXIT: +; r1 = dptr => preserved and pointing to the output data +; r2 = dinc => number of bytes per "block" or "Group" in this stage +; this is: R< number of radix-R blocks or groups processed in this stage +; this is: N/R +; r0,r4-r12,r14 corrupted + +inptr RN 0 ; input buffer +dptr RN 1 ; output/scratch buffer +N RN 2 ; size of the FFT + +dptr RN 1 ; data pointer - points to end (load in reverse order) +dinc RN 2 ; bytes between data elements at this level of FFT +count RN 3 ; (elements per block<<16) | (blocks per stage) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; GENERAL STAGE INTERFACE +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; The GENERAL STAGE macros "GS_RAD" have the following interface. +; +; To describe the arguments, suppose this routine is called as stage j +; in a k-stage FFT with N=R1*R2*...*Rk. This stage is radix R=Rj. +; +; ON ENTRY: +; REGISTERS: +; r0 = cptr => Pointer to twiddle coefficients for this stage consisting +; of complex numbers of size (1< points to the working buffer consisting of N complex +; numbers of size (1< number of bytes per "block" or "Group" in the last stage: +; dinc = (R1*R2*...*R(j-1))< number of blocks or Groups in the last stage: +; count = Rj*R(j+1)*...*Rk +; NB dinc*count = N< Updated to the end of the coefficients for the stage +; (the coefficients for the next stage will usually follow) +; r1 = dptr => preserved and pointing to the output data +; r2 = dinc => number of bytes per "block" or "Group" in this stage: +; dinc = (R1*R2*..*Rj)< number of radix-R blocks or groups processed in this stage +; count = R(j+1)*...*Rk = (input count)/R +; r0,r4-r12,r14 corrupted + +cptr RN 0 ; pointer to twiddle coefficients +dptr RN 1 ; pointer to FFT data working buffer +dinc RN 2 ; bytes per block/group at this stage +count RN 3 ; number of blocks/groups at this stage + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; LAST STAGE INTERFACE +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; The LAST STAGE macros "LS_RAD" have the following interface. +; +; ON ENTRY: +; REGISTERS: +; r0 = cptr => Pointer to twiddle coefficients for this stage consisting +; of complex numbers of size (1< points to the working buffer consisting of N complex +; numbers of size (1< number of bytes per "block" or "Group" in the last stage: +; dinc = (N/R)< Bytes between twiddle values in the array pointed to by cptr +; +; ACTION: +; The routine should +; (1) Twiddle the input data +; (2) Perform a (last stage optimised) radix R stage on the data +; (3) Perform the actions in place, result written to the dptr buffer +; +; ON EXIT: +; r0 = cptr => Updated to point to real-to-complex conversion coefficients +; r1 = dptr => preserved and pointing to the output data +; r2 = dinc => number of bytes per "block" or "Group" in this stage: +; dinc = N< Pointer to twiddle coefficients for this stage +; This consists of (1,w,w^2,w^3,...,w^(N/4-1)). +; There is a stride between each coeficient specified by cinc +; r1 = dptr => points to the working buffer consisting of N/2 complex +; numbers of size (1< (N/2)< Bytes between twiddle value in array pointed to by cptr +; r4 = dout => Output buffer (usually the same as dptr) +; +; ACTION: +; The routine should take the output of an N/2 point complex FFT and convert +; it to the output of an N point real FFT, assuming that the real input +; inputs were packed up into the real,imag,real,imag,... buffers of the complex +; input. The output is N/2 complex numbers of the form: +; y[0]+i*y[N/2], y[1], y[2], ..., y[N/2-1] +; where y[0],...,y[N-1] is the output from a complex transform of the N +; real inputs. +; +; ON EXIT: +; r0-r12,r14 corrupted + +cptr RN 0 ; pointer to twiddle coefficients +dptr RN 1 ; pointer to FFT data working buffer +dinc RN 2 ; (N/2)<"" + IF "$di"<>"" + MOV $di, $di $postldshift + ENDIF + MOV $dr, $dr $postldshift + ENDIF + MEND + + ; Store a complex data item in the output data buffer + MACRO + STORE $dp, $di, $re, $im + IF "$dataformat"="W" + STR $im, [$dp, #4] + STR $re, [$dp], $di + MEXIT + ENDIF + IF "$dataformat"="H" + STRH $im, [$dp, #2] + STRH $re, [$dp], $di + MEXIT + ENDIF + ERROR "Unsupported save format: $dataformat" + MEND + + ; Store a complex data item in the output data buffer + MACRO + STOREP $dp, $re, $im + IF "$dataformat"="W" + STMIA $dp!, {$re,$im} + MEXIT + ENDIF + IF "$dataformat"="H" + STRH $im, [$dp, #2] + STRH $re, [$dp], #4 + MEXIT + ENDIF + ERROR "Unsupported save format: $dataformat" + MEND + + MACRO + STORE3P $dp, $re0, $im0, $re1, $im1, $re2, $im2 + IF "$dataformat"="W" + STMIA $dp!, {$re0,$im0, $re1,$im1, $re2,$im2} + MEXIT + ENDIF + IF "$dataformat"="H" + STRH $im0, [$dp, #2] + STRH $re0, [$dp], #4 + STRH $im1, [$dp, #2] + STRH $re1, [$dp], #4 + STRH $im2, [$dp, #2] + STRH $re2, [$dp], #4 + MEXIT + ENDIF + ERROR "Unsupported save format: $dataformat" + MEND + + ; do different command depending on forward/inverse FFT + MACRO + DOi $for, $bac, $d, $s1, $s2, $shift + IF "$shift"="" + $for $d, $s1, $s2 + ELSE + $for $d, $s1, $s2, $shift + ENDIF + MEND + + ; d = s1 + s2 if w=exp(+2*pi*i/N) j=+i - inverse transform + ; d = s1 - s2 if w=exp(-2*pi*i/N) j=-i - forward transform + MACRO + ADDi $d, $s1, $s2, $shift + DOi SUB, ADD, $d, $s1, $s2, $shift + MEND + + ; d = s1 - s2 if w=exp(+2*pi*i/N) j=+i - inverse transform + ; d = s1 + s2 if w=exp(-2*pi*i/N) j=-i - forward transform + MACRO + SUBi $d, $s1, $s2, $shift + DOi ADD, SUB, $d, $s1, $s2, $shift + MEND + + ; check that $val is in the range -$max to +$max-1 + ; set carry flag (sicky) if not (2 cycles) + ; has the advantage of not needing a separate register + ; to store the overflow state + MACRO + CHECKOV $val, $tmp, $max + EOR $tmp, $val, $val, ASR#31 + CMPCC $tmp, $max + MEND + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Macro's to perform the twiddle stage (complex multiply by coefficient) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; The coefficients are stored in different formats according to the +; precision and processor architecture. The coefficients required +; will be of the form: +; +; c(k) = cos( + k*2*pi*i/N ), s(k) = sin( + k*2*pi*i/N ) +; +; c(k) + i*s(k) = exp(+2*pi*k*i/N) +; +; for some k's. The storage formats are: +; +; Format Data +; Q14S (c-s, s) in Q14 format, 16-bits per real +; Q14R (c, s) in Q14 format, 16-bits per real +; Q30S (c-s, s) in Q30 format, 32-bits per real +; +; The operation to be performed is one of: +; +; a+i*b = (x+i*y)*(c-i*s) => forward transform +; OR a+i*b = (x+i*y)*(c+i*s) => inverse transform +; +; For the R format the operation is quite simple - requiring 4 muls +; and 2 adds: +; +; Forward: a = x*c+y*s, b = y*c-x*s +; Inverse: a = x*c-y*s, b = y*c+x*s +; +; For the S format the operations is more complex but only requires +; three multiplies, and is simpler to schedule: +; +; Forward: a = (y-x)*s + x*(c+s) = x*(c-s) + (x+y)*s +; b = (y-x)*s + y*(c-s) = y*(c+s) - (x+y)*s +; +; Inverse: a = (x-y)*s + x*(c-s) +; b = (x-y)*s + y*(c+s) +; +; S advantage 16bit: 1ADD, 1SUB, 1MUL, 2MLA instead of 1SUB, 3MUL, 1MLA +; S advantage 32bit: 2ADD, 1SUB, 2SMULL, 1SMLAL instead of 1RSB, 2SMULL, 2SMLAL +; So S wins except for a very fast multiplier (eg 9E) +; +; NB The coefficients must always be the second operand on processor that +; take a variable number of cycles per multiply - so the FFT time remains constant + + ; This twiddle takes unpacked real and imaginary values + ; Expects (cr,ci) = (c-s,s) on input + ; Sets (cr,ci) = (a,b) on output + MACRO + TWIDDLE $xr, $xi, $cr, $ci, $t0, $t1 + IF qshift>=0 :LAND: qshift<32 + SUB $t1, $xi, $xr ; y-x + MUL $t0, $t1, $ci ; (y-x)*s + ADD $t1, $cr, $ci, LSL #1 ; t1 = c+s allow mul to finish on SA + MLA $ci, $xi, $cr, $t0 ; b + MLA $cr, $xr, $t1, $t0 ; a + ELSE + ADD $t1, $cr, $ci, LSL #1 ; t1 = c+s + SMULL $cr, $t0, $xi, $cr ; t0 = y*(c-s) + SUB $xi, $xi, $xr ; xr = y-x + allow mul to finish on SA + SMULL $ci, $cr, $xi, $ci ; cr = (y-x)*s + ADD $ci, $cr, $t0 ; b + allow mul to finish on SA + SMLAL $t0, $cr, $xr, $t1 ; a + ENDIF + MEND + + ; The following twiddle variant is similar to the above + ; except that it is for an "E" processor varient. A standard + ; 4 multiply twiddle is used as it requires the same number + ; of cycles and needs less intermediate precision + ; + ; $co = coeficent real and imaginary (c,s) (packed) + ; $xx = input data real and imaginary part (packed) + ; + ; $xr = destination register for real part of product + ; $xi = destination register for imaginary part of product + ; + ; All registers should be distinct + ; + MACRO + TWIDDLE_E $xr, $xi, $c0, $t0, $xx, $xxi + SMULBT $t0, $xx, $c0 + SMULBB $xr, $xx, $c0 + IF "$xxi"="" + SMULTB $xi, $xx, $c0 + SMLATT $xr, $xx, $c0, $xr + ELSE + SMULBB $xi, $xxi, $c0 + SMLABT $xr, $xxi, $c0, $xr + ENDIF + SUB $xi, $xi, $t0 + MEND + + ; Scale data value in by the coefficient, writing result to out + ; The coeficient must be the second multiplicand + ; The post mul shift need not be done so in most cases this + ; is just a multiply (unless you need higher precision) + ; coef must be preserved + MACRO + SCALE $out, $in, $coef, $tmp + IF qshift>=0 :LAND: qshift<32 + MUL $out, $in, $coef + ELSE + SMULL $tmp, $out, $in, $coef + ENDIF + MEND + + MACRO + DECODEFORMAT $out, $format + GBLS $out.log + GBLS $out.format +$out.format SETS "$format" + IF "$format"="B" +$out.log SETS "1" + MEXIT + ENDIF + IF "$format"="H" +$out.log SETS "2" + MEXIT + ENDIF + IF "$format"="W" +$out.log SETS "3" + MEXIT + ENDIF + ERROR "Unrecognised format for $out: $format" + MEND + + ; generate a string in $var of the correct right shift + ; amount - negative values = left shift + MACRO + SETSHIFT $var, $value + LCLA svalue +svalue SETA $value +$var SETS "" + IF svalue>0 :LAND: svalue<32 +$var SETS ",ASR #0x$svalue" + ENDIF +svalue SETA -svalue + IF svalue>0 :LAND: svalue<32 +$var SETS ",LSL #0x$svalue" + ENDIF + MEND + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; CODE to decipher the FFT options ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + ; The $flags variable specifies the FFT options + ; The global string $name is set to a textual version + ; The global string $table is set the table name + MACRO + FFT_OPTIONS_STRING $flags, $name + GBLS $name + GBLS qname ; name of the precision (eg Q14, Q30) + GBLS direction ; name of the direction (eg I, F) + GBLS radix ; name of the radix (2, 4E, 4B, 4O etc) + GBLS intype ; name of input data type (if real) + GBLS prescale ; flag to indicate prescale + GBLS outpos ; position for the output data + GBLS datainformat ; bytes per input data item + GBLS dataformat ; bytes per working item + GBLS coefformat ; bytes per coefficient working item + GBLS coeforder ; R=(c,s) S=(c-s,s) storage format + GBLA datainlog ; shift to bytes per input complex + GBLA datalog ; shift to bytes per working complex + GBLA coeflog ; shift to bytes per coefficient complex + GBLA qshift ; right shift after multiply + GBLA norm + GBLA architecture ; 4=Arch4(7TDMI,SA), 5=Arch5TE(ARM9E) + GBLS cdshift + GBLS postmulshift + GBLS postldshift + GBLS postmulshift1 + GBLS postldshift1 + GBLL reversed ; flag to indicate input is already bit reversed + GBLS tablename + + + ; find what sort of processor we are building the FFT for +architecture SETA 4 ; Architecture 4 (7TDMI, StrongARM etc) +;qname SETS {CPU} +; P $qname + IF ((({ARCHITECTURE}:CC:"aaaa"):LEFT:3="5TE") :LOR: (({ARCHITECTURE}:CC:"aa"):LEFT:1="6")) +architecture SETA 5 ; Architecture 5 (ARM9E, E extensions) +; P arch E + ENDIF + +reversed SETL {FALSE} + ; decode input order + IF ($flags:AND:FFT_INPUTORDER)=FFT_REVERSED +reversed SETL {TRUE} + ENDIF + + ; decode radix type to $radix + IF ($flags:AND:FFT_RADIX)=FFT_RADIX4 +radix SETS "4E" + ENDIF + IF ($flags:AND:FFT_RADIX)=FFT_RADIX4_8F +radix SETS "4O" + ENDIF + IF ($flags:AND:FFT_RADIX)=FFT_RADIX4_2L +radix SETS "4B" + ENDIF + + ; decode direction to $direction +direction SETS "F" + + ; decode data size to $qname, and *log's + IF ($flags:AND:FFT_DATA_SIZES)=FFT_32bit +qname SETS "Q30" +datainlog SETA 3 ; 8 bytes per complex +datalog SETA 3 +coeflog SETA 3 +datainformat SETS "W" +dataformat SETS "W" +coefformat SETS "W" +qshift SETA -2 ; shift left top word of 32 bit result + ENDIF + IF ($flags:AND:FFT_DATA_SIZES)=FFT_16bit +qname SETS "Q14" +datainlog SETA 2 +datalog SETA 2 +coeflog SETA 2 +datainformat SETS "H" +dataformat SETS "H" +coefformat SETS "H" +qshift SETA 14 + ENDIF + + ; find the coefficient ordering +coeforder SETS "S" + IF (architecture>=5):LAND:(qshift<16) +coeforder SETS "R" + ENDIF + + ; decode real vs complex input data type +intype SETS "" + IF ($flags:AND:FFT_INPUTTYPE)=FFT_REAL +intype SETS "R" + ENDIF + + ; decode on outpos +outpos SETS "" + IF ($flags:AND:FFT_OUTPUTPOS)=FFT_OUT_INBUF +outpos SETS "I" + ENDIF + + ; decode on prescale +prescale SETS "" + IF ($flags:AND:FFT_INPUTSCALE)=FFT_PRESCALE +prescale SETS "P" + ENDIF + + ; decode on output scale +norm SETA 1 + IF ($flags:AND:FFT_OUTPUTSCALE)=FFT_NONORM +norm SETA 0 + ENDIF + + ; calculate shift to convert data offsets to coefficient offsets + SETSHIFT cdshift, ($datalog)-($coeflog) + +$name SETS "$radix$direction$qname$intype$outpos$prescale" + MEND + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; FFT GENERATOR ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; FFT options bitfield + +FFT_DIRECTION EQU 0x00000001 ; direction select bit +FFT_FORWARD EQU 0x00000000 ; forward exp(-ijkw) coefficient FFT +FFT_INVERSE EQU 0x00000001 ; inverse exp(+ijkw) coefficient FFT + +FFT_INPUTORDER EQU 0x00000002 ; input order select field +FFT_BITREV EQU 0x00000000 ; input data is in normal order (bit reverse) +FFT_REVERSED EQU 0x00000002 ; assume input data is already bit revesed + +FFT_INPUTSCALE EQU 0x00000004 ; select scale on input data +FFT_NOPRESCALE EQU 0x00000000 ; do not scale input data +FFT_PRESCALE EQU 0x00000004 ; scale input data up by a register amount + +FFT_INPUTTYPE EQU 0x00000010 ; selector for real/complex input data +FFT_COMPLEX EQU 0x00000000 ; do complex FFT of N points +FFT_REAL EQU 0x00000010 ; do a 2*N point real FFT + +FFT_OUTPUTPOS EQU 0x00000020 ; where is the output placed? +FFT_OUT_OUTBUF EQU 0x00000000 ; default - in the output buffer +FFT_OUT_INBUF EQU 0x00000020 ; copy it back to the input buffer + +FFT_RADIX EQU 0x00000F00 ; radix select +FFT_RADIX4 EQU 0x00000000 ; radix 4 (log_2 N must be even) +FFT_RADIX4_8F EQU 0x00000100 ; radix 4 with radix 8 first stage +FFT_RADIX4_2L EQU 0x00000200 ; radix 4 with optional radix 2 last stage + +FFT_OUTPUTSCALE EQU 0x00001000 ; select output scale value +FFT_NORMALISE EQU 0x00000000 ; default - divide by N during algorithm +FFT_NONORM EQU 0x00001000 ; calculate the raw sum (no scale) + +FFT_DATA_SIZES EQU 0x000F0000 +FFT_16bit EQU 0x00000000 ; 16-bit data and Q14 coefs +FFT_32bit EQU 0x00010000 ; 32-bit data and Q30 coefs + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_mac_inverse.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_mac_inverse.h new file mode 100644 index 0000000000..785b8f02d5 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_mac_inverse.h @@ -0,0 +1,774 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: fft_mac.h,v +; Revision: 1.14 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; +; Shared macros and interface definition file. + +; NB: All the algorithms in this code are Decimation in Time. ARM +; is much better at Decimation in Time (as opposed to Decimation +; in Frequency) due to the position of the barrel shifter. Decimation +; in time has the twiddeling at the start of the butterfly, where as +; decimation in frequency has it at the end of the butterfly. The +; post multiply shifts can be hidden for Decimation in Time. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; FIRST STAGE INTERFACE +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; The FIRST STAGE macros "FS_RAD" have the following interface: +; +; ON ENTRY: +; REGISTERS: +; r0 = inptr => points to the input buffer consisting of N complex +; numbers of size (1< points to the output buffer consisting of N complex +; numbers of size (1< is the number of points in the transform +; r3 = pscale => shift to prescale input by (if applicable) +; ASSEMBLER VARIABLES: +; reversed => logical variable, true if input data is already bit reversed +; The data needs to be bit reversed otherwise +; +; ACTION: +; The routine should +; (1) Bit reverse the data as required for the whole FFT (unless +; the reversed flag is set) +; (2) Prescale the input data by +; (3) Perform a radix R first stage on the data +; (4) Place the processed data in the output array pointed to be dptr +; +; ON EXIT: +; r1 = dptr => preserved and pointing to the output data +; r2 = dinc => number of bytes per "block" or "Group" in this stage +; this is: R< number of radix-R blocks or groups processed in this stage +; this is: N/R +; r0,r4-r12,r14 corrupted + +inptr RN 0 ; input buffer +dptr RN 1 ; output/scratch buffer +N RN 2 ; size of the FFT + +dptr RN 1 ; data pointer - points to end (load in reverse order) +dinc RN 2 ; bytes between data elements at this level of FFT +count RN 3 ; (elements per block<<16) | (blocks per stage) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; GENERAL STAGE INTERFACE +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; The GENERAL STAGE macros "GS_RAD" have the following interface. +; +; To describe the arguments, suppose this routine is called as stage j +; in a k-stage FFT with N=R1*R2*...*Rk. This stage is radix R=Rj. +; +; ON ENTRY: +; REGISTERS: +; r0 = cptr => Pointer to twiddle coefficients for this stage consisting +; of complex numbers of size (1< points to the working buffer consisting of N complex +; numbers of size (1< number of bytes per "block" or "Group" in the last stage: +; dinc = (R1*R2*...*R(j-1))< number of blocks or Groups in the last stage: +; count = Rj*R(j+1)*...*Rk +; NB dinc*count = N< Updated to the end of the coefficients for the stage +; (the coefficients for the next stage will usually follow) +; r1 = dptr => preserved and pointing to the output data +; r2 = dinc => number of bytes per "block" or "Group" in this stage: +; dinc = (R1*R2*..*Rj)< number of radix-R blocks or groups processed in this stage +; count = R(j+1)*...*Rk = (input count)/R +; r0,r4-r12,r14 corrupted + +cptr RN 0 ; pointer to twiddle coefficients +dptr RN 1 ; pointer to FFT data working buffer +dinc RN 2 ; bytes per block/group at this stage +count RN 3 ; number of blocks/groups at this stage + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; LAST STAGE INTERFACE +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; The LAST STAGE macros "LS_RAD" have the following interface. +; +; ON ENTRY: +; REGISTERS: +; r0 = cptr => Pointer to twiddle coefficients for this stage consisting +; of complex numbers of size (1< points to the working buffer consisting of N complex +; numbers of size (1< number of bytes per "block" or "Group" in the last stage: +; dinc = (N/R)< Bytes between twiddle values in the array pointed to by cptr +; +; ACTION: +; The routine should +; (1) Twiddle the input data +; (2) Perform a (last stage optimised) radix R stage on the data +; (3) Perform the actions in place, result written to the dptr buffer +; +; ON EXIT: +; r0 = cptr => Updated to point to real-to-complex conversion coefficients +; r1 = dptr => preserved and pointing to the output data +; r2 = dinc => number of bytes per "block" or "Group" in this stage: +; dinc = N< Pointer to twiddle coefficients for this stage +; This consists of (1,w,w^2,w^3,...,w^(N/4-1)). +; There is a stride between each coeficient specified by cinc +; r1 = dptr => points to the working buffer consisting of N/2 complex +; numbers of size (1< (N/2)< Bytes between twiddle value in array pointed to by cptr +; r4 = dout => Output buffer (usually the same as dptr) +; +; ACTION: +; The routine should take the output of an N/2 point complex FFT and convert +; it to the output of an N point real FFT, assuming that the real input +; inputs were packed up into the real,imag,real,imag,... buffers of the complex +; input. The output is N/2 complex numbers of the form: +; y[0]+i*y[N/2], y[1], y[2], ..., y[N/2-1] +; where y[0],...,y[N-1] is the output from a complex transform of the N +; real inputs. +; +; ON EXIT: +; r0-r12,r14 corrupted + +cptr RN 0 ; pointer to twiddle coefficients +dptr RN 1 ; pointer to FFT data working buffer +dinc RN 2 ; (N/2)<"" + IF "$di"<>"" + MOV $di, $di $postldshift + ENDIF + MOV $dr, $dr $postldshift + ENDIF + MEND + + ; Store a complex data item in the output data buffer + MACRO + STORE $dp, $di, $re, $im + IF "$dataformat"="W" + STR $im, [$dp, #4] + STR $re, [$dp], $di + MEXIT + ENDIF + IF "$dataformat"="H" + STRH $im, [$dp, #2] + STRH $re, [$dp], $di + MEXIT + ENDIF + ERROR "Unsupported save format: $dataformat" + MEND + + ; Store a complex data item in the output data buffer + MACRO + STOREP $dp, $re, $im + IF "$dataformat"="W" + STMIA $dp!, {$re,$im} + MEXIT + ENDIF + IF "$dataformat"="H" + STRH $im, [$dp, #2] + STRH $re, [$dp], #4 + MEXIT + ENDIF + ERROR "Unsupported save format: $dataformat" + MEND + + MACRO + STORE3P $dp, $re0, $im0, $re1, $im1, $re2, $im2 + IF "$dataformat"="W" + STMIA $dp!, {$re0,$im0, $re1,$im1, $re2,$im2} + MEXIT + ENDIF + IF "$dataformat"="H" + STRH $im0, [$dp, #2] + STRH $re0, [$dp], #4 + STRH $im1, [$dp, #2] + STRH $re1, [$dp], #4 + STRH $im2, [$dp, #2] + STRH $re2, [$dp], #4 + MEXIT + ENDIF + ERROR "Unsupported save format: $dataformat" + MEND + + ; do different command depending on forward/inverse FFT + MACRO + DOi $for, $bac, $d, $s1, $s2, $shift + IF "$shift"="" + $bac $d, $s1, $s2 + ELSE + $bac $d, $s1, $s2, $shift + ENDIF + MEND + + ; d = s1 + s2 if w=exp(+2*pi*i/N) j=+i - inverse transform + ; d = s1 - s2 if w=exp(-2*pi*i/N) j=-i - forward transform + MACRO + ADDi $d, $s1, $s2, $shift + DOi SUB, ADD, $d, $s1, $s2, $shift + MEND + + ; d = s1 - s2 if w=exp(+2*pi*i/N) j=+i - inverse transform + ; d = s1 + s2 if w=exp(-2*pi*i/N) j=-i - forward transform + MACRO + SUBi $d, $s1, $s2, $shift + DOi ADD, SUB, $d, $s1, $s2, $shift + MEND + + ; check that $val is in the range -$max to +$max-1 + ; set carry flag (sicky) if not (2 cycles) + ; has the advantage of not needing a separate register + ; to store the overflow state + MACRO + CHECKOV $val, $tmp, $max + EOR $tmp, $val, $val, ASR#31 + CMPCC $tmp, $max + MEND + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Macro's to perform the twiddle stage (complex multiply by coefficient) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; The coefficients are stored in different formats according to the +; precision and processor architecture. The coefficients required +; will be of the form: +; +; c(k) = cos( + k*2*pi*i/N ), s(k) = sin( + k*2*pi*i/N ) +; +; c(k) + i*s(k) = exp(+2*pi*k*i/N) +; +; for some k's. The storage formats are: +; +; Format Data +; Q14S (c-s, s) in Q14 format, 16-bits per real +; Q14R (c, s) in Q14 format, 16-bits per real +; Q30S (c-s, s) in Q30 format, 32-bits per real +; +; The operation to be performed is one of: +; +; a+i*b = (x+i*y)*(c-i*s) => forward transform +; OR a+i*b = (x+i*y)*(c+i*s) => inverse transform +; +; For the R format the operation is quite simple - requiring 4 muls +; and 2 adds: +; +; Forward: a = x*c+y*s, b = y*c-x*s +; Inverse: a = x*c-y*s, b = y*c+x*s +; +; For the S format the operations is more complex but only requires +; three multiplies, and is simpler to schedule: +; +; Forward: a = (y-x)*s + x*(c+s) = x*(c-s) + (x+y)*s +; b = (y-x)*s + y*(c-s) = y*(c+s) - (x+y)*s +; +; Inverse: a = (x-y)*s + x*(c-s) +; b = (x-y)*s + y*(c+s) +; +; S advantage 16bit: 1ADD, 1SUB, 1MUL, 2MLA instead of 1SUB, 3MUL, 1MLA +; S advantage 32bit: 2ADD, 1SUB, 2SMULL, 1SMLAL instead of 1RSB, 2SMULL, 2SMLAL +; So S wins except for a very fast multiplier (eg 9E) +; +; NB The coefficients must always be the second operand on processor that +; take a variable number of cycles per multiply - so the FFT time remains constant + + ; This twiddle takes unpacked real and imaginary values + ; Expects (cr,ci) = (c-s,s) on input + ; Sets (cr,ci) = (a,b) on output + MACRO + TWIDDLE $xr, $xi, $cr, $ci, $t0, $t1 + IF qshift>=0 :LAND: qshift<32 + SUB $t1, $xr, $xi ; x-y + MUL $t0, $t1, $ci ; (x-y)*s + ADD $ci, $cr, $ci, LSL #1 ; ci = c+s allow mul to finish on SA + MLA $cr, $xr, $cr, $t0 ; a + MLA $ci, $xi, $ci, $t0 ; b + ELSE + ADD $t1, $cr, $ci, LSL #1 ; c+s + SMULL $t0, $cr, $xr, $cr ; x*(c-s) + SUB $xr, $xr, $xi ; x-y + allow mul to finish on SA + SMULL $t0, $ci, $xr, $ci ; (x-y)*s + ADD $cr, $cr, $ci ; a + allow mul to finish on SA + SMLAL $t0, $ci, $xi, $t1 ; b + ENDIF + MEND + + ; The following twiddle variant is similar to the above + ; except that it is for an "E" processor varient. A standard + ; 4 multiply twiddle is used as it requires the same number + ; of cycles and needs less intermediate precision + ; + ; $co = coeficent real and imaginary (c,s) (packed) + ; $xx = input data real and imaginary part (packed) + ; + ; $xr = destination register for real part of product + ; $xi = destination register for imaginary part of product + ; + ; All registers should be distinct + ; + MACRO + TWIDDLE_E $xr, $xi, $c0, $t0, $xx, $xxi + SMULBB $t0, $xx, $c0 + SMULBT $xi, $xx, $c0 + IF "$xxi"="" + SMULTT $xr, $xx, $c0 + SMLATB $xi, $xx, $c0, $xi + ELSE + SMULBT $xr, $xxi, $c0 + SMLABB $xi, $xxi, $c0, $xi + ENDIF + SUB $xr, $t0, $xr + MEND + + ; Scale data value in by the coefficient, writing result to out + ; The coeficient must be the second multiplicand + ; The post mul shift need not be done so in most cases this + ; is just a multiply (unless you need higher precision) + ; coef must be preserved + MACRO + SCALE $out, $in, $coef, $tmp + IF qshift>=0 :LAND: qshift<32 + MUL $out, $in, $coef + ELSE + SMULL $tmp, $out, $in, $coef + ENDIF + MEND + + MACRO + DECODEFORMAT $out, $format + GBLS $out.log + GBLS $out.format +$out.format SETS "$format" + IF "$format"="B" +$out.log SETS "1" + MEXIT + ENDIF + IF "$format"="H" +$out.log SETS "2" + MEXIT + ENDIF + IF "$format"="W" +$out.log SETS "3" + MEXIT + ENDIF + ERROR "Unrecognised format for $out: $format" + MEND + + ; generate a string in $var of the correct right shift + ; amount - negative values = left shift + MACRO + SETSHIFT $var, $value + LCLA svalue +svalue SETA $value +$var SETS "" + IF svalue>0 :LAND: svalue<32 +$var SETS ",ASR #0x$svalue" + ENDIF +svalue SETA -svalue + IF svalue>0 :LAND: svalue<32 +$var SETS ",LSL #0x$svalue" + ENDIF + MEND + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; CODE to decipher the FFT options ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + ; The $flags variable specifies the FFT options + ; The global string $name is set to a textual version + ; The global string $table is set the table name + MACRO + FFT_OPTIONS_STRING $flags, $name + GBLS $name + GBLS qname ; name of the precision (eg Q14, Q30) + GBLS direction ; name of the direction (eg I, F) + GBLS radix ; name of the radix (2, 4E, 4B, 4O etc) + GBLS intype ; name of input data type (if real) + GBLS prescale ; flag to indicate prescale + GBLS outpos ; position for the output data + GBLS datainformat ; bytes per input data item + GBLS dataformat ; bytes per working item + GBLS coefformat ; bytes per coefficient working item + GBLS coeforder ; R=(c,s) S=(c-s,s) storage format + GBLA datainlog ; shift to bytes per input complex + GBLA datalog ; shift to bytes per working complex + GBLA coeflog ; shift to bytes per coefficient complex + GBLA qshift ; right shift after multiply + GBLA norm + GBLA architecture ; 4=Arch4(7TDMI,SA), 5=Arch5TE(ARM9E) + GBLS cdshift + GBLS postmulshift + GBLS postldshift + GBLS postmulshift1 + GBLS postldshift1 + GBLL reversed ; flag to indicate input is already bit reversed + GBLS tablename + + + ; find what sort of processor we are building the FFT for +architecture SETA 4 ; Architecture 4 (7TDMI, StrongARM etc) +;qname SETS {CPU} +; P $qname + IF ((({ARCHITECTURE}:CC:"aaaa"):LEFT:3="5TE") :LOR: (({ARCHITECTURE}:CC:"aa"):LEFT:1="6")) +architecture SETA 5 ; Architecture 5 (ARM9E, E extensions) +; P arch E + ENDIF + +reversed SETL {FALSE} + ; decode input order + IF ($flags:AND:FFT_INPUTORDER)=FFT_REVERSED +reversed SETL {TRUE} + ENDIF + + ; decode radix type to $radix + IF ($flags:AND:FFT_RADIX)=FFT_RADIX4 +radix SETS "4E" + ENDIF + IF ($flags:AND:FFT_RADIX)=FFT_RADIX4_8F +radix SETS "4O" + ENDIF + IF ($flags:AND:FFT_RADIX)=FFT_RADIX4_2L +radix SETS "4B" + ENDIF + + ; decode direction to $direction +direction SETS "I" + + ; decode data size to $qname, and *log's + IF ($flags:AND:FFT_DATA_SIZES)=FFT_32bit +qname SETS "Q30" +datainlog SETA 3 ; 8 bytes per complex +datalog SETA 3 +coeflog SETA 3 +datainformat SETS "W" +dataformat SETS "W" +coefformat SETS "W" +qshift SETA -2 ; shift left top word of 32 bit result + ENDIF + IF ($flags:AND:FFT_DATA_SIZES)=FFT_16bit +qname SETS "Q14" +datainlog SETA 2 +datalog SETA 2 +coeflog SETA 2 +datainformat SETS "H" +dataformat SETS "H" +coefformat SETS "H" +qshift SETA 14 + ENDIF + + ; find the coefficient ordering +coeforder SETS "S" + IF (architecture>=5):LAND:(qshift<16) +coeforder SETS "R" + ENDIF + + ; decode real vs complex input data type +intype SETS "" + IF ($flags:AND:FFT_INPUTTYPE)=FFT_REAL +intype SETS "R" + ENDIF + + ; decode on outpos +outpos SETS "" + IF ($flags:AND:FFT_OUTPUTPOS)=FFT_OUT_INBUF +outpos SETS "I" + ENDIF + + ; decode on prescale +prescale SETS "" + IF ($flags:AND:FFT_INPUTSCALE)=FFT_PRESCALE +prescale SETS "P" + ENDIF + + ; decode on output scale +norm SETA 1 + IF ($flags:AND:FFT_OUTPUTSCALE)=FFT_NONORM +norm SETA 0 + ENDIF + + ; calculate shift to convert data offsets to coefficient offsets + SETSHIFT cdshift, ($datalog)-($coeflog) + +$name SETS "$radix$direction$qname$intype$outpos$prescale" + MEND + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; FFT GENERATOR ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; FFT options bitfield + +FFT_DIRECTION EQU 0x00000001 ; direction select bit +FFT_FORWARD EQU 0x00000000 ; forward exp(-ijkw) coefficient FFT +FFT_INVERSE EQU 0x00000001 ; inverse exp(+ijkw) coefficient FFT + +FFT_INPUTORDER EQU 0x00000002 ; input order select field +FFT_BITREV EQU 0x00000000 ; input data is in normal order (bit reverse) +FFT_REVERSED EQU 0x00000002 ; assume input data is already bit revesed + +FFT_INPUTSCALE EQU 0x00000004 ; select scale on input data +FFT_NOPRESCALE EQU 0x00000000 ; do not scale input data +FFT_PRESCALE EQU 0x00000004 ; scale input data up by a register amount + +FFT_INPUTTYPE EQU 0x00000010 ; selector for real/complex input data +FFT_COMPLEX EQU 0x00000000 ; do complex FFT of N points +FFT_REAL EQU 0x00000010 ; do a 2*N point real FFT + +FFT_OUTPUTPOS EQU 0x00000020 ; where is the output placed? +FFT_OUT_OUTBUF EQU 0x00000000 ; default - in the output buffer +FFT_OUT_INBUF EQU 0x00000020 ; copy it back to the input buffer + +FFT_RADIX EQU 0x00000F00 ; radix select +FFT_RADIX4 EQU 0x00000000 ; radix 4 (log_2 N must be even) +FFT_RADIX4_8F EQU 0x00000100 ; radix 4 with radix 8 first stage +FFT_RADIX4_2L EQU 0x00000200 ; radix 4 with optional radix 2 last stage + +FFT_OUTPUTSCALE EQU 0x00001000 ; select output scale value +FFT_NORMALISE EQU 0x00000000 ; default - divide by N during algorithm +FFT_NONORM EQU 0x00001000 ; calculate the raw sum (no scale) + +FFT_DATA_SIZES EQU 0x000F0000 +FFT_16bit EQU 0x00000000 ; 16-bit data and Q14 coefs +FFT_32bit EQU 0x00010000 ; 32-bit data and Q30 coefs + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_main_forward.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_main_forward.h new file mode 100644 index 0000000000..aa49a01092 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_main_forward.h @@ -0,0 +1,101 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: fft_main.h,v +; Revision: 1.10 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; + + INCLUDE fft_mac_forward.h ; general macros + INCLUDE fs_rad8_forward.h ; first stage, radix 8 macros + INCLUDE gs_rad4.h ; general stage, radix 4 macros + +; The macro in this file generates a whole FFT by glueing together +; FFT stage macros. It is designed to handle a range of power-of-2 +; FFT's, the power of 2 set at run time. + +; The following should be set up: +; +; $flags = a 32-bit integer indicating what FFT code to generate +; formed by a bitmask of the above FFT_* flag definitions +; (see fft_mac.h) +; +; r0 = inptr = address of the input buffer +; r1 = dptr = address of the output buffer +; r2 = N = the number of points in the FFT +; r3 = = optional pre-left shift to apply to the input data +; +; The contents of the input buffer are preserved (provided that the +; input and output buffer are different, which must be the case unless +; no bitreversal is required and the input is provided pre-reversed). + + MACRO + GENERATE_FFT $flags + ; decode the options word + FFT_OPTIONS_STRING $flags, name + + IF "$outpos"<>"" + ; stack the input buffer address for later on + STMFD sp!, {inptr} + ENDIF + + ; Do first stage - radix 4 or radix 8 depending on parity + IF "$radix"="4O" + FS_RAD8 +tablename SETS "_8" +tablename SETS "$qname$coeforder$tablename" + ELSE + FS_RAD4 +tablename SETS "_4" +tablename SETS "$qname$coeforder$tablename" + ENDIF + IMPORT t_$tablename + LDR cptr, =t_$tablename ; coefficient table + CMP count, #1 + BEQ %FT10 ; exit for small case + +12 ; General stage loop + GS_RAD4 + CMP count, #2 + BGT %BT12 + + IF "$radix"="4B" + ; support odd parity as well + ;BLT %FT10 ; less than 2 left (ie, finished) + ;LS_RAD2 ; finish off with a radix 2 stage + ENDIF + +10 ; we've finished the complex FFT + IF ($flags:AND:FFT_INPUTTYPE)=FFT_REAL + ; convert to a real FFT + IF "$outpos"="I" + LDMFD sp!, {dout} + ELSE + MOV dout, dptr + ENDIF + ; dinc = (N/2) >> datalog where N is the number of real points + IMPORT s_$tablename + LDR t0, = s_$tablename + LDR t0, [t0] ; max N handled by the table + MOV t1, dinc, LSR #($datalog-1) ; real N we want to handle + CMP t0, t1 + MOV cinc, #3<<$coeflog ; radix 4 table stage + MOVEQ cinc, #1<<$coeflog ; radix 4 table stage + LS_ZTOR + ENDIF + + MEND + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_main_inverse.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_main_inverse.h new file mode 100644 index 0000000000..0a0dfc45ca --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/fft_main_inverse.h @@ -0,0 +1,101 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: fft_main.h,v +; Revision: 1.10 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; + + INCLUDE fft_mac_inverse.h ; general macros + INCLUDE fs_rad8_inverse.h ; first stage, radix 8 macros + INCLUDE gs_rad4.h ; general stage, radix 4 macros + +; The macro in this file generates a whole FFT by glueing together +; FFT stage macros. It is designed to handle a range of power-of-2 +; FFT's, the power of 2 set at run time. + +; The following should be set up: +; +; $flags = a 32-bit integer indicating what FFT code to generate +; formed by a bitmask of the above FFT_* flag definitions +; (see fft_mac.h) +; +; r0 = inptr = address of the input buffer +; r1 = dptr = address of the output buffer +; r2 = N = the number of points in the FFT +; r3 = = optional pre-left shift to apply to the input data +; +; The contents of the input buffer are preserved (provided that the +; input and output buffer are different, which must be the case unless +; no bitreversal is required and the input is provided pre-reversed). + + MACRO + GENERATE_FFT $flags + ; decode the options word + FFT_OPTIONS_STRING $flags, name + + IF "$outpos"<>"" + ; stack the input buffer address for later on + STMFD sp!, {inptr} + ENDIF + + ; Do first stage - radix 4 or radix 8 depending on parity + IF "$radix"="4O" + FS_RAD8 +tablename SETS "_8" +tablename SETS "$qname$coeforder$tablename" + ELSE + FS_RAD4 +tablename SETS "_4" +tablename SETS "$qname$coeforder$tablename" + ENDIF + IMPORT t_$tablename + LDR cptr, =t_$tablename ; coefficient table + CMP count, #1 + BEQ %FT10 ; exit for small case + +12 ; General stage loop + GS_RAD4 + CMP count, #2 + BGT %BT12 + + IF "$radix"="4B" + ; support odd parity as well + ;BLT %FT10 ; less than 2 left (ie, finished) + ;LS_RAD2 ; finish off with a radix 2 stage + ENDIF + +10 ; we've finished the complex FFT + IF ($flags:AND:FFT_INPUTTYPE)=FFT_REAL + ; convert to a real FFT + IF "$outpos"="I" + LDMFD sp!, {dout} + ELSE + MOV dout, dptr + ENDIF + ; dinc = (N/2) >> datalog where N is the number of real points + IMPORT s_$tablename + LDR t0, = s_$tablename + LDR t0, [t0] ; max N handled by the table + MOV t1, dinc, LSR #($datalog-1) ; real N we want to handle + CMP t0, t1 + MOV cinc, #3<<$coeflog ; radix 4 table stage + MOVEQ cinc, #1<<$coeflog ; radix 4 table stage + LS_ZTOR + ENDIF + + MEND + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/fs_rad8_forward.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/fs_rad8_forward.h new file mode 100644 index 0000000000..bcbf267af2 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/fs_rad8_forward.h @@ -0,0 +1,236 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: fs_rad8.h,v +; Revision: 1.5 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; +; This file contains first stage, radix-8 code +; It bit reverses (assuming a power of 2 FFT) and performs the first stage +; + + MACRO + FS_RAD8 + SETSHIFT postldshift, 3*norm + SETSHIFT postmulshift, 3*norm+qshift + SETSHIFT postldshift1, 3*norm-1 + SETSHIFT postmulshift1, 3*norm+qshift-1 + IF "$prescale"<>"" + STMFD sp!, {dptr, N, r3} + ELSE + STMFD sp!, {dptr, N} + ENDIF + MOV bitrev, #0 + MOV dinc, N, LSL #($datalog-2) +12 ; first (radix 8) stage loop + ; do first two (radix 2) stages + FIRST_STAGE_RADIX8_ODD dinc, "dinc, LSR #1", bitrev + FIRST_STAGE_RADIX8_EVEN dinc, bitrev + ; third (radix 2) stage + LDMFD sp!, {x0r, x0i} + ADD $h0r, $h0r, x0r $postldshift ; standard add + ADD $h0i, $h0i, x0i $postldshift + SUB x0r, $h0r, x0r $postldshift1 + SUB x0i, $h0i, x0i $postldshift1 + STORE dptr, #1<<$datalog, $h0r, $h0i + LDMFD sp!, {x1r, x1i} + ADD $h1r, $h1r, x1r $postmulshift + ADD $h1i, $h1i, x1i $postmulshift + SUB x1r, $h1r, x1r $postmulshift1 + SUB x1i, $h1i, x1i $postmulshift1 + STORE dptr, #1<<$datalog, $h1r, $h1i + LDMFD sp!, {x2r, x2i} + SUBi $h2r, $h2r, x2r $postldshift ; note that x2r & x2i were + ADDi $h2i, $h2i, x2i $postldshift ; swapped above + ADDi x2r, $h2r, x2r $postldshift1 + SUBi x2i, $h2i, x2i $postldshift1 + STORE dptr, #1<<$datalog, $h2r, $h2i + LDMFD sp!, {x3r, x3i} + ADD $h3r, $h3r, x3r $postmulshift + ADD $h3i, $h3i, x3i $postmulshift + SUB x3r, $h3r, x3r $postmulshift1 + SUB x3i, $h3i, x3i $postmulshift1 + STORE dptr, #1<<$datalog, $h3r, $h3i + STORE dptr, #1<<$datalog, x0r, x0i + STORE dptr, #1<<$datalog, x1r, x1i + STORE dptr, #1<<$datalog, x2r, x2i + STORE dptr, #1<<$datalog, x3r, x3i + + IF reversed + SUBS dinc, dinc, #2<<$datalog + BGT %BT12 + ELSE + ; increment the count in a bit reverse manner + EOR bitrev, bitrev, dinc, LSR #($datalog-2+4) ; t0 = (N/8)>>1 + TST bitrev, dinc, LSR #($datalog-2+4) + BNE %BT12 + ; get here for 1/2 the loops - carry to next bit + EOR bitrev, bitrev, dinc, LSR #($datalog-2+5) + TST bitrev, dinc, LSR #($datalog-2+5) + BNE %BT12 + ; get here for 1/4 of the loops - stop unrolling + MOV t0, dinc, LSR #($datalog-2+6) +15 ; bit reverse increment loop + EOR bitrev, bitrev, t0 + TST bitrev, t0 + BNE %BT12 + ; get here for 1/8 of the loops (or when finished) + MOVS t0, t0, LSR #1 ; move down to next bit + BNE %BT15 ; carry on if we haven't run off the bottom + ENDIF + + IF "$prescale"<>"" + LDMFD sp!, {dptr, N, r3} + ELSE + LDMFD sp!, {dptr, N} + ENDIF + MOV count, N, LSR #3 ; start with N/8 blocks 8 each + MOV dinc, #8<<$datalog ; initial skip is 8 elements + MEND + + + + MACRO + FIRST_STAGE_RADIX8_ODD $dinc, $dinc_lsr1, $bitrev + + IF reversed + ; load non bit reversed + ADD t0, inptr, #4<<$datalog + LOADDATAI t0, #1<<$datalog, x0r, x0i + LOADDATAI t0, #1<<$datalog, x1r, x1i + LOADDATAI t0, #1<<$datalog, x2r, x2i + LOADDATAI t0, #1<<$datalog, x3r, x3i + ELSE + ; load data elements 1,3,5,7 into register order 1,5,3,7 + ADD t0, inptr, $bitrev, LSL #$datalog + ADD t0, t0, $dinc_lsr1 ; load in odd terms first + LOADDATAI t0, $dinc, x0r, x0i + LOADDATAI t0, $dinc, x2r, x2i + LOADDATAI t0, $dinc, x1r, x1i + LOADDATAI t0, $dinc, x3r, x3i + ENDIF + + IF "$prescale"="P" + LDR t0, [sp, #8] + MOV x0r, x0r, LSL t0 + MOV x0i, x0i, LSL t0 + MOV x1r, x1r, LSL t0 + MOV x1i, x1i, LSL t0 + MOV x2r, x2r, LSL t0 + MOV x2i, x2i, LSL t0 + MOV x3r, x3r, LSL t0 + MOV x3i, x3i, LSL t0 + ENDIF + + SETREG h2, x3r, x3i + SETREG h3, t0, t1 + ; first stage (radix 2) butterflies + ADD x0r, x0r, x1r + ADD x0i, x0i, x1i + SUB x1r, x0r, x1r, LSL #1 + SUB x1i, x0i, x1i, LSL #1 + SUB $h3r, x2r, x3r + SUB $h3i, x2i, x3i + ADD $h2r, x2r, x3r + ADD $h2i, x2i, x3i + ; second stage (radix 2) butterflies + SUB x2i, x0r, $h2r ; swap real and imag here + SUB x2r, x0i, $h2i ; for use later + ADD x0r, x0r, $h2r + ADD x0i, x0i, $h2i + ADDi x3r, x1r, $h3i + SUBi x3i, x1i, $h3r + SUBi x1r, x1r, $h3i + ADDi x1i, x1i, $h3r + ; do the 1/sqrt(2) (+/-1 +/- i) twiddles for third stage + LCLS tempname +tempname SETS "R_rad8" + IMPORT t_$qname$tempname + LDR t1, =t_$qname$tempname +; IMPORT t_$qname.R_rad8 +; LDR t1, =t_$qname.R_rad8 + LOADCOEFR t1, t1 + + STMFD sp!, {dinc} ;;; FIXME!!! + + ADD t0, x1r, x1i ; real part when * (1-i) + SCALE x1r, t0, t1, dinc ; scale by 1/sqrt(2) + RSB t0, t0, x1i, LSL #1 ; imag part when * (1-i) + SCALE x1i, t0, t1, dinc ; scale by 1/sqrt(2) + SUB t0, x3i, x3r ; real part when * (-1-i) + SCALE x3r, t0, t1, dinc ; scale by 1/sqrt(2) + SUB t0, t0, x3i, LSL #1 ; imag part when * (-1-i) + SCALE x3i, t0, t1, dinc ; scale by 1/sqrt(2) + + LDMFD sp!, {dinc} ;;; FIXME!!! + STMFD sp!, {x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i} + MEND + + MACRO + FIRST_STAGE_RADIX8_EVEN $dinc, $bitrev + ; load elements 0,2,4,6 into register order 0,4,2,6 + SETREGS h, x1r, x1i, x2r, x2i, x3r, x3i, t0, t1 + SETREG g3, x0r, x0i + + IF reversed + ; load normally + LOADDATAI inptr, #1<<$datalog, $h0r, $h0i + LOADDATAI inptr, #1<<$datalog, $h1r, $h1i + LOADDATAI inptr, #1<<$datalog, $h2r, $h2i + LOADDATAI inptr, #1<<$datalog, $h3r, $h3i + ADD inptr, inptr, #4<<$datalog + ELSE + ; load bit reversed + ADD x0r, inptr, $bitrev, LSL #$datalog + LOADDATAI x0r, $dinc, $h0r, $h0i + LOADDATAI x0r, $dinc, $h2r, $h2i + LOADDATAI x0r, $dinc, $h1r, $h1i + LOADDATAI x0r, $dinc, $h3r, $h3i + ENDIF + + IF "$prescale"="P" + LDR x0r, [sp, #8+32] ; NB we've stacked 8 extra regs! + MOV $h0r, $h0r, LSL x0r + MOV $h0i, $h0i, LSL x0r + MOV $h1r, $h1r, LSL x0r + MOV $h1i, $h1i, LSL x0r + MOV $h2r, $h2r, LSL x0r + MOV $h2i, $h2i, LSL x0r + MOV $h3r, $h3r, LSL x0r + MOV $h3i, $h3i, LSL x0r + ENDIF + + SHIFTDATA $h0r, $h0i + ; first stage (radix 2) butterflies + ADD $h0r, $h0r, $h1r $postldshift + ADD $h0i, $h0i, $h1i $postldshift + SUB $h1r, $h0r, $h1r $postldshift1 + SUB $h1i, $h0i, $h1i $postldshift1 + SUB $g3r, $h2r, $h3r + SUB $g3i, $h2i, $h3i + ADD $h2r, $h2r, $h3r + ADD $h2i, $h2i, $h3i + ; second stage (radix 2) butterflies + ADD $h0r, $h0r, $h2r $postldshift + ADD $h0i, $h0i, $h2i $postldshift + SUB $h2r, $h0r, $h2r $postldshift1 + SUB $h2i, $h0i, $h2i $postldshift1 + ADDi $h3r, $h1r, $g3i $postldshift + SUBi $h3i, $h1i, $g3r $postldshift + SUBi $h1r, $h1r, $g3i $postldshift + ADDi $h1i, $h1i, $g3r $postldshift + MEND + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/fs_rad8_inverse.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/fs_rad8_inverse.h new file mode 100644 index 0000000000..e7d451c553 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/fs_rad8_inverse.h @@ -0,0 +1,236 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: fs_rad8.h,v +; Revision: 1.5 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; +; This file contains first stage, radix-8 code +; It bit reverses (assuming a power of 2 FFT) and performs the first stage +; + + MACRO + FS_RAD8 + SETSHIFT postldshift, 3*norm + SETSHIFT postmulshift, 3*norm+qshift + SETSHIFT postldshift1, 3*norm-1 + SETSHIFT postmulshift1, 3*norm+qshift-1 + IF "$prescale"<>"" + STMFD sp!, {dptr, N, r3} + ELSE + STMFD sp!, {dptr, N} + ENDIF + MOV bitrev, #0 + MOV dinc, N, LSL #($datalog-2) +12 ; first (radix 8) stage loop + ; do first two (radix 2) stages + FIRST_STAGE_RADIX8_ODD dinc, "dinc, LSR #1", bitrev + FIRST_STAGE_RADIX8_EVEN dinc, bitrev + ; third (radix 2) stage + LDMFD sp!, {x0r, x0i} + ADD $h0r, $h0r, x0r $postldshift ; standard add + ADD $h0i, $h0i, x0i $postldshift + SUB x0r, $h0r, x0r $postldshift1 + SUB x0i, $h0i, x0i $postldshift1 + STORE dptr, #1<<$datalog, $h0r, $h0i + LDMFD sp!, {x1r, x1i} + ADD $h1r, $h1r, x1r $postmulshift + ADD $h1i, $h1i, x1i $postmulshift + SUB x1r, $h1r, x1r $postmulshift1 + SUB x1i, $h1i, x1i $postmulshift1 + STORE dptr, #1<<$datalog, $h1r, $h1i + LDMFD sp!, {x2r, x2i} + SUBi $h2r, $h2r, x2r $postldshift ; note that x2r & x2i were + ADDi $h2i, $h2i, x2i $postldshift ; swapped above + ADDi x2r, $h2r, x2r $postldshift1 + SUBi x2i, $h2i, x2i $postldshift1 + STORE dptr, #1<<$datalog, $h2r, $h2i + LDMFD sp!, {x3r, x3i} + ADD $h3r, $h3r, x3r $postmulshift + ADD $h3i, $h3i, x3i $postmulshift + SUB x3r, $h3r, x3r $postmulshift1 + SUB x3i, $h3i, x3i $postmulshift1 + STORE dptr, #1<<$datalog, $h3r, $h3i + STORE dptr, #1<<$datalog, x0r, x0i + STORE dptr, #1<<$datalog, x1r, x1i + STORE dptr, #1<<$datalog, x2r, x2i + STORE dptr, #1<<$datalog, x3r, x3i + + IF reversed + SUBS dinc, dinc, #2<<$datalog + BGT %BT12 + ELSE + ; increment the count in a bit reverse manner + EOR bitrev, bitrev, dinc, LSR #($datalog-2+4) ; t0 = (N/8)>>1 + TST bitrev, dinc, LSR #($datalog-2+4) + BNE %BT12 + ; get here for 1/2 the loops - carry to next bit + EOR bitrev, bitrev, dinc, LSR #($datalog-2+5) + TST bitrev, dinc, LSR #($datalog-2+5) + BNE %BT12 + ; get here for 1/4 of the loops - stop unrolling + MOV t0, dinc, LSR #($datalog-2+6) +15 ; bit reverse increment loop + EOR bitrev, bitrev, t0 + TST bitrev, t0 + BNE %BT12 + ; get here for 1/8 of the loops (or when finished) + MOVS t0, t0, LSR #1 ; move down to next bit + BNE %BT15 ; carry on if we haven't run off the bottom + ENDIF + + IF "$prescale"<>"" + LDMFD sp!, {dptr, N, r3} + ELSE + LDMFD sp!, {dptr, N} + ENDIF + MOV count, N, LSR #3 ; start with N/8 blocks 8 each + MOV dinc, #8<<$datalog ; initial skip is 8 elements + MEND + + + + MACRO + FIRST_STAGE_RADIX8_ODD $dinc, $dinc_lsr1, $bitrev + + IF reversed + ; load non bit reversed + ADD t0, inptr, #4<<$datalog + LOADDATAI t0, #1<<$datalog, x0r, x0i + LOADDATAI t0, #1<<$datalog, x1r, x1i + LOADDATAI t0, #1<<$datalog, x2r, x2i + LOADDATAI t0, #1<<$datalog, x3r, x3i + ELSE + ; load data elements 1,3,5,7 into register order 1,5,3,7 + ADD t0, inptr, $bitrev, LSL #$datalog + ADD t0, t0, $dinc_lsr1 ; load in odd terms first + LOADDATAI t0, $dinc, x0r, x0i + LOADDATAI t0, $dinc, x2r, x2i + LOADDATAI t0, $dinc, x1r, x1i + LOADDATAI t0, $dinc, x3r, x3i + ENDIF + + IF "$prescale"="P" + LDR t0, [sp, #8] + MOV x0r, x0r, LSL t0 + MOV x0i, x0i, LSL t0 + MOV x1r, x1r, LSL t0 + MOV x1i, x1i, LSL t0 + MOV x2r, x2r, LSL t0 + MOV x2i, x2i, LSL t0 + MOV x3r, x3r, LSL t0 + MOV x3i, x3i, LSL t0 + ENDIF + + SETREG h2, x3r, x3i + SETREG h3, t0, t1 + ; first stage (radix 2) butterflies + ADD x0r, x0r, x1r + ADD x0i, x0i, x1i + SUB x1r, x0r, x1r, LSL #1 + SUB x1i, x0i, x1i, LSL #1 + SUB $h3r, x2r, x3r + SUB $h3i, x2i, x3i + ADD $h2r, x2r, x3r + ADD $h2i, x2i, x3i + ; second stage (radix 2) butterflies + SUB x2i, x0r, $h2r ; swap real and imag here + SUB x2r, x0i, $h2i ; for use later + ADD x0r, x0r, $h2r + ADD x0i, x0i, $h2i + ADDi x3r, x1r, $h3i + SUBi x3i, x1i, $h3r + SUBi x1r, x1r, $h3i + ADDi x1i, x1i, $h3r + ; do the 1/sqrt(2) (+/-1 +/- i) twiddles for third stage + LCLS tempname +tempname SETS "R_rad8" + IMPORT t_$qname$tempname + LDR t1, =t_$qname$tempname +; IMPORT t_$qname.R_rad8 +; LDR t1, =t_$qname.R_rad8 + LOADCOEFR t1, t1 + + STMFD sp!, {dinc} ;;; FIXME!!! + + SUB t0, x1r, x1i ; real part when * (1+i) + SCALE x1r, t0, t1, dinc ; scale by 1/sqrt(2) + ADD t0, t0, x1i, LSL #1 ; imag part when * (1+i) + SCALE x1i, t0, t1, dinc ; scale by 1/sqrt(2) + SUB t0, x3r, x3i ; imag part when * (-1+i) + SCALE x3i, t0, t1, dinc ; scale by 1/sqrt(2) + SUB t0, t0, x3r, LSL #1 ; real part when * (-1+i) + SCALE x3r, t0, t1, dinc ; scale by 1/sqrt(2) + + LDMFD sp!, {dinc} ;;; FIXME!!! + STMFD sp!, {x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i} + MEND + + MACRO + FIRST_STAGE_RADIX8_EVEN $dinc, $bitrev + ; load elements 0,2,4,6 into register order 0,4,2,6 + SETREGS h, x1r, x1i, x2r, x2i, x3r, x3i, t0, t1 + SETREG g3, x0r, x0i + + IF reversed + ; load normally + LOADDATAI inptr, #1<<$datalog, $h0r, $h0i + LOADDATAI inptr, #1<<$datalog, $h1r, $h1i + LOADDATAI inptr, #1<<$datalog, $h2r, $h2i + LOADDATAI inptr, #1<<$datalog, $h3r, $h3i + ADD inptr, inptr, #4<<$datalog + ELSE + ; load bit reversed + ADD x0r, inptr, $bitrev, LSL #$datalog + LOADDATAI x0r, $dinc, $h0r, $h0i + LOADDATAI x0r, $dinc, $h2r, $h2i + LOADDATAI x0r, $dinc, $h1r, $h1i + LOADDATAI x0r, $dinc, $h3r, $h3i + ENDIF + + IF "$prescale"="P" + LDR x0r, [sp, #8+32] ; NB we've stacked 8 extra regs! + MOV $h0r, $h0r, LSL x0r + MOV $h0i, $h0i, LSL x0r + MOV $h1r, $h1r, LSL x0r + MOV $h1i, $h1i, LSL x0r + MOV $h2r, $h2r, LSL x0r + MOV $h2i, $h2i, LSL x0r + MOV $h3r, $h3r, LSL x0r + MOV $h3i, $h3i, LSL x0r + ENDIF + + SHIFTDATA $h0r, $h0i + ; first stage (radix 2) butterflies + ADD $h0r, $h0r, $h1r $postldshift + ADD $h0i, $h0i, $h1i $postldshift + SUB $h1r, $h0r, $h1r $postldshift1 + SUB $h1i, $h0i, $h1i $postldshift1 + SUB $g3r, $h2r, $h3r + SUB $g3i, $h2i, $h3i + ADD $h2r, $h2r, $h3r + ADD $h2i, $h2i, $h3i + ; second stage (radix 2) butterflies + ADD $h0r, $h0r, $h2r $postldshift + ADD $h0i, $h0i, $h2i $postldshift + SUB $h2r, $h0r, $h2r $postldshift1 + SUB $h2i, $h0i, $h2i $postldshift1 + ADDi $h3r, $h1r, $g3i $postldshift + SUBi $h3i, $h1i, $g3r $postldshift + SUBi $h1r, $h1r, $g3i $postldshift + ADDi $h1i, $h1i, $g3r $postldshift + MEND + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/gs_rad4.h b/common_audio/signal_processing_library/main/source/fft_ARM9E/gs_rad4.h new file mode 100644 index 0000000000..ec392ea658 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/gs_rad4.h @@ -0,0 +1,111 @@ +; +; $Copyright: +; ---------------------------------------------------------------- +; This confidential and proprietary software may be used only as +; authorised by a licensing agreement from ARM Limited +; (C) COPYRIGHT 2000,2002 ARM Limited +; ALL RIGHTS RESERVED +; The entire notice above must be reproduced on all authorised +; copies and copies may only be made to the extent permitted +; by a licensing agreement from ARM Limited. +; ---------------------------------------------------------------- +; File: gs_rad4.h,v +; Revision: 1.8 +; ---------------------------------------------------------------- +; $ +; +; Optimised ARM assembler multi-radix FFT +; Please read the readme.txt before this file +; +; This file contains the general stage, radix 4 macro + + MACRO + GS_RAD4 + SETSHIFT postldshift, 2*norm + SETSHIFT postmulshift, 2*norm+qshift + ; dinc contains the number of bytes between the values to read + ; for the radix 4 bufferfly + ; Thus: + ; dinc*4 = number of bytes between the blocks at this level + ; dinc>>datalog = number of elements in each block at this level + MOV count, count, LSR #2 ; a quarter the blocks per stage + STMFD sp!, {dptr, count} + ADD t0, dinc, dinc, LSL #1 ; 3*dinc + ADD dptr, dptr, t0 ; move to last of 4 butterflys + SUB count, count, #1<<16 ; prepare top half of counter +12 ; block loop + ; set top half of counter to (elements/block - 1) + ADD count, count, dinc, LSL #(16-$datalog) +15 ; butterfly loop + IF (architecture>=5):LAND:(qshift<16) + ; E extensions available (21 cycles) + ; But needs a different table format + LDMIA cptr!, {x0i, x1i, x2i} + LDR x2r, [dptr], -dinc + LDR x1r, [dptr], -dinc + LDR x0r, [dptr], -dinc + TWIDDLE_E x3r, x3i, x2i, t0, x2r + TWIDDLE_E x2r, x2i, x1i, t0, x1r + TWIDDLE_E x1r, x1i, x0i, t0, x0r + ELSE + ; load next three twiddle factors (66 @ 4 cycles/mul) + LOADCOEFS cptr, x1r, x1i, x2r, x2i, x3r, x3i + ; load data in reversed order & perform twiddles + LOADDATA dptr, -dinc, x0r, x0i + TWIDDLE x0r, x0i, x3r, x3i, t0, t1 + LOADDATA dptr, -dinc, x0r, x0i + TWIDDLE x0r, x0i, x2r, x2i, t0, t1 + LOADDATA dptr, -dinc, x0r, x0i + TWIDDLE x0r, x0i, x1r, x1i, t0, t1 + ENDIF + LOADDATAZ dptr, x0r, x0i + SHIFTDATA x0r, x0i + ; now calculate the h's + ; h[0,k] = g[0,k] + g[2,k] + ; h[1,k] = g[0,k] - g[2,k] + ; h[2,k] = g[1,k] + g[3,k] + ; h[3,k] = g[1,k] - g[3,k] + SETREGS h,t0,t1,x0r,x0i,x1r,x1i,x2r,x2i + ADD $h0r, x0r, x1r $postmulshift + ADD $h0i, x0i, x1i $postmulshift + SUB $h1r, x0r, x1r $postmulshift + SUB $h1i, x0i, x1i $postmulshift + ADD $h2r, x2r, x3r + ADD $h2i, x2i, x3i + SUB $h3r, x2r, x3r + SUB $h3i, x2i, x3i + ; now calculate the y's and store results + ; y[0*N/4+k] = h[0,k] + h[2,k] + ; y[1*N/4+k] = h[1,k] + j*h[3,k] + ; y[2*N/4+k] = h[0,k] - h[2,k] + ; y[3*N/4+k] = h[1,k] - j*h[3,k] + SETREG y0,x3r,x3i + ADD $y0r, $h0r, $h2r $postmulshift + ADD $y0i, $h0i, $h2i $postmulshift + STORE dptr, dinc, $y0r, $y0i + SUBi $y0r, $h1r, $h3i $postmulshift + ADDi $y0i, $h1i, $h3r $postmulshift + STORE dptr, dinc, $y0r, $y0i + SUB $y0r, $h0r, $h2r $postmulshift + SUB $y0i, $h0i, $h2i $postmulshift + STORE dptr, dinc, $y0r, $y0i + ADDi $y0r, $h1r, $h3i $postmulshift + SUBi $y0i, $h1i, $h3r $postmulshift + STOREP dptr, $y0r, $y0i + ; continue butterfly loop + SUBS count, count, #1<<16 + BGE %BT15 + ; decrement counts for block loop + ADD t0, dinc, dinc, LSL #1 ; dinc * 3 + ADD dptr, dptr, t0 ; move onto next block + SUB cptr, cptr, t0 $cdshift ; move back to coeficients start + SUB count, count, #1 ; done one more block + MOVS t1, count, LSL #16 + BNE %BT12 ; still more blocks to do + ; finished stage + ADD cptr, cptr, t0 $cdshift ; move onto next stage coeficients + LDMFD sp!, {dptr, count} + MOV dinc, dinc, LSL #2 ; four times the entries per block + MEND + + END diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/readme.txt b/common_audio/signal_processing_library/main/source/fft_ARM9E/readme.txt new file mode 100644 index 0000000000..a4929ef418 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/readme.txt @@ -0,0 +1,91 @@ +# $Copyright: +# ---------------------------------------------------------------- +# This confidential and proprietary software may be used only as +# authorised by a licensing agreement from ARM Limited +# (C) COPYRIGHT 2000,2002 ARM Limited +# ALL RIGHTS RESERVED +# The entire notice above must be reproduced on all authorised +# copies and copies may only be made to the extent permitted +# by a licensing agreement from ARM Limited. +# ---------------------------------------------------------------- +# File: readme.txt,v +# Revision: 1.4 +# ---------------------------------------------------------------- +# $ + + + +!!! To fully understand the FFT/ARM9E/WIN_MOB implementation in SPLIB, +!!! you have to refer to the full set of files in RVDS' package: +!!! C:\Program Files\ARM\RVDS\Examples\3.0\79\windows\fft_v5te. + + + + ARM Assembler FFT implementation + ================================ + + Overview + ======== + +This implementation has been restructured to allow FFT's of varying radix +rather than the fixed radix-2 or radix-4 versions allowed earlier. The +implementation of an optimised assembler FFT of a given size (N points) +consists of chaining together a sequence of stages 1,2,3,...,k such that the +j'th stage has radix Rj and: + + N = R1*R2*R3*...*Rk + +For the ARM implementations we keep the size of the Rj's decreasing with +increasing j, EXCEPT that if there are any non power of 2 factors (ie, odd +prime factors) then these come before all the power of 2 factors. + +For example: + + N=64 would be implemented as stages: + radix 4, radix 4, radix 4 + + N=128 would be implemented as stages: + radix 8, radix 4, radix 4 + OR + radix 4, radix 4, radix 4, radix 2 + + N=192 would be implemented as stages: + radix 3, radix 4, radix 4, radix 4 + +The bitreversal is usally combined with the first stage where possible. + + + Structure + ========= + +The actual FFT routine is built out of a hierarchy of macros. All stage +macros and filenames are one of: + + fs_rad => the macro implements a radix First Stage (usually + including the bit reversal) + + gs_rad => the macro implements a radix General Stage (any + stage except the first - includes the twiddle operations) + + ls_rad => the macro implements a radix Last Stage (this macro + is like the gs_rad version but is optimised for + efficiency in the last stage) + + ls_ztor => this macro converts the output of a complex FFT to + be the first half of the output of a real FFT of + double the number of input points. + +Other files are: + + fft_mac.h => Macro's and register definitions shared by all radix + implementations + + fft_main.h => Main FFT macros drawing together the stage macros + to produce a complete FFT + + + Interfaces + ========== + +The register interfaces for the different type of stage macros are described +at the start of fft_mac.h diff --git a/common_audio/signal_processing_library/main/source/fft_ARM9E/t_01024_8.c b/common_audio/signal_processing_library/main/source/fft_ARM9E/t_01024_8.c new file mode 100644 index 0000000000..17efd07c60 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/t_01024_8.c @@ -0,0 +1,695 @@ +/* + * Copyright (C) ARM Limited 1998-2002. All rights reserved. + * + * t_01024_8.c + * + */ + +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_library/main/source/fft_ARM9E/t_rad.c b/common_audio/signal_processing_library/main/source/fft_ARM9E/t_rad.c new file mode 100644 index 0000000000..66ed6addb4 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/fft_ARM9E/t_rad.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) ARM Limited 1998-2000. All rights reserved. + * + * t_rad.c + * + */ + +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/signal_processing_library/main/source/filter_ar.c b/common_audio/signal_processing_library/main/source/filter_ar.c new file mode 100644 index 0000000000..30a56c1c64 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/filter_ar.c @@ -0,0 +1,92 @@ +/* + * 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; + + state_low_length = state_low_length; + filtered_low_length = filtered_low_length; + + 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_library/main/source/filter_ar4.c b/common_audio/signal_processing_library/main/source/filter_ar4.c new file mode 100644 index 0000000000..f60bd4f3a9 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/filter_ar4.c @@ -0,0 +1,130 @@ +/* + * filter_ar4.c + * + * This file contains the function WebRtcSpl_FilterAR4(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +int WebRtcSpl_FilterAR4(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, int max_length, WebRtc_Word16 *filtered_low, + int filtered_low_length) +{ + WebRtc_Word32 o; + WebRtc_Word32 oLOW; + int i; + int j; + int stop; + G_CONST WebRtc_Word16 *a_ptr; + WebRtc_Word16 *filtered_ptr; + WebRtc_Word16 *filtered_low_ptr; + WebRtc_Word16 *state_ptr; + WebRtc_Word16 *state_low_ptr; + G_CONST WebRtc_Word16 *x_ptr = &x[0]; + WebRtc_Word16 *filteredFINAL_ptr = filtered; + WebRtc_Word16 *filteredFINAL_LOW_ptr = filtered_low; + +#ifdef _DEBUG + if (max_length < x_length) + { + printf(" FilterAR4 : out vector is shorter than in vector\n"); + exit(0); + } + if (state_length != a_length - 1) + { + printf(" FilterAR4 : state vector does not have the correct length\n"); + exit(0); + } +#endif + + /* Unused input variable */ + max_length = max_length; + state_low_length = state_low_length; + filtered_low_length = filtered_low_length; + + for (i = 0; i < 4; i++) + { + a_ptr = &a[1]; + filtered_ptr = &filtered[i - 1]; + filtered_low_ptr = &filtered_low[i - 1]; + state_ptr = &state[state_length - 1]; + state_low_ptr = &state_low[state_length - 1]; + + o = (WebRtc_Word32)(*x_ptr++) << 12; // Q12 operations + 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); // Q12 operations + *filteredFINAL_ptr = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);// Q12 operations + *filteredFINAL_LOW_ptr++ = (WebRtc_Word16)(o - ((WebRtc_Word32)(*filteredFINAL_ptr++) + << 12)); + } + + for (i = 4; i < x_length; i++) + { + /* Calculate filtered[0] */ + a_ptr = &a[1]; + filtered_ptr = &filtered[i - 1]; + filtered_low_ptr = &filtered_low[i - 1]; + + o = (WebRtc_Word32)(*x_ptr++) << 12; // Q12 operations + oLOW = 0; + + o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--); + oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--); + + o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--); + oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--); + + o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--); + oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--); + + o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--); + oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--); + + o += (oLOW >> 12); // Q12 operations + *filteredFINAL_ptr = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);// Q12 operations + *filteredFINAL_LOW_ptr++ = (WebRtc_Word16)(o - ((WebRtc_Word32)(*filteredFINAL_ptr++) + << 12)); + } + + if (x_length >= state_length) + { + WebRtcSpl_CopyFromEndW16(filtered, x_length, a_length - 1, state, state_length); + WebRtcSpl_CopyFromEndW16(filtered_low, x_length, a_length - 1, state_low, state_length); + } 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_library/main/source/filter_ar_fast_q12.c b/common_audio/signal_processing_library/main/source/filter_ar_fast_q12.c new file mode 100644 index 0000000000..6184da3f4c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/filter_ar_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_FilterARFastQ12(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_FilterARFastQ12(WebRtc_Word16 *in, WebRtc_Word16 *out, WebRtc_Word16 *A, + WebRtc_Word16 A_length, WebRtc_Word16 length) +{ + WebRtc_Word32 o; + int i, j; + + WebRtc_Word16 *x_ptr = &in[0]; + WebRtc_Word16 *filtered_ptr = &out[0]; + + for (i = 0; i < length; i++) + { + // Calculate filtered[i] + G_CONST WebRtc_Word16 *a_ptr = &A[0]; + WebRtc_Word16 *state_ptr = &out[i - 1]; + + o = WEBRTC_SPL_MUL_16_16(*x_ptr++, *a_ptr++); + + for (j = 1; j < A_length; j++) + { + o -= WEBRTC_SPL_MUL_16_16(*a_ptr++,*state_ptr--); + } + + // Saturate the output + o = WEBRTC_SPL_SAT((WebRtc_Word32)134215679, o, (WebRtc_Word32)-134217728); + + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); + } + + return; +} diff --git a/common_audio/signal_processing_library/main/source/filter_ar_sample_based.c b/common_audio/signal_processing_library/main/source/filter_ar_sample_based.c new file mode 100644 index 0000000000..3d4ccac4b1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/filter_ar_sample_based.c @@ -0,0 +1,48 @@ +/* + * filter_ar_sample_based.c + * + * This file contains the function WebRtcSpl_FilterARSampleBased(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_FilterARSampleBased(WebRtc_Word16 *InOut, WebRtc_Word16 *InOutLOW, + WebRtc_Word16 *Coef, WebRtc_Word16 orderCoef) +{ + int k; + WebRtc_Word32 temp, tempLOW; + WebRtc_Word16 *ptrIn, *ptrInLOW, *ptrCoef; + + temp = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)*InOut, 12); + tempLOW = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)*InOutLOW, 12); + + // Filter integer part + ptrIn = InOut - 1; + ptrCoef = Coef + 1; + for (k = 0; k < orderCoef; k++) + { + temp -= WEBRTC_SPL_MUL_16_16((*ptrCoef), (*ptrIn)); + ptrCoef++; + ptrIn--; + } + + // Filter lower part (Q12) + ptrInLOW = InOutLOW - 1; + ptrCoef = Coef + 1; + for (k = 0; k < orderCoef; k++) + { + tempLOW -= WEBRTC_SPL_MUL_16_16((*ptrCoef), (*ptrInLOW)); + ptrCoef++; + ptrInLOW--; + } + + temp += WEBRTC_SPL_RSHIFT_W32(tempLOW, 12); // build WebRtc_Word32 result in Q12 + + // 2048 == (0.5 << 12) for rounding, InOut is in (Q0) + *InOut = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp+2048), 12); + + // InOutLOW is in Q12 + *InOutLOW = (WebRtc_Word16)(temp - (WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)(*InOut), 12))); +} diff --git a/common_audio/signal_processing_library/main/source/filter_ma.c b/common_audio/signal_processing_library/main/source/filter_ma.c new file mode 100644 index 0000000000..1db04cfa55 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/filter_ma.c @@ -0,0 +1,68 @@ +/* + * filter_ma.c + * + * This file contains the function WebRtcSpl_FilterMA(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +int WebRtcSpl_FilterMA(G_CONST WebRtc_Word16 *b, int b_length, G_CONST WebRtc_Word16 *x, + int x_length, WebRtc_Word16 *state, int state_length, + WebRtc_Word16 *filtered, int max_length) +{ + WebRtc_Word32 o; + int i, j, stop; + WebRtc_Word16 *filtered_ptr = filtered; + + /* Unused input variable */ + max_length = max_length; + + for (i = 0; i < x_length; i++) + { + G_CONST WebRtc_Word16 *b_ptr = &b[0]; + G_CONST WebRtc_Word16 *x_ptr = &x[i]; + WebRtc_Word16 *state_ptr = &state[state_length - 1]; + + o = (WebRtc_Word32)0; + stop = (i < b_length) ? i + 1 : b_length; + + for (j = 0; j < stop; j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + } + for (j = i + 1; j < b_length; j++) + { + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + } + + /* If output is higher than 32768, saturate it. Same with negative side + 2^27 = 134217728, which corresponds to 32768 in Q12 */ + if (o < (WebRtc_Word32)-134217728) + o = (WebRtc_Word32)-134217728; + + if (o > (WebRtc_Word32)(134217727 - 2048)) + o = (WebRtc_Word32)(134217727 - 2048); + + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); + } + + /* Save filter state */ + if (x_length >= state_length) + { + WebRtcSpl_CopyFromEndW16(x, x_length, b_length - 1, state, state_length); + } else + { + for (i = 0; i < state_length - x_length; i++) + { + state[i] = state[i + x_length]; + } + for (i = 0; i < x_length; i++) + { + state[state_length - x_length + i] = x[i]; + } + } + + return x_length; +} diff --git a/common_audio/signal_processing_library/main/source/filter_ma4.c b/common_audio/signal_processing_library/main/source/filter_ma4.c new file mode 100644 index 0000000000..d0dc7e46da --- /dev/null +++ b/common_audio/signal_processing_library/main/source/filter_ma4.c @@ -0,0 +1,120 @@ +/* + * filter_ma4.c + * + * This file contains the function WebRtcSpl_FilterMA4(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +int WebRtcSpl_FilterMA4(G_CONST WebRtc_Word16 *b, int b_length, G_CONST WebRtc_Word16 *x, + int x_length, WebRtc_Word16 *state, int state_length, + WebRtc_Word16 *filtered, int max_length) +{ + WebRtc_Word32 o; + int i; + + WebRtc_Word16 *filtered_ptr = filtered; + /* Calculate filtered[0] */G_CONST WebRtc_Word16 *b_ptr = &b[0]; + G_CONST WebRtc_Word16 *x_ptr = &x[0]; + WebRtc_Word16 *state_ptr = &state[state_length - 1]; + + /* Unused input variable */ + max_length = max_length; + + o = (WebRtc_Word32)0; + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); // Q12 operations + +#ifdef _DEBUG + if (max_length < x_length) + { + printf("FilterMA4: out vector is shorter than in vector\n"); + exit(0); + } + if ((state_length != 4) || (b_length != 5)) + { + printf("FilterMA4: state or coefficient vector does not have the correct length\n"); + exit(0); + } +#endif + + /* Calculate filtered[1] */ + b_ptr = &b[0]; + x_ptr = &x[1]; + state_ptr = &state[state_length - 1]; + o = (WebRtc_Word32)0; + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); // Q12 operations + + /* Calculate filtered[2] */ + b_ptr = &b[0]; + x_ptr = &x[2]; + state_ptr = &state[state_length - 1]; + o = (WebRtc_Word32)0; + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); // Q12 operations + + /* Calculate filtered[3] */ + b_ptr = &b[0]; + x_ptr = &x[3]; + state_ptr = &state[state_length - 1]; + o = (WebRtc_Word32)0; + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *state_ptr--); + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); // Q12 operations + + for (i = 4; i < x_length; i++) + { + o = (WebRtc_Word32)0; + + b_ptr = &b[0]; + x_ptr = &x[i]; + + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--); + + *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12); // Q12 operations + } + + if (x_length >= state_length) + { + WebRtcSpl_CopyFromEndW16(x, x_length, b_length - 1, state, state_length); + } else + { + for (i = 0; i < state_length - x_length; i++) + { + state[i] = state[i + x_length]; + } + for (i = 0; i < x_length; i++) + { + state[state_length - x_length + i] = x[i]; + } + } + + return x_length; +} diff --git a/common_audio/signal_processing_library/main/source/filter_ma_fast_q12.c b/common_audio/signal_processing_library/main/source/filter_ma_fast_q12.c new file mode 100644 index 0000000000..19ad9b166d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/get_column.c b/common_audio/signal_processing_library/main/source/get_column.c new file mode 100644 index 0000000000..a01a5308e8 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/get_column.c @@ -0,0 +1,46 @@ +/* + * get_column.c + * + * This file contains the function WebRtcSpl_GetColumn(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +WebRtc_Word16 WebRtcSpl_GetColumn(G_CONST WebRtc_Word32 *matrix, WebRtc_Word16 number_of_rows, + WebRtc_Word16 number_of_cols, WebRtc_Word16 column_chosen, + WebRtc_Word32 *column_out, WebRtc_Word16 max_length) +{ + WebRtc_Word16 i; + WebRtc_Word32 *outarrptr = column_out; + G_CONST WebRtc_Word32 *matptr = &matrix[column_chosen]; + +#ifdef _DEBUG + if (max_length < number_of_rows) + { + printf(" GetColumn : out vector is shorter than the column length\n"); + exit(0); + } + if ((column_chosen < 0) || (column_chosen >= number_of_cols)) + { + printf(" GetColumn : selected column is negative or larger than the dimension of the matrix\n"); + exit(0); + } +#endif + + /* Unused input variable */ + max_length = max_length; + + for (i = 0; i < number_of_rows; i++) + { + (*outarrptr++) = (*matptr); + matptr += number_of_cols; + } + return number_of_rows; +} diff --git a/common_audio/signal_processing_library/main/source/get_hanning_window.c b/common_audio/signal_processing_library/main/source/get_hanning_window.c new file mode 100644 index 0000000000..2845c8385a --- /dev/null +++ b/common_audio/signal_processing_library/main/source/get_hanning_window.c @@ -0,0 +1,41 @@ +/* + * 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" + +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++) = WebRtcSpl_kHanningTable[index >> 22]; + } + +} diff --git a/common_audio/signal_processing_library/main/source/get_row.c b/common_audio/signal_processing_library/main/source/get_row.c new file mode 100644 index 0000000000..fca109620a --- /dev/null +++ b/common_audio/signal_processing_library/main/source/get_row.c @@ -0,0 +1,45 @@ +/* + * get_rows.c + * + * This file contains the function WebRtcSpl_GetRow(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +WebRtc_Word16 WebRtcSpl_GetRow(G_CONST WebRtc_Word32 *matrix, WebRtc_Word16 number_of_rows, + WebRtc_Word16 number_of_cols, WebRtc_Word16 row_chosen, + WebRtc_Word32 *row_out, WebRtc_Word16 max_length) +{ + WebRtc_Word16 i; + WebRtc_Word32 *outarrptr = row_out; + G_CONST WebRtc_Word32 *matptr = &matrix[row_chosen * number_of_cols]; + +#ifdef _DEBUG + if (max_length < number_of_cols) + { + printf(" GetRow : out vector is shorter than the row length\n"); + exit(0); + } + if ((row_chosen < 0) || (row_chosen >= number_of_rows)) + { + printf(" GetRow : selected row is negative or larger than the dimension of the matrix\n"); + exit(0); + } +#endif + /* Unused input variable */ + max_length = max_length; + number_of_rows = number_of_rows; + + for (i = 0; i < number_of_cols; i++) + { + (*outarrptr++) = (*matptr++); + } + return number_of_cols; +} diff --git a/common_audio/signal_processing_library/main/source/get_scaling.c b/common_audio/signal_processing_library/main/source/get_scaling.c new file mode 100644 index 0000000000..44a47c6a17 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/get_scaling.c @@ -0,0 +1,46 @@ +/* + * 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_GetScaling(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +int WebRtcSpl_GetScaling(WebRtc_Word16 *in_vector, int in_vector_length, int times) +{ + int nbits = WebRtcSpl_GetSizeInBits(times); + int i; + WebRtc_Word16 sabs; + int t; + WebRtc_Word16 *sptr = in_vector; + WebRtc_Word16 smax = *sptr++; + + for (i = in_vector_length - 1; i > 0; i--) + { + sabs = WEBRTC_SPL_ABS_W16 (*sptr); + sptr++; + if (sabs > smax) + smax = sabs; + } + + t = WebRtcSpl_NormW32((WebRtc_Word32)smax << 16); + + if (smax == 0) + { + return 0; // Since norm(0) returns 0 + } else + { + return (t > nbits) ? 0 : nbits - t; + } +} diff --git a/common_audio/signal_processing_library/main/source/get_scaling_square.c b/common_audio/signal_processing_library/main/source/get_scaling_square.c new file mode 100644 index 0000000000..dccbf334fd --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/get_size_in_bits.c b/common_audio/signal_processing_library/main/source/get_size_in_bits.c new file mode 100644 index 0000000000..53853f0531 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/get_size_in_bits.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_GetSizeInBits(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 value) +{ + + int bits = 0; + + // Fast binary search to find the number of bits used + if ((0xFFFF0000 & value)) + bits = 16; + if ((0x0000FF00 & (value >> bits))) + bits += 8; + if ((0x000000F0 & (value >> bits))) + bits += 4; + if ((0x0000000C & (value >> bits))) + bits += 2; + if ((0x00000002 & (value >> bits))) + bits += 1; + if ((0x00000001 & (value >> bits))) + bits += 1; + + return bits; +} + +#endif diff --git a/common_audio/signal_processing_library/main/source/hanning_table.c b/common_audio/signal_processing_library/main/source/hanning_table.c new file mode 100644 index 0000000000..112d0e592f --- /dev/null +++ b/common_audio/signal_processing_library/main/source/hanning_table.c @@ -0,0 +1,53 @@ +/* + * 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 Hanning table with 256 entries. + * + */ + +#include "signal_processing_library.h" + +// Hanning table with 256 entries +WebRtc_Word16 WebRtcSpl_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 +}; diff --git a/common_audio/signal_processing_library/main/source/ilbc_specific_functions.c b/common_audio/signal_processing_library/main/source/ilbc_specific_functions.c new file mode 100644 index 0000000000..5a9e5773b3 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/ilbc_specific_functions.c @@ -0,0 +1,120 @@ +/* + * 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 iLBC specific functions + * WebRtcSpl_ScaleAndAddVectorsWithRound() + * WebRtcSpl_ReverseOrderMultArrayElements() + * WebRtcSpl_ElementwiseVectorMult() + * WebRtcSpl_AddVectorsAndShift() + * WebRtcSpl_AddAffineVectorToVector() + * WebRtcSpl_AffineTransformVector() + * + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ScaleAndAddVectorsWithRound(WebRtc_Word16 *vector1, WebRtc_Word16 scale1, + WebRtc_Word16 *vector2, WebRtc_Word16 scale2, + WebRtc_Word16 right_shifts, WebRtc_Word16 *out, + WebRtc_Word16 vector_length) +{ + int i; + WebRtc_Word16 roundVal; + roundVal = 1 << right_shifts; + roundVal = roundVal >> 1; + for (i = 0; i < vector_length; i++) + { + out[i] = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16(vector1[i], scale1) + + WEBRTC_SPL_MUL_16_16(vector2[i], scale2) + roundVal) >> right_shifts); + } +} + +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_library/main/source/increase_seed.c b/common_audio/signal_processing_library/main/source/increase_seed.c new file mode 100644 index 0000000000..ac19983e70 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/increase_seed.c @@ -0,0 +1,24 @@ +/* + * 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_IncreaseSeed(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_UWord32 WebRtcSpl_IncreaseSeed(WebRtc_UWord32 *seed) +{ + seed[0] = (seed[0] * ((WebRtc_Word32)69069) + 1) & (WEBRTC_SPL_MAX_SEED_USED - 1); + return seed[0]; +} diff --git a/common_audio/signal_processing_library/main/source/k_to_a.c b/common_audio/signal_processing_library/main/source/k_to_a.c new file mode 100644 index 0000000000..48adc54d68 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/k_to_a.c @@ -0,0 +1,51 @@ +/* + * refl_coef_to_lpc.c + * + * 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_library/main/source/k_to_a_qscale.c b/common_audio/signal_processing_library/main/source/k_to_a_qscale.c new file mode 100644 index 0000000000..c5f27ce7ce --- /dev/null +++ b/common_audio/signal_processing_library/main/source/k_to_a_qscale.c @@ -0,0 +1,54 @@ +/* + * 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_KToAQScale(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_KToAQScale(WebRtc_Word16* k, int use_order, int Q, WebRtc_Word16* a) +{ + WebRtc_Word16 any[WEBRTC_SPL_MAX_LPC_ORDER]; + WebRtc_Word16* aptr; + WebRtc_Word16* aptr2; + WebRtc_Word16* anyptr; + WebRtc_Word16* kptr; + int m, i, Qscale; + + Qscale = 15 - Q; // Q-domain for A-coeff + kptr = k; + *a = *k >> Qscale; + + for (m = 0; m < (use_order - 1); m++) + { + kptr++; + aptr = a; + aptr2 = &a[m]; + anyptr = any; + + for (i = 0; i < m + 1; i++) + *anyptr++ = (*aptr++) + (WebRtc_Word16)(((WebRtc_Word32)(*aptr2--) + * (WebRtc_Word32)*kptr) >> 15); + + any[m + 1] = *kptr >> Qscale; // compute the next coefficient for next loop + aptr = a; + anyptr = any; + for (i = 0; i < (m + 2); i++) + { + *aptr = *anyptr; + *aptr++; + *anyptr++; + } + } +} diff --git a/common_audio/signal_processing_library/main/source/k_to_lar_w16.c b/common_audio/signal_processing_library/main/source/k_to_lar_w16.c new file mode 100644 index 0000000000..4bba708c82 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/k_to_lar_w16.c @@ -0,0 +1,31 @@ +/* + * k_to_lar_w16.c + * + * This file contains the function WebRtcSpl_KToLarW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_KToLarW16(WebRtc_Word16 *kLar, int use_order) +{ + // The LARs are computed from the reflection coefficients using + // a linear approximation of the logarithm. + WebRtc_Word16 tmp16; + int i; + for (i = 0; i < use_order; i++, kLar++) + { + tmp16 = WEBRTC_SPL_ABS_W16( *kLar ); + if (tmp16 < 22118) + tmp16 >>= 1; + else if (tmp16 < 31130) + tmp16 -= 11059; + else + { + tmp16 -= 26112; + tmp16 <<= 2; + } + *kLar = *kLar < 0 ? -tmp16 : tmp16; + } +} diff --git a/common_audio/signal_processing_library/main/source/k_to_lar_w32.c b/common_audio/signal_processing_library/main/source/k_to_lar_w32.c new file mode 100644 index 0000000000..6caaa87f7f --- /dev/null +++ b/common_audio/signal_processing_library/main/source/k_to_lar_w32.c @@ -0,0 +1,31 @@ +/* + * k_to_lar_w32.c + * + * This file contains the function WebRtcSpl_KToLarW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_KToLarW32(WebRtc_Word32 *kLar, int use_order) +{ + // The LARs are computed from the reflection coefficients using + // a linear approximation of the logarithm. + WebRtc_Word32 tmp; + int i; + for (i = 0; i < use_order; i++, kLar++) + { + tmp = WEBRTC_SPL_ABS_W16(*kLar); + if (tmp < (WebRtc_Word32)1300000000) + tmp >>= 1; + else if (tmp < (WebRtc_Word32)2000000000) + tmp -= 650000000; + else + { + tmp -= 1662500000; + tmp <<= 2; + } + *kLar = *kLar < 0 ? -tmp : tmp; + } +} diff --git a/common_audio/signal_processing_library/main/source/lar_to_k_w16.c b/common_audio/signal_processing_library/main/source/lar_to_k_w16.c new file mode 100644 index 0000000000..7860a73ec1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/lar_to_k_w16.c @@ -0,0 +1,29 @@ +/* + * lar_to_refl_coef_w16.c + * + * This file contains the function WebRtcSpl_LarToReflCoefW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_LarToReflCoefW16(WebRtc_Word16 *kLAR, int use_order) +{ + int i; + WebRtc_Word16 temp; + for (i = 0; i < use_order; i++, kLAR++) + { + if ( *kLAR < 0) + { + temp = *kLAR == WEBRTC_SPL_WORD16_MIN ? WEBRTC_SPL_WORD16_MAX : -( *kLAR); + *kLAR = -((temp < 11059) ? temp << 1 : ((temp < 20070) ? temp + 11059 + : WEBRTC_SPL_ADD_SAT_W16( temp >> 2, 26112 ))); + } else + { + temp = *kLAR; + *kLAR = (temp < 11059) ? temp << 1 : ((temp < 20070) ? temp + 11059 + : WEBRTC_SPL_ADD_SAT_W16( temp >> 2, 26112 )); + } + } +} diff --git a/common_audio/signal_processing_library/main/source/lar_to_k_w32.c b/common_audio/signal_processing_library/main/source/lar_to_k_w32.c new file mode 100644 index 0000000000..fe65491ea3 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/lar_to_k_w32.c @@ -0,0 +1,32 @@ +/* + * lar_to_refl_coef_w32.c + * + * This file contains the function WebRtcSpl_LarToReflCoefW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_LarToReflCoefW32(WebRtc_Word32 *kLAR, int use_order) +{ + int i; + WebRtc_Word32 temp; + for (i = 0; i < use_order; i++, kLAR++) + { + if (*kLAR < 0) + { + temp = (*kLAR == WEBRTC_SPL_WORD32_MIN) ? WEBRTC_SPL_WORD32_MAX : -(*kLAR); + *kLAR = -((temp < (WebRtc_Word32)650000000) ? temp << 1 : ((temp + < (WebRtc_Word32)1350000000) ? temp + 650000000 + : WEBRTC_SPL_ADD_SAT_W32( temp >> 2, 1662500000 ))); + } else + { + temp = *kLAR; + *kLAR = (temp < (WebRtc_Word32)650000000) ? temp << 1 : ((temp + < (WebRtc_Word32)1350000000) ? temp + 650000000 + : WEBRTC_SPL_ADD_SAT_W32( temp >> 2, 1662500000 )); + } + + } +} diff --git a/common_audio/signal_processing_library/main/source/levinson_durbin.c b/common_audio/signal_processing_library/main/source/levinson_durbin.c new file mode 100644 index 0000000000..4e11cdb1fe --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/lpc_coefficients.c b/common_audio/signal_processing_library/main/source/lpc_coefficients.c new file mode 100644 index 0000000000..8ec53d1a45 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/lpc_coefficients.c @@ -0,0 +1,37 @@ +/* + * 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_Lpc(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +int WebRtcSpl_Lpc(G_CONST WebRtc_Word16 *x, int x_length, int order, + WebRtc_Word16 *lpcvec) // out Q12 +{ + int cvlen, corrvlen; + int scaleDUMMY; + WebRtc_Word32 corrvector[WEBRTC_SPL_MAX_LPC_ORDER + 1]; + WebRtc_Word16 reflCoefs[WEBRTC_SPL_MAX_LPC_ORDER]; + + cvlen = order + 1; + corrvlen = WebRtcSpl_AutoCorrelation(x, x_length, order, corrvector, &scaleDUMMY); + if (*corrvector == 0) + *corrvector = WEBRTC_SPL_WORD16_MAX; + + WebRtcSpl_AutoCorrToReflCoef(corrvector, order, reflCoefs); + WebRtcSpl_ReflCoefToLpc(reflCoefs, order, lpcvec); + + return cvlen; +} diff --git a/common_audio/signal_processing_library/main/source/lpc_to_refl_coef.c b/common_audio/signal_processing_library/main/source/lpc_to_refl_coef.c new file mode 100644 index 0000000000..2cb83c2e1d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/max_abs_index_w16.c b/common_audio/signal_processing_library/main/source/max_abs_index_w16.c new file mode 100644 index 0000000000..ff95bf3741 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_abs_index_w16.c @@ -0,0 +1,33 @@ +/* + * max_abs_index_w16.c + * + * This file contains the function WebRtcSpl_MaxAbsIndexW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_MaxAbsIndexW16(G_CONST WebRtc_Word16* vector, + WebRtc_Word16 vector_length) +{ + WebRtc_Word16 tempMax; + WebRtc_Word16 absTemp; + WebRtc_Word16 tempMaxIndex, i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + tempMaxIndex = 0; + tempMax = WEBRTC_SPL_ABS_W16(*tmpvector); + tmpvector++; + for (i = 1; i < vector_length; i++) + { + absTemp = WEBRTC_SPL_ABS_W16(*tmpvector); + tmpvector++; + if (absTemp > tempMax) + { + tempMax = absTemp; + tempMaxIndex = i; + } + } + return tempMaxIndex; +} diff --git a/common_audio/signal_processing_library/main/source/max_abs_value_w16.c b/common_audio/signal_processing_library/main/source/max_abs_value_w16.c new file mode 100644 index 0000000000..a03b454949 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_abs_value_w16.c @@ -0,0 +1,75 @@ +/* + * max_abs_value_w16.c + * + * This file contains the function WebRtcSpl_MaxAbsValueW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length) +{ + WebRtc_Word32 tempMax = 0; + WebRtc_Word32 absVal; + WebRtc_Word16 totMax; + int i; + G_CONST WebRtc_Word16 *tmpvector = vector; + +#ifdef _ARM_OPT_ +#pragma message("NOTE: _ARM_OPT_ optimizations are used") + WebRtc_Word16 len4 = (length >> 2) << 2; +#endif + +#ifndef _ARM_OPT_ + for (i = 0; i < length; i++) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } +#else + for (i = 0; i < len4; i = i + 4) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } + + for (i = len4; i < len; i++) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } +#endif + totMax = (WebRtc_Word16)WEBRTC_SPL_MIN(tempMax, WEBRTC_SPL_WORD16_MAX); + return totMax; +} diff --git a/common_audio/signal_processing_library/main/source/max_abs_value_w32.c b/common_audio/signal_processing_library/main/source/max_abs_value_w32.c new file mode 100644 index 0000000000..589db5a620 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_abs_value_w32.c @@ -0,0 +1,31 @@ +/* + * max_abs_value_w32.c + * + * This file contains the function WebRtcSpl_MaxAbsValueW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word32 WebRtcSpl_MaxAbsValueW32(G_CONST WebRtc_Word32 *vector, // (i) Input vector + WebRtc_Word16 length) // (i) Number of elements +{ + WebRtc_UWord32 tempMax = 0; + WebRtc_UWord32 absVal; + WebRtc_Word32 retval; + int i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + for (i = 0; i < length; i++) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } + retval = (WebRtc_Word32)(WEBRTC_SPL_MIN(tempMax, WEBRTC_SPL_WORD32_MAX)); + return retval; +} diff --git a/common_audio/signal_processing_library/main/source/max_index_w16.c b/common_audio/signal_processing_library/main/source/max_index_w16.c new file mode 100644 index 0000000000..bc17518fb1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_index_w16.c @@ -0,0 +1,28 @@ +/* + * max_index_w16.c + * + * This file contains the function WebRtcSpl_MaxIndexW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_MaxIndexW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMax; + WebRtc_Word16 tempMaxIndex, i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + tempMaxIndex = 0; + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if ( *tmpvector++ > tempMax) + { + tempMax = vector[i]; + tempMaxIndex = i; + } + } + return tempMaxIndex; +} diff --git a/common_audio/signal_processing_library/main/source/max_index_w32.c b/common_audio/signal_processing_library/main/source/max_index_w32.c new file mode 100644 index 0000000000..64913096cf --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_index_w32.c @@ -0,0 +1,29 @@ +/* + * max_index_w32.c + * + * This file contains the function WebRtcSpl_MaxIndexW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_MaxIndexW32(G_CONST WebRtc_Word32* vector, // (i) Input vector + WebRtc_Word16 length) // (i) Number of elements +{ + WebRtc_Word32 tempMax; + WebRtc_Word16 tempMaxIndex, i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + tempMaxIndex = 0; + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + { + tempMax = vector[i]; + tempMaxIndex = i; + } + } + return tempMaxIndex; +} diff --git a/common_audio/signal_processing_library/main/source/max_value_w16.c b/common_audio/signal_processing_library/main/source/max_value_w16.c new file mode 100644 index 0000000000..09b8c66613 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_value_w16.c @@ -0,0 +1,30 @@ +/* + * max_value_w16.c + * + * This file contains the function WebRtcSpl_MaxValueW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef XSCALE_OPT + +WebRtc_Word16 WebRtcSpl_MaxValueW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMax; + WebRtc_Word16 i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + tempMax = vector[i]; + } + return tempMax; +} + +#else +#pragma message(">> max_value_w16.c is excluded from this build") +#endif diff --git a/common_audio/signal_processing_library/main/source/max_value_w32.c b/common_audio/signal_processing_library/main/source/max_value_w32.c new file mode 100644 index 0000000000..7c97ace9e0 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/max_value_w32.c @@ -0,0 +1,31 @@ +/* + * max_value_w32.c + * + * This file contains the function WebRtcSpl_MaxValueW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef XSCALE_OPT + +WebRtc_Word32 WebRtcSpl_MaxValueW32(G_CONST WebRtc_Word32* vector, // (i) Input vector + WebRtc_Word16 length) // (i) Number of elements +{ + WebRtc_Word32 tempMax; + WebRtc_Word16 i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + tempMax = vector[i]; + } + return tempMax; +} + +#else +#pragma message(">> max_value_w32.c is excluded from this build") +#endif diff --git a/common_audio/signal_processing_library/main/source/memcpy_reversed_order.c b/common_audio/signal_processing_library/main/source/memcpy_reversed_order.c new file mode 100644 index 0000000000..c4190e276d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/memcpy_reversed_order.c @@ -0,0 +1,30 @@ +/* + * 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_MemCpyReversedOrder(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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++; + } +} diff --git a/common_audio/signal_processing_library/main/source/memset_w16.c b/common_audio/signal_processing_library/main/source/memset_w16.c new file mode 100644 index 0000000000..c60bc8acb5 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/memset_w16.c @@ -0,0 +1,29 @@ +/* + * 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_MemSetW16(). + * The description header can be found in signal_processing_library.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; + } +} diff --git a/common_audio/signal_processing_library/main/source/memset_w32.c b/common_audio/signal_processing_library/main/source/memset_w32.c new file mode 100644 index 0000000000..60468d7aff --- /dev/null +++ b/common_audio/signal_processing_library/main/source/memset_w32.c @@ -0,0 +1,29 @@ +/* + * 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_MemSetW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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; + } +} diff --git a/common_audio/signal_processing_library/main/source/min_index_w16.c b/common_audio/signal_processing_library/main/source/min_index_w16.c new file mode 100644 index 0000000000..8226fae237 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/min_index_w16.c @@ -0,0 +1,35 @@ +/* + * min_index_w16.c + * + * This file contains the function WebRtcSpl_MinIndexW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef XSCALE_OPT + +WebRtc_Word16 WebRtcSpl_MinIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 vector_length) +{ + WebRtc_Word16 tempMin; + WebRtc_Word16 tempMinIndex, i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + // Find index of smallest value + tempMinIndex = 0; + tempMin = *tmpvector++; + for (i = 1; i < vector_length; i++) + { + if (*tmpvector++ < tempMin) + { + tempMin = vector[i]; + tempMinIndex = i; + } + } + return tempMinIndex; +} + +#else +#pragma message(">> min_index_w16.c is excluded from this build") +#endif diff --git a/common_audio/signal_processing_library/main/source/min_index_w32.c b/common_audio/signal_processing_library/main/source/min_index_w32.c new file mode 100644 index 0000000000..2b53f9000c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/min_index_w32.c @@ -0,0 +1,36 @@ +/* + * min_index_w16.c + * + * This file contains the function WebRtcSpl_MinIndexW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef XSCALE_OPT + +WebRtc_Word16 WebRtcSpl_MinIndexW32(G_CONST WebRtc_Word32* vector, // (i) Input vector + WebRtc_Word16 vector_length) // (i) Number of elements +{ + WebRtc_Word32 tempMin; + WebRtc_Word16 tempMinIndex, i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + // Find index of smallest value + tempMinIndex = 0; + tempMin = *tmpvector++; + for (i = 1; i < vector_length; i++) + { + if (*tmpvector++ < tempMin) + { + tempMin = vector[i]; + tempMinIndex = i; + } + } + return tempMinIndex; +} + +#else +#pragma message(">> max_index_w16.c is excluded from this build") +#endif diff --git a/common_audio/signal_processing_library/main/source/min_max_operations.c b/common_audio/signal_processing_library/main/source/min_max_operations.c new file mode 100644 index 0000000000..cf5e9a7d43 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/min_max_operations.c @@ -0,0 +1,305 @@ +/* + * 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_MaxAbsValueW16() + * WebRtcSpl_MaxAbsIndexW16() + * WebRtcSpl_MaxAbsValueW32() + * WebRtcSpl_MaxValueW16() + * WebRtcSpl_MaxIndexW16() + * WebRtcSpl_MaxValueW32() + * WebRtcSpl_MaxIndexW32() + * WebRtcSpl_MinValueW16() + * WebRtcSpl_MinIndexW16() + * WebRtcSpl_MinValueW32() + * WebRtcSpl_MinIndexW32() + * + * The description header can be found in signal_processing_library.h. + * + */ + +#include "signal_processing_library.h" + +// Maximum absolute value of word16 vector. +WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length) +{ + WebRtc_Word32 tempMax = 0; + WebRtc_Word32 absVal; + WebRtc_Word16 totMax; + int i; + G_CONST WebRtc_Word16 *tmpvector = vector; + +#ifdef _ARM_OPT_ +#pragma message("NOTE: _ARM_OPT_ optimizations are used") + + WebRtc_Word16 len4 = (length >> 2) << 2; + + for (i = 0; i < len4; i = i + 4) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } + + for (i = len4; i < len; i++) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } +#else + for (i = 0; i < length; i++) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } + totMax = (WebRtc_Word16)WEBRTC_SPL_MIN(tempMax, WEBRTC_SPL_WORD16_MAX); + return totMax; +#endif +} + +// Index of maximum absolute value in a word16 vector. +WebRtc_Word16 WebRtcSpl_MaxAbsIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMax; + WebRtc_Word16 absTemp; + WebRtc_Word16 tempMaxIndex = 0; + WebRtc_Word16 i = 0; + G_CONST WebRtc_Word16 *tmpvector = vector; + + tempMax = WEBRTC_SPL_ABS_W16(*tmpvector); + tmpvector++; + for (i = 1; i < length; i++) + { + absTemp = WEBRTC_SPL_ABS_W16(*tmpvector); + tmpvector++; + if (absTemp > tempMax) + { + tempMax = absTemp; + tempMaxIndex = i; + } + } + return tempMaxIndex; +} + +// Maximum absolute value of word32 vector. +WebRtc_Word32 WebRtcSpl_MaxAbsValueW32(G_CONST WebRtc_Word32 *vector, WebRtc_Word16 length) +{ + WebRtc_UWord32 tempMax = 0; + WebRtc_UWord32 absVal; + WebRtc_Word32 retval; + int i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + for (i = 0; i < length; i++) + { + absVal = WEBRTC_SPL_ABS_W32((*tmpvector)); + if (absVal > tempMax) + { + tempMax = absVal; + } + tmpvector++; + } + retval = (WebRtc_Word32)(WEBRTC_SPL_MIN(tempMax, WEBRTC_SPL_WORD32_MAX)); + return retval; +} + +// Maximum value of word16 vector. +#ifndef XSCALE_OPT +WebRtc_Word16 WebRtcSpl_MaxValueW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMax; + WebRtc_Word16 i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + tempMax = vector[i]; + } + return tempMax; +} +#else +#pragma message(">> WebRtcSpl_MaxValueW16 is excluded from this build") +#endif + +// Index of maximum value in a word16 vector. +WebRtc_Word16 WebRtcSpl_MaxIndexW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMax; + WebRtc_Word16 tempMaxIndex = 0; + WebRtc_Word16 i = 0; + G_CONST WebRtc_Word16 *tmpvector = vector; + + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + { + tempMax = vector[i]; + tempMaxIndex = i; + } + } + return tempMaxIndex; +} + +// Maximum value of word32 vector. +#ifndef XSCALE_OPT +WebRtc_Word32 WebRtcSpl_MaxValueW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length) +{ + WebRtc_Word32 tempMax; + WebRtc_Word16 i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + tempMax = vector[i]; + } + return tempMax; +} +#else +#pragma message(">> WebRtcSpl_MaxValueW32 is excluded from this build") +#endif + +// Index of maximum value in a word32 vector. +WebRtc_Word16 WebRtcSpl_MaxIndexW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length) +{ + WebRtc_Word32 tempMax; + WebRtc_Word16 tempMaxIndex = 0; + WebRtc_Word16 i = 0; + G_CONST WebRtc_Word32 *tmpvector = vector; + + tempMax = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ > tempMax) + { + tempMax = vector[i]; + tempMaxIndex = i; + } + } + return tempMaxIndex; +} + +// Minimum value of word16 vector. +WebRtc_Word16 WebRtcSpl_MinValueW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMin; + WebRtc_Word16 i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + // Find the minimum value + tempMin = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ < tempMin) + tempMin = (vector[i]); + } + return tempMin; +} + +// Index of minimum value in a word16 vector. +#ifndef XSCALE_OPT +WebRtc_Word16 WebRtcSpl_MinIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length) +{ + WebRtc_Word16 tempMin; + WebRtc_Word16 tempMinIndex = 0; + WebRtc_Word16 i = 0; + G_CONST WebRtc_Word16* tmpvector = vector; + + // Find index of smallest value + tempMin = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ < tempMin) + { + tempMin = vector[i]; + tempMinIndex = i; + } + } + return tempMinIndex; +} +#else +#pragma message(">> WebRtcSpl_MinIndexW16 is excluded from this build") +#endif + +// Minimum value of word32 vector. +WebRtc_Word32 WebRtcSpl_MinValueW32(G_CONST WebRtc_Word32 *vector, WebRtc_Word16 length) +{ + WebRtc_Word32 tempMin; + WebRtc_Word16 i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + // Find the minimum value + tempMin = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ < tempMin) + tempMin = (vector[i]); + } + return tempMin; +} + +// Index of minimum value in a word32 vector. +#ifndef XSCALE_OPT +WebRtc_Word16 WebRtcSpl_MinIndexW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length) +{ + WebRtc_Word32 tempMin; + WebRtc_Word16 tempMinIndex = 0; + WebRtc_Word16 i = 0; + G_CONST WebRtc_Word32 *tmpvector = vector; + + // Find index of smallest value + tempMin = *tmpvector++; + for (i = 1; i < length; i++) + { + if (*tmpvector++ < tempMin) + { + tempMin = vector[i]; + tempMinIndex = i; + } + } + return tempMinIndex; +} +#else +#pragma message(">> WebRtcSpl_MinIndexW32 is excluded from this build") +#endif diff --git a/common_audio/signal_processing_library/main/source/min_value_w16.c b/common_audio/signal_processing_library/main/source/min_value_w16.c new file mode 100644 index 0000000000..81d9a8a432 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/min_value_w16.c @@ -0,0 +1,20 @@ +/* + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_MinValueW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 vector_length) +{ + WebRtc_Word16 tempMin; + WebRtc_Word16 i; + G_CONST WebRtc_Word16 *tmpvector = vector; + + /* Find the minimum value */ + tempMin = *tmpvector++; + for (i = 1; i < vector_length; i++) + { + if ( *tmpvector++ < tempMin) + tempMin = (vector[i]); + } + return tempMin; +} diff --git a/common_audio/signal_processing_library/main/source/min_value_w32.c b/common_audio/signal_processing_library/main/source/min_value_w32.c new file mode 100644 index 0000000000..f4576549c7 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/min_value_w32.c @@ -0,0 +1,22 @@ +/* + */ + +#include "signal_processing_library.h" + +/* (o) Minimum value of input vector */ +WebRtc_Word32 WebRtcSpl_MinValueW32(G_CONST WebRtc_Word32 *vector, /* (i) Input vector */ + WebRtc_Word16 vector_length) /* (i) Number of elements */ +{ + WebRtc_Word32 tempMin; + WebRtc_Word16 i; + G_CONST WebRtc_Word32 *tmpvector = vector; + + /* Find the minimum value */ + tempMin = *tmpvector++; + for (i = 1; i < vector_length; i++) + { + if ( *tmpvector++ < tempMin) + tempMin = (vector[i]); + } + return tempMin; +} diff --git a/common_audio/signal_processing_library/main/source/norm_u32.c b/common_audio/signal_processing_library/main/source/norm_u32.c new file mode 100644 index 0000000000..c903a64632 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/norm_u32.c @@ -0,0 +1,42 @@ +/* + * 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_NormU32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +int WebRtcSpl_NormU32(WebRtc_UWord32 value) +{ + int zeros = 0; + + if (value == 0) + return 0; + + if (!(0xFFFF0000 & value)) + zeros = 16; + if (!(0xFF000000 & (value << zeros))) + zeros += 8; + if (!(0xF0000000 & (value << zeros))) + zeros += 4; + if (!(0xC0000000 & (value << zeros))) + zeros += 2; + if (!(0x80000000 & (value << zeros))) + zeros += 1; + + return zeros; +} +#endif diff --git a/common_audio/signal_processing_library/main/source/norm_w16.c b/common_audio/signal_processing_library/main/source/norm_w16.c new file mode 100644 index 0000000000..be6711d53f --- /dev/null +++ b/common_audio/signal_processing_library/main/source/norm_w16.c @@ -0,0 +1,40 @@ +/* + * 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_NormW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +int WebRtcSpl_NormW16(WebRtc_Word16 value) +{ + int zeros = 0; + + if (value <= 0) + value ^= 0xFFFF; + + if ( !(0xFF80 & value)) + zeros = 8; + if ( !(0xF800 & (value << zeros))) + zeros += 4; + if ( !(0xE000 & (value << zeros))) + zeros += 2; + if ( !(0xC000 & (value << zeros))) + zeros += 1; + + return zeros; +} +#endif diff --git a/common_audio/signal_processing_library/main/source/norm_w32.c b/common_audio/signal_processing_library/main/source/norm_w32.c new file mode 100644 index 0000000000..d45633501a --- /dev/null +++ b/common_audio/signal_processing_library/main/source/norm_w32.c @@ -0,0 +1,45 @@ +/* + * 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_NormW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +int WebRtcSpl_NormW32(WebRtc_Word32 value) +{ + int zeros = 0; + + if (value <= 0) + value ^= 0xFFFFFFFF; + + // Fast binary search to determine the number of left shifts required to 32-bit normalize + // the value + if (!(0xFFFF8000 & value)) + zeros = 16; + if (!(0xFF800000 & (value << zeros))) + zeros += 8; + if (!(0xF8000000 & (value << zeros))) + zeros += 4; + if (!(0xE0000000 & (value << zeros))) + zeros += 2; + if (!(0xC0000000 & (value << zeros))) + zeros += 1; + + return zeros; +} + +#endif diff --git a/common_audio/signal_processing_library/main/source/ones_array_w16.c b/common_audio/signal_processing_library/main/source/ones_array_w16.c new file mode 100644 index 0000000000..b19aac71bf --- /dev/null +++ b/common_audio/signal_processing_library/main/source/ones_array_w16.c @@ -0,0 +1,20 @@ +/* + * ones_array_w16.c + * + * This file contains the function WebRtcSpl_OnesArrayW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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; +} diff --git a/common_audio/signal_processing_library/main/source/ones_array_w32.c b/common_audio/signal_processing_library/main/source/ones_array_w32.c new file mode 100644 index 0000000000..f7e1bc5730 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/ones_array_w32.c @@ -0,0 +1,20 @@ +/* + * ones_array_w32.c + * + * This file contains the function WebRtcSpl_OnesArrayW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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_library/main/source/rand_n.c b/common_audio/signal_processing_library/main/source/rand_n.c new file mode 100644 index 0000000000..c328188f7c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/rand_n.c @@ -0,0 +1,14 @@ +/* + * rand_n.c + * + * This file contains the function WebRtcSpl_RandN(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_RandN(WebRtc_UWord32 *seed) +{ + return (WebRtcSpl_kRandNTable[WebRtcSpl_IncreaseSeed(seed) >> 23]); +} diff --git a/common_audio/signal_processing_library/main/source/rand_n_array.c b/common_audio/signal_processing_library/main/source/rand_n_array.c new file mode 100644 index 0000000000..075de73b9c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/rand_n_array.c @@ -0,0 +1,53 @@ +/* + * rand_n_array.c + * + * This file contains the function WebRtcSpl_RandNArray(). + * The description header can be found in signal_processing_library.h + * + */ + +#include + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_RandNArray(WebRtc_Word16* vector, + WebRtc_Word16 vector_length, + WebRtc_UWord32* seed) +{ + WebRtc_Word16 startpos; + WebRtc_Word16 endpos; + WebRtc_Word16* vecptr; + + startpos = (WebRtc_Word16)((*seed) & 0x1FF); // Value between 0 and 511 + *seed = *seed + vector_length; + endpos = (WebRtc_Word16)((*seed) & 0x1FF); // Value between 0 and 511 + + if (vector_length < 512) + { + if (endpos > startpos) + { + WEBRTC_SPL_MEMCPY_W16(vector, &WebRtcSpl_kRandNTable[startpos], vector_length); + } else + { + WEBRTC_SPL_MEMCPY_W16(vector, &WebRtcSpl_kRandNTable[startpos], (512 - startpos)); + WEBRTC_SPL_MEMCPY_W16(&vector[512-startpos], WebRtcSpl_kRandNTable, + (vector_length - (512 - startpos))); + } + } else + { + WebRtc_Word16 lensave = vector_length; + + WEBRTC_SPL_MEMCPY_W16(vector, &WebRtcSpl_kRandNTable[startpos], (512-startpos)); + vecptr = &vector[512 - startpos]; + vector_length = vector_length - (512 - startpos); + while (vector_length > 512) + { + WEBRTC_SPL_MEMCPY_W16(vecptr, WebRtcSpl_kRandNTable, 512); + vecptr += 512; + vector_length -= 512; + } + WEBRTC_SPL_MEMCPY_W16(vecptr, WebRtcSpl_kRandNTable, vector_length); + vector_length = lensave; + } + return vector_length; +} diff --git a/common_audio/signal_processing_library/main/source/rand_u.c b/common_audio/signal_processing_library/main/source/rand_u.c new file mode 100644 index 0000000000..ef6c3a30d1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/rand_u.c @@ -0,0 +1,14 @@ +/* + * rand_u.c + * + * This file contains the function WebRtcSpl_RandU(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_RandU(WebRtc_UWord32 *seed) +{ + return ((WebRtc_Word16)(WebRtcSpl_IncreaseSeed(seed) >> 16)); +} diff --git a/common_audio/signal_processing_library/main/source/rand_u_array.c b/common_audio/signal_processing_library/main/source/rand_u_array.c new file mode 100644 index 0000000000..99e54b5628 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/rand_u_array.c @@ -0,0 +1,24 @@ +/* + * rand_u_array.c + * + * This file contains the function WebRtcSpl_RandUArray(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +/* + * create 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_library/main/source/randn_table.c b/common_audio/signal_processing_library/main/source/randn_table.c new file mode 100644 index 0000000000..734fa79a68 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/randn_table.c @@ -0,0 +1,85 @@ +/* + * 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. + */ + + +/* + * Table with 512 samples from a normal distribution with mean 1 and std 1 + * The values are shifted up 13 steps (multiplied by 8192) + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_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 +}; diff --git a/common_audio/signal_processing_library/main/source/randomization_functions.c b/common_audio/signal_processing_library/main/source/randomization_functions.c new file mode 100644 index 0000000000..6bc87c76ff --- /dev/null +++ b/common_audio/signal_processing_library/main/source/randomization_functions.c @@ -0,0 +1,52 @@ +/* + * 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" + +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 WebRtcSpl_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_library/main/source/refl_coef_to_lpc.c b/common_audio/signal_processing_library/main/source/refl_coef_to_lpc.c new file mode 100644 index 0000000000..d07804dee7 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/replace_in_mid_u8.c b/common_audio/signal_processing_library/main/source/replace_in_mid_u8.c new file mode 100644 index 0000000000..c06caf87cc --- /dev/null +++ b/common_audio/signal_processing_library/main/source/replace_in_mid_u8.c @@ -0,0 +1,29 @@ +/* + */ + +#include + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +WebRtc_Word16 WebRtcSpl_ReplaceInMidU8(unsigned char *in_vector, WebRtc_Word16 in_length, + WebRtc_Word16 pos, unsigned char *insert_vector, + WebRtc_Word16 insert_length) +{ +#ifdef _DEBUG + if (in_length < insert_length + pos) + { + printf("chreplacemid : vector currently shorter than the length required to insert the samples\n"); + exit(0); + } +#endif + + /* A unsigned char is 1 bytes long */ + WEBRTC_SPL_MEMCPY_W8(&in_vector[pos], insert_vector, insert_length); + + return (in_length); +} diff --git a/common_audio/signal_processing_library/main/source/replace_in_mid_w16.c b/common_audio/signal_processing_library/main/source/replace_in_mid_w16.c new file mode 100644 index 0000000000..a81a49e1b4 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/replace_in_mid_w16.c @@ -0,0 +1,27 @@ +/* + */ +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_ReplaceInMidW16(WebRtc_Word16 *in_vector, WebRtc_Word16 in_length, + WebRtc_Word16 pos, WebRtc_Word16 *insert_vector, + WebRtc_Word16 insert_length) +{ +#ifdef _DEBUG + if (in_length < insert_length + pos) + { + printf("w16replacemid : vector currently shorter than the length required to insert the samples\n"); + exit(0); + } +#endif + + /* A WebRtc_Word16 is 2 bytes long */ + WEBRTC_SPL_MEMCPY_W16(&in_vector[pos], insert_vector, insert_length); + + return (in_length); +} diff --git a/common_audio/signal_processing_library/main/source/replace_in_mid_w32.c b/common_audio/signal_processing_library/main/source/replace_in_mid_w32.c new file mode 100644 index 0000000000..695685cc1d --- /dev/null +++ b/common_audio/signal_processing_library/main/source/replace_in_mid_w32.c @@ -0,0 +1,28 @@ +/* + */ + +#include +#ifdef _DEBUG +#include +#include +#endif + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_ReplaceInMidW32(WebRtc_Word32 *in_vector, WebRtc_Word16 in_length, + WebRtc_Word16 pos, WebRtc_Word32 *insert_vector, + WebRtc_Word16 length) +{ +#ifdef _DEBUG + if (in_length < length + pos) + { + printf("w32replacemid : vector currently shorter than the length required to insert the samples\n"); + exit(0); + } +#endif + + /* A WebRtc_Word32 is 4 bytes long */ + WEBRTC_SPL_MEMCPY_W32(&in_vector[pos], insert_vector, length); + + return (in_length); +} diff --git a/common_audio/signal_processing_library/main/source/resample.c b/common_audio/signal_processing_library/main/source/resample.c new file mode 100644 index 0000000000..19d1778558 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/resample_48khz.c b/common_audio/signal_processing_library/main/source/resample_48khz.c new file mode 100644 index 0000000000..31cbe6b6a9 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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 +#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_library/main/source/resample_by_2.c b/common_audio/signal_processing_library/main/source/resample_by_2.c new file mode 100644 index 0000000000..7ed4cfde09 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/resample_by_2.c @@ -0,0 +1,135 @@ +/* + * 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" + +// allpass filter coefficients. +static const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528}; +static const WebRtc_UWord16 kResampleAllpass2[3] = {12199, 37471, 60255}; + +// decimator +void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len, + WebRtc_Word16* out, WebRtc_Word32* filtState) +{ + const WebRtc_Word16 *inptr; + WebRtc_Word16 *outptr; + WebRtc_Word32 *state; + WebRtc_Word32 tmp1, tmp2, diff, in32, out32; + WebRtc_Word16 i; + + // local versions of pointers to input and output arrays + inptr = in; // input array + outptr = out; // output array (of length len/2) + state = filtState; // filter state array; length = 8 + + for (i = (len >> 1); i > 0; i--) + { + // lower allpass filter + in32 = (WebRtc_Word32)(*inptr++) << 10; + diff = in32 - state[1]; + tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[0], diff, state[0] ); + state[0] = in32; + diff = tmp1 - state[2]; + tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[1], diff, state[1] ); + state[1] = tmp1; + diff = tmp2 - state[3]; + state[3] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[2], diff, state[2] ); + state[2] = tmp2; + + // upper allpass filter + in32 = (WebRtc_Word32)(*inptr++) << 10; + diff = in32 - state[5]; + tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[0], diff, state[4] ); + state[4] = in32; + diff = tmp1 - state[6]; + tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[1], diff, state[5] ); + state[5] = tmp1; + diff = tmp2 - state[7]; + state[7] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[2], diff, state[6] ); + state[6] = tmp2; + + // add two allpass outputs, divide by two and round + out32 = (state[3] + state[7] + 1024) >> 11; + + // limit amplitude to prevent wrap-around, and write to output array + if (out32 > 32767) + *outptr++ = 32767; + else if (out32 < -32768) + *outptr++ = -32768; + else + *outptr++ = (WebRtc_Word16)out32; + } +} + +void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, WebRtc_Word16* out, + WebRtc_Word32* filtState) +{ + const WebRtc_Word16 *inptr; + WebRtc_Word16 *outptr; + WebRtc_Word32 *state; + WebRtc_Word32 tmp1, tmp2, diff, in32, out32; + WebRtc_Word16 i; + + // local versions of pointers to input and output arrays + inptr = in; // input array + outptr = out; // output array (of length len*2) + state = filtState; // filter state array; length = 8 + + for (i = len; i > 0; i--) + { + // lower allpass filter + in32 = (WebRtc_Word32)(*inptr++) << 10; + diff = in32 - state[1]; + tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[0], diff, state[0] ); + state[0] = in32; + diff = tmp1 - state[2]; + tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[1], diff, state[1] ); + state[1] = tmp1; + diff = tmp2 - state[3]; + state[3] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[2], diff, state[2] ); + state[2] = tmp2; + + // round; limit amplitude to prevent wrap-around; write to output array + out32 = (state[3] + 512) >> 10; + if (out32 > 32767) + *outptr++ = 32767; + else if (out32 < -32768) + *outptr++ = -32768; + else + *outptr++ = (WebRtc_Word16)out32; + + // upper allpass filter + diff = in32 - state[5]; + tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[0], diff, state[4] ); + state[4] = in32; + diff = tmp1 - state[6]; + tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[1], diff, state[5] ); + state[5] = tmp1; + diff = tmp2 - state[7]; + state[7] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[2], diff, state[6] ); + state[6] = tmp2; + + // round; limit amplitude to prevent wrap-around; write to output array + out32 = (state[7] + 512) >> 10; + if (out32 > 32767) + *outptr++ = 32767; + else if (out32 < -32768) + *outptr++ = -32768; + else + *outptr++ = (WebRtc_Word16)out32; + } +} diff --git a/common_audio/signal_processing_library/main/source/resample_by_2_internal.c b/common_audio/signal_processing_library/main/source/resample_by_2_internal.c new file mode 100644 index 0000000000..cbd2395803 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/resample_by_2_internal.h b/common_audio/signal_processing_library/main/source/resample_by_2_internal.h new file mode 100644 index 0000000000..b6ac9f0cb4 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/resample_fractional.c b/common_audio/signal_processing_library/main/source/resample_fractional.c new file mode 100644 index 0000000000..51003d45d7 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/resample_to_16khz.c b/common_audio/signal_processing_library/main/source/resample_to_16khz.c new file mode 100644 index 0000000000..a88e35fae0 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/resample_to_16khz.c @@ -0,0 +1,269 @@ +/* + * resample_to_16khz.c + * + * TODO(bjornv): + * + */ + +#include +#include + +#include "signal_processing_library.h" + +/************************************************************ + * + * WebRtcSpl_InitResamplerTo16(...) + * + * Initializes the mode of the resampler + * allowed modes: + * 8, 11, 12, 16, 22, 24, 32, 44, 48 (kHz) + * + * Returns 0 - OK + * -1 - Error (unsupported mode) + * + ************************************************************/ +WebRtc_Word16 WebRtcSpl_InitResamplerTo16(WebRtcSpl_StateTo16khz* state, + WebRtc_Word16 mode) +{ + switch (mode) + { + case 8: + state->blockSizeIn = 1; + state->stepSizeIn = 1; + state->blockSizeOut = 2; + break; + case 11: + state->blockSizeIn = 18; + state->stepSizeIn = 11; + state->blockSizeOut = 8; + break; + case 12: + state->blockSizeIn = 9; + state->stepSizeIn = 3; + state->blockSizeOut = 2; + break; + case 16: + state->blockSizeIn = 1; + state->stepSizeIn = 1; + state->blockSizeOut = 1; + break; + case 22: + state->blockSizeIn = 18; + state->stepSizeIn = 11; + state->blockSizeOut = 8; + break; + case 24: + state->blockSizeIn = 9; + state->stepSizeIn = 3; + state->blockSizeOut = 2; + break; + case 32: + state->blockSizeIn = 2; + state->stepSizeIn = 2; + state->blockSizeOut = 1; + break; + case 44: + state->blockSizeIn = 18; + state->stepSizeIn = 11; + state->blockSizeOut = 8; + break; + case 48: + state->blockSizeIn = 9; + state->stepSizeIn = 3; + state->blockSizeOut = 2; + break; + default: + return -1; + } + + state->mode = mode; + WebRtcSpl_ResetResamplerTo16(state); + return 0; +} + +/************************************************************ + * + * WebRtcSpl_ResetResamplerTo16(...) + * + * Resets the filter state of the resampler, but does not + * change the mode + * + ************************************************************/ +void WebRtcSpl_ResetResamplerTo16(WebRtcSpl_StateTo16khz* state) +{ + memset(state->upsampleBy2FilterState, 0, 8 * sizeof(WebRtc_Word32)); + memset(state->downsampleBy2FilterState, 0, 8 * sizeof(WebRtc_Word32)); + memset(state->speechBlockIn, 0, 18 * sizeof(WebRtc_Word32)); + memset(state->speechBlockIn, 0, 8 * sizeof(WebRtc_Word32)); + state->blockPositionIn = 0; +} + +/*********************************************************** + * + * Update the speechBlockIn buffer with new data + * Internal function used by WebRtcSpl_ResamplerTo16() + * + ***********************************************************/ +WebRtc_Word16 WebRtcSpl_BlockUpdateIn(WebRtcSpl_StateTo16khz *state, WebRtc_Word16 *data, + WebRtc_Word16 len, WebRtc_Word16 *pos) +{ + WebRtc_Word16 SamplesLeft = len - *pos; + int i; + + if ((SamplesLeft + state->blockPositionIn) >= state->blockSizeIn) + { + for (i = 0; i < state->blockSizeIn - state->blockPositionIn; i++) + { + state->speechBlockIn[state->blockPositionIn + i] = (WebRtc_Word32)data[*pos]; + (*pos)++; + } + state->blockPositionIn = state->blockSizeIn; + return 1; + } else + { + for (i = 0; i < SamplesLeft; i++) + { + state->speechBlockIn[state->blockPositionIn + i] = (WebRtc_Word32)data[*pos]; + (*pos)++; + } + state->blockPositionIn += SamplesLeft; + return 0; + } +} + +/*********************************************************** + * + * Move data from speechBlockOut to data[] and update + * speechBlockIn buffer. + * Internal function used by WebRtcSpl_ResamplerTo16() + * + ***********************************************************/ + +WebRtc_Word16 WebRtcSpl_BlockUpdateOut(WebRtcSpl_StateTo16khz *state, WebRtc_Word16 *data, + WebRtc_Word16 *pos) +{ + int i; + for (i = 0; i < state->blockSizeOut; i++) + { + data[*pos] + = (WebRtc_Word16)WEBRTC_SPL_SAT(32767,((state->speechBlockOut[i])>>15), -32768); + (*pos)++; + } + /* Move data in input vector */ + state->blockPositionIn -= state->stepSizeIn; + memmove(state->speechBlockIn, &(state->speechBlockIn[state->stepSizeIn]), + sizeof(WebRtc_Word32) * (state->blockPositionIn)); + return 0; +} + +/********************************************************************************** + * + * WebRtcSpl_ResamplerTo16(...) + * + * Resample input[] vector (with sample rate specified by init function) to 16 kHz + * and put result in output[] vector + * + * Limitation: + * For 32, 44 and 48 kHz input vector the number of input samples have to be even + * if the output[] vectors given by WebRtcSpl_ResamplerTo16() are concatenated. + * + * Returns 0 - OK + * -1 - Error (unsupported mode) + * + **********************************************************************************/ +WebRtc_Word16 WebRtcSpl_ResamplerTo16(WebRtcSpl_StateTo16khz *state, + WebRtc_Word16 *input, WebRtc_Word16 inlen, + WebRtc_Word16 *output, WebRtc_Word16 *outlen) +{ + + WebRtc_Word16 NoOfSamples; + WebRtc_Word16 VecPosIn = 0; + WebRtc_Word16 VecPosOut = 0; + WebRtc_Word16 *tmpVec; + + switch (state->mode) + { + case 8: + WebRtcSpl_UpsampleBy2(input, inlen, output, state->upsampleBy2FilterState); + *outlen = inlen * 2; + break; + case 11: + tmpVec = (WebRtc_Word16*)malloc(inlen * 2 * sizeof(WebRtc_Word16)); + WebRtcSpl_UpsampleBy2(input, inlen, tmpVec, state->upsampleBy2FilterState); + NoOfSamples = inlen * 2; + while (WebRtcSpl_BlockUpdateIn(state, tmpVec, NoOfSamples, &VecPosIn)) + { + WebRtcSpl_Resample44khzTo32khz(state->speechBlockIn, state->speechBlockOut, 1); + WebRtcSpl_BlockUpdateOut(state, output, &VecPosOut); + } + *outlen = VecPosOut; + free(tmpVec); + break; + case 12: + tmpVec = (WebRtc_Word16*)malloc(inlen * 2 * sizeof(WebRtc_Word16)); + WebRtcSpl_UpsampleBy2(input, inlen, tmpVec, state->upsampleBy2FilterState); + NoOfSamples = inlen * 2; + while (WebRtcSpl_BlockUpdateIn(state, tmpVec, NoOfSamples, &VecPosIn)) + { + WebRtcSpl_Resample48khzTo32khz(state->speechBlockIn, state->speechBlockOut, 1); + WebRtcSpl_BlockUpdateOut(state, output, &VecPosOut); + } + *outlen = VecPosOut; + free(tmpVec); + break; + case 16: + memcpy(output, input, inlen * sizeof(WebRtc_Word16)); + *outlen = inlen; + break; + case 22: + NoOfSamples = inlen; + while (WebRtcSpl_BlockUpdateIn(state, input, NoOfSamples, &VecPosIn)) + { + WebRtcSpl_Resample44khzTo32khz(state->speechBlockIn, state->speechBlockOut, 1); + WebRtcSpl_BlockUpdateOut(state, output, &VecPosOut); + } + *outlen = VecPosOut; + break; + case 24: + NoOfSamples = inlen; + while (WebRtcSpl_BlockUpdateIn(state, input, NoOfSamples, &VecPosIn)) + { + WebRtcSpl_Resample48khzTo32khz(state->speechBlockIn, state->speechBlockOut, 1); + WebRtcSpl_BlockUpdateOut(state, output, &VecPosOut); + } + *outlen = VecPosOut; + break; + case 32: + WebRtcSpl_DownsampleBy2(input, inlen, output, state->downsampleBy2FilterState); + *outlen = inlen >> 1; + break; + case 44: + tmpVec = (WebRtc_Word16*)malloc((inlen >> 1) * sizeof(WebRtc_Word16)); + WebRtcSpl_DownsampleBy2(input, inlen, tmpVec, state->downsampleBy2FilterState); + NoOfSamples = inlen >> 1; + while (WebRtcSpl_BlockUpdateIn(state, tmpVec, NoOfSamples, &VecPosIn)) + { + WebRtcSpl_Resample44khzTo32khz(state->speechBlockIn, state->speechBlockOut, 1); + WebRtcSpl_BlockUpdateOut(state, output, &VecPosOut); + } + *outlen = VecPosOut; + free(tmpVec); + break; + case 48: + tmpVec = (WebRtc_Word16*)malloc((inlen >> 1) * sizeof(WebRtc_Word16)); + WebRtcSpl_DownsampleBy2(input, inlen, tmpVec, state->downsampleBy2FilterState); + NoOfSamples = inlen >> 1; + while (WebRtcSpl_BlockUpdateIn(state, tmpVec, NoOfSamples, &VecPosIn)) + { + WebRtcSpl_Resample48khzTo32khz(state->speechBlockIn, state->speechBlockOut, 1); + WebRtcSpl_BlockUpdateOut(state, output, &VecPosOut); + } + *outlen = VecPosOut; + free(tmpVec); + break; + default: + return -1; + } + return 0; + +} diff --git a/common_audio/signal_processing_library/main/source/reverse_order_mult_array_elements.c b/common_audio/signal_processing_library/main/source/reverse_order_mult_array_elements.c new file mode 100644 index 0000000000..d9d5d9edc7 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/reverse_order_mult_array_elements.c @@ -0,0 +1,25 @@ +/* + * reverse_order_mult_array_elements.c + * + * This file contains the function WebRtcSpl_ReverseOrderMultArrayElements(). + * The description header can be found in signal_processing_library.h + * + */ + +#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); + } +} diff --git a/common_audio/signal_processing_library/main/source/scale_add_round_rshift16_arrays.c b/common_audio/signal_processing_library/main/source/scale_add_round_rshift16_arrays.c new file mode 100644 index 0000000000..0fe19eb2da --- /dev/null +++ b/common_audio/signal_processing_library/main/source/scale_add_round_rshift16_arrays.c @@ -0,0 +1,31 @@ +/* + * scale_and_add_vectors_r_shift16.c + * + * This file contains the function WebRtcSpl_ScaleAndAddVectorsRShift16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ScaleAndAddVectorsRShift16(G_CONST WebRtc_Word16 *in1, WebRtc_Word16 gain1, + G_CONST WebRtc_Word16 *in2, WebRtc_Word16 gain2, + WebRtc_Word16 *out, int nrOfElements) +{ + /* Performs vector operation: out = (gain1*in1+2^15)>>16 + (gain2*in2+2^15)>>16 */ + 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 < nrOfElements; i++) + { + ( *outptr++) + = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(gain1, *in1ptr++) + (WebRtc_Word32)32768), 16) + + (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(gain2, *in2ptr++) + (WebRtc_Word32)32768), 16); + } +} diff --git a/common_audio/signal_processing_library/main/source/scale_and_add_vectors.c b/common_audio/signal_processing_library/main/source/scale_and_add_vectors.c new file mode 100644 index 0000000000..d800ed4fa9 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/scale_and_add_vectors.c @@ -0,0 +1,30 @@ +/* + * scale_and_add_vectors.c + * + * This file contains the function WebRtcSpl_ScaleAndAddVectors(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/scale_and_add_vectors_with_round.c b/common_audio/signal_processing_library/main/source/scale_and_add_vectors_with_round.c new file mode 100644 index 0000000000..8e575395e1 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/scale_and_add_vectors_with_round.c @@ -0,0 +1,25 @@ +/* + * scale_and_add_vectors_with_round.c + * + * This file contains the function WebRtcSpl_ScaleAndAddVectorsWithRound(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_ScaleAndAddVectorsWithRound(WebRtc_Word16 *vec1, WebRtc_Word16 scale1, + WebRtc_Word16 *vec2, WebRtc_Word16 scale2, + WebRtc_Word16 rshifts, WebRtc_Word16 *out, + WebRtc_Word16 length) +{ + int i; + WebRtc_Word16 roundVal; + roundVal = 1 << rshifts; + roundVal = roundVal >> 1; + for (i = 0; i < length; i++) + { + out[i] = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16(vec1[i],scale1) + + WEBRTC_SPL_MUL_16_16(vec2[i],scale2) + roundVal) >> rshifts); + } +} diff --git a/common_audio/signal_processing_library/main/source/scale_vector.c b/common_audio/signal_processing_library/main/source/scale_vector.c new file mode 100644 index 0000000000..6af44b8be6 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/scale_vector.c @@ -0,0 +1,27 @@ +/* + * scale_vector.c + * + * This file contains the function WebRtcSpl_ScaleVector(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/scale_vectors_with_sat.c b/common_audio/signal_processing_library/main/source/scale_vectors_with_sat.c new file mode 100644 index 0000000000..59853c4e0c --- /dev/null +++ b/common_audio/signal_processing_library/main/source/scale_vectors_with_sat.c @@ -0,0 +1,29 @@ +/* + * scale_vector_with_sat.c + * + * This file contains the function WebRtcSpl_ScaleVectorWithSat(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +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++) = (WebRtc_Word16)WEBRTC_SPL_SAT(32767, tmpW32, -32768); + } +} diff --git a/common_audio/signal_processing_library/main/source/set_column.c b/common_audio/signal_processing_library/main/source/set_column.c new file mode 100644 index 0000000000..8e87acb5ba --- /dev/null +++ b/common_audio/signal_processing_library/main/source/set_column.c @@ -0,0 +1,48 @@ +/* + * set_column.c + * + * This file contains the function WebRtcSpl_SetColumn(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +/* + * Insert a vector into a column in the matrix + */ +void WebRtcSpl_SetColumn(G_CONST WebRtc_Word32 *in_column, WebRtc_Word16 in_column_length, + WebRtc_Word32 *matrix, WebRtc_Word16 number_of_rows, + WebRtc_Word16 number_of_cols, WebRtc_Word16 column_chosen) +{ + WebRtc_Word16 i; + G_CONST WebRtc_Word32 *inarrptr = in_column; + WebRtc_Word32 *matptr = &matrix[column_chosen]; + +#ifdef _DEBUG + if (in_column_length != number_of_rows) + { + printf(" SetColumn : the vector to be inserted does not have the same length as a column in the matrix\n"); + exit(0); + } + if ((column_chosen < 0) || (column_chosen >= number_of_cols)) + { + printf(" SetColumn : selected column is negative or larger than the dimension of the matrix\n"); + exit(0); + } +#endif + + /* Unused input variable */ + number_of_rows = number_of_rows; + + for (i = 0; i < in_column_length; i++) + { + (*matptr) = (*inarrptr++); + matptr += number_of_cols; + } +} diff --git a/common_audio/signal_processing_library/main/source/set_row.c b/common_audio/signal_processing_library/main/source/set_row.c new file mode 100644 index 0000000000..b8978f7bc4 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/set_row.c @@ -0,0 +1,46 @@ +/* + * set_row.c + * + * This file contains the function WebRtcSpl_SetRow(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifdef _DEBUG +#include +#include +#endif + +/* + * Insert a vector into a row in the matrix + */ +void WebRtcSpl_SetRow(G_CONST WebRtc_Word32 *in_row, WebRtc_Word16 in_column_length, + WebRtc_Word32 *matrix, WebRtc_Word16 number_of_rows, + WebRtc_Word16 number_of_cols, WebRtc_Word16 row_chosen) +{ + WebRtc_Word16 i; + G_CONST WebRtc_Word32 *inarrptr = in_row; + WebRtc_Word32 *matptr = &matrix[row_chosen * number_of_cols]; + +#ifdef _DEBUG + if (in_column_length != number_of_cols) + { + printf(" SetRow : the vector to be inserted does not have the same length as a row in the matrix\n"); + exit(0); + } + if ((row_chosen < 0) || (row_chosen >= number_of_rows)) + { + printf(" SetRow : selected row is negative or larger than the dimension of the matrix\n"); + exit(0); + } +#endif + /* Unused input variable */ + number_of_rows = number_of_rows; + + for (i = 0; i < in_column_length; i++) + { + (*matptr++) = (*inarrptr++); + } +} diff --git a/common_audio/signal_processing_library/main/source/sin_table.c b/common_audio/signal_processing_library/main/source/sin_table.c new file mode 100644 index 0000000000..ea44666b49 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/sin_table.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 360 degree sine table. + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_kSinTable[] = { + 0, 142, 285, 428, 571, 713, 856, 998, 1140, + 1281, 1422, 1563, 1703, 1842, 1981, 2120, 2258, 2395, + 2531, 2667, 2801, 2935, 3068, 3200, 3331, 3462, 3591, + 3719, 3845, 3971, 4095, 4219, 4341, 4461, 4580, 4698, + 4815, 4930, 5043, 5155, 5265, 5374, 5481, 5586, 5690, + 5792, 5892, 5991, 6087, 6182, 6275, 6366, 6455, 6542, + 6627, 6710, 6791, 6870, 6947, 7021, 7094, 7164, 7233, + 7299, 7362, 7424, 7483, 7540, 7595, 7647, 7697, 7745, + 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 8067, + 8091, 8112, 8130, 8147, 8160, 8172, 8180, 8187, 8190, + 8191, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112, + 8091, 8067, 8041, 8012, 7982, 7948, 7912, 7874, 7834, + 7791, 7745, 7697, 7647, 7595, 7540, 7483, 7424, 7362, + 7299, 7233, 7164, 7094, 7021, 6947, 6870, 6791, 6710, + 6627, 6542, 6455, 6366, 6275, 6182, 6087, 5991, 5892, + 5792, 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, + 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 3845, + 3719, 3591, 3462, 3331, 3200, 3068, 2935, 2801, 2667, + 2531, 2395, 2258, 2120, 1981, 1842, 1703, 1563, 1422, + 1281, 1140, 998, 856, 713, 571, 428, 285, 142, + 0, -142, -285, -428, -571, -713, -856, -998, -1140, + -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395, + -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591, + -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698, + -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690, + -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542, + -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233, + -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745, + -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067, + -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190, + -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112, + -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834, + -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362, + -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710, + -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892, + -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930, + -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845, + -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667, + -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, + -1281, -1140, -998, -856, -713, -571, -428, -285, -142 +}; diff --git a/common_audio/signal_processing_library/main/source/sin_table_1024.c b/common_audio/signal_processing_library/main/source/sin_table_1024.c new file mode 100644 index 0000000000..a2007f9d83 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/sin_table_1024.c @@ -0,0 +1,150 @@ +/* + * 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 1024 point sine table. + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_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, +}; diff --git a/common_audio/signal_processing_library/main/source/spl.gyp b/common_audio/signal_processing_library/main/source/spl.gyp new file mode 100644 index 0000000000..2dfa0fc9b9 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/spl.gyp @@ -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. + +{ + 'includes': [ + '../../../../common_settings.gypi', # Common settings + ], + 'targets': [ + { + 'target_name': 'spl', + 'type': '<(library)', + 'include_dirs': [ + '../interface', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../interface', + ], + }, + 'sources': [ + '../interface/signal_processing_library.h', + '../interface/spl_inl.h', + 'add_sat_w16.c', + 'add_sat_w32.c', + 'auto_corr_to_refl_coef.c', + 'auto_correlation.c', + 'complex_fft.c', + 'complex_ifft.c', + 'complex_bit_reverse.c', + 'copy_set_operations.c', + 'cos_table.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', + 'get_size_in_bits.c', + 'hanning_table.c', + 'ilbc_specific_functions.c', + 'levinson_durbin.c', + 'lpc_to_refl_coef.c', + 'min_max_operations.c', + 'norm_u32.c', + 'norm_w16.c', + 'norm_w32.c', + 'randn_table.c', + 'randomization_functions.c', + 'refl_coef_to_lpc.c', + 'resample.c', + 'resample_48khz.c', + 'resample_by_2.c', + 'resample_by_2_internal.c', + 'resample_by_2_internal.h', + 'resample_fractional.c', + 'sin_table.c', + 'sin_table_1024.c', + 'spl_sqrt.c', + 'spl_version.c', + 'splitting_filter.c', + 'sqrt_of_one_minus_x_squared.c', + 'sub_sat_w16.c', + 'sub_sat_w32.c', + 'vector_scaling_operations.c', + ], + }, + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/common_audio/signal_processing_library/main/source/spl_sqrt.c b/common_audio/signal_processing_library/main/source/spl_sqrt.c new file mode 100644 index 0000000000..cfe2cd3f34 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/spl_version.c b/common_audio/signal_processing_library/main/source/spl_version.c new file mode 100644 index 0000000000..936925ea14 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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 +#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_library/main/source/splitting_filter.c b/common_audio/signal_processing_library/main/source/splitting_filter.c new file mode 100644 index 0000000000..98442f43ce --- /dev/null +++ b/common_audio/signal_processing_library/main/source/splitting_filter.c @@ -0,0 +1,200 @@ +/* + * 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] = (WebRtc_Word16)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, + tmp, WEBRTC_SPL_WORD16_MIN); + + tmp = filter1[i] - filter2[i] + 1024; + tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11); + high_band[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, + tmp, WEBRTC_SPL_WORD16_MIN); + } +} + +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++] = (WebRtc_Word16)WEBRTC_SPL_SAT(32767, tmp, -32768); + + tmp = WEBRTC_SPL_RSHIFT_W32(filter1[i] + 512, 10); + out_data[k++] = (WebRtc_Word16)WEBRTC_SPL_SAT(32767, tmp, -32768); + } + +} diff --git a/common_audio/signal_processing_library/main/source/sqrt_of_one_minus_x_squared.c b/common_audio/signal_processing_library/main/source/sqrt_of_one_minus_x_squared.c new file mode 100644 index 0000000000..9fb2c73bc5 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/sub_sat_w16.c b/common_audio/signal_processing_library/main/source/sub_sat_w16.c new file mode 100644 index 0000000000..a48c3d5db2 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/sub_sat_w16.c @@ -0,0 +1,48 @@ +/* + * 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_SubSatW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS +#ifndef XSCALE_OPT + +WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1, WebRtc_Word16 var2) +{ + WebRtc_Word32 l_diff; + WebRtc_Word16 s_diff; + + // perform subtraction + l_diff = (WebRtc_Word32)var1 - (WebRtc_Word32)var2; + + // default setting + s_diff = (WebRtc_Word16)l_diff; + + // check for overflow + if (l_diff > (WebRtc_Word32)32767) + s_diff = (WebRtc_Word16)32767; + + // check for underflow + if (l_diff < (WebRtc_Word32)-32768) + s_diff = (WebRtc_Word16)-32768; + + return s_diff; +} + +#else +#pragma message(">> WebRtcSpl_SubSatW16.c is excluded from this build") +#endif // XSCALE_OPT +#endif // SPL_NO_DOUBLE_IMPLEMENTATIONS diff --git a/common_audio/signal_processing_library/main/source/sub_sat_w32.c b/common_audio/signal_processing_library/main/source/sub_sat_w32.c new file mode 100644 index 0000000000..add3675b9f --- /dev/null +++ b/common_audio/signal_processing_library/main/source/sub_sat_w32.c @@ -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. + */ + + +/* + * This file contains the function WebRtcSpl_SubSatW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#ifndef SPL_NO_DOUBLE_IMPLEMENTATIONS + +WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 var1, WebRtc_Word32 var2) +{ + WebRtc_Word32 l_diff; + + // perform subtraction + l_diff = var1 - var2; + + // check for underflow + if ((var1 < 0) && (var2 > 0) && (l_diff > 0)) + l_diff = (WebRtc_Word32)0x80000000; + // check for overflow + if ((var1 > 0) && (var2 < 0) && (l_diff < 0)) + l_diff = (WebRtc_Word32)0x7FFFFFFF; + + return l_diff; +} + +#endif diff --git a/common_audio/signal_processing_library/main/source/update_energy_from_array.c b/common_audio/signal_processing_library/main/source/update_energy_from_array.c new file mode 100644 index 0000000000..7af6470c69 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/update_energy_from_array.c @@ -0,0 +1,25 @@ +/* + * update_energy_from_array.c + * + * This file contains the function WebRtcSpl_UpdateEnergyFromArray(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_UpdateEnergyFromArray(WebRtc_Word32 *E, WebRtc_Word16 *vector, + WebRtc_Word16 vector_length, WebRtc_Word16 alpha, + WebRtc_Word16 round_factor) +{ + int loop; + WebRtc_Word32 tmp32a; + + for (loop = 0; loop < vector_length; loop++) + { + tmp32a = WEBRTC_SPL_MUL_16_16(vector[loop], vector[loop]); + tmp32a = (WebRtc_Word32)(tmp32a - *E + round_factor); // rounding factor + tmp32a = tmp32a >> alpha; + *E += tmp32a; + } +} diff --git a/common_audio/signal_processing_library/main/source/update_energy_from_value.c b/common_audio/signal_processing_library/main/source/update_energy_from_value.c new file mode 100644 index 0000000000..1a97e85f95 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/update_energy_from_value.c @@ -0,0 +1,34 @@ +/* + * update_energy_from_value.c + * + * This file contains the function WebRtcSpl_UpdateEnergyFromValue(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_UpdateEnergyFromValue(WebRtc_Word32 *energy, WebRtc_Word16 weight1, + WebRtc_Word32 new_data, WebRtc_Word16 weight2) +{ + int sh1, sh2; + WebRtc_Word32 tmp32a, tmp32b; + WebRtc_Word16 tmp16a, tmp16b; + + tmp32a = *energy; /* Let tmp32a */ + tmp32b = new_data; /* Let tmp32b */ + + /* Make tmp32a to a WebRtc_Word16 in Q(sh1-16) domain */ + sh1 = WebRtcSpl_NormW32(tmp32a); + tmp16a = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(tmp32a, sh1 - 16); + + /* Make tmp32b to a WebRtc_Word16 in Q(sh2-16) domain */ + sh2 = WebRtcSpl_NormW32(tmp32b); + tmp16b = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(tmp32b, sh2 - 16); + + /* Determine weight1*tmp16a + weight2*tmp16b */ + tmp32a = WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(tmp16a, weight1, sh1 - 1); + tmp32b = WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(tmp16b, weight2, sh2 - 1); + + *energy = tmp32a + tmp32b; +} diff --git a/common_audio/signal_processing_library/main/source/update_filter.c b/common_audio/signal_processing_library/main/source/update_filter.c new file mode 100644 index 0000000000..dc72f982b3 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/update_filter.c @@ -0,0 +1,21 @@ +/* + * update_filter.c + * + * This file contains the function WebRtcSpl_UpdateFilter(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +void WebRtcSpl_UpdateFilter(WebRtc_Word16 gain, int vector_length, WebRtc_Word16* phi, + WebRtc_Word16* H) +{ + int i; + + for (i = 0; i < vector_length; i++) + { + *H += (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(gain, *phi++, 16); + H++; + } +} diff --git a/common_audio/signal_processing_library/main/source/vector_scaling_operations.c b/common_audio/signal_processing_library/main/source/vector_scaling_operations.c new file mode 100644 index 0000000000..47362ee886 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/vector_scaling_operations.c @@ -0,0 +1,151 @@ +/* + * 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 functions + * WebRtcSpl_VectorBitShiftW16() + * WebRtcSpl_VectorBitShiftW32() + * WebRtcSpl_VectorBitShiftW32ToW16() + * WebRtcSpl_ScaleVector() + * WebRtcSpl_ScaleVectorWithSat() + * WebRtcSpl_ScaleAndAddVectors() + * + * The description header can be found in signal_processing_library.h + * + */ + +#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++) = (WebRtc_Word16)WEBRTC_SPL_SAT(32767, tmpW32, -32768); + } +} + +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); + } +} diff --git a/common_audio/signal_processing_library/main/source/webrtc_fft_4ofq14_gcc_android.s b/common_audio/signal_processing_library/main/source/webrtc_fft_4ofq14_gcc_android.s new file mode 100644 index 0000000000..c1a893b3e4 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/webrtc_fft_4ofq14_gcc_android.s @@ -0,0 +1,227 @@ + .globl FFT_4OFQ14 + +FFT_4OFQ14: + stmdb sp!, {r4 - r11, lr} + ldr lr, =s_Q14S_8 + ldr lr, [lr] + cmp r2, lr + movgt r0, #1 + ldmgtia sp!, {r4 - r11, pc} + stmdb sp!, {r1, r2} + mov r3, #0 + mov r2, r2 + +LBL1: + add r12, r0, r3, lsl #2 + add r12, r12, r2, lsr #1 + ldrsh r5, [r12, #2] + ldrsh r4, [r12], +r2 + ldrsh r9, [r12, #2] + ldrsh r8, [r12], +r2 + ldrsh r7, [r12, #2] + ldrsh r6, [r12], +r2 + ldrsh r11, [r12, #2] + ldrsh r10, [r12], +r2 + add r4, r4, r6 + add r5, r5, r7 + sub r6, r4, r6, lsl #1 + sub r7, r5, r7, lsl #1 + sub r12, r8, r10 + sub lr, r9, r11 + add r10, r8, r10 + add r11, r9, r11 + sub r9, r4, r10 + sub r8, r5, r11 + add r4, r4, r10 + add r5, r5, r11 + sub r10, r6, lr + add r11, r7, r12 + add r6, r6, lr + sub r7, r7, r12 + ldr lr, =t_Q14R_rad8 + ldrsh lr, [lr] + stmdb sp!, {r2} + add r12, r6, r7 + mul r6, r12, lr + rsb r12, r12, r7, lsl #1 + mul r7, r12, lr + sub r12, r11, r10 + mul r10, r12, lr + sub r12, r12, r11, lsl #1 + mul r11, r12, lr + ldmia sp!, {r2} + stmdb sp!, {r4 - r11} + add r4, r0, r3, lsl #2 + ldrsh r7, [r4, #2] + ldrsh r6, [r4], +r2 + ldrsh r11, [r4, #2] + ldrsh r10, [r4], +r2 + ldrsh r9, [r4, #2] + ldrsh r8, [r4], +r2 + ldrsh lr, [r4, #2] + ldrsh r12, [r4], +r2 + mov r7, r7, asr #3 + mov r6, r6, asr #3 + add r6, r6, r8, asr #3 + add r7, r7, r9, asr #3 + sub r8, r6, r8, asr #2 + sub r9, r7, r9, asr #2 + sub r4, r10, r12 + sub r5, r11, lr + add r10, r10, r12 + add r11, r11, lr + add r6, r6, r10, asr #3 + add r7, r7, r11, asr #3 + sub r10, r6, r10, asr #2 + sub r11, r7, r11, asr #2 + sub r12, r8, r5, asr #3 + add lr, r9, r4, asr #3 + add r8, r8, r5, asr #3 + sub r9, r9, r4, asr #3 + ldmia sp!, {r4, r5} + add r6, r6, r4, asr #3 + add r7, r7, r5, asr #3 + sub r4, r6, r4, asr #2 + sub r5, r7, r5, asr #2 + strh r7, [r1, #2] + strh r6, [r1], #4 + ldmia sp!, {r6, r7} + add r8, r8, r6, asr #17 + add r9, r9, r7, asr #17 + sub r6, r8, r6, asr #16 + sub r7, r9, r7, asr #16 + strh r9, [r1, #2] + strh r8, [r1], #4 + ldmia sp!, {r8, r9} + add r10, r10, r8, asr #3 + sub r11, r11, r9, asr #3 + sub r8, r10, r8, asr #2 + add r9, r11, r9, asr #2 + strh r11, [r1, #2] + strh r10, [r1], #4 + ldmia sp!, {r10, r11} + add r12, r12, r10, asr #17 + add lr, lr, r11, asr #17 + sub r10, r12, r10, asr #16 + sub r11, lr, r11, asr #16 + strh lr, [r1, #2] + strh r12, [r1], #4 + strh r5, [r1, #2] + strh r4, [r1], #4 + strh r7, [r1, #2] + strh r6, [r1], #4 + strh r9, [r1, #2] + strh r8, [r1], #4 + strh r11, [r1, #2] + strh r10, [r1], #4 + eor r3, r3, r2, lsr #4 + tst r3, r2, lsr #4 + bne LBL1 + + eor r3, r3, r2, lsr #5 + tst r3, r2, lsr #5 + bne LBL1 + + mov r12, r2, lsr #6 + +LBL2: + eor r3, r3, r12 + tst r3, r12 + bne LBL1 + + movs r12, r12, lsr #1 + bne LBL2 + + ldmia sp!, {r1, r2} + mov r3, r2, lsr #3 + mov r2, #0x20 + ldr r0, =t_Q14S_8 + cmp r3, #1 + beq LBL3 + +LBL6: + mov r3, r3, lsr #2 + stmdb sp!, {r1, r3} + add r12, r2, r2, lsl #1 + add r1, r1, r12 + sub r3, r3, #1, 16 + +LBL5: + add r3, r3, r2, lsl #14 + +LBL4: + ldrsh r6, [r0], #2 + ldrsh r7, [r0], #2 + ldrsh r8, [r0], #2 + ldrsh r9, [r0], #2 + ldrsh r10, [r0], #2 + ldrsh r11, [r0], #2 + ldrsh r5, [r1, #2] + ldrsh r4, [r1], -r2 + sub lr, r5, r4 + mul r12, lr, r11 + add lr, r10, r11, lsl #1 + mla r11, r5, r10, r12 + mla r10, r4, lr, r12 + ldrsh r5, [r1, #2] + ldrsh r4, [r1], -r2 + sub lr, r5, r4 + mul r12, lr, r9 + add lr, r8, r9, lsl #1 + mla r9, r5, r8, r12 + mla r8, r4, lr, r12 + ldrsh r5, [r1, #2] + ldrsh r4, [r1], -r2 + sub lr, r5, r4 + mul r12, lr, r7 + add lr, r6, r7, lsl #1 + mla r7, r5, r6, r12 + mla r6, r4, lr, r12 + ldrsh r5, [r1, #2] + ldrsh r4, [r1] + mov r5, r5, asr #2 + mov r4, r4, asr #2 + add r12, r4, r6, asr #16 + add lr, r5, r7, asr #16 + sub r4, r4, r6, asr #16 + sub r5, r5, r7, asr #16 + add r6, r8, r10 + add r7, r9, r11 + sub r8, r8, r10 + sub r9, r9, r11 + add r10, r12, r6, asr #16 + add r11, lr, r7, asr #16 + strh r11, [r1, #2] + strh r10, [r1], +r2 + add r10, r4, r9, asr #16 + sub r11, r5, r8, asr #16 + strh r11, [r1, #2] + strh r10, [r1], +r2 + sub r10, r12, r6, asr #16 + sub r11, lr, r7, asr #16 + strh r11, [r1, #2] + strh r10, [r1], +r2 + sub r10, r4, r9, asr #16 + add r11, r5, r8, asr #16 + strh r11, [r1, #2] + strh r10, [r1], #4 + subs r3, r3, #1, 16 + bge LBL4 + add r12, r2, r2, lsl #1 + add r1, r1, r12 + sub r0, r0, r12 + sub r3, r3, #1 + movs lr, r3, lsl #16 + bne LBL5 + add r0, r0, r12 + ldmia sp!, {r1, r3} + mov r2, r2, lsl #2 + cmp r3, #2 + bgt LBL6 + +LBL3: + mov r0, #0 + ldmia sp!, {r4 - r11, pc} + andeq r3, r1, r0, lsr #32 + andeq r10, r1, r12, ror #31 + andeq r3, r1, r8, lsr #32 diff --git a/common_audio/signal_processing_library/main/source/webrtc_fft_4oiq14_gcc_android.s b/common_audio/signal_processing_library/main/source/webrtc_fft_4oiq14_gcc_android.s new file mode 100644 index 0000000000..cc93291119 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/webrtc_fft_4oiq14_gcc_android.s @@ -0,0 +1,221 @@ + .globl FFT_4OIQ14 + +FFT_4OIQ14: + stmdb sp!, {r4 - r11, lr} + ldr lr, =s_Q14S_8 + ldr lr, [lr] + cmp r2, lr + movgt r0, #1 + ldmgtia sp!, {r4 - r11, pc} + stmdb sp!, {r1, r2} + mov r3, #0 + mov r2, r2 + +LBL1: + add r12, r0, r3, lsl #2 + add r12, r12, r2, lsr #1 + ldrsh r5, [r12, #2] + ldrsh r4, [r12], +r2 + ldrsh r9, [r12, #2] + ldrsh r8, [r12], +r2 + ldrsh r7, [r12, #2] + ldrsh r6, [r12], +r2 + ldrsh r11, [r12, #2] + ldrsh r10, [r12], +r2 + add r4, r4, r6 + add r5, r5, r7 + sub r6, r4, r6, lsl #1 + sub r7, r5, r7, lsl #1 + sub r12, r8, r10 + sub lr, r9, r11 + add r10, r8, r10 + add r11, r9, r11 + sub r9, r4, r10 + sub r8, r5, r11 + add r4, r4, r10 + add r5, r5, r11 + add r10, r6, lr + sub r11, r7, r12 + sub r6, r6, lr + add r7, r7, r12 + ldr lr, =t_Q14R_rad8 + ldrsh lr, [lr] + stmdb sp!, {r2} + sub r12, r6, r7 + mul r6, r12, lr + add r12, r12, r7, lsl #1 + mul r7, r12, lr + sub r12, r10, r11 + mul r11, r12, lr + sub r12, r12, r10, lsl #1 + mul r10, r12, lr + ldmia sp!, {r2} + stmdb sp!, {r4 - r11} + add r4, r0, r3, lsl #2 + ldrsh r7, [r4, #2] + ldrsh r6, [r4], +r2 + ldrsh r11, [r4, #2] + ldrsh r10, [r4], +r2 + ldrsh r9, [r4, #2] + ldrsh r8, [r4], +r2 + ldrsh lr, [r4, #2] + ldrsh r12, [r4], +r2 + add r6, r6, r8 + add r7, r7, r9 + sub r8, r6, r8, lsl #1 + sub r9, r7, r9, lsl #1 + sub r4, r10, r12 + sub r5, r11, lr + add r10, r10, r12 + add r11, r11, lr + add r6, r6, r10 + add r7, r7, r11 + sub r10, r6, r10, lsl #1 + sub r11, r7, r11, lsl #1 + add r12, r8, r5 + sub lr, r9, r4 + sub r8, r8, r5 + add r9, r9, r4 + ldmia sp!, {r4, r5} + add r6, r6, r4 + add r7, r7, r5 + sub r4, r6, r4, lsl #1 + sub r5, r7, r5, lsl #1 + strh r7, [r1, #2] + strh r6, [r1], #4 + ldmia sp!, {r6, r7} + add r8, r8, r6, asr #14 + add r9, r9, r7, asr #14 + sub r6, r8, r6, asr #13 + sub r7, r9, r7, asr #13 + strh r9, [r1, #2] + strh r8, [r1], #4 + ldmia sp!, {r8, r9} + sub r10, r10, r8 + add r11, r11, r9 + add r8, r10, r8, lsl #1 + sub r9, r11, r9, lsl #1 + strh r11, [r1, #2] + strh r10, [r1], #4 + ldmia sp!, {r10, r11} + add r12, r12, r10, asr #14 + add lr, lr, r11, asr #14 + sub r10, r12, r10, asr #13 + sub r11, lr, r11, asr #13 + strh lr, [r1, #2] + strh r12, [r1], #4 + strh r5, [r1, #2] + strh r4, [r1], #4 + strh r7, [r1, #2] + strh r6, [r1], #4 + strh r9, [r1, #2] + strh r8, [r1], #4 + strh r11, [r1, #2] + strh r10, [r1], #4 + eor r3, r3, r2, lsr #4 + tst r3, r2, lsr #4 + bne LBL1 + eor r3, r3, r2, lsr #5 + tst r3, r2, lsr #5 + bne LBL1 + mov r12, r2, lsr #6 + + +LBL2: + eor r3, r3, r12 + tst r3, r12 + bne LBL1 + movs r12, r12, lsr #1 + bne LBL2 + ldmia sp!, {r1, r2} + mov r3, r2, lsr #3 + mov r2, #0x20 + ldr r0, =t_Q14S_8 + cmp r3, #1 + beq LBL3 + +LBL6: + mov r3, r3, lsr #2 + stmdb sp!, {r1, r3} + add r12, r2, r2, lsl #1 + add r1, r1, r12 + sub r3, r3, #1, 16 + +LBL5: + add r3, r3, r2, lsl #14 + +LBL4: + ldrsh r6, [r0], #2 + ldrsh r7, [r0], #2 + ldrsh r8, [r0], #2 + ldrsh r9, [r0], #2 + ldrsh r10, [r0], #2 + ldrsh r11, [r0], #2 + ldrsh r5, [r1, #2] + ldrsh r4, [r1], -r2 + sub lr, r4, r5 + mul r12, lr, r11 + add r11, r10, r11, lsl #1 + mla r10, r4, r10, r12 + mla r11, r5, r11, r12 + ldrsh r5, [r1, #2] + ldrsh r4, [r1], -r2 + sub lr, r4, r5 + mul r12, lr, r9 + add r9, r8, r9, lsl #1 + mla r8, r4, r8, r12 + mla r9, r5, r9, r12 + ldrsh r5, [r1, #2] + ldrsh r4, [r1], -r2 + sub lr, r4, r5 + mul r12, lr, r7 + add r7, r6, r7, lsl #1 + mla r6, r4, r6, r12 + mla r7, r5, r7, r12 + ldrsh r5, [r1, #2] + ldrsh r4, [r1] + add r12, r4, r6, asr #14 + add lr, r5, r7, asr #14 + sub r4, r4, r6, asr #14 + sub r5, r5, r7, asr #14 + add r6, r8, r10 + add r7, r9, r11 + sub r8, r8, r10 + sub r9, r9, r11 + add r10, r12, r6, asr #14 + add r11, lr, r7, asr #14 + strh r11, [r1, #2] + strh r10, [r1], +r2 + sub r10, r4, r9, asr #14 + add r11, r5, r8, asr #14 + strh r11, [r1, #2] + strh r10, [r1], +r2 + sub r10, r12, r6, asr #14 + sub r11, lr, r7, asr #14 + strh r11, [r1, #2] + strh r10, [r1], +r2 + add r10, r4, r9, asr #14 + sub r11, r5, r8, asr #14 + strh r11, [r1, #2] + strh r10, [r1], #4 + subs r3, r3, #1, 16 + bge LBL4 + add r12, r2, r2, lsl #1 + add r1, r1, r12 + sub r0, r0, r12 + sub r3, r3, #1 + movs lr, r3, lsl #16 + bne LBL5 + add r0, r0, r12 + ldmia sp!, {r1, r3} + mov r2, r2, lsl #2 + cmp r3, #2 + bgt LBL6 + +LBL3: + mov r0, #0 + ldmia sp!, {r4 - r11, pc} + andeq r3, r1, r0, lsr #32 + andeq r10, r1, r12, ror #31 + andeq r3, r1, r8, lsr #32 + diff --git a/common_audio/signal_processing_library/main/source/webrtc_fft_t_1024_8.c b/common_audio/signal_processing_library/main/source/webrtc_fft_t_1024_8.c new file mode 100644 index 0000000000..b587380523 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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_library/main/source/webrtc_fft_t_rad.c b/common_audio/signal_processing_library/main/source/webrtc_fft_t_rad.c new file mode 100644 index 0000000000..13fbd9f53e --- /dev/null +++ b/common_audio/signal_processing_library/main/source/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/signal_processing_library/main/source/zeros_array_w16.c b/common_audio/signal_processing_library/main/source/zeros_array_w16.c new file mode 100644 index 0000000000..e72c2fee93 --- /dev/null +++ b/common_audio/signal_processing_library/main/source/zeros_array_w16.c @@ -0,0 +1,15 @@ +/* + * zeros_array_w16.c + * + * This file contains the function WebRtcSpl_ZerosArrayW16(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_ZerosArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length) +{ + WebRtcSpl_MemSetW16(vector, 0, length); + return length; +} diff --git a/common_audio/signal_processing_library/main/source/zeros_array_w32.c b/common_audio/signal_processing_library/main/source/zeros_array_w32.c new file mode 100644 index 0000000000..9853927d7b --- /dev/null +++ b/common_audio/signal_processing_library/main/source/zeros_array_w32.c @@ -0,0 +1,15 @@ +/* + * zeros_array_w32.c + * + * This file contains the function WebRtcSpl_ZerosArrayW32(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_Word16 WebRtcSpl_ZerosArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length) +{ + WebRtcSpl_MemSetW32(vector, 0, length); + return length; +} diff --git a/common_audio/signal_processing_library/main/test/unit_test/unit_test.cc b/common_audio/signal_processing_library/main/test/unit_test/unit_test.cc new file mode 100644 index 0000000000..19cc553f65 --- /dev/null +++ b/common_audio/signal_processing_library/main/test/unit_test/unit_test.cc @@ -0,0 +1,478 @@ +/* + * 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 SPL unit_test. + * + */ + +#include "unit_test.h" +#include "signal_processing_library.h" + +class SplEnvironment : public ::testing::Environment { + public: + virtual void SetUp() { + } + virtual void TearDown() { + } +}; + +SplTest::SplTest() +{ +} + +void SplTest::SetUp() { +} + +void SplTest::TearDown() { +} + +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_ptr1 = 0; + 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(-2147483645, WEBRTC_SPL_UMUL(a, b)); + b = WEBRTC_SPL_WORD16_MAX >> 1; + EXPECT_EQ(65535, WEBRTC_SPL_UMUL_RSFT16(a, b)); + EXPECT_EQ(1073627139, WEBRTC_SPL_UMUL_16_16(a, b)); + EXPECT_EQ(16382, WEBRTC_SPL_UMUL_16_16_RSFT16(a, b)); + EXPECT_EQ(-49149, WEBRTC_SPL_UMUL_32_16(a, b)); + EXPECT_EQ(65535, 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(0, 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(-49149, WEBRTC_SPL_MUL_16_16(a, b)); + 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 + // Positive means left shift + EXPECT_EQ(32766, WEBRTC_SPL_SHIFT_W16(a, 1)); + EXPECT_EQ(32766, WEBRTC_SPL_SHIFT_W32(a, 1)); + + // 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(8191, WEBRTC_SPL_RSHIFT_U32(a, 1)); + EXPECT_EQ(32766, WEBRTC_SPL_LSHIFT_U32(a, 1)); + + EXPECT_EQ(1470, WEBRTC_SPL_RAND(A)); +} + +TEST_F(SplTest, InlineTest) { + + WebRtc_Word16 a = 121; + WebRtc_Word16 b = -17; + WebRtc_Word32 A = 111121; + WebRtc_Word32 B = -1711; + char* bVersion = (char*) malloc(8); + + EXPECT_EQ(104, WebRtcSpl_AddSatW16(a, b)); + EXPECT_EQ(138, WebRtcSpl_SubSatW16(a, b)); + + EXPECT_EQ(109410, WebRtcSpl_AddSatW32(A, B)); + EXPECT_EQ(112832, WebRtcSpl_SubSatW32(A, B)); + + EXPECT_EQ(17, WebRtcSpl_GetSizeInBits(A)); + EXPECT_EQ(14, WebRtcSpl_NormW32(A)); + EXPECT_EQ(4, WebRtcSpl_NormW16(B)); + EXPECT_EQ(15, WebRtcSpl_NormU32(A)); + + EXPECT_EQ(0, WebRtcSpl_get_version(bVersion, 8)); +} + +TEST_F(SplTest, MathOperationsTest) { + + int A = 117; + WebRtc_Word32 num = 117; + WebRtc_Word32 den = -5; + WebRtc_UWord16 denU = 5; + EXPECT_EQ(10, WebRtcSpl_Sqrt(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(23, WebRtcSpl_DivU32U16(num, denU)); + EXPECT_EQ(0, WebRtcSpl_DivW32HiLow(128, 0, 256)); +} + +TEST_F(SplTest, BasicArrayOperationsTest) { + + + int B[] = {4, 12, 133, 1100}; + int Bs[] = {2, 6, 66, 550}; + WebRtc_UWord8* b8 = (WebRtc_UWord8*) malloc(4); + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* b32 = (WebRtc_Word32*) malloc(4); + + WebRtc_UWord8* bTmp8 = (WebRtc_UWord8*) malloc(4); + WebRtc_Word16* bTmp16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* bTmp32 = (WebRtc_Word32*) malloc(4); + + WebRtcSpl_MemSetW16(b16, 3, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(3, b16[kk]); + } + EXPECT_EQ(4, WebRtcSpl_ZerosArrayW16(b16, 4)); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(0, b16[kk]); + } + EXPECT_EQ(4, WebRtcSpl_OnesArrayW16(b16, 4)); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(1, b16[kk]); + } + WebRtcSpl_MemSetW32(b32, 3, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(3, b32[kk]); + } + EXPECT_EQ(4, WebRtcSpl_ZerosArrayW32(b32, 4)); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(0, b32[kk]); + } + EXPECT_EQ(4, WebRtcSpl_OnesArrayW32(b32, 4)); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(1, b32[kk]); + } + for (int kk = 0; kk < 4; ++kk) { + bTmp8[kk] = (WebRtc_Word8)kk; + bTmp16[kk] = (WebRtc_Word16)kk; + bTmp32[kk] = (WebRtc_Word32)kk; + } + WEBRTC_SPL_MEMCPY_W8(b8, bTmp8, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(b8[kk], bTmp8[kk]); + } + WEBRTC_SPL_MEMCPY_W16(b16, bTmp16, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(b16[kk], bTmp16[kk]); + } +// WEBRTC_SPL_MEMCPY_W32(b32, bTmp32, 4); +// for (int kk = 0; kk < 4; ++kk) { +// EXPECT_EQ(b32[kk], bTmp32[kk]); +// } + EXPECT_EQ(2, WebRtcSpl_CopyFromEndW16(b16, 4, 2, bTmp16)); + for (int kk = 0; kk < 2; ++kk) { + EXPECT_EQ(kk+2, bTmp16[kk]); + } + + for (int kk = 0; kk < 4; ++kk) { + b32[kk] = B[kk]; + b16[kk] = (WebRtc_Word16)B[kk]; + } + WebRtcSpl_VectorBitShiftW32ToW16(bTmp16, 4, b32, 1); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((B[kk]>>1), bTmp16[kk]); + } + WebRtcSpl_VectorBitShiftW16(bTmp16, 4, b16, 1); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((B[kk]>>1), bTmp16[kk]); + } + WebRtcSpl_VectorBitShiftW32(bTmp32, 4, b32, 1); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((B[kk]>>1), bTmp32[kk]); + } + + WebRtcSpl_MemCpyReversedOrder(&bTmp16[3], b16, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(b16[3-kk], bTmp16[kk]); + } + +} + +TEST_F(SplTest, MinMaxOperationsTest) { + + + int B[] = {4, 12, 133, -1100}; + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* b32 = (WebRtc_Word32*) malloc(4); + + for (int kk = 0; kk < 4; ++kk) { + b16[kk] = B[kk]; + b32[kk] = B[kk]; + } + + EXPECT_EQ(1100, WebRtcSpl_MaxAbsValueW16(b16, 4)); + EXPECT_EQ(1100, WebRtcSpl_MaxAbsValueW32(b32, 4)); + EXPECT_EQ(133, WebRtcSpl_MaxValueW16(b16, 4)); + EXPECT_EQ(133, WebRtcSpl_MaxValueW32(b32, 4)); + EXPECT_EQ(3, WebRtcSpl_MaxAbsIndexW16(b16, 4)); + EXPECT_EQ(2, WebRtcSpl_MaxIndexW16(b16, 4)); + EXPECT_EQ(2, WebRtcSpl_MaxIndexW32(b32, 4)); + + EXPECT_EQ(-1100, WebRtcSpl_MinValueW16(b16, 4)); + EXPECT_EQ(-1100, WebRtcSpl_MinValueW32(b32, 4)); + EXPECT_EQ(3, WebRtcSpl_MinIndexW16(b16, 4)); + EXPECT_EQ(3, WebRtcSpl_MinIndexW32(b32, 4)); + + EXPECT_EQ(0, WebRtcSpl_GetScalingSquare(b16, 4, 1)); + +} + +TEST_F(SplTest, VectorOperationsTest) { + + + int B[] = {4, 12, 133, 1100}; + WebRtc_Word16* a16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* b32 = (WebRtc_Word32*) malloc(4); + WebRtc_Word16* bTmp16 = (WebRtc_Word16*) malloc(4); + + for (int kk = 0; kk < 4; ++kk) { + a16[kk] = B[kk]; + b16[kk] = B[kk]; + } + + WebRtcSpl_AffineTransformVector(bTmp16, b16, 3, 7, 2, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((B[kk]*3+7)>>2, bTmp16[kk]); + } + WebRtcSpl_ScaleAndAddVectorsWithRound(b16, 3, b16, 2, 2, bTmp16, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((B[kk]*3+B[kk]*2+2)>>2, bTmp16[kk]); + } + + WebRtcSpl_AddAffineVectorToVector(bTmp16, b16, 3, 7, 2, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(((B[kk]*3+B[kk]*2+2)>>2)+((b16[kk]*3+7)>>2), bTmp16[kk]); + } + + WebRtcSpl_CrossCorrelation(b32, b16, bTmp16, 4, 2, 2, 0); + for (int kk = 0; kk < 2; ++kk) { + EXPECT_EQ(614236, b32[kk]); + } +// EXPECT_EQ(, WebRtcSpl_DotProduct(b16, bTmp16, 4)); + EXPECT_EQ(306962, WebRtcSpl_DotProductWithScale(b16, b16, 4, 2)); + + WebRtcSpl_ScaleVector(b16, bTmp16, 13, 4, 2); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]); + } + WebRtcSpl_ScaleVectorWithSat(b16, bTmp16, 13, 4, 2); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]); + } + WebRtcSpl_ScaleAndAddVectors(a16, 13, 2, b16, 7, 2, bTmp16, 4); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(((a16[kk]*13)>>2)+((b16[kk]*7)>>2), bTmp16[kk]); + } + + WebRtcSpl_AddVectorsAndShift(bTmp16, a16, b16, 4, 2); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(B[kk] >> 1, bTmp16[kk]); + } + WebRtcSpl_ReverseOrderMultArrayElements(bTmp16, a16, &b16[3], 4, 2); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((a16[kk]*b16[3-kk])>>2, bTmp16[kk]); + } + WebRtcSpl_ElementwiseVectorMult(bTmp16, a16, b16, 4, 6); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ((a16[kk]*b16[kk])>>6, bTmp16[kk]); + } + + WebRtcSpl_SqrtOfOneMinusXSquared(b16, 4, bTmp16); + for (int kk = 0; kk < 3; ++kk) { + EXPECT_EQ(32767, bTmp16[kk]); + } + EXPECT_EQ(32749, bTmp16[3]); +} + +TEST_F(SplTest, EstimatorsTest) { + + + int B[] = {4, 12, 133, 1100}; + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* b32 = (WebRtc_Word32*) malloc(4); + WebRtc_Word16* bTmp16 = (WebRtc_Word16*) malloc(4); + + for (int kk = 0; kk < 4; ++kk) { + b16[kk] = B[kk]; + b32[kk] = B[kk]; + } + + EXPECT_EQ(0, WebRtcSpl_LevinsonDurbin(b32, b16, bTmp16, 2)); + +} + +TEST_F(SplTest, FilterTest) { + + + WebRtc_Word16 A[] = {1, 2, 33, 100}; + WebRtc_Word16 A5[] = {1, 2, 33, 100, -5}; + WebRtc_Word16 B[] = {4, 12, 133, 110}; + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word16* bTmp16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word16* bTmp16Low = (WebRtc_Word16*) malloc(4); + WebRtc_Word16* bState = (WebRtc_Word16*) malloc(4); + WebRtc_Word16* bStateLow = (WebRtc_Word16*) malloc(4); + + WebRtcSpl_ZerosArrayW16(bState, 4); + WebRtcSpl_ZerosArrayW16(bStateLow, 4); + + for (int kk = 0; kk < 4; ++kk) { + b16[kk] = A[kk]; + } + + // MA filters + WebRtcSpl_FilterMAFastQ12(b16, bTmp16, B, 4, 4); + for (int kk = 0; kk < 4; ++kk) { + //EXPECT_EQ(aTmp16[kk], bTmp16[kk]); + } + // AR filters + WebRtcSpl_FilterARFastQ12(b16, bTmp16, A, 4, 4); + for (int kk = 0; kk < 4; ++kk) { +// EXPECT_EQ(aTmp16[kk], bTmp16[kk]); + } + EXPECT_EQ(4, WebRtcSpl_FilterAR(A5, 5, b16, 4, bState, 4, bStateLow, 4, bTmp16, bTmp16Low, 4)); + +} + +TEST_F(SplTest, RandTest) { + + + WebRtc_Word16 BU[] = {3653, 12446, 8525, 30691}; + WebRtc_Word16 BN[] = {3459, -11689, -258, -3738}; + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_UWord32* bSeed = (WebRtc_UWord32*) malloc(1); + + bSeed[0] = 100000; + + EXPECT_EQ(464449057, WebRtcSpl_IncreaseSeed(bSeed)); + EXPECT_EQ(31565, WebRtcSpl_RandU(bSeed)); + EXPECT_EQ(-9786, WebRtcSpl_RandN(bSeed)); + EXPECT_EQ(4, WebRtcSpl_RandUArray(b16, 4, bSeed)); + for (int kk = 0; kk < 4; ++kk) { + EXPECT_EQ(BU[kk], b16[kk]); + } +} + +TEST_F(SplTest, SignalProcessingTest) { + + + int A[] = {1, 2, 33, 100}; + WebRtc_Word16* b16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* b32 = (WebRtc_Word32*) malloc(4); + + WebRtc_Word16* bTmp16 = (WebRtc_Word16*) malloc(4); + WebRtc_Word32* bTmp32 = (WebRtc_Word32*) malloc(4); + + int bScale = 0; + + for (int kk = 0; kk < 4; ++kk) { + b16[kk] = A[kk]; + b32[kk] = A[kk]; + } + + EXPECT_EQ(2, WebRtcSpl_AutoCorrelation(b16, 4, 1, bTmp32, &bScale)); + WebRtcSpl_ReflCoefToLpc(b16, 4, bTmp16); +// for (int kk = 0; kk < 4; ++kk) { +// EXPECT_EQ(aTmp16[kk], bTmp16[kk]); +// } + WebRtcSpl_LpcToReflCoef(bTmp16, 4, b16); +// for (int kk = 0; kk < 4; ++kk) { +// EXPECT_EQ(a16[kk], b16[kk]); +// } + WebRtcSpl_AutoCorrToReflCoef(b32, 4, bTmp16); +// for (int kk = 0; kk < 4; ++kk) { +// EXPECT_EQ(aTmp16[kk], bTmp16[kk]); +// } + WebRtcSpl_GetHanningWindow(bTmp16, 4); +// for (int kk = 0; kk < 4; ++kk) { +// EXPECT_EQ(aTmp16[kk], bTmp16[kk]); +// } + + for (int kk = 0; kk < 4; ++kk) { + b16[kk] = A[kk]; + } + EXPECT_EQ(11094 , WebRtcSpl_Energy(b16, 4, &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]); + } +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + SplEnvironment* env = new SplEnvironment; + ::testing::AddGlobalTestEnvironment(env); + + return RUN_ALL_TESTS(); +} diff --git a/common_audio/signal_processing_library/main/test/unit_test/unit_test.h b/common_audio/signal_processing_library/main/test/unit_test/unit_test.h new file mode 100644 index 0000000000..d7babe734b --- /dev/null +++ b/common_audio/signal_processing_library/main/test/unit_test/unit_test.h @@ -0,0 +1,30 @@ +/* + * 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 the function WebRtcSpl_CopyFromBeginU8(). + * The description header can be found in signal_processing_library.h + * + */ + +#ifndef WEBRTC_SPL_UNIT_TEST_H_ +#define WEBRTC_SPL_UNIT_TEST_H_ + +#include + +class SplTest: public ::testing::Test +{ +protected: + SplTest(); + virtual void SetUp(); + virtual void TearDown(); +}; + +#endif // WEBRTC_SPL_UNIT_TEST_H_ diff --git a/common_audio/vad/OWNERS b/common_audio/vad/OWNERS new file mode 100644 index 0000000000..913285113f --- /dev/null +++ b/common_audio/vad/OWNERS @@ -0,0 +1,2 @@ +bjornv@google.com +jks@google.com diff --git a/common_audio/vad/main/interface/webrtc_vad.h b/common_audio/vad/main/interface/webrtc_vad.h new file mode 100644 index 0000000000..be6c8d28d9 --- /dev/null +++ b/common_audio/vad/main/interface/webrtc_vad.h @@ -0,0 +1,159 @@ +/* + * 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 VAD API calls. Specific function calls are given below. + */ + +#ifndef WEBRTC_VAD_WEBRTC_VAD_H_ +#define WEBRTC_VAD_WEBRTC_VAD_H_ + +#include "typedefs.h" + +typedef struct WebRtcVadInst VadInst; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * WebRtcVad_get_version(...) + * + * This function returns the version number of the code. + * + * Output: + * - version : Pointer to a buffer where the version info will + * be stored. + * Input: + * - size_in_bytes : Size of the buffer. + * + */ +WebRtc_Word16 WebRtcVad_get_version(char *version, int size_in_bytes); + +/**************************************************************************** + * WebRtcVad_AssignSize(...) + * + * This functions get the size needed for storing the instance for encoder + * and decoder, respectively + * + * Input/Output: + * - size_in_bytes : Pointer to integer where the size is returned + * + * Return value : 0 + */ +WebRtc_Word16 WebRtcVad_AssignSize(int *size_in_bytes); + +/**************************************************************************** + * WebRtcVad_Assign(...) + * + * This functions Assigns memory for the instances. + * + * Input: + * - vad_inst_addr : Address to where to assign memory + * Output: + * - vad_inst : Pointer to the instance that should be created + * + * Return value : 0 - Ok + * -1 - Error + */ +WebRtc_Word16 WebRtcVad_Assign(VadInst **vad_inst, void *vad_inst_addr); + +/**************************************************************************** + * WebRtcVad_Create(...) + * + * This function creates an instance to the VAD structure + * + * Input: + * - vad_inst : Pointer to VAD instance that should be created + * + * Output: + * - vad_inst : Pointer to created VAD instance + * + * Return value : 0 - Ok + * -1 - Error + */ +WebRtc_Word16 WebRtcVad_Create(VadInst **vad_inst); + +/**************************************************************************** + * WebRtcVad_Free(...) + * + * This function frees the dynamic memory of a specified VAD instance + * + * Input: + * - vad_inst : Pointer to VAD instance that should be freed + * + * Return value : 0 - Ok + * -1 - Error + */ +WebRtc_Word16 WebRtcVad_Free(VadInst *vad_inst); + +/**************************************************************************** + * WebRtcVad_Init(...) + * + * This function initializes a VAD instance + * + * Input: + * - vad_inst : Instance that should be initialized + * + * Output: + * - vad_inst : Initialized instance + * + * Return value : 0 - Ok + * -1 - Error + */ +WebRtc_Word16 WebRtcVad_Init(VadInst *vad_inst); + +/**************************************************************************** + * WebRtcVad_set_mode(...) + * + * This function initializes a VAD instance + * + * Input: + * - vad_inst : VAD instance + * - mode : Aggressiveness setting (0, 1, 2, or 3) + * + * Output: + * - vad_inst : Initialized instance + * + * Return value : 0 - Ok + * -1 - Error + */ +WebRtc_Word16 WebRtcVad_set_mode(VadInst *vad_inst, WebRtc_Word16 mode); + +/**************************************************************************** + * WebRtcVad_Process(...) + * + * This functions does a VAD for the inserted speech frame + * + * Input + * - vad_inst : VAD Instance. Needs to be initiated before call. + * - fs : sampling frequency (Hz): 8000, 16000, or 32000 + * - speech_frame : Pointer to speech frame buffer + * - frame_length : Length of speech frame buffer in number of samples + * + * Output: + * - vad_inst : Updated VAD instance + * + * Return value : 1 - Active Voice + * 0 - Non-active Voice + * -1 - Error + */ +WebRtc_Word16 WebRtcVad_Process(VadInst *vad_inst, + WebRtc_Word16 fs, + WebRtc_Word16 *speech_frame, + WebRtc_Word16 frame_length); + +#ifdef __cplusplus +} +#endif + +#endif // WEBRTC_VAD_WEBRTC_VAD_H_ diff --git a/common_audio/vad/main/source/vad.gyp b/common_audio/vad/main/source/vad.gyp new file mode 100644 index 0000000000..754b684d5b --- /dev/null +++ b/common_audio/vad/main/source/vad.gyp @@ -0,0 +1,51 @@ +# 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': [ + '../../../../common_settings.gypi', # Common settings + ], + 'targets': [ + { + 'target_name': 'vad', + 'type': '<(library)', + 'dependencies': [ + '../../../signal_processing_library/main/source/spl.gyp:spl', + ], + 'include_dirs': [ + '../interface', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../interface', + ], + }, + 'sources': [ + '../interface/webrtc_vad.h', + 'webrtc_vad.c', + 'vad_const.c', + 'vad_const.h', + 'vad_defines.h', + 'vad_core.c', + 'vad_core.h', + 'vad_filterbank.c', + 'vad_filterbank.h', + 'vad_gmm.c', + 'vad_gmm.h', + 'vad_sp.c', + 'vad_sp.h', + ], + }, + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/common_audio/vad/main/source/vad_const.c b/common_audio/vad/main/source/vad_const.c new file mode 100644 index 0000000000..47b6a4b8ca --- /dev/null +++ b/common_audio/vad/main/source/vad_const.c @@ -0,0 +1,80 @@ +/* + * 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 the constant values used internally in VAD. + */ + +#include "vad_const.h" + +// Spectrum Weighting +const WebRtc_Word16 kSpectrumWeight[6] = {6, 8, 10, 12, 14, 16}; + +const WebRtc_Word16 kCompVar = 22005; + +// Constant 160*log10(2) in Q9 +const WebRtc_Word16 kLogConst = 24660; + +// Constant log2(exp(1)) in Q12 +const WebRtc_Word16 kLog10Const = 5909; + +// Q15 +const WebRtc_Word16 kNoiseUpdateConst = 655; +const WebRtc_Word16 kSpeechUpdateConst = 6554; + +// Q8 +const WebRtc_Word16 kBackEta = 154; + +// Coefficients used by WebRtcVad_HpOutput, Q14 +const WebRtc_Word16 kHpZeroCoefs[3] = {6631, -13262, 6631}; +const WebRtc_Word16 kHpPoleCoefs[3] = {16384, -7756, 5620}; + +// Allpass filter coefficients, upper and lower, in Q15 +// Upper: 0.64, Lower: 0.17 +const WebRtc_Word16 kAllPassCoefsQ15[2] = {20972, 5571}; +const WebRtc_Word16 kAllPassCoefsQ13[2] = {5243, 1392}; // Q13 + +// Minimum difference between the two models, Q5 +const WebRtc_Word16 kMinimumDifference[6] = {544, 544, 576, 576, 576, 576}; + +// Upper limit of mean value for speech model, Q7 +const WebRtc_Word16 kMaximumSpeech[6] = {11392, 11392, 11520, 11520, 11520, 11520}; + +// Minimum value for mean value +const WebRtc_Word16 kMinimumMean[2] = {640, 768}; + +// Upper limit of mean value for noise model, Q7 +const WebRtc_Word16 kMaximumNoise[6] = {9216, 9088, 8960, 8832, 8704, 8576}; + +// Adjustment for division with two in WebRtcVad_SplitFilter +const WebRtc_Word16 kOffsetVector[6] = {368, 368, 272, 176, 176, 176}; + +// Start values for the Gaussian models, Q7 +// Weights for the two Gaussians for the six channels (noise) +const WebRtc_Word16 kNoiseDataWeights[12] = {34, 62, 72, 66, 53, 25, 94, 66, 56, 62, 75, 103}; + +// Weights for the two Gaussians for the six channels (speech) +const WebRtc_Word16 kSpeechDataWeights[12] = {48, 82, 45, 87, 50, 47, 80, 46, 83, 41, 78, 81}; + +// Means for the two Gaussians for the six channels (noise) +const WebRtc_Word16 kNoiseDataMeans[12] = {6738, 4892, 7065, 6715, 6771, 3369, 7646, 3863, + 7820, 7266, 5020, 4362}; + +// Means for the two Gaussians for the six channels (speech) +const WebRtc_Word16 kSpeechDataMeans[12] = {8306, 10085, 10078, 11823, 11843, 6309, 9473, + 9571, 10879, 7581, 8180, 7483}; + +// Stds for the two Gaussians for the six channels (noise) +const WebRtc_Word16 kNoiseDataStds[12] = {378, 1064, 493, 582, 688, 593, 474, 697, 475, 688, + 421, 455}; + +// Stds for the two Gaussians for the six channels (speech) +const WebRtc_Word16 kSpeechDataStds[12] = {555, 505, 567, 524, 585, 1231, 509, 828, 492, 1540, + 1079, 850}; diff --git a/common_audio/vad/main/source/vad_const.h b/common_audio/vad/main/source/vad_const.h new file mode 100644 index 0000000000..ee5067fe1e --- /dev/null +++ b/common_audio/vad/main/source/vad_const.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 header file includes the declarations of the internally used constants. + */ + +#ifndef WEBRTC_VAD_CONST_H_ +#define WEBRTC_VAD_CONST_H_ + +#include "typedefs.h" + +// Spectrum Weighting +WEBRTC_EXTERN const WebRtc_Word16 kSpectrumWeight[]; +WEBRTC_EXTERN const WebRtc_Word16 kCompVar; +// Logarithm constant +WEBRTC_EXTERN const WebRtc_Word16 kLogConst; +WEBRTC_EXTERN const WebRtc_Word16 kLog10Const; +// Q15 +WEBRTC_EXTERN const WebRtc_Word16 kNoiseUpdateConst; +WEBRTC_EXTERN const WebRtc_Word16 kSpeechUpdateConst; +// Q8 +WEBRTC_EXTERN const WebRtc_Word16 kBackEta; +// Coefficients used by WebRtcVad_HpOutput, Q14 +WEBRTC_EXTERN const WebRtc_Word16 kHpZeroCoefs[]; +WEBRTC_EXTERN const WebRtc_Word16 kHpPoleCoefs[]; +// Allpass filter coefficients, upper and lower, in Q15 resp. Q13 +WEBRTC_EXTERN const WebRtc_Word16 kAllPassCoefsQ15[]; +WEBRTC_EXTERN const WebRtc_Word16 kAllPassCoefsQ13[]; +// Minimum difference between the two models, Q5 +WEBRTC_EXTERN const WebRtc_Word16 kMinimumDifference[]; +// Maximum value when updating the speech model, Q7 +WEBRTC_EXTERN const WebRtc_Word16 kMaximumSpeech[]; +// Minimum value for mean value +WEBRTC_EXTERN const WebRtc_Word16 kMinimumMean[]; +// Upper limit of mean value for noise model, Q7 +WEBRTC_EXTERN const WebRtc_Word16 kMaximumNoise[]; +// Adjustment for division with two in WebRtcVad_SplitFilter +WEBRTC_EXTERN const WebRtc_Word16 kOffsetVector[]; +// Start values for the Gaussian models, Q7 +WEBRTC_EXTERN const WebRtc_Word16 kNoiseDataWeights[]; +WEBRTC_EXTERN const WebRtc_Word16 kSpeechDataWeights[]; +WEBRTC_EXTERN const WebRtc_Word16 kNoiseDataMeans[]; +WEBRTC_EXTERN const WebRtc_Word16 kSpeechDataMeans[]; +WEBRTC_EXTERN const WebRtc_Word16 kNoiseDataStds[]; +WEBRTC_EXTERN const WebRtc_Word16 kSpeechDataStds[]; + +#endif // WEBRTC_VAD_CONST_H_ diff --git a/common_audio/vad/main/source/vad_core.c b/common_audio/vad/main/source/vad_core.c new file mode 100644 index 0000000000..e8829993d5 --- /dev/null +++ b/common_audio/vad/main/source/vad_core.c @@ -0,0 +1,685 @@ +/* + * 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 the implementation of the core functionality in VAD. + * For function description, see vad_core.h. + */ + +#include "vad_core.h" +#include "vad_const.h" +#include "vad_defines.h" +#include "vad_filterbank.h" +#include "vad_gmm.h" +#include "vad_sp.h" +#include "signal_processing_library.h" + +static const int kInitCheck = 42; + +// Initialize VAD +int WebRtcVad_InitCore(VadInstT *inst, short mode) +{ + int i; + + // Initialization of struct + inst->vad = 1; + inst->frame_counter = 0; + inst->over_hang = 0; + inst->num_of_speech = 0; + + // Initialization of downsampling filter state + inst->downsampling_filter_states[0] = 0; + inst->downsampling_filter_states[1] = 0; + inst->downsampling_filter_states[2] = 0; + inst->downsampling_filter_states[3] = 0; + + // Read initial PDF parameters + for (i = 0; i < NUM_TABLE_VALUES; i++) + { + inst->noise_means[i] = kNoiseDataMeans[i]; + inst->speech_means[i] = kSpeechDataMeans[i]; + inst->noise_stds[i] = kNoiseDataStds[i]; + inst->speech_stds[i] = kSpeechDataStds[i]; + } + + // Index and Minimum value vectors are initialized + for (i = 0; i < 16 * NUM_CHANNELS; i++) + { + inst->low_value_vector[i] = 10000; + inst->index_vector[i] = 0; + } + + for (i = 0; i < 5; i++) + { + inst->upper_state[i] = 0; + inst->lower_state[i] = 0; + } + + for (i = 0; i < 4; i++) + { + inst->hp_filter_state[i] = 0; + } + + // Init mean value memory, for FindMin function + inst->mean_value[0] = 1600; + inst->mean_value[1] = 1600; + inst->mean_value[2] = 1600; + inst->mean_value[3] = 1600; + inst->mean_value[4] = 1600; + inst->mean_value[5] = 1600; + + if (mode == 0) + { + // Quality mode + inst->over_hang_max_1[0] = OHMAX1_10MS_Q; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_Q; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_Q; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_Q; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_Q; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_Q; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_Q; + inst->individual[1] = INDIVIDUAL_20MS_Q; + inst->individual[2] = INDIVIDUAL_30MS_Q; + + inst->total[0] = TOTAL_10MS_Q; + inst->total[1] = TOTAL_20MS_Q; + inst->total[2] = TOTAL_30MS_Q; + } else if (mode == 1) + { + // Low bitrate mode + inst->over_hang_max_1[0] = OHMAX1_10MS_LBR; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_LBR; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_LBR; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_LBR; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_LBR; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_LBR; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_LBR; + inst->individual[1] = INDIVIDUAL_20MS_LBR; + inst->individual[2] = INDIVIDUAL_30MS_LBR; + + inst->total[0] = TOTAL_10MS_LBR; + inst->total[1] = TOTAL_20MS_LBR; + inst->total[2] = TOTAL_30MS_LBR; + } else if (mode == 2) + { + // Aggressive mode + inst->over_hang_max_1[0] = OHMAX1_10MS_AGG; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_AGG; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_AGG; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_AGG; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_AGG; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_AGG; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_AGG; + inst->individual[1] = INDIVIDUAL_20MS_AGG; + inst->individual[2] = INDIVIDUAL_30MS_AGG; + + inst->total[0] = TOTAL_10MS_AGG; + inst->total[1] = TOTAL_20MS_AGG; + inst->total[2] = TOTAL_30MS_AGG; + } else + { + // Very aggressive mode + inst->over_hang_max_1[0] = OHMAX1_10MS_VAG; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_VAG; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_VAG; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_VAG; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_VAG; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_VAG; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_VAG; + inst->individual[1] = INDIVIDUAL_20MS_VAG; + inst->individual[2] = INDIVIDUAL_30MS_VAG; + + inst->total[0] = TOTAL_10MS_VAG; + inst->total[1] = TOTAL_20MS_VAG; + inst->total[2] = TOTAL_30MS_VAG; + } + + inst->init_flag = kInitCheck; + + return 0; +} + +// Set aggressiveness mode +int WebRtcVad_set_mode_core(VadInstT *inst, short mode) +{ + + if (mode == 0) + { + // Quality mode + inst->over_hang_max_1[0] = OHMAX1_10MS_Q; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_Q; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_Q; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_Q; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_Q; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_Q; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_Q; + inst->individual[1] = INDIVIDUAL_20MS_Q; + inst->individual[2] = INDIVIDUAL_30MS_Q; + + inst->total[0] = TOTAL_10MS_Q; + inst->total[1] = TOTAL_20MS_Q; + inst->total[2] = TOTAL_30MS_Q; + } else if (mode == 1) + { + // Low bitrate mode + inst->over_hang_max_1[0] = OHMAX1_10MS_LBR; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_LBR; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_LBR; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_LBR; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_LBR; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_LBR; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_LBR; + inst->individual[1] = INDIVIDUAL_20MS_LBR; + inst->individual[2] = INDIVIDUAL_30MS_LBR; + + inst->total[0] = TOTAL_10MS_LBR; + inst->total[1] = TOTAL_20MS_LBR; + inst->total[2] = TOTAL_30MS_LBR; + } else if (mode == 2) + { + // Aggressive mode + inst->over_hang_max_1[0] = OHMAX1_10MS_AGG; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_AGG; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_AGG; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_AGG; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_AGG; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_AGG; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_AGG; + inst->individual[1] = INDIVIDUAL_20MS_AGG; + inst->individual[2] = INDIVIDUAL_30MS_AGG; + + inst->total[0] = TOTAL_10MS_AGG; + inst->total[1] = TOTAL_20MS_AGG; + inst->total[2] = TOTAL_30MS_AGG; + } else if (mode == 3) + { + // Very aggressive mode + inst->over_hang_max_1[0] = OHMAX1_10MS_VAG; // Overhang short speech burst + inst->over_hang_max_1[1] = OHMAX1_20MS_VAG; // Overhang short speech burst + inst->over_hang_max_1[2] = OHMAX1_30MS_VAG; // Overhang short speech burst + inst->over_hang_max_2[0] = OHMAX2_10MS_VAG; // Overhang long speech burst + inst->over_hang_max_2[1] = OHMAX2_20MS_VAG; // Overhang long speech burst + inst->over_hang_max_2[2] = OHMAX2_30MS_VAG; // Overhang long speech burst + + inst->individual[0] = INDIVIDUAL_10MS_VAG; + inst->individual[1] = INDIVIDUAL_20MS_VAG; + inst->individual[2] = INDIVIDUAL_30MS_VAG; + + inst->total[0] = TOTAL_10MS_VAG; + inst->total[1] = TOTAL_20MS_VAG; + inst->total[2] = TOTAL_30MS_VAG; + } else + { + return -1; + } + + return 0; +} + +// Calculate VAD decision by first extracting feature values and then calculate +// probability for both speech and background noise. + +WebRtc_Word16 WebRtcVad_CalcVad32khz(VadInstT *inst, WebRtc_Word16 *speech_frame, + int frame_length) +{ + WebRtc_Word16 len, vad; + WebRtc_Word16 speechWB[480]; // Downsampled speech frame: 960 samples (30ms in SWB) + WebRtc_Word16 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; +} + +WebRtc_Word16 WebRtcVad_CalcVad16khz(VadInstT *inst, WebRtc_Word16 *speech_frame, + int frame_length) +{ + WebRtc_Word16 len, vad; + WebRtc_Word16 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; +} + +WebRtc_Word16 WebRtcVad_CalcVad8khz(VadInstT *inst, WebRtc_Word16 *speech_frame, + int frame_length) +{ + WebRtc_Word16 feature_vector[NUM_CHANNELS], total_power; + + // Get power in the bands + total_power = WebRtcVad_get_features(inst, speech_frame, frame_length, feature_vector); + + // Make a VAD + inst->vad = WebRtcVad_GmmProbability(inst, feature_vector, total_power, frame_length); + + return inst->vad; +} + +// Calculate probability for both speech and background noise, and perform a +// hypothesis-test. +WebRtc_Word16 WebRtcVad_GmmProbability(VadInstT *inst, WebRtc_Word16 *feature_vector, + WebRtc_Word16 total_power, int frame_length) +{ + int n, k; + WebRtc_Word16 backval; + WebRtc_Word16 h0, h1; + WebRtc_Word16 ratvec, xval; + WebRtc_Word16 vadflag; + WebRtc_Word16 shifts0, shifts1; + WebRtc_Word16 tmp16, tmp16_1, tmp16_2; + WebRtc_Word16 diff, nr, pos; + WebRtc_Word16 nmk, nmk2, nmk3, smk, smk2, nsk, ssk; + WebRtc_Word16 delt, ndelt; + WebRtc_Word16 maxspe, maxmu; + WebRtc_Word16 deltaN[NUM_TABLE_VALUES], deltaS[NUM_TABLE_VALUES]; + WebRtc_Word16 ngprvec[NUM_TABLE_VALUES], sgprvec[NUM_TABLE_VALUES]; + WebRtc_Word32 h0test, h1test; + WebRtc_Word32 tmp32_1, tmp32_2; + WebRtc_Word32 dotVal; + WebRtc_Word32 nmid, smid; + WebRtc_Word32 probn[NUM_MODELS], probs[NUM_MODELS]; + WebRtc_Word16 *nmean1ptr, *nmean2ptr, *smean1ptr, *smean2ptr, *nstd1ptr, *nstd2ptr, + *sstd1ptr, *sstd2ptr; + WebRtc_Word16 overhead1, overhead2, individualTest, totalTest; + + // Set the thresholds to different values based on frame length + if (frame_length == 80) + { + // 80 input samples + overhead1 = inst->over_hang_max_1[0]; + overhead2 = inst->over_hang_max_2[0]; + individualTest = inst->individual[0]; + totalTest = inst->total[0]; + } else if (frame_length == 160) + { + // 160 input samples + overhead1 = inst->over_hang_max_1[1]; + overhead2 = inst->over_hang_max_2[1]; + individualTest = inst->individual[1]; + totalTest = inst->total[1]; + } else + { + // 240 input samples + overhead1 = inst->over_hang_max_1[2]; + overhead2 = inst->over_hang_max_2[2]; + individualTest = inst->individual[2]; + totalTest = inst->total[2]; + } + + if (total_power > MIN_ENERGY) + { // If signal present at all + + // Set pointers to the gaussian parameters + nmean1ptr = &inst->noise_means[0]; + nmean2ptr = &inst->noise_means[NUM_CHANNELS]; + smean1ptr = &inst->speech_means[0]; + smean2ptr = &inst->speech_means[NUM_CHANNELS]; + nstd1ptr = &inst->noise_stds[0]; + nstd2ptr = &inst->noise_stds[NUM_CHANNELS]; + sstd1ptr = &inst->speech_stds[0]; + sstd2ptr = &inst->speech_stds[NUM_CHANNELS]; + + vadflag = 0; + dotVal = 0; + for (n = 0; n < NUM_CHANNELS; n++) + { // For all channels + + pos = WEBRTC_SPL_LSHIFT_W16(n, 1); + xval = feature_vector[n]; + + // Probability for Noise, Q7 * Q20 = Q27 + tmp32_1 = WebRtcVad_GaussianProbability(xval, *nmean1ptr++, *nstd1ptr++, + &deltaN[pos]); + probn[0] = (WebRtc_Word32)(kNoiseDataWeights[n] * tmp32_1); + tmp32_1 = WebRtcVad_GaussianProbability(xval, *nmean2ptr++, *nstd2ptr++, + &deltaN[pos + 1]); + probn[1] = (WebRtc_Word32)(kNoiseDataWeights[n + NUM_CHANNELS] * tmp32_1); + h0test = probn[0] + probn[1]; // Q27 + h0 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(h0test, 12); // Q15 + + // Probability for Speech + tmp32_1 = WebRtcVad_GaussianProbability(xval, *smean1ptr++, *sstd1ptr++, + &deltaS[pos]); + probs[0] = (WebRtc_Word32)(kSpeechDataWeights[n] * tmp32_1); + tmp32_1 = WebRtcVad_GaussianProbability(xval, *smean2ptr++, *sstd2ptr++, + &deltaS[pos + 1]); + probs[1] = (WebRtc_Word32)(kSpeechDataWeights[n + NUM_CHANNELS] * tmp32_1); + h1test = probs[0] + probs[1]; // Q27 + h1 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(h1test, 12); // Q15 + + // Get likelihood ratio. Approximate log2(H1/H0) with shifts0 - shifts1 + shifts0 = WebRtcSpl_NormW32(h0test); + shifts1 = WebRtcSpl_NormW32(h1test); + + if ((h0test > 0) && (h1test > 0)) + { + ratvec = shifts0 - shifts1; + } else if (h1test > 0) + { + ratvec = 31 - shifts1; + } else if (h0test > 0) + { + ratvec = shifts0 - 31; + } else + { + ratvec = 0; + } + + // VAD decision with spectrum weighting + dotVal += WEBRTC_SPL_MUL_16_16(ratvec, kSpectrumWeight[n]); + + // Individual channel test + if ((ratvec << 2) > individualTest) + { + vadflag = 1; + } + + // Probabilities used when updating model + if (h0 > 0) + { + tmp32_1 = probn[0] & 0xFFFFF000; // Q27 + tmp32_2 = WEBRTC_SPL_LSHIFT_W32(tmp32_1, 2); // Q29 + ngprvec[pos] = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32_2, h0); + ngprvec[pos + 1] = 16384 - ngprvec[pos]; + } else + { + ngprvec[pos] = 16384; + ngprvec[pos + 1] = 0; + } + + // Probabilities used when updating model + if (h1 > 0) + { + tmp32_1 = probs[0] & 0xFFFFF000; + tmp32_2 = WEBRTC_SPL_LSHIFT_W32(tmp32_1, 2); + sgprvec[pos] = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32_2, h1); + sgprvec[pos + 1] = 16384 - sgprvec[pos]; + } else + { + sgprvec[pos] = 0; + sgprvec[pos + 1] = 0; + } + } + + // Overall test + if (dotVal >= totalTest) + { + vadflag |= 1; + } + + // Set pointers to the means and standard deviations. + nmean1ptr = &inst->noise_means[0]; + smean1ptr = &inst->speech_means[0]; + nstd1ptr = &inst->noise_stds[0]; + sstd1ptr = &inst->speech_stds[0]; + + maxspe = 12800; + + // Update the model's parameters + for (n = 0; n < NUM_CHANNELS; n++) + { + + pos = WEBRTC_SPL_LSHIFT_W16(n, 1); + + // Get min value in past which is used for long term correction + backval = WebRtcVad_FindMinimum(inst, feature_vector[n], n); // Q4 + + // Compute the "global" mean, that is the sum of the two means weighted + nmid = WEBRTC_SPL_MUL_16_16(kNoiseDataWeights[n], *nmean1ptr); // Q7 * Q7 + nmid += WEBRTC_SPL_MUL_16_16(kNoiseDataWeights[n+NUM_CHANNELS], + *(nmean1ptr+NUM_CHANNELS)); + tmp16_1 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(nmid, 6); // Q8 + + for (k = 0; k < NUM_MODELS; k++) + { + + nr = pos + k; + + nmean2ptr = nmean1ptr + k * NUM_CHANNELS; + smean2ptr = smean1ptr + k * NUM_CHANNELS; + nstd2ptr = nstd1ptr + k * NUM_CHANNELS; + sstd2ptr = sstd1ptr + k * NUM_CHANNELS; + nmk = *nmean2ptr; + smk = *smean2ptr; + nsk = *nstd2ptr; + ssk = *sstd2ptr; + + // Update noise mean vector if the frame consists of noise only + nmk2 = nmk; + if (!vadflag) + { + // deltaN = (x-mu)/sigma^2 + // ngprvec[k] = probn[k]/(probn[0] + probn[1]) + + delt = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ngprvec[nr], + deltaN[nr], 11); // Q14*Q11 + nmk2 = nmk + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(delt, + kNoiseUpdateConst, + 22); // Q7+(Q14*Q15>>22) + } + + // Long term correction of the noise mean + ndelt = WEBRTC_SPL_LSHIFT_W16(backval, 4); + ndelt -= tmp16_1; // Q8 - Q8 + nmk3 = nmk2 + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(ndelt, + kBackEta, + 9); // Q7+(Q8*Q8)>>9 + + // Control that the noise mean does not drift to much + tmp16 = WEBRTC_SPL_LSHIFT_W16(k+5, 7); + if (nmk3 < tmp16) + nmk3 = tmp16; + tmp16 = WEBRTC_SPL_LSHIFT_W16(72+k-n, 7); + if (nmk3 > tmp16) + nmk3 = tmp16; + *nmean2ptr = nmk3; + + if (vadflag) + { + // Update speech mean vector: + // deltaS = (x-mu)/sigma^2 + // sgprvec[k] = probn[k]/(probn[0] + probn[1]) + + delt = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(sgprvec[nr], + deltaS[nr], + 11); // (Q14*Q11)>>11=Q14 + tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(delt, + kSpeechUpdateConst, + 21) + 1; + smk2 = smk + (tmp16 >> 1); // Q7 + (Q14 * Q15 >> 22) + + // 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; + + *smean2ptr = smk2; + + // (Q7>>3) = Q4 + tmp16 = WEBRTC_SPL_RSHIFT_W16((smk + 4), 3); + + tmp16 = feature_vector[n] - tmp16; // Q4 + tmp32_1 = WEBRTC_SPL_MUL_16_16_RSFT(deltaS[nr], tmp16, 3); + tmp32_2 = tmp32_1 - (WebRtc_Word32)4096; // Q12 + tmp16 = WEBRTC_SPL_RSHIFT_W16((sgprvec[nr]), 2); + tmp32_1 = (WebRtc_Word32)(tmp16 * tmp32_2);// (Q15>>3)*(Q14>>2)=Q12*Q12=Q24 + + tmp32_2 = WEBRTC_SPL_RSHIFT_W32(tmp32_1, 4); // Q20 + + // 0.1 * Q20 / Q7 = Q13 + if (tmp32_2 > 0) + tmp16 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32_2, ssk * 10); + else + { + tmp16 = (WebRtc_Word16)WebRtcSpl_DivW32W16(-tmp32_2, ssk * 10); + tmp16 = -tmp16; + } + // divide by 4 giving an update factor of 0.025 + tmp16 += 128; // Rounding + ssk += WEBRTC_SPL_RSHIFT_W16(tmp16, 8); + // Division with 8 plus Q7 + if (ssk < MIN_STD) + ssk = MIN_STD; + *sstd2ptr = ssk; + } else + { + // Update GMM variance vectors + // deltaN * (feature_vector[n] - nmk) - 1, Q11 * Q4 + tmp16 = feature_vector[n] - WEBRTC_SPL_RSHIFT_W16(nmk, 3); + + // (Q15>>3) * (Q14>>2) = Q12 * Q12 = Q24 + tmp32_1 = WEBRTC_SPL_MUL_16_16_RSFT(deltaN[nr], tmp16, 3) - 4096; + tmp16 = WEBRTC_SPL_RSHIFT_W16((ngprvec[nr]+2), 2); + tmp32_2 = (WebRtc_Word32)(tmp16 * tmp32_1); + tmp32_1 = WEBRTC_SPL_RSHIFT_W32(tmp32_2, 14); + // Q20 * approx 0.001 (2^-10=0.0009766) + + // Q20 / Q7 = Q13 + tmp16 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32_1, nsk); + if (tmp32_1 > 0) + tmp16 = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32_1, nsk); + else + { + tmp16 = (WebRtc_Word16)WebRtcSpl_DivW32W16(-tmp32_1, nsk); + tmp16 = -tmp16; + } + tmp16 += 32; // Rounding + nsk += WEBRTC_SPL_RSHIFT_W16(tmp16, 6); + + if (nsk < MIN_STD) + nsk = MIN_STD; + + *nstd2ptr = nsk; + } + } + + // Separate models if they are too close - nmid in Q14 + nmid = WEBRTC_SPL_MUL_16_16(kNoiseDataWeights[n], *nmean1ptr); + nmid += WEBRTC_SPL_MUL_16_16(kNoiseDataWeights[n+NUM_CHANNELS], *nmean2ptr); + + // smid in Q14 + smid = WEBRTC_SPL_MUL_16_16(kSpeechDataWeights[n], *smean1ptr); + smid += WEBRTC_SPL_MUL_16_16(kSpeechDataWeights[n+NUM_CHANNELS], *smean2ptr); + + // diff = "global" speech mean - "global" noise mean + diff = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(smid, 9); + tmp16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(nmid, 9); + diff -= tmp16; + + if (diff < kMinimumDifference[n]) + { + + tmp16 = kMinimumDifference[n] - diff; // Q5 + + // tmp16_1 = ~0.8 * (kMinimumDifference - diff) in Q7 + // tmp16_2 = ~0.2 * (kMinimumDifference - diff) in Q7 + tmp16_1 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(13, tmp16, 2); + tmp16_2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(3, tmp16, 2); + + // First Gauss, speech model + tmp16 = tmp16_1 + *smean1ptr; + *smean1ptr = tmp16; + smid = WEBRTC_SPL_MUL_16_16(tmp16, kSpeechDataWeights[n]); + + // Second Gauss, speech model + tmp16 = tmp16_1 + *smean2ptr; + *smean2ptr = tmp16; + smid += WEBRTC_SPL_MUL_16_16(tmp16, kSpeechDataWeights[n+NUM_CHANNELS]); + + // First Gauss, noise model + tmp16 = *nmean1ptr - tmp16_2; + *nmean1ptr = tmp16; + + nmid = WEBRTC_SPL_MUL_16_16(tmp16, kNoiseDataWeights[n]); + + // Second Gauss, noise model + tmp16 = *nmean2ptr - tmp16_2; + *nmean2ptr = tmp16; + nmid += WEBRTC_SPL_MUL_16_16(tmp16, kNoiseDataWeights[n+NUM_CHANNELS]); + } + + // Control that the speech & noise means do not drift to much + maxspe = kMaximumSpeech[n]; + tmp16_2 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(smid, 7); + if (tmp16_2 > maxspe) + { // Upper limit of speech model + tmp16_2 -= maxspe; + + *smean1ptr -= tmp16_2; + *smean2ptr -= tmp16_2; + } + + tmp16_2 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(nmid, 7); + if (tmp16_2 > kMaximumNoise[n]) + { + tmp16_2 -= kMaximumNoise[n]; + + *nmean1ptr -= tmp16_2; + *nmean2ptr -= tmp16_2; + } + + *nmean1ptr++; + *smean1ptr++; + *nstd1ptr++; + *sstd1ptr++; + } + inst->frame_counter++; + } else + { + vadflag = 0; + } + + // Hangover smoothing + if (!vadflag) + { + if (inst->over_hang > 0) + { + vadflag = 2 + inst->over_hang; + inst->over_hang = inst->over_hang - 1; + } + inst->num_of_speech = 0; + } else + { + inst->num_of_speech = inst->num_of_speech + 1; + if (inst->num_of_speech > NSP_MAX) + { + inst->num_of_speech = NSP_MAX; + inst->over_hang = overhead2; + } else + inst->over_hang = overhead1; + } + return vadflag; +} diff --git a/common_audio/vad/main/source/vad_core.h b/common_audio/vad/main/source/vad_core.h new file mode 100644 index 0000000000..544caf5ab3 --- /dev/null +++ b/common_audio/vad/main/source/vad_core.h @@ -0,0 +1,132 @@ +/* + * 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 descriptions of the core VAD calls. + */ + +#ifndef WEBRTC_VAD_CORE_H_ +#define WEBRTC_VAD_CORE_H_ + +#include "typedefs.h" +#include "vad_defines.h" + +typedef struct VadInstT_ +{ + + WebRtc_Word16 vad; + WebRtc_Word32 downsampling_filter_states[4]; + WebRtc_Word16 noise_means[NUM_TABLE_VALUES]; + WebRtc_Word16 speech_means[NUM_TABLE_VALUES]; + WebRtc_Word16 noise_stds[NUM_TABLE_VALUES]; + WebRtc_Word16 speech_stds[NUM_TABLE_VALUES]; + WebRtc_Word32 frame_counter; + WebRtc_Word16 over_hang; // Over Hang + WebRtc_Word16 num_of_speech; + WebRtc_Word16 index_vector[16 * NUM_CHANNELS]; + WebRtc_Word16 low_value_vector[16 * NUM_CHANNELS]; + WebRtc_Word16 mean_value[NUM_CHANNELS]; + WebRtc_Word16 upper_state[5]; + WebRtc_Word16 lower_state[5]; + WebRtc_Word16 hp_filter_state[4]; + WebRtc_Word16 over_hang_max_1[3]; + WebRtc_Word16 over_hang_max_2[3]; + WebRtc_Word16 individual[3]; + WebRtc_Word16 total[3]; + + short init_flag; + +} VadInstT; + +/**************************************************************************** + * WebRtcVad_InitCore(...) + * + * This function initializes a VAD instance + * + * Input: + * - inst : Instance that should be initialized + * - mode : Aggressiveness degree + * 0 (High quality) - 3 (Highly aggressive) + * + * Output: + * - inst : Initialized instance + * + * Return value : 0 - Ok + * -1 - Error + */ +int WebRtcVad_InitCore(VadInstT* inst, short mode); + +/**************************************************************************** + * 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* inst, short mode); + +/**************************************************************************** + * 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 + */ +WebRtc_Word16 WebRtcVad_CalcVad32khz(VadInstT* inst, WebRtc_Word16* speech_frame, + int frame_length); +WebRtc_Word16 WebRtcVad_CalcVad16khz(VadInstT* inst, WebRtc_Word16* speech_frame, + int frame_length); +WebRtc_Word16 WebRtcVad_CalcVad8khz(VadInstT* inst, WebRtc_Word16* speech_frame, + int frame_length); + +/**************************************************************************** + * WebRtcVad_GmmProbability(...) + * + * This function calculates the probabilities for background noise and + * speech using Gaussian Mixture Models. A hypothesis-test is performed to decide + * which type of signal is most probable. + * + * Input: + * - inst : Pointer to VAD instance + * - feature_vector : Feature vector = log10(energy in frequency band) + * - total_power : Total power in frame. + * - frame_length : Number of input samples + * + * Output: + * VAD decision : 0 - noise, 1 - speech + * + */ +WebRtc_Word16 WebRtcVad_GmmProbability(VadInstT* inst, WebRtc_Word16* feature_vector, + WebRtc_Word16 total_power, int frame_length); + +#endif // WEBRTC_VAD_CORE_H_ diff --git a/common_audio/vad/main/source/vad_define.h b/common_audio/vad/main/source/vad_define.h new file mode 100644 index 0000000000..eb27faf7a6 --- /dev/null +++ b/common_audio/vad/main/source/vad_define.h @@ -0,0 +1,81 @@ +/* + * vad_define.h + * + * TODO(bjornv): add header + */ + +#define NUM_CHANNELS 6 // Eight frequency bands +#define NUM_MODELS 2 // Number of Gaussian models +#define NUM_TABLE_VALUES NUM_CHANNELS * NUM_MODELS + +#define MIN_ENERGY 10 +#define ALPHA1 6553 // 0.2 in Q15 +#define ALPHA2 32439 // 0.99 in Q15 +#define NSP_MAX 6 // Maximum number of VAD=1 frames in a row counted +#define MIN_STD 384 // Minimum standard deviation +// Mode 0, Quality thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_Q 24 +#define INDIVIDUAL_20MS_Q 21 // (log10(2)*66)<<2 ~=16 +#define INDIVIDUAL_30MS_Q 24 + +#define TOTAL_10MS_Q 57 +#define TOTAL_20MS_Q 48 +#define TOTAL_30MS_Q 57 + +#define OHMAX1_10MS_Q 8 // Max Overhang 1 +#define OHMAX2_10MS_Q 14 // Max Overhang 2 +#define OHMAX1_20MS_Q 4 // Max Overhang 1 +#define OHMAX2_20MS_Q 7 // Max Overhang 2 +#define OHMAX1_30MS_Q 3 +#define OHMAX2_30MS_Q 5 + +// Mode 1, Low bitrate thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_LBR 37 +#define INDIVIDUAL_20MS_LBR 32 +#define INDIVIDUAL_30MS_LBR 37 + +#define TOTAL_10MS_LBR 100 +#define TOTAL_20MS_LBR 80 +#define TOTAL_30MS_LBR 100 + +#define OHMAX1_10MS_LBR 8 // Max Overhang 1 +#define OHMAX2_10MS_LBR 14 // Max Overhang 2 +#define OHMAX1_20MS_LBR 4 +#define OHMAX2_20MS_LBR 7 + +#define OHMAX1_30MS_LBR 3 +#define OHMAX2_30MS_LBR 5 + +// Mode 2, Very aggressive thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_AGG 82 +#define INDIVIDUAL_20MS_AGG 78 +#define INDIVIDUAL_30MS_AGG 82 + +#define TOTAL_10MS_AGG 285 //580 +#define TOTAL_20MS_AGG 260 +#define TOTAL_30MS_AGG 285 + +#define OHMAX1_10MS_AGG 6 // Max Overhang 1 +#define OHMAX2_10MS_AGG 9 // Max Overhang 2 +#define OHMAX1_20MS_AGG 3 +#define OHMAX2_20MS_AGG 5 + +#define OHMAX1_30MS_AGG 2 +#define OHMAX2_30MS_AGG 3 + +// Mode 3, Super aggressive thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_VAG 94 +#define INDIVIDUAL_20MS_VAG 94 +#define INDIVIDUAL_30MS_VAG 94 + +#define TOTAL_10MS_VAG 1100 //1700 +#define TOTAL_20MS_VAG 1050 +#define TOTAL_30MS_VAG 1100 + +#define OHMAX1_10MS_VAG 6 // Max Overhang 1 +#define OHMAX2_10MS_VAG 9 // Max Overhang 2 +#define OHMAX1_20MS_VAG 3 +#define OHMAX2_20MS_VAG 5 + +#define OHMAX1_30MS_VAG 2 +#define OHMAX2_30MS_VAG 3 diff --git a/common_audio/vad/main/source/vad_defines.h b/common_audio/vad/main/source/vad_defines.h new file mode 100644 index 0000000000..b33af2ef7d --- /dev/null +++ b/common_audio/vad/main/source/vad_defines.h @@ -0,0 +1,95 @@ +/* + * 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 macros used in VAD. + */ + +#ifndef WEBRTC_VAD_DEFINES_H_ +#define WEBRTC_VAD_DEFINES_H_ + +#define NUM_CHANNELS 6 // Eight frequency bands +#define NUM_MODELS 2 // Number of Gaussian models +#define NUM_TABLE_VALUES NUM_CHANNELS * NUM_MODELS + +#define MIN_ENERGY 10 +#define ALPHA1 6553 // 0.2 in Q15 +#define ALPHA2 32439 // 0.99 in Q15 +#define NSP_MAX 6 // Maximum number of VAD=1 frames in a row counted +#define MIN_STD 384 // Minimum standard deviation +// Mode 0, Quality thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_Q 24 +#define INDIVIDUAL_20MS_Q 21 // (log10(2)*66)<<2 ~=16 +#define INDIVIDUAL_30MS_Q 24 + +#define TOTAL_10MS_Q 57 +#define TOTAL_20MS_Q 48 +#define TOTAL_30MS_Q 57 + +#define OHMAX1_10MS_Q 8 // Max Overhang 1 +#define OHMAX2_10MS_Q 14 // Max Overhang 2 +#define OHMAX1_20MS_Q 4 // Max Overhang 1 +#define OHMAX2_20MS_Q 7 // Max Overhang 2 +#define OHMAX1_30MS_Q 3 +#define OHMAX2_30MS_Q 5 + +// Mode 1, Low bitrate thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_LBR 37 +#define INDIVIDUAL_20MS_LBR 32 +#define INDIVIDUAL_30MS_LBR 37 + +#define TOTAL_10MS_LBR 100 +#define TOTAL_20MS_LBR 80 +#define TOTAL_30MS_LBR 100 + +#define OHMAX1_10MS_LBR 8 // Max Overhang 1 +#define OHMAX2_10MS_LBR 14 // Max Overhang 2 +#define OHMAX1_20MS_LBR 4 +#define OHMAX2_20MS_LBR 7 + +#define OHMAX1_30MS_LBR 3 +#define OHMAX2_30MS_LBR 5 + +// Mode 2, Very aggressive thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_AGG 82 +#define INDIVIDUAL_20MS_AGG 78 +#define INDIVIDUAL_30MS_AGG 82 + +#define TOTAL_10MS_AGG 285 //580 +#define TOTAL_20MS_AGG 260 +#define TOTAL_30MS_AGG 285 + +#define OHMAX1_10MS_AGG 6 // Max Overhang 1 +#define OHMAX2_10MS_AGG 9 // Max Overhang 2 +#define OHMAX1_20MS_AGG 3 +#define OHMAX2_20MS_AGG 5 + +#define OHMAX1_30MS_AGG 2 +#define OHMAX2_30MS_AGG 3 + +// Mode 3, Super aggressive thresholds - Different thresholds for the different frame lengths +#define INDIVIDUAL_10MS_VAG 94 +#define INDIVIDUAL_20MS_VAG 94 +#define INDIVIDUAL_30MS_VAG 94 + +#define TOTAL_10MS_VAG 1100 //1700 +#define TOTAL_20MS_VAG 1050 +#define TOTAL_30MS_VAG 1100 + +#define OHMAX1_10MS_VAG 6 // Max Overhang 1 +#define OHMAX2_10MS_VAG 9 // Max Overhang 2 +#define OHMAX1_20MS_VAG 3 +#define OHMAX2_20MS_VAG 5 + +#define OHMAX1_30MS_VAG 2 +#define OHMAX2_30MS_VAG 3 + +#endif // WEBRTC_VAD_DEFINES_H_ diff --git a/common_audio/vad/main/source/vad_filterbank.c b/common_audio/vad/main/source/vad_filterbank.c new file mode 100644 index 0000000000..11392c917a --- /dev/null +++ b/common_audio/vad/main/source/vad_filterbank.c @@ -0,0 +1,267 @@ +/* + * 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 the implementation of the internal filterbank associated functions. + * For function description, see vad_filterbank.h. + */ + +#include "vad_filterbank.h" +#include "vad_defines.h" +#include "vad_const.h" +#include "signal_processing_library.h" + +void WebRtcVad_HpOutput(WebRtc_Word16 *in_vector, + WebRtc_Word16 in_vector_length, + WebRtc_Word16 *out_vector, + WebRtc_Word16 *filter_state) +{ + WebRtc_Word16 i, *pi, *outPtr; + WebRtc_Word32 tmpW32; + + pi = &in_vector[0]; + outPtr = &out_vector[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 < in_vector_length; i++) + { + // all-zero section (filter coefficients in Q14) + tmpW32 = (WebRtc_Word32)WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[0], (*pi)); + tmpW32 += (WebRtc_Word32)WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[1], filter_state[0]); + tmpW32 += (WebRtc_Word32)WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[2], filter_state[1]); // Q14 + filter_state[1] = filter_state[0]; + filter_state[0] = *pi++; + + // all-pole section + tmpW32 -= (WebRtc_Word32)WEBRTC_SPL_MUL_16_16(kHpPoleCoefs[1], filter_state[2]); // Q14 + tmpW32 -= (WebRtc_Word32)WEBRTC_SPL_MUL_16_16(kHpPoleCoefs[2], filter_state[3]); + filter_state[3] = filter_state[2]; + filter_state[2] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32 (tmpW32, 14); + *outPtr++ = filter_state[2]; + } +} + +void WebRtcVad_Allpass(WebRtc_Word16 *in_vector, + WebRtc_Word16 *out_vector, + WebRtc_Word16 filter_coefficients, + int vector_length, + WebRtc_Word16 *filter_state) +{ + // 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 n; + WebRtc_Word16 tmp16; + WebRtc_Word32 tmp32, in32, state32; + + state32 = WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)(*filter_state)), 16); // Q31 + + for (n = 0; n < vector_length; n++) + { + + tmp32 = state32 + WEBRTC_SPL_MUL_16_16(filter_coefficients, (*in_vector)); + tmp16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 16); + *out_vector++ = tmp16; + in32 = WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)(*in_vector)), 14); + state32 = in32 - WEBRTC_SPL_MUL_16_16(filter_coefficients, tmp16); + state32 = WEBRTC_SPL_LSHIFT_W32(state32, 1); + in_vector += 2; + } + + *filter_state = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(state32, 16); +} + +void WebRtcVad_SplitFilter(WebRtc_Word16 *in_vector, + WebRtc_Word16 *out_vector_hp, + WebRtc_Word16 *out_vector_lp, + WebRtc_Word16 *upper_state, + WebRtc_Word16 *lower_state, + int in_vector_length) +{ + WebRtc_Word16 tmpOut; + int k, halflen; + + // Downsampling by 2 and get two branches + halflen = WEBRTC_SPL_RSHIFT_W16(in_vector_length, 1); + + // All-pass filtering upper branch + WebRtcVad_Allpass(&in_vector[0], out_vector_hp, kAllPassCoefsQ15[0], halflen, upper_state); + + // All-pass filtering lower branch + WebRtcVad_Allpass(&in_vector[1], out_vector_lp, kAllPassCoefsQ15[1], halflen, lower_state); + + // Make LP and HP signals + for (k = 0; k < halflen; k++) + { + tmpOut = *out_vector_hp; + *out_vector_hp++ -= *out_vector_lp; + *out_vector_lp++ += tmpOut; + } +} + +WebRtc_Word16 WebRtcVad_get_features(VadInstT *inst, + WebRtc_Word16 *in_vector, + int frame_size, + WebRtc_Word16 *out_vector) +{ + int curlen, filtno; + WebRtc_Word16 vecHP1[120], vecLP1[120]; + WebRtc_Word16 vecHP2[60], vecLP2[60]; + WebRtc_Word16 *ptin; + WebRtc_Word16 *hptout, *lptout; + WebRtc_Word16 power = 0; + + // Split at 2000 Hz and downsample + filtno = 0; + ptin = in_vector; + hptout = vecHP1; + lptout = vecLP1; + curlen = frame_size; + WebRtcVad_SplitFilter(ptin, hptout, lptout, &inst->upper_state[filtno], + &inst->lower_state[filtno], curlen); + + // Split at 3000 Hz and downsample + filtno = 1; + ptin = vecHP1; + hptout = vecHP2; + lptout = vecLP2; + curlen = WEBRTC_SPL_RSHIFT_W16(frame_size, 1); + + WebRtcVad_SplitFilter(ptin, hptout, lptout, &inst->upper_state[filtno], + &inst->lower_state[filtno], curlen); + + // Energy in 3000 Hz - 4000 Hz + curlen = WEBRTC_SPL_RSHIFT_W16(curlen, 1); + WebRtcVad_LogOfEnergy(vecHP2, &out_vector[5], &power, kOffsetVector[5], curlen); + + // Energy in 2000 Hz - 3000 Hz + WebRtcVad_LogOfEnergy(vecLP2, &out_vector[4], &power, kOffsetVector[4], curlen); + + // Split at 1000 Hz and downsample + filtno = 2; + ptin = vecLP1; + hptout = vecHP2; + lptout = vecLP2; + curlen = WEBRTC_SPL_RSHIFT_W16(frame_size, 1); + WebRtcVad_SplitFilter(ptin, hptout, lptout, &inst->upper_state[filtno], + &inst->lower_state[filtno], curlen); + + // Energy in 1000 Hz - 2000 Hz + curlen = WEBRTC_SPL_RSHIFT_W16(curlen, 1); + WebRtcVad_LogOfEnergy(vecHP2, &out_vector[3], &power, kOffsetVector[3], curlen); + + // Split at 500 Hz + filtno = 3; + ptin = vecLP2; + hptout = vecHP1; + lptout = vecLP1; + + WebRtcVad_SplitFilter(ptin, hptout, lptout, &inst->upper_state[filtno], + &inst->lower_state[filtno], curlen); + + // Energy in 500 Hz - 1000 Hz + curlen = WEBRTC_SPL_RSHIFT_W16(curlen, 1); + WebRtcVad_LogOfEnergy(vecHP1, &out_vector[2], &power, kOffsetVector[2], curlen); + // Split at 250 Hz + filtno = 4; + ptin = vecLP1; + hptout = vecHP2; + lptout = vecLP2; + + WebRtcVad_SplitFilter(ptin, hptout, lptout, &inst->upper_state[filtno], + &inst->lower_state[filtno], curlen); + + // Energy in 250 Hz - 500 Hz + curlen = WEBRTC_SPL_RSHIFT_W16(curlen, 1); + WebRtcVad_LogOfEnergy(vecHP2, &out_vector[1], &power, kOffsetVector[1], curlen); + + // Remove DC and LFs + WebRtcVad_HpOutput(vecLP2, curlen, vecHP1, inst->hp_filter_state); + + // Power in 80 Hz - 250 Hz + WebRtcVad_LogOfEnergy(vecHP1, &out_vector[0], &power, kOffsetVector[0], curlen); + + return power; +} + +void WebRtcVad_LogOfEnergy(WebRtc_Word16 *vector, + WebRtc_Word16 *enerlogval, + WebRtc_Word16 *power, + WebRtc_Word16 offset, + int vector_length) +{ + WebRtc_Word16 enerSum = 0; + WebRtc_Word16 zeros, frac, log2; + WebRtc_Word32 energy; + + int shfts = 0, shfts2; + + energy = WebRtcSpl_Energy(vector, vector_length, &shfts); + + if (energy > 0) + { + + shfts2 = 16 - WebRtcSpl_NormW32(energy); + shfts += shfts2; + // "shfts" is the total number of right shifts that has been done to enerSum. + enerSum = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(energy, -shfts2); + + // Find: + // 160*log10(enerSum*2^shfts) = 160*log10(2)*log2(enerSum*2^shfts) = + // 160*log10(2)*(log2(enerSum) + log2(2^shfts)) = + // 160*log10(2)*(log2(enerSum) + shfts) + + zeros = WebRtcSpl_NormU32(enerSum); + frac = (WebRtc_Word16)(((WebRtc_UWord32)((WebRtc_Word32)(enerSum) << zeros) + & 0x7FFFFFFF) >> 21); + log2 = (WebRtc_Word16)(((31 - zeros) << 10) + frac); + + *enerlogval = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(kLogConst, log2, 19) + + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(shfts, kLogConst, 9); + + if (*enerlogval < 0) + { + *enerlogval = 0; + } + } else + { + *enerlogval = 0; + shfts = -15; + enerSum = 0; + } + + *enerlogval += offset; + + // Total power in frame + if (*power <= MIN_ENERGY) + { + if (shfts > 0) + { + *power += MIN_ENERGY + 1; + } else if (WEBRTC_SPL_SHIFT_W16(enerSum, shfts) > MIN_ENERGY) + { + *power += MIN_ENERGY + 1; + } else + { + *power += WEBRTC_SPL_SHIFT_W16(enerSum, shfts); + } + } +} diff --git a/common_audio/vad/main/source/vad_filterbank.h b/common_audio/vad/main/source/vad_filterbank.h new file mode 100644 index 0000000000..a5507ead65 --- /dev/null +++ b/common_audio/vad/main/source/vad_filterbank.h @@ -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. + */ + + +/* + * This header file includes the description of the internal VAD call + * WebRtcVad_GaussianProbability. + */ + +#ifndef WEBRTC_VAD_FILTERBANK_H_ +#define WEBRTC_VAD_FILTERBANK_H_ + +#include "vad_core.h" + +/**************************************************************************** + * WebRtcVad_HpOutput(...) + * + * This function removes DC from the lowest frequency band + * + * Input: + * - in_vector : Samples in the frequency interval 0 - 250 Hz + * - in_vector_length : Length of input and output vector + * - filter_state : Current state of the filter + * + * Output: + * - out_vector : Samples in the frequency interval 80 - 250 Hz + * - filter_state : Updated state of the filter + * + */ +void WebRtcVad_HpOutput(WebRtc_Word16* in_vector, + WebRtc_Word16 in_vector_length, + WebRtc_Word16* out_vector, + WebRtc_Word16* filter_state); + +/**************************************************************************** + * WebRtcVad_Allpass(...) + * + * This function is used when before splitting a speech file into + * different frequency bands + * + * Note! Do NOT let the arrays in_vector and out_vector correspond to the same address. + * + * Input: + * - in_vector : (Q0) + * - filter_coefficients : (Q15) + * - vector_length : Length of input and output vector + * - filter_state : Current state of the filter (Q(-1)) + * + * Output: + * - out_vector : Output speech signal (Q(-1)) + * - filter_state : Updated state of the filter (Q(-1)) + * + */ +void WebRtcVad_Allpass(WebRtc_Word16* in_vector, + WebRtc_Word16* outw16, + WebRtc_Word16 filter_coefficients, + int vector_length, + WebRtc_Word16* filter_state); + +/**************************************************************************** + * WebRtcVad_SplitFilter(...) + * + * This function is used when before splitting a speech file into + * different frequency bands + * + * Input: + * - in_vector : Input signal to be split into two frequency bands. + * - upper_state : Current state of the upper filter + * - lower_state : Current state of the lower filter + * - in_vector_length : Length of input vector + * + * Output: + * - out_vector_hp : Upper half of the spectrum + * - out_vector_lp : Lower half of the spectrum + * - upper_state : Updated state of the upper filter + * - lower_state : Updated state of the lower filter + * + */ +void WebRtcVad_SplitFilter(WebRtc_Word16* in_vector, + WebRtc_Word16* out_vector_hp, + WebRtc_Word16* out_vector_lp, + WebRtc_Word16* upper_state, + WebRtc_Word16* lower_state, + int in_vector_length); + +/**************************************************************************** + * WebRtcVad_get_features(...) + * + * This function is used to get the logarithm of the power of each of the + * 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 + * + * Input: + * - inst : Pointer to VAD instance + * - in_vector : Input speech signal + * - frame_size : Frame size, in number of samples + * + * Output: + * - out_vector : 10*log10(power in each freq. band), Q4 + * + * Return: total power in the signal (NOTE! This value is not exact since it + * is only used in a comparison. + */ +WebRtc_Word16 WebRtcVad_get_features(VadInstT* inst, + WebRtc_Word16* in_vector, + int frame_size, + WebRtc_Word16* out_vector); + +/**************************************************************************** + * WebRtcVad_LogOfEnergy(...) + * + * This function is used to get the logarithm of the power of one frequency band. + * + * Input: + * - vector : Input speech samples for one frequency band + * - offset : Offset value for the current frequency band + * - vector_length : Length of input vector + * + * Output: + * - enerlogval : 10*log10(energy); + * - power : Update total power in speech frame. NOTE! This value + * is not exact since it is only used in a comparison. + * + */ +void WebRtcVad_LogOfEnergy(WebRtc_Word16* vector, + WebRtc_Word16* enerlogval, + WebRtc_Word16* power, + WebRtc_Word16 offset, + int vector_length); + +#endif // WEBRTC_VAD_FILTERBANK_H_ diff --git a/common_audio/vad/main/source/vad_gmm.c b/common_audio/vad/main/source/vad_gmm.c new file mode 100644 index 0000000000..23d12fb335 --- /dev/null +++ b/common_audio/vad/main/source/vad_gmm.c @@ -0,0 +1,70 @@ +/* + * 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 the implementation of the internal VAD call + * WebRtcVad_GaussianProbability. For function description, see vad_gmm.h. + */ + +#include "vad_gmm.h" +#include "signal_processing_library.h" +#include "vad_const.h" + +WebRtc_Word32 WebRtcVad_GaussianProbability(WebRtc_Word16 in_sample, + WebRtc_Word16 mean, + WebRtc_Word16 std, + WebRtc_Word16 *delta) +{ + WebRtc_Word16 tmp16, tmpDiv, tmpDiv2, expVal, tmp16_1, tmp16_2; + WebRtc_Word32 tmp32, y32; + + // Calculate tmpDiv=1/std, in Q10 + tmp32 = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_W16(std,1) + (WebRtc_Word32)131072; // 1 in Q17 + tmpDiv = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp32, std); // Q17/Q7 = Q10 + + // Calculate tmpDiv2=1/std^2, in Q14 + tmp16 = WEBRTC_SPL_RSHIFT_W16(tmpDiv, 2); // From Q10 to Q8 + tmpDiv2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, tmp16, 2); // (Q8 * Q8)>>2 = Q14 + + tmp16 = WEBRTC_SPL_LSHIFT_W16(in_sample, 3); // Q7 + tmp16 = tmp16 - mean; // Q7 - Q7 = Q7 + + // To be used later, when updating noise/speech model + // delta = (x-m)/std^2, in Q11 + *delta = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmpDiv2, tmp16, 10); //(Q14*Q7)>>10 = Q11 + + // Calculate tmp32=(x-m)^2/(2*std^2), in Q10 + tmp32 = (WebRtc_Word32)WEBRTC_SPL_MUL_16_16_RSFT(*delta, tmp16, 9); // One shift for /2 + + // Calculate expVal ~= exp(-(x-m)^2/(2*std^2)) ~= exp2(-log2(exp(1))*tmp32) + if (tmp32 < kCompVar) + { + // Calculate tmp16 = log2(exp(1))*tmp32 , in Q10 + tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((WebRtc_Word16)tmp32, + kLog10Const, 12); + tmp16 = -tmp16; + tmp16_2 = (WebRtc_Word16)(0x0400 | (tmp16 & 0x03FF)); + tmp16_1 = (WebRtc_Word16)(tmp16 ^ 0xFFFF); + tmp16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(tmp16_1, 10); + tmp16 += 1; + // Calculate expVal=log2(-tmp32), in Q10 + expVal = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)tmp16_2, tmp16); + + } else + { + expVal = 0; + } + + // Calculate y32=(1/std)*exp(-(x-m)^2/(2*std^2)), in Q20 + y32 = WEBRTC_SPL_MUL_16_16(tmpDiv, expVal); // Q10 * Q10 = Q20 + + return y32; // Q20 +} diff --git a/common_audio/vad/main/source/vad_gmm.h b/common_audio/vad/main/source/vad_gmm.h new file mode 100644 index 0000000000..e0747fb7e5 --- /dev/null +++ b/common_audio/vad/main/source/vad_gmm.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 includes the description of the internal VAD call + * WebRtcVad_GaussianProbability. + */ + +#ifndef WEBRTC_VAD_GMM_H_ +#define WEBRTC_VAD_GMM_H_ + +#include "typedefs.h" + +/**************************************************************************** + * WebRtcVad_GaussianProbability(...) + * + * This function calculates the probability for the value 'in_sample', given that in_sample + * comes from a normal distribution with mean 'mean' and standard deviation 'std'. + * + * Input: + * - in_sample : Input sample in Q4 + * - mean : mean value in the statistical model, Q7 + * - std : standard deviation, Q7 + * + * Output: + * + * - delta : Value used when updating the model, Q11 + * + * Return: + * - out : out = 1/std * exp(-(x-m)^2/(2*std^2)); + * Probability for x. + * + */ +WebRtc_Word32 WebRtcVad_GaussianProbability(WebRtc_Word16 in_sample, + WebRtc_Word16 mean, + WebRtc_Word16 std, + WebRtc_Word16 *delta); + +#endif // WEBRTC_VAD_GMM_H_ diff --git a/common_audio/vad/main/source/vad_sp.c b/common_audio/vad/main/source/vad_sp.c new file mode 100644 index 0000000000..f347ab5904 --- /dev/null +++ b/common_audio/vad/main/source/vad_sp.c @@ -0,0 +1,231 @@ +/* + * 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 the implementation of the VAD internal calls for Downsampling and + * FindMinimum. + * For function call descriptions; See vad_sp.h. + */ + +#include "vad_sp.h" +#include "vad_defines.h" +#include "vad_const.h" +#include "signal_processing_library.h" + +// Downsampling filter based on the splitting filter and the allpass functions +// in vad_filterbank.c +void WebRtcVad_Downsampling(WebRtc_Word16* signal_in, + WebRtc_Word16* signal_out, + WebRtc_Word32* filter_state, + int inlen) +{ + WebRtc_Word16 tmp16_1, tmp16_2; + WebRtc_Word32 tmp32_1, tmp32_2; + int n, halflen; + + // Downsampling by 2 and get two branches + halflen = WEBRTC_SPL_RSHIFT_W16(inlen, 1); + + tmp32_1 = filter_state[0]; + tmp32_2 = filter_state[1]; + + // Filter coefficients in Q13, filter state in Q0 + for (n = 0; n < halflen; n++) + { + // All-pass filtering upper branch + tmp16_1 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32_1, 1) + + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[0]), + *signal_in, 14); + *signal_out = tmp16_1; + tmp32_1 = (WebRtc_Word32)(*signal_in++) + - (WebRtc_Word32)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[0]), tmp16_1, 12); + + // All-pass filtering lower branch + tmp16_2 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32_2, 1) + + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[1]), + *signal_in, 14); + *signal_out++ += tmp16_2; + tmp32_2 = (WebRtc_Word32)(*signal_in++) + - (WebRtc_Word32)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[1]), tmp16_2, 12); + } + filter_state[0] = tmp32_1; + filter_state[1] = tmp32_2; +} + +WebRtc_Word16 WebRtcVad_FindMinimum(VadInstT* inst, + WebRtc_Word16 x, + int n) +{ + int i, j, k, II = -1, offset; + WebRtc_Word16 meanV, alpha; + WebRtc_Word32 tmp32, tmp32_1; + WebRtc_Word16 *valptr, *idxptr, *p1, *p2, *p3; + + // Offset to beginning of the 16 minimum values in memory + offset = WEBRTC_SPL_LSHIFT_W16(n, 4); + + // Pointer to memory for the 16 minimum values and the age of each value + idxptr = &inst->index_vector[offset]; + valptr = &inst->low_value_vector[offset]; + + // Each value in low_value_vector is getting 1 loop older. + // Update age of each value in indexVal, and remove old values. + for (i = 0; i < 16; i++) + { + p3 = idxptr + i; + if (*p3 != 100) + { + *p3 += 1; + } else + { + p1 = valptr + i + 1; + p2 = p3 + 1; + for (j = i; j < 16; j++) + { + *(valptr + j) = *p1++; + *(idxptr + j) = *p2++; + } + *(idxptr + 15) = 101; + *(valptr + 15) = 10000; + } + } + + // Check if x smaller than any of the values in low_value_vector. + // If so, find position. + if (x < *(valptr + 7)) + { + if (x < *(valptr + 3)) + { + if (x < *(valptr + 1)) + { + if (x < *valptr) + { + II = 0; + } else + { + II = 1; + } + } else if (x < *(valptr + 2)) + { + II = 2; + } else + { + II = 3; + } + } else if (x < *(valptr + 5)) + { + if (x < *(valptr + 4)) + { + II = 4; + } else + { + II = 5; + } + } else if (x < *(valptr + 6)) + { + II = 6; + } else + { + II = 7; + } + } else if (x < *(valptr + 15)) + { + if (x < *(valptr + 11)) + { + if (x < *(valptr + 9)) + { + if (x < *(valptr + 8)) + { + II = 8; + } else + { + II = 9; + } + } else if (x < *(valptr + 10)) + { + II = 10; + } else + { + II = 11; + } + } else if (x < *(valptr + 13)) + { + if (x < *(valptr + 12)) + { + II = 12; + } else + { + II = 13; + } + } else if (x < *(valptr + 14)) + { + II = 14; + } else + { + II = 15; + } + } + + // Put new min value on right position and shift bigger values up + if (II > -1) + { + for (i = 15; i > II; i--) + { + k = i - 1; + *(valptr + i) = *(valptr + k); + *(idxptr + i) = *(idxptr + k); + } + *(valptr + II) = x; + *(idxptr + II) = 1; + } + + meanV = 0; + if ((inst->frame_counter) > 4) + { + j = 5; + } else + { + j = inst->frame_counter; + } + + if (j > 2) + { + meanV = *(valptr + 2); + } else if (j > 0) + { + meanV = *valptr; + } else + { + meanV = 1600; + } + + if (inst->frame_counter > 0) + { + if (meanV < inst->mean_value[n]) + { + alpha = (WebRtc_Word16)ALPHA1; // 0.2 in Q15 + } else + { + alpha = (WebRtc_Word16)ALPHA2; // 0.99 in Q15 + } + } else + { + alpha = 0; + } + + tmp32 = WEBRTC_SPL_MUL_16_16((alpha+1), inst->mean_value[n]); + tmp32_1 = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_WORD16_MAX - alpha, meanV); + tmp32 += tmp32_1; + tmp32 += 16384; + inst->mean_value[n] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 15); + + return inst->mean_value[n]; +} diff --git a/common_audio/vad/main/source/vad_sp.h b/common_audio/vad/main/source/vad_sp.h new file mode 100644 index 0000000000..ae15c11ad6 --- /dev/null +++ b/common_audio/vad/main/source/vad_sp.h @@ -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 header file includes the VAD internal calls for Downsampling and FindMinimum. + * Specific function calls are given below. + */ + +#ifndef WEBRTC_VAD_SP_H_ +#define WEBRTC_VAD_SP_H_ + +#include "vad_core.h" + +/**************************************************************************** + * WebRtcVad_Downsampling(...) + * + * Downsamples the signal a factor 2, eg. 32->16 or 16->8 + * + * Input: + * - signal_in : Input signal + * - in_length : Length of input signal in samples + * + * Input & Output: + * - filter_state : Filter state for first all-pass filters + * + * Output: + * - signal_out : Downsampled signal (of length len/2) + */ +void WebRtcVad_Downsampling(WebRtc_Word16* signal_in, + WebRtc_Word16* signal_out, + WebRtc_Word32* filter_state, + int in_length); + +/**************************************************************************** + * WebRtcVad_FindMinimum(...) + * + * Find the five lowest values of x in 100 frames long window. Return a mean + * value of these five values. + * + * Input: + * - feature_value : Feature value + * - channel : Channel number + * + * Input & Output: + * - inst : State information + * + * Output: + * return value : Weighted minimum value for a moving window. + */ +WebRtc_Word16 WebRtcVad_FindMinimum(VadInstT* inst, WebRtc_Word16 feature_value, int channel); + +#endif // WEBRTC_VAD_SP_H_ diff --git a/common_audio/vad/main/source/webrtc_vad.c b/common_audio/vad/main/source/webrtc_vad.c new file mode 100644 index 0000000000..23ec13780e --- /dev/null +++ b/common_audio/vad/main/source/webrtc_vad.c @@ -0,0 +1,197 @@ +/* + * 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 the VAD API calls. For a specific function call description, + * see webrtc_vad.h + */ + +#include +#include + +#include "webrtc_vad.h" +#include "vad_core.h" + +static const int kInitCheck = 42; + +WebRtc_Word16 WebRtcVad_get_version(char *version, int length_bytes) +{ + const char my_version[] = "VAD 1.2.0"; + + if (version == NULL) + { + return -1; + } + + if (length_bytes < sizeof(my_version)) + { + return -1; + } + + memcpy(version, my_version, sizeof(my_version)); + return 0; +} + +WebRtc_Word16 WebRtcVad_AssignSize(int *size_in_bytes) +{ + *size_in_bytes = sizeof(VadInstT) * 2 / sizeof(WebRtc_Word16); + return 0; +} + +WebRtc_Word16 WebRtcVad_Assign(VadInst **vad_inst, void *vad_inst_addr) +{ + + if (vad_inst == NULL) + { + return -1; + } + + if (vad_inst_addr != NULL) + { + *vad_inst = (VadInst*)vad_inst_addr; + return 0; + } else + { + return -1; + } +} + +WebRtc_Word16 WebRtcVad_Create(VadInst **vad_inst) +{ + + VadInstT *vad_ptr = NULL; + + if (vad_inst == NULL) + { + return -1; + } + + *vad_inst = NULL; + + vad_ptr = (VadInstT *)malloc(sizeof(VadInstT)); + *vad_inst = (VadInst *)vad_ptr; + + if (vad_ptr == NULL) + { + return -1; + } + + vad_ptr->init_flag = 0; + + return 0; +} + +WebRtc_Word16 WebRtcVad_Free(VadInst *vad_inst) +{ + + if (vad_inst == NULL) + { + return -1; + } + + free(vad_inst); + return 0; +} + +WebRtc_Word16 WebRtcVad_Init(VadInst *vad_inst) +{ + short mode = 0; // Default high quality + + if (vad_inst == NULL) + { + return -1; + } + + return WebRtcVad_InitCore((VadInstT*)vad_inst, mode); +} + +WebRtc_Word16 WebRtcVad_set_mode(VadInst *vad_inst, WebRtc_Word16 mode) +{ + VadInstT* vad_ptr; + + if (vad_inst == NULL) + { + return -1; + } + + vad_ptr = (VadInstT*)vad_inst; + if (vad_ptr->init_flag != kInitCheck) + { + return -1; + } + + return WebRtcVad_set_mode_core((VadInstT*)vad_inst, mode); +} + +WebRtc_Word16 WebRtcVad_Process(VadInst *vad_inst, + WebRtc_Word16 fs, + WebRtc_Word16 *speech_frame, + WebRtc_Word16 frame_length) +{ + WebRtc_Word16 vad; + VadInstT* vad_ptr; + + if (vad_inst == NULL) + { + return -1; + } + + vad_ptr = (VadInstT*)vad_inst; + if (vad_ptr->init_flag != kInitCheck) + { + return -1; + } + + if (speech_frame == NULL) + { + return -1; + } + + if (fs == 32000) + { + if ((frame_length != 320) && (frame_length != 640) && (frame_length != 960)) + { + return -1; + } + vad = WebRtcVad_CalcVad32khz((VadInstT*)vad_inst, speech_frame, frame_length); + + } else if (fs == 16000) + { + if ((frame_length != 160) && (frame_length != 320) && (frame_length != 480)) + { + return -1; + } + vad = WebRtcVad_CalcVad16khz((VadInstT*)vad_inst, speech_frame, frame_length); + + } else if (fs == 8000) + { + if ((frame_length != 80) && (frame_length != 160) && (frame_length != 240)) + { + return -1; + } + vad = WebRtcVad_CalcVad8khz((VadInstT*)vad_inst, speech_frame, frame_length); + + } else + { + return -1; // Not a supported sampling frequency + } + + if (vad > 0) + { + return 1; + } else if (vad == 0) + { + return 0; + } else + { + return -1; + } +} diff --git a/common_audio/vad/main/test/unit_test/unit_test.cc b/common_audio/vad/main/test/unit_test/unit_test.cc new file mode 100644 index 0000000000..8ac793e44e --- /dev/null +++ b/common_audio/vad/main/test/unit_test/unit_test.cc @@ -0,0 +1,123 @@ +/* + * 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 the implementation of the VAD unit tests. + */ + +#include +#include "unit_test.h" +#include "webrtc_vad.h" + + +class VadEnvironment : public ::testing::Environment { + public: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + +VadTest::VadTest() +{ +} + +void VadTest::SetUp() { +} + +void VadTest::TearDown() { +} + +TEST_F(VadTest, ApiTest) { + VadInst *vad_inst; + int i, j, k; + short zeros[960]; + short speech[960]; + char version[32]; + + // Valid test cases + int fs[3] = {8000, 16000, 32000}; + int nMode[4] = {0, 1, 2, 3}; + int framelen[3][3] = {{80, 160, 240}, + {160, 320, 480}, {320, 640, 960}} ; + int vad_counter = 0; + + memset(zeros, 0, sizeof(short) * 960); + memset(speech, 1, sizeof(short) * 960); + speech[13] = 1374; + speech[73] = -3747; + + + + // WebRtcVad_get_version() + WebRtcVad_get_version(version); + //printf("API Test for %s\n", version); + + // Null instance tests + EXPECT_EQ(-1, WebRtcVad_Create(NULL)); + EXPECT_EQ(-1, WebRtcVad_Init(NULL)); + EXPECT_EQ(-1, WebRtcVad_Assign(NULL, NULL)); + EXPECT_EQ(-1, WebRtcVad_Free(NULL)); + EXPECT_EQ(-1, WebRtcVad_set_mode(NULL, nMode[0])); + EXPECT_EQ(-1, WebRtcVad_Process(NULL, fs[0], speech, framelen[0][0])); + + + EXPECT_EQ(WebRtcVad_Create(&vad_inst), 0); + + // Not initialized tests + EXPECT_EQ(-1, WebRtcVad_Process(vad_inst, fs[0], speech, framelen[0][0])); + EXPECT_EQ(-1, WebRtcVad_set_mode(vad_inst, nMode[0])); + + // WebRtcVad_Init() tests + EXPECT_EQ(WebRtcVad_Init(vad_inst), 0); + + // WebRtcVad_set_mode() tests + EXPECT_EQ(-1, WebRtcVad_set_mode(vad_inst, -1)); + EXPECT_EQ(-1, WebRtcVad_set_mode(vad_inst, 4)); + + for (i = 0; i < sizeof(nMode)/sizeof(nMode[0]); i++) { + EXPECT_EQ(WebRtcVad_set_mode(vad_inst, nMode[i]), 0); + } + + // WebRtcVad_Process() tests + EXPECT_EQ(-1, WebRtcVad_Process(vad_inst, fs[0], NULL, framelen[0][0])); + EXPECT_EQ(-1, WebRtcVad_Process(vad_inst, 12000, speech, framelen[0][0])); + EXPECT_EQ(-1, WebRtcVad_Process(vad_inst, fs[0], speech, framelen[1][1])); + EXPECT_EQ(WebRtcVad_Process(vad_inst, fs[0], zeros, framelen[0][0]), 0); + for (i = 0; i < sizeof(fs)/sizeof(fs[0]); i++) { + for (j = 0; j < sizeof(framelen[0])/sizeof(framelen[0][0]); j++) { + for (k = 0; k < sizeof(nMode)/sizeof(nMode[0]); k++) { + EXPECT_EQ(WebRtcVad_set_mode(vad_inst, nMode[k]), 0); +// printf("%d\n", WebRtcVad_Process(vad_inst, fs[i], speech, framelen[i][j])); + if (vad_counter < 9) + { + EXPECT_EQ(WebRtcVad_Process(vad_inst, fs[i], speech, framelen[i][j]), 1); + } else + { + EXPECT_EQ(WebRtcVad_Process(vad_inst, fs[i], speech, framelen[i][j]), 0); + } + vad_counter++; + } + } + } + + EXPECT_EQ(0, WebRtcVad_Free(vad_inst)); + +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + VadEnvironment* env = new VadEnvironment; + ::testing::AddGlobalTestEnvironment(env); + + return RUN_ALL_TESTS(); +} diff --git a/common_audio/vad/main/test/unit_test/unit_test.h b/common_audio/vad/main/test/unit_test/unit_test.h new file mode 100644 index 0000000000..62dac11de4 --- /dev/null +++ b/common_audio/vad/main/test/unit_test/unit_test.h @@ -0,0 +1,28 @@ +/* + * 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 declaration of the VAD unit test. + */ + +#ifndef WEBRTC_VAD_UNIT_TEST_H_ +#define WEBRTC_VAD_UNIT_TEST_H_ + +#include + +class VadTest : public ::testing::Test { + protected: + VadTest(); + virtual void SetUp(); + virtual void TearDown(); +}; + +#endif // WEBRTC_VAD_UNIT_TEST_H_