Initial commit of source files
This commit is contained in:
parent
87ca4f70f3
commit
35f5c9ced4
7
AUTHORS
Normal file
7
AUTHORS
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Names should be added to this file like so:
|
||||||
|
# Name or Organization <email address>
|
||||||
|
|
||||||
|
Google Inc.
|
||||||
|
|
||||||
|
# autofoo-based build system
|
||||||
|
Arun Raghavan <arun.raghavan@collabora.co.uk>
|
29
COPYING
Normal file
29
COPYING
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Copyright (c) 2011, Google Inc. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
* Neither the name of Google nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
PATENTS
Normal file
24
PATENTS
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Additional IP Rights Grant (Patents)
|
||||||
|
|
||||||
|
"This implementation" means the copyrightable works distributed by
|
||||||
|
Google as part of the WebRTC code package.
|
||||||
|
|
||||||
|
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
||||||
|
no-charge, irrevocable (except as stated in this section) patent
|
||||||
|
license to make, have made, use, offer to sell, sell, import,
|
||||||
|
transfer, and otherwise run, modify and propagate the contents of this
|
||||||
|
implementation of the WebRTC code package, where such license applies
|
||||||
|
only to those patent claims, both currently owned by Google and
|
||||||
|
acquired in the future, licensable by Google that are necessarily
|
||||||
|
infringed by this implementation of the WebRTC code package. This
|
||||||
|
grant does not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of this implementation. If you or
|
||||||
|
your agent or exclusive licensee institute or order or agree to the
|
||||||
|
institution of patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that this
|
||||||
|
implementation of the WebRTC code package or any code incorporated
|
||||||
|
within this implementation of the WebRTC code package constitutes
|
||||||
|
direct or contributory patent infringement, or inducement of patent
|
||||||
|
infringement, then any patent rights granted to you under this License
|
||||||
|
for this implementation of the WebRTC code package shall terminate as
|
||||||
|
of the date such litigation is filed.
|
3
src/common_audio/signal_processing_library/OWNERS
Normal file
3
src/common_audio/signal_processing_library/OWNERS
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bjornv@webrtc.org
|
||||||
|
tina.legrand@webrtc.org
|
||||||
|
jan.skoglund@webrtc.org
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// This header file includes the inline functions in
|
||||||
|
// the fix point signal processing library.
|
||||||
|
|
||||||
|
#ifndef WEBRTC_SPL_SPL_INL_H_
|
||||||
|
#define WEBRTC_SPL_SPL_INL_H_
|
||||||
|
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
#include "spl_inl_armv7.h"
|
||||||
|
#else
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
|
||||||
|
WebRtc_Word32 l_var2) {
|
||||||
|
WebRtc_Word32 l_sum;
|
||||||
|
|
||||||
|
// perform long addition
|
||||||
|
l_sum = l_var1 + l_var2;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
|
||||||
|
WebRtc_Word32 l_var2) {
|
||||||
|
WebRtc_Word32 l_diff;
|
||||||
|
|
||||||
|
// perform subtraction
|
||||||
|
l_diff = l_var1 - l_var2;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
if (0xFFFF0000 & n) {
|
||||||
|
bits = 16;
|
||||||
|
} else {
|
||||||
|
bits = 0;
|
||||||
|
}
|
||||||
|
if (0x0000FF00 & (n >> bits)) bits += 8;
|
||||||
|
if (0x000000F0 & (n >> bits)) bits += 4;
|
||||||
|
if (0x0000000C & (n >> bits)) bits += 2;
|
||||||
|
if (0x00000002 & (n >> bits)) bits += 1;
|
||||||
|
if (0x00000001 & (n >> bits)) bits += 1;
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
|
||||||
|
int zeros;
|
||||||
|
|
||||||
|
if (a <= 0) a ^= 0xFFFFFFFF;
|
||||||
|
|
||||||
|
if (!(0xFFFF8000 & a)) {
|
||||||
|
zeros = 16;
|
||||||
|
} else {
|
||||||
|
zeros = 0;
|
||||||
|
}
|
||||||
|
if (!(0xFF800000 & (a << zeros))) zeros += 8;
|
||||||
|
if (!(0xF8000000 & (a << zeros))) zeros += 4;
|
||||||
|
if (!(0xE0000000 & (a << zeros))) zeros += 2;
|
||||||
|
if (!(0xC0000000 & (a << zeros))) zeros += 1;
|
||||||
|
|
||||||
|
return zeros;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
|
||||||
|
int zeros;
|
||||||
|
|
||||||
|
if (a == 0) return 0;
|
||||||
|
|
||||||
|
if (!(0xFFFF0000 & a)) {
|
||||||
|
zeros = 16;
|
||||||
|
} else {
|
||||||
|
zeros = 0;
|
||||||
|
}
|
||||||
|
if (!(0xFF000000 & (a << zeros))) zeros += 8;
|
||||||
|
if (!(0xF0000000 & (a << zeros))) zeros += 4;
|
||||||
|
if (!(0xC0000000 & (a << zeros))) zeros += 2;
|
||||||
|
if (!(0x80000000 & (a << zeros))) zeros += 1;
|
||||||
|
|
||||||
|
return zeros;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
|
||||||
|
int zeros;
|
||||||
|
|
||||||
|
if (a <= 0) a ^= 0xFFFF;
|
||||||
|
|
||||||
|
if (!(0xFF80 & a)) {
|
||||||
|
zeros = 8;
|
||||||
|
} else {
|
||||||
|
zeros = 0;
|
||||||
|
}
|
||||||
|
if (!(0xF800 & (a << zeros))) zeros += 4;
|
||||||
|
if (!(0xE000 & (a << zeros))) zeros += 2;
|
||||||
|
if (!(0xC000 & (a << zeros))) zeros += 1;
|
||||||
|
|
||||||
|
return zeros;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBRTC_ARCH_ARM_V7A
|
||||||
|
|
||||||
|
#endif // WEBRTC_SPL_SPL_INL_H_
|
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* 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 for ARM processors in
|
||||||
|
// the fix point signal processing library.
|
||||||
|
|
||||||
|
#ifndef WEBRTC_SPL_SPL_INL_ARMV7_H_
|
||||||
|
#define WEBRTC_SPL_SPL_INL_ARMV7_H_
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
|
||||||
|
WebRtc_Word32 tmp;
|
||||||
|
|
||||||
|
__asm__("clz %0, %1":"=r"(tmp):"r"(n));
|
||||||
|
|
||||||
|
return (WebRtc_Word16)(32 - tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
if (a == 0) return 0;
|
||||||
|
|
||||||
|
__asm__("clz %0, %1":"=r"(tmp):"r"(a));
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
|
||||||
|
WebRtc_Word32 tmp;
|
||||||
|
|
||||||
|
if (a <= 0) a ^= 0xFFFFFFFF;
|
||||||
|
|
||||||
|
__asm__("clz %0, %1":"=r"(tmp):"r"(a));
|
||||||
|
|
||||||
|
return tmp - 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBRTC_SPL_SPL_INL_ARMV7_H_
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 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
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
WebRtc_Word32 wri;
|
||||||
|
WebRtc_Word32 frfi_r;
|
||||||
|
__asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
|
||||||
|
"r"((WebRtc_Word32)wr), "r"((WebRtc_Word32)wi));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = m; i < n; i += istep)
|
||||||
|
{
|
||||||
|
j = i + l;
|
||||||
|
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
__asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(frfi_r) :
|
||||||
|
"r"((WebRtc_Word32)frfi[2*j]), "r"((WebRtc_Word32)frfi[2*j +1]));
|
||||||
|
__asm__("smlsd %0, %1, %2, %3" : "=r"(tr32) :
|
||||||
|
"r"(wri), "r"(frfi_r), "r"(CFFTRND));
|
||||||
|
__asm__("smladx %0, %1, %2, %3" : "=r"(ti32) :
|
||||||
|
"r"(wri), "r"(frfi_r), "r"(CFFTRND));
|
||||||
|
|
||||||
|
#else
|
||||||
|
tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
|
||||||
|
- WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND;
|
||||||
|
|
||||||
|
ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
|
||||||
|
+ WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CFFTSFT);
|
||||||
|
ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CFFTSFT);
|
||||||
|
|
||||||
|
qr32 = ((WebRtc_Word32)frfi[2 * i]) << CFFTSFT;
|
||||||
|
qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CFFTSFT;
|
||||||
|
|
||||||
|
frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||||
|
(qr32 - tr32 + CFFTRND2), 1 + CFFTSFT);
|
||||||
|
frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||||
|
(qi32 - ti32 + CFFTRND2), 1 + CFFTSFT);
|
||||||
|
frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||||
|
(qr32 + tr32 + CFFTRND2), 1 + CFFTSFT);
|
||||||
|
frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||||
|
(qi32 + ti32 + CFFTRND2), 1 + CFFTSFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--k;
|
||||||
|
l = istep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
WebRtc_Word32 wri;
|
||||||
|
WebRtc_Word32 frfi_r;
|
||||||
|
__asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
|
||||||
|
"r"((WebRtc_Word32)wr), "r"((WebRtc_Word32)wi));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = m; i < n; i += istep)
|
||||||
|
{
|
||||||
|
j = i + l;
|
||||||
|
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
__asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(frfi_r) :
|
||||||
|
"r"((WebRtc_Word32)frfi[2*j]), "r"((WebRtc_Word32)frfi[2*j +1]));
|
||||||
|
__asm__("smlsd %0, %1, %2, %3" : "=r"(tr32) :
|
||||||
|
"r"(wri), "r"(frfi_r), "r"(CIFFTRND));
|
||||||
|
__asm__("smladx %0, %1, %2, %3" : "=r"(ti32) :
|
||||||
|
"r"(wri), "r"(frfi_r), "r"(CIFFTRND));
|
||||||
|
#else
|
||||||
|
|
||||||
|
tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
|
||||||
|
- WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CIFFTRND;
|
||||||
|
|
||||||
|
ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
|
||||||
|
+ WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CIFFTRND;
|
||||||
|
#endif
|
||||||
|
tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CIFFTSFT);
|
||||||
|
ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CIFFTSFT);
|
||||||
|
|
||||||
|
qr32 = ((WebRtc_Word32)frfi[2 * i]) << CIFFTSFT;
|
||||||
|
qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CIFFTSFT;
|
||||||
|
|
||||||
|
frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2),
|
||||||
|
shift+CIFFTSFT);
|
||||||
|
frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||||
|
(qi32 - ti32 + round2), shift + CIFFTSFT);
|
||||||
|
frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2),
|
||||||
|
shift + CIFFTSFT);
|
||||||
|
frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
|
||||||
|
(qi32 + ti32 + round2), shift + CIFFTSFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
--k;
|
||||||
|
l = istep;
|
||||||
|
}
|
||||||
|
return scale;
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains the implementation of functions
|
||||||
|
* WebRtcSpl_MemSetW16()
|
||||||
|
* WebRtcSpl_MemSetW32()
|
||||||
|
* WebRtcSpl_MemCpyReversedOrder()
|
||||||
|
* WebRtcSpl_CopyFromEndW16()
|
||||||
|
* WebRtcSpl_ZerosArrayW16()
|
||||||
|
* WebRtcSpl_ZerosArrayW32()
|
||||||
|
* WebRtcSpl_OnesArrayW16()
|
||||||
|
* WebRtcSpl_OnesArrayW32()
|
||||||
|
*
|
||||||
|
* The description header can be found in signal_processing_library.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
|
||||||
|
|
||||||
|
void WebRtcSpl_MemSetW16(WebRtc_Word16 *ptr, WebRtc_Word16 set_value, int length)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
WebRtc_Word16 *arrptr = ptr;
|
||||||
|
|
||||||
|
for (j = length; j > 0; j--)
|
||||||
|
{
|
||||||
|
*arrptr++ = set_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRtcSpl_MemSetW32(WebRtc_Word32 *ptr, WebRtc_Word32 set_value, int length)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
WebRtc_Word32 *arrptr = ptr;
|
||||||
|
|
||||||
|
for (j = length; j > 0; j--)
|
||||||
|
{
|
||||||
|
*arrptr++ = set_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRtcSpl_MemCpyReversedOrder(WebRtc_Word16* dest, WebRtc_Word16* source, int length)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
WebRtc_Word16* destPtr = dest;
|
||||||
|
WebRtc_Word16* sourcePtr = source;
|
||||||
|
|
||||||
|
for (j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
*destPtr-- = *sourcePtr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcSpl_CopyFromEndW16(G_CONST WebRtc_Word16 *vector_in,
|
||||||
|
WebRtc_Word16 length,
|
||||||
|
WebRtc_Word16 samples,
|
||||||
|
WebRtc_Word16 *vector_out)
|
||||||
|
{
|
||||||
|
// Copy the last <samples> of the input vector to vector_out
|
||||||
|
WEBRTC_SPL_MEMCPY_W16(vector_out, &vector_in[length - samples], samples);
|
||||||
|
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcSpl_ZerosArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length)
|
||||||
|
{
|
||||||
|
WebRtcSpl_MemSetW16(vector, 0, length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcSpl_ZerosArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length)
|
||||||
|
{
|
||||||
|
WebRtcSpl_MemSetW32(vector, 0, length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcSpl_OnesArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length)
|
||||||
|
{
|
||||||
|
WebRtc_Word16 i;
|
||||||
|
WebRtc_Word16 *tmpvec = vector;
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
*tmpvec++ = 1;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcSpl_OnesArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length)
|
||||||
|
{
|
||||||
|
WebRtc_Word16 i;
|
||||||
|
WebRtc_Word32 *tmpvec = vector;
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
*tmpvec++ = 1;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
@ -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
|
||||||
|
};
|
@ -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
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains the function WebRtcSpl_FilterAR().
|
||||||
|
* The description header can be found in signal_processing_library.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
|
||||||
|
int WebRtcSpl_FilterAR(G_CONST WebRtc_Word16* a,
|
||||||
|
int a_length,
|
||||||
|
G_CONST WebRtc_Word16* x,
|
||||||
|
int x_length,
|
||||||
|
WebRtc_Word16* state,
|
||||||
|
int state_length,
|
||||||
|
WebRtc_Word16* state_low,
|
||||||
|
int state_low_length,
|
||||||
|
WebRtc_Word16* filtered,
|
||||||
|
WebRtc_Word16* filtered_low,
|
||||||
|
int filtered_low_length)
|
||||||
|
{
|
||||||
|
WebRtc_Word32 o;
|
||||||
|
WebRtc_Word32 oLOW;
|
||||||
|
int i, j, stop;
|
||||||
|
G_CONST WebRtc_Word16* x_ptr = &x[0];
|
||||||
|
WebRtc_Word16* filteredFINAL_ptr = filtered;
|
||||||
|
WebRtc_Word16* filteredFINAL_LOW_ptr = filtered_low;
|
||||||
|
|
||||||
|
for (i = 0; i < x_length; i++)
|
||||||
|
{
|
||||||
|
// Calculate filtered[i] and filtered_low[i]
|
||||||
|
G_CONST WebRtc_Word16* a_ptr = &a[1];
|
||||||
|
WebRtc_Word16* filtered_ptr = &filtered[i - 1];
|
||||||
|
WebRtc_Word16* filtered_low_ptr = &filtered_low[i - 1];
|
||||||
|
WebRtc_Word16* state_ptr = &state[state_length - 1];
|
||||||
|
WebRtc_Word16* state_low_ptr = &state_low[state_length - 1];
|
||||||
|
|
||||||
|
o = (WebRtc_Word32)(*x_ptr++) << 12;
|
||||||
|
oLOW = (WebRtc_Word32)0;
|
||||||
|
|
||||||
|
stop = (i < a_length) ? i + 1 : a_length;
|
||||||
|
for (j = 1; j < stop; j++)
|
||||||
|
{
|
||||||
|
o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--);
|
||||||
|
oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--);
|
||||||
|
}
|
||||||
|
for (j = i + 1; j < a_length; j++)
|
||||||
|
{
|
||||||
|
o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *state_ptr--);
|
||||||
|
oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *state_low_ptr--);
|
||||||
|
}
|
||||||
|
|
||||||
|
o += (oLOW >> 12);
|
||||||
|
*filteredFINAL_ptr = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);
|
||||||
|
*filteredFINAL_LOW_ptr++ = (WebRtc_Word16)(o - ((WebRtc_Word32)(*filteredFINAL_ptr++)
|
||||||
|
<< 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the filter state
|
||||||
|
if (x_length >= state_length)
|
||||||
|
{
|
||||||
|
WebRtcSpl_CopyFromEndW16(filtered, x_length, a_length - 1, state);
|
||||||
|
WebRtcSpl_CopyFromEndW16(filtered_low, x_length, a_length - 1, state_low);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
for (i = 0; i < state_length - x_length; i++)
|
||||||
|
{
|
||||||
|
state[i] = state[i + x_length];
|
||||||
|
state_low[i] = state_low[i + x_length];
|
||||||
|
}
|
||||||
|
for (i = 0; i < x_length; i++)
|
||||||
|
{
|
||||||
|
state[state_length - x_length + i] = filtered[i];
|
||||||
|
state[state_length - x_length + i] = filtered_low[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return x_length;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
};
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#if !(defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM_NEON))
|
||||||
|
|
||||||
|
// Maximum absolute value of word16 vector.
|
||||||
|
WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(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;
|
||||||
|
|
||||||
|
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
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM_NEON))
|
||||||
|
|
||||||
|
#include <arm_neon.h>
|
||||||
|
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
|
||||||
|
// Maximum absolute value of word16 vector.
|
||||||
|
WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(const WebRtc_Word16* vector,
|
||||||
|
WebRtc_Word16 length) {
|
||||||
|
WebRtc_Word32 temp_max = 0;
|
||||||
|
WebRtc_Word32 abs_val;
|
||||||
|
WebRtc_Word16 tot_max;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
__asm__("vmov.i16 d25, #0" : : : "d25");
|
||||||
|
|
||||||
|
for (i = 0; i < length - 7; i += 8) {
|
||||||
|
__asm__("vld1.16 {d26, d27}, [%0]" : : "r"(&vector[i]) : "q13");
|
||||||
|
__asm__("vabs.s16 q13, q13" : : : "q13");
|
||||||
|
__asm__("vpmax.s16 d26, d27" : : : "q13");
|
||||||
|
__asm__("vpmax.s16 d25, d26" : : : "d25", "d26");
|
||||||
|
}
|
||||||
|
__asm__("vpmax.s16 d25, d25" : : : "d25");
|
||||||
|
__asm__("vpmax.s16 d25, d25" : : : "d25");
|
||||||
|
__asm__("vmov.s16 %0, d25[0]" : "=r"(temp_max): : "d25");
|
||||||
|
|
||||||
|
for (; i < length; i++) {
|
||||||
|
abs_val = WEBRTC_SPL_ABS_W32((vector[i]));
|
||||||
|
if (abs_val > temp_max) {
|
||||||
|
temp_max = abs_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tot_max = (WebRtc_Word16)WEBRTC_SPL_MIN(temp_max, WEBRTC_SPL_WORD16_MAX);
|
||||||
|
return tot_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -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
|
||||||
|
};
|
@ -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;
|
||||||
|
}
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains resampling functions between 48 kHz and nb/wb.
|
||||||
|
* The description header can be found in signal_processing_library.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
#include "resample_by_2_internal.h"
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
///// 48 kHz -> 16 kHz /////
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
// 48 -> 16 resampler
|
||||||
|
void WebRtcSpl_Resample48khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
|
||||||
|
WebRtcSpl_State48khzTo16khz* state, WebRtc_Word32* tmpmem)
|
||||||
|
{
|
||||||
|
///// 48 --> 48(LP) /////
|
||||||
|
// WebRtc_Word16 in[480]
|
||||||
|
// WebRtc_Word32 out[480]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_LPBy2ShortToInt(in, 480, tmpmem + 16, state->S_48_48);
|
||||||
|
|
||||||
|
///// 48 --> 32 /////
|
||||||
|
// WebRtc_Word32 in[480]
|
||||||
|
// WebRtc_Word32 out[320]
|
||||||
|
/////
|
||||||
|
// copy state to and from input array
|
||||||
|
memcpy(tmpmem + 8, state->S_48_32, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memcpy(state->S_48_32, tmpmem + 488, 8 * sizeof(WebRtc_Word32));
|
||||||
|
WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 160);
|
||||||
|
|
||||||
|
///// 32 --> 16 /////
|
||||||
|
// WebRtc_Word32 in[320]
|
||||||
|
// WebRtc_Word16 out[160]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_DownBy2IntToShort(tmpmem, 320, out, state->S_32_16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize state of 48 -> 16 resampler
|
||||||
|
void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state)
|
||||||
|
{
|
||||||
|
memset(state->S_48_48, 0, 16 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_48_32, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_32_16, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
///// 16 kHz -> 48 kHz /////
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
// 16 -> 48 resampler
|
||||||
|
void WebRtcSpl_Resample16khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
|
||||||
|
WebRtcSpl_State16khzTo48khz* state, WebRtc_Word32* tmpmem)
|
||||||
|
{
|
||||||
|
///// 16 --> 32 /////
|
||||||
|
// WebRtc_Word16 in[160]
|
||||||
|
// WebRtc_Word32 out[320]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_UpBy2ShortToInt(in, 160, tmpmem + 16, state->S_16_32);
|
||||||
|
|
||||||
|
///// 32 --> 24 /////
|
||||||
|
// WebRtc_Word32 in[320]
|
||||||
|
// WebRtc_Word32 out[240]
|
||||||
|
// copy state to and from input array
|
||||||
|
/////
|
||||||
|
memcpy(tmpmem + 8, state->S_32_24, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memcpy(state->S_32_24, tmpmem + 328, 8 * sizeof(WebRtc_Word32));
|
||||||
|
WebRtcSpl_Resample32khzTo24khz(tmpmem + 8, tmpmem, 80);
|
||||||
|
|
||||||
|
///// 24 --> 48 /////
|
||||||
|
// WebRtc_Word32 in[240]
|
||||||
|
// WebRtc_Word16 out[480]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize state of 16 -> 48 resampler
|
||||||
|
void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state)
|
||||||
|
{
|
||||||
|
memset(state->S_16_32, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_32_24, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_24_48, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
///// 48 kHz -> 8 kHz /////
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
// 48 -> 8 resampler
|
||||||
|
void WebRtcSpl_Resample48khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
|
||||||
|
WebRtcSpl_State48khzTo8khz* state, WebRtc_Word32* tmpmem)
|
||||||
|
{
|
||||||
|
///// 48 --> 24 /////
|
||||||
|
// WebRtc_Word16 in[480]
|
||||||
|
// WebRtc_Word32 out[240]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_DownBy2ShortToInt(in, 480, tmpmem + 256, state->S_48_24);
|
||||||
|
|
||||||
|
///// 24 --> 24(LP) /////
|
||||||
|
// WebRtc_Word32 in[240]
|
||||||
|
// WebRtc_Word32 out[240]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_LPBy2IntToInt(tmpmem + 256, 240, tmpmem + 16, state->S_24_24);
|
||||||
|
|
||||||
|
///// 24 --> 16 /////
|
||||||
|
// WebRtc_Word32 in[240]
|
||||||
|
// WebRtc_Word32 out[160]
|
||||||
|
/////
|
||||||
|
// copy state to and from input array
|
||||||
|
memcpy(tmpmem + 8, state->S_24_16, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memcpy(state->S_24_16, tmpmem + 248, 8 * sizeof(WebRtc_Word32));
|
||||||
|
WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 80);
|
||||||
|
|
||||||
|
///// 16 --> 8 /////
|
||||||
|
// WebRtc_Word32 in[160]
|
||||||
|
// WebRtc_Word16 out[80]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_DownBy2IntToShort(tmpmem, 160, out, state->S_16_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize state of 48 -> 8 resampler
|
||||||
|
void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state)
|
||||||
|
{
|
||||||
|
memset(state->S_48_24, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_24_24, 0, 16 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_24_16, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_16_8, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
///// 8 kHz -> 48 kHz /////
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
// 8 -> 48 resampler
|
||||||
|
void WebRtcSpl_Resample8khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
|
||||||
|
WebRtcSpl_State8khzTo48khz* state, WebRtc_Word32* tmpmem)
|
||||||
|
{
|
||||||
|
///// 8 --> 16 /////
|
||||||
|
// WebRtc_Word16 in[80]
|
||||||
|
// WebRtc_Word32 out[160]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_UpBy2ShortToInt(in, 80, tmpmem + 264, state->S_8_16);
|
||||||
|
|
||||||
|
///// 16 --> 12 /////
|
||||||
|
// WebRtc_Word32 in[160]
|
||||||
|
// WebRtc_Word32 out[120]
|
||||||
|
/////
|
||||||
|
// copy state to and from input array
|
||||||
|
memcpy(tmpmem + 256, state->S_16_12, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memcpy(state->S_16_12, tmpmem + 416, 8 * sizeof(WebRtc_Word32));
|
||||||
|
WebRtcSpl_Resample32khzTo24khz(tmpmem + 256, tmpmem + 240, 40);
|
||||||
|
|
||||||
|
///// 12 --> 24 /////
|
||||||
|
// WebRtc_Word32 in[120]
|
||||||
|
// WebRtc_Word16 out[240]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_UpBy2IntToInt(tmpmem + 240, 120, tmpmem, state->S_12_24);
|
||||||
|
|
||||||
|
///// 24 --> 48 /////
|
||||||
|
// WebRtc_Word32 in[240]
|
||||||
|
// WebRtc_Word16 out[480]
|
||||||
|
/////
|
||||||
|
WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize state of 8 -> 48 resampler
|
||||||
|
void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state)
|
||||||
|
{
|
||||||
|
memset(state->S_8_16, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_16_12, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_12_24, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
memset(state->S_24_48, 0, 8 * sizeof(WebRtc_Word32));
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
|
||||||
|
WebRtc_Word16 i;
|
||||||
|
|
||||||
|
register WebRtc_Word32 state0 = filtState[0];
|
||||||
|
register WebRtc_Word32 state1 = filtState[1];
|
||||||
|
register WebRtc_Word32 state2 = filtState[2];
|
||||||
|
register WebRtc_Word32 state3 = filtState[3];
|
||||||
|
register WebRtc_Word32 state4 = filtState[4];
|
||||||
|
register WebRtc_Word32 state5 = filtState[5];
|
||||||
|
register WebRtc_Word32 state6 = filtState[6];
|
||||||
|
register WebRtc_Word32 state7 = filtState[7];
|
||||||
|
|
||||||
|
for (i = (len >> 1); i > 0; i--)
|
||||||
|
{
|
||||||
|
// lower allpass filter
|
||||||
|
in32 = (WebRtc_Word32)(*in++) << 10;
|
||||||
|
diff = in32 - state1;
|
||||||
|
tmp1 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass2[0], diff, state0);
|
||||||
|
state0 = in32;
|
||||||
|
diff = tmp1 - state2;
|
||||||
|
tmp2 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass2[1], diff, state1);
|
||||||
|
state1 = tmp1;
|
||||||
|
diff = tmp2 - state3;
|
||||||
|
state3 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass2[2], diff, state2);
|
||||||
|
state2 = tmp2;
|
||||||
|
|
||||||
|
// upper allpass filter
|
||||||
|
in32 = (WebRtc_Word32)(*in++) << 10;
|
||||||
|
diff = in32 - state5;
|
||||||
|
tmp1 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass1[0], diff, state4);
|
||||||
|
state4 = in32;
|
||||||
|
diff = tmp1 - state6;
|
||||||
|
tmp2 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass1[1], diff, state5);
|
||||||
|
state5 = tmp1;
|
||||||
|
diff = tmp2 - state7;
|
||||||
|
state7 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass1[2], diff, state6);
|
||||||
|
state6 = tmp2;
|
||||||
|
|
||||||
|
// add two allpass outputs, divide by two and round
|
||||||
|
out32 = (state3 + state7 + 1024) >> 11;
|
||||||
|
|
||||||
|
// limit amplitude to prevent wrap-around, and write to output array
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
__asm__("ssat %r0, #16, %r1" : "=r"(*out) : "r"(out32));
|
||||||
|
out++;
|
||||||
|
#else
|
||||||
|
if (out32 > 32767)
|
||||||
|
*out++ = 32767;
|
||||||
|
else if (out32 < -32768)
|
||||||
|
*out++ = -32768;
|
||||||
|
else
|
||||||
|
*out++ = (WebRtc_Word16)out32;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
filtState[0] = state0;
|
||||||
|
filtState[1] = state1;
|
||||||
|
filtState[2] = state2;
|
||||||
|
filtState[3] = state3;
|
||||||
|
filtState[4] = state4;
|
||||||
|
filtState[5] = state5;
|
||||||
|
filtState[6] = state6;
|
||||||
|
filtState[7] = state7;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, WebRtc_Word16* out,
|
||||||
|
WebRtc_Word32* filtState)
|
||||||
|
{
|
||||||
|
WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
|
||||||
|
WebRtc_Word16 i;
|
||||||
|
|
||||||
|
register WebRtc_Word32 state0 = filtState[0];
|
||||||
|
register WebRtc_Word32 state1 = filtState[1];
|
||||||
|
register WebRtc_Word32 state2 = filtState[2];
|
||||||
|
register WebRtc_Word32 state3 = filtState[3];
|
||||||
|
register WebRtc_Word32 state4 = filtState[4];
|
||||||
|
register WebRtc_Word32 state5 = filtState[5];
|
||||||
|
register WebRtc_Word32 state6 = filtState[6];
|
||||||
|
register WebRtc_Word32 state7 = filtState[7];
|
||||||
|
|
||||||
|
for (i = len; i > 0; i--)
|
||||||
|
{
|
||||||
|
// lower allpass filter
|
||||||
|
in32 = (WebRtc_Word32)(*in++) << 10;
|
||||||
|
diff = in32 - state1;
|
||||||
|
tmp1 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass1[0], diff, state0);
|
||||||
|
state0 = in32;
|
||||||
|
diff = tmp1 - state2;
|
||||||
|
tmp2 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass1[1], diff, state1);
|
||||||
|
state1 = tmp1;
|
||||||
|
diff = tmp2 - state3;
|
||||||
|
state3 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass1[2], diff, state2);
|
||||||
|
state2 = tmp2;
|
||||||
|
|
||||||
|
// round; limit amplitude to prevent wrap-around; write to output array
|
||||||
|
out32 = (state3 + 512) >> 10;
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
__asm__("ssat %r0, #16, %r1":"=r"(*out): "r"(out32));
|
||||||
|
out++;
|
||||||
|
#else
|
||||||
|
if (out32 > 32767)
|
||||||
|
*out++ = 32767;
|
||||||
|
else if (out32 < -32768)
|
||||||
|
*out++ = -32768;
|
||||||
|
else
|
||||||
|
*out++ = (WebRtc_Word16)out32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// upper allpass filter
|
||||||
|
diff = in32 - state5;
|
||||||
|
tmp1 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass2[0], diff, state4);
|
||||||
|
state4 = in32;
|
||||||
|
diff = tmp1 - state6;
|
||||||
|
tmp2 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass2[1], diff, state5);
|
||||||
|
state5 = tmp1;
|
||||||
|
diff = tmp2 - state7;
|
||||||
|
state7 = WEBRTC_SPL_SCALEDIFF32(kResampleAllpass2[2], diff, state6);
|
||||||
|
state6 = tmp2;
|
||||||
|
|
||||||
|
// round; limit amplitude to prevent wrap-around; write to output array
|
||||||
|
out32 = (state7 + 512) >> 10;
|
||||||
|
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||||
|
__asm__("ssat %r0, #16, %r1":"=r"(*out): "r"(out32));
|
||||||
|
out++;
|
||||||
|
#else
|
||||||
|
if (out32 > 32767)
|
||||||
|
*out++ = 32767;
|
||||||
|
else if (out32 < -32768)
|
||||||
|
*out++ = -32768;
|
||||||
|
else
|
||||||
|
*out++ = (WebRtc_Word16)out32;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
filtState[0] = state0;
|
||||||
|
filtState[1] = state1;
|
||||||
|
filtState[2] = state2;
|
||||||
|
filtState[3] = state3;
|
||||||
|
filtState[4] = state4;
|
||||||
|
filtState[5] = state5;
|
||||||
|
filtState[6] = state6;
|
||||||
|
filtState[7] = state7;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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_
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
};
|
@ -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,
|
||||||
|
};
|
@ -0,0 +1,73 @@
|
|||||||
|
# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Use of this source code is governed by a BSD-style license
|
||||||
|
# that can be found in the LICENSE file in the root of the source
|
||||||
|
# tree. An additional intellectual property rights grant can be found
|
||||||
|
# in the file PATENTS. All contributing project authors may
|
||||||
|
# be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'spl',
|
||||||
|
'type': '<(library)',
|
||||||
|
'include_dirs': [
|
||||||
|
'../interface',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': [
|
||||||
|
'../interface',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'sources': [
|
||||||
|
'../interface/signal_processing_library.h',
|
||||||
|
'../interface/spl_inl.h',
|
||||||
|
'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',
|
||||||
|
'hanning_table.c',
|
||||||
|
'ilbc_specific_functions.c',
|
||||||
|
'levinson_durbin.c',
|
||||||
|
'lpc_to_refl_coef.c',
|
||||||
|
'min_max_operations.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_sqrt_floor.c',
|
||||||
|
'spl_version.c',
|
||||||
|
'splitting_filter.c',
|
||||||
|
'sqrt_of_one_minus_x_squared.c',
|
||||||
|
'vector_scaling_operations.c',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# tab-width:2
|
||||||
|
# indent-tabs-mode:nil
|
||||||
|
# End:
|
||||||
|
# vim: set expandtab tabstop=2 shiftwidth=2:
|
@ -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;
|
||||||
|
}
|
@ -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 function WebRtcSpl_SqrtFloor().
|
||||||
|
* The description header can be found in signal_processing_library.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
|
||||||
|
#define WEBRTC_SPL_SQRT_ITER(N) \
|
||||||
|
try1 = root + (1 << (N)); \
|
||||||
|
if (value >= try1 << (N)) \
|
||||||
|
{ \
|
||||||
|
value -= try1 << (N); \
|
||||||
|
root |= 2 << (N); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// (out) Square root of input parameter
|
||||||
|
WebRtc_Word32 WebRtcSpl_SqrtFloor(WebRtc_Word32 value)
|
||||||
|
{
|
||||||
|
// new routine for performance, 4 cycles/bit in ARM
|
||||||
|
// output precision is 16 bits
|
||||||
|
|
||||||
|
WebRtc_Word32 root = 0, try1;
|
||||||
|
|
||||||
|
WEBRTC_SPL_SQRT_ITER (15);
|
||||||
|
WEBRTC_SPL_SQRT_ITER (14);
|
||||||
|
WEBRTC_SPL_SQRT_ITER (13);
|
||||||
|
WEBRTC_SPL_SQRT_ITER (12);
|
||||||
|
WEBRTC_SPL_SQRT_ITER (11);
|
||||||
|
WEBRTC_SPL_SQRT_ITER (10);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 9);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 8);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 7);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 6);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 5);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 4);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 3);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 2);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 1);
|
||||||
|
WEBRTC_SPL_SQRT_ITER ( 0);
|
||||||
|
|
||||||
|
return root >> 1;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file contains the function WebRtcSpl_get_version().
|
||||||
|
* The description header can be found in signal_processing_library.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcSpl_get_version(char* version, WebRtc_Word16 length_in_bytes)
|
||||||
|
{
|
||||||
|
strncpy(version, "1.2.0", length_in_bytes);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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 };
|
@ -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 };
|
@ -0,0 +1,494 @@
|
|||||||
|
/*
|
||||||
|
* 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[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(10, WebRtcSpl_SqrtFloor(A));
|
||||||
|
|
||||||
|
|
||||||
|
EXPECT_EQ(-91772805, WebRtcSpl_DivResultInQ31(den, num));
|
||||||
|
EXPECT_EQ(-23, WebRtcSpl_DivW32W16ResW16(num, (WebRtc_Word16)den));
|
||||||
|
EXPECT_EQ(-23, WebRtcSpl_DivW32W16(num, (WebRtc_Word16)den));
|
||||||
|
EXPECT_EQ(23, WebRtcSpl_DivU32U16(num, denU));
|
||||||
|
EXPECT_EQ(0, WebRtcSpl_DivW32HiLow(128, 0, 256));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, BasicArrayOperationsTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
int B[] = {4, 12, 133, 1100};
|
||||||
|
int Bs[] = {2, 6, 66, 550};
|
||||||
|
WebRtc_UWord8 b8[kVectorSize];
|
||||||
|
WebRtc_Word16 b16[kVectorSize];
|
||||||
|
WebRtc_Word32 b32[kVectorSize];
|
||||||
|
|
||||||
|
WebRtc_UWord8 bTmp8[kVectorSize];
|
||||||
|
WebRtc_Word16 bTmp16[kVectorSize];
|
||||||
|
WebRtc_Word32 bTmp32[kVectorSize];
|
||||||
|
|
||||||
|
WebRtcSpl_MemSetW16(b16, 3, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(3, b16[kk]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ(kVectorSize, WebRtcSpl_ZerosArrayW16(b16, kVectorSize));
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(0, b16[kk]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ(kVectorSize, WebRtcSpl_OnesArrayW16(b16, kVectorSize));
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(1, b16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_MemSetW32(b32, 3, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(3, b32[kk]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ(kVectorSize, WebRtcSpl_ZerosArrayW32(b32, kVectorSize));
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(0, b32[kk]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ(kVectorSize, WebRtcSpl_OnesArrayW32(b32, kVectorSize));
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(1, b32[kk]);
|
||||||
|
}
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
bTmp8[kk] = (WebRtc_Word8)kk;
|
||||||
|
bTmp16[kk] = (WebRtc_Word16)kk;
|
||||||
|
bTmp32[kk] = (WebRtc_Word32)kk;
|
||||||
|
}
|
||||||
|
WEBRTC_SPL_MEMCPY_W8(b8, bTmp8, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(b8[kk], bTmp8[kk]);
|
||||||
|
}
|
||||||
|
WEBRTC_SPL_MEMCPY_W16(b16, bTmp16, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(b16[kk], bTmp16[kk]);
|
||||||
|
}
|
||||||
|
// WEBRTC_SPL_MEMCPY_W32(b32, bTmp32, kVectorSize);
|
||||||
|
// for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
// EXPECT_EQ(b32[kk], bTmp32[kk]);
|
||||||
|
// }
|
||||||
|
EXPECT_EQ(2, WebRtcSpl_CopyFromEndW16(b16, kVectorSize, 2, bTmp16));
|
||||||
|
for (int kk = 0; kk < 2; ++kk) {
|
||||||
|
EXPECT_EQ(kk+2, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
b32[kk] = B[kk];
|
||||||
|
b16[kk] = (WebRtc_Word16)B[kk];
|
||||||
|
}
|
||||||
|
WebRtcSpl_VectorBitShiftW32ToW16(bTmp16, kVectorSize, b32, 1);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((B[kk]>>1), bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_VectorBitShiftW16(bTmp16, kVectorSize, b16, 1);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((B[kk]>>1), bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_VectorBitShiftW32(bTmp32, kVectorSize, b32, 1);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((B[kk]>>1), bTmp32[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtcSpl_MemCpyReversedOrder(&bTmp16[3], b16, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(b16[3-kk], bTmp16[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, MinMaxOperationsTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
int B[] = {4, 12, 133, -1100};
|
||||||
|
WebRtc_Word16 b16[kVectorSize];
|
||||||
|
WebRtc_Word32 b32[kVectorSize];
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
b16[kk] = B[kk];
|
||||||
|
b32[kk] = B[kk];
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(1100, WebRtcSpl_MaxAbsValueW16(b16, kVectorSize));
|
||||||
|
EXPECT_EQ(1100, WebRtcSpl_MaxAbsValueW32(b32, kVectorSize));
|
||||||
|
EXPECT_EQ(133, WebRtcSpl_MaxValueW16(b16, kVectorSize));
|
||||||
|
EXPECT_EQ(133, WebRtcSpl_MaxValueW32(b32, kVectorSize));
|
||||||
|
EXPECT_EQ(3, WebRtcSpl_MaxAbsIndexW16(b16, kVectorSize));
|
||||||
|
EXPECT_EQ(2, WebRtcSpl_MaxIndexW16(b16, kVectorSize));
|
||||||
|
EXPECT_EQ(2, WebRtcSpl_MaxIndexW32(b32, kVectorSize));
|
||||||
|
|
||||||
|
EXPECT_EQ(-1100, WebRtcSpl_MinValueW16(b16, kVectorSize));
|
||||||
|
EXPECT_EQ(-1100, WebRtcSpl_MinValueW32(b32, kVectorSize));
|
||||||
|
EXPECT_EQ(3, WebRtcSpl_MinIndexW16(b16, kVectorSize));
|
||||||
|
EXPECT_EQ(3, WebRtcSpl_MinIndexW32(b32, kVectorSize));
|
||||||
|
|
||||||
|
EXPECT_EQ(0, WebRtcSpl_GetScalingSquare(b16, kVectorSize, 1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, VectorOperationsTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
int B[] = {4, 12, 133, 1100};
|
||||||
|
WebRtc_Word16 a16[kVectorSize];
|
||||||
|
WebRtc_Word16 b16[kVectorSize];
|
||||||
|
WebRtc_Word32 b32[kVectorSize];
|
||||||
|
WebRtc_Word16 bTmp16[kVectorSize];
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
a16[kk] = B[kk];
|
||||||
|
b16[kk] = B[kk];
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtcSpl_AffineTransformVector(bTmp16, b16, 3, 7, 2, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((B[kk]*3+7)>>2, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_ScaleAndAddVectorsWithRound(b16, 3, b16, 2, 2, bTmp16, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((B[kk]*3+B[kk]*2+2)>>2, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtcSpl_AddAffineVectorToVector(bTmp16, b16, 3, 7, 2, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(((B[kk]*3+B[kk]*2+2)>>2)+((b16[kk]*3+7)>>2), bTmp16[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtcSpl_CrossCorrelation(b32, b16, bTmp16, kVectorSize, 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, kVectorSize, 2));
|
||||||
|
|
||||||
|
WebRtcSpl_ScaleVector(b16, bTmp16, 13, kVectorSize, 2);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_ScaleVectorWithSat(b16, bTmp16, 13, kVectorSize, 2);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_ScaleAndAddVectors(a16, 13, 2, b16, 7, 2, bTmp16, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(((a16[kk]*13)>>2)+((b16[kk]*7)>>2), bTmp16[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtcSpl_AddVectorsAndShift(bTmp16, a16, b16, kVectorSize, 2);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(B[kk] >> 1, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_ReverseOrderMultArrayElements(bTmp16, a16, &b16[3], kVectorSize, 2);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((a16[kk]*b16[3-kk])>>2, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
WebRtcSpl_ElementwiseVectorMult(bTmp16, a16, b16, kVectorSize, 6);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ((a16[kk]*b16[kk])>>6, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtcSpl_SqrtOfOneMinusXSquared(b16, kVectorSize, bTmp16);
|
||||||
|
for (int kk = 0; kk < kVectorSize - 1; ++kk) {
|
||||||
|
EXPECT_EQ(32767, bTmp16[kk]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ(32749, bTmp16[kVectorSize - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, EstimatorsTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
int B[] = {4, 12, 133, 1100};
|
||||||
|
WebRtc_Word16 b16[kVectorSize];
|
||||||
|
WebRtc_Word32 b32[kVectorSize];
|
||||||
|
WebRtc_Word16 bTmp16[kVectorSize];
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
b16[kk] = B[kk];
|
||||||
|
b32[kk] = B[kk];
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(0, WebRtcSpl_LevinsonDurbin(b32, b16, bTmp16, 2));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, FilterTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
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[kVectorSize];
|
||||||
|
WebRtc_Word16 bTmp16[kVectorSize];
|
||||||
|
WebRtc_Word16 bTmp16Low[kVectorSize];
|
||||||
|
WebRtc_Word16 bState[kVectorSize];
|
||||||
|
WebRtc_Word16 bStateLow[kVectorSize];
|
||||||
|
|
||||||
|
WebRtcSpl_ZerosArrayW16(bState, kVectorSize);
|
||||||
|
WebRtcSpl_ZerosArrayW16(bStateLow, kVectorSize);
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
b16[kk] = A[kk];
|
||||||
|
}
|
||||||
|
|
||||||
|
// MA filters
|
||||||
|
WebRtcSpl_FilterMAFastQ12(b16, bTmp16, B, kVectorSize, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
//EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
|
||||||
|
}
|
||||||
|
// AR filters
|
||||||
|
WebRtcSpl_FilterARFastQ12(b16, bTmp16, A, kVectorSize, kVectorSize);
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
// EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ(kVectorSize, WebRtcSpl_FilterAR(A5,
|
||||||
|
5,
|
||||||
|
b16,
|
||||||
|
kVectorSize,
|
||||||
|
bState,
|
||||||
|
kVectorSize,
|
||||||
|
bStateLow,
|
||||||
|
kVectorSize,
|
||||||
|
bTmp16,
|
||||||
|
bTmp16Low,
|
||||||
|
kVectorSize));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, RandTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
WebRtc_Word16 BU[] = {3653, 12446, 8525, 30691};
|
||||||
|
WebRtc_Word16 BN[] = {3459, -11689, -258, -3738};
|
||||||
|
WebRtc_Word16 b16[kVectorSize];
|
||||||
|
WebRtc_UWord32 bSeed = 100000;
|
||||||
|
|
||||||
|
EXPECT_EQ(464449057, WebRtcSpl_IncreaseSeed(&bSeed));
|
||||||
|
EXPECT_EQ(31565, WebRtcSpl_RandU(&bSeed));
|
||||||
|
EXPECT_EQ(-9786, WebRtcSpl_RandN(&bSeed));
|
||||||
|
EXPECT_EQ(kVectorSize, WebRtcSpl_RandUArray(b16, kVectorSize, &bSeed));
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
EXPECT_EQ(BU[kk], b16[kk]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, SignalProcessingTest) {
|
||||||
|
|
||||||
|
|
||||||
|
const int kVectorSize = 4;
|
||||||
|
int A[] = {1, 2, 33, 100};
|
||||||
|
WebRtc_Word16 b16[kVectorSize];
|
||||||
|
WebRtc_Word32 b32[kVectorSize];
|
||||||
|
|
||||||
|
WebRtc_Word16 bTmp16[kVectorSize];
|
||||||
|
WebRtc_Word32 bTmp32[kVectorSize];
|
||||||
|
|
||||||
|
int bScale = 0;
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
b16[kk] = A[kk];
|
||||||
|
b32[kk] = A[kk];
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(2, WebRtcSpl_AutoCorrelation(b16, kVectorSize, 1, bTmp32, &bScale));
|
||||||
|
WebRtcSpl_ReflCoefToLpc(b16, kVectorSize, bTmp16);
|
||||||
|
// for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
// EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
|
||||||
|
// }
|
||||||
|
WebRtcSpl_LpcToReflCoef(bTmp16, kVectorSize, b16);
|
||||||
|
// for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
// EXPECT_EQ(a16[kk], b16[kk]);
|
||||||
|
// }
|
||||||
|
WebRtcSpl_AutoCorrToReflCoef(b32, kVectorSize, bTmp16);
|
||||||
|
// for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
// EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
|
||||||
|
// }
|
||||||
|
WebRtcSpl_GetHanningWindow(bTmp16, kVectorSize);
|
||||||
|
// for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
// EXPECT_EQ(aTmp16[kk], bTmp16[kk]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (int kk = 0; kk < kVectorSize; ++kk) {
|
||||||
|
b16[kk] = A[kk];
|
||||||
|
}
|
||||||
|
EXPECT_EQ(11094 , WebRtcSpl_Energy(b16, kVectorSize, &bScale));
|
||||||
|
EXPECT_EQ(0, bScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SplTest, FFTTest) {
|
||||||
|
|
||||||
|
|
||||||
|
WebRtc_Word16 B[] = {1, 2, 33, 100,
|
||||||
|
2, 3, 34, 101,
|
||||||
|
3, 4, 35, 102,
|
||||||
|
4, 5, 36, 103};
|
||||||
|
|
||||||
|
EXPECT_EQ(0, WebRtcSpl_ComplexFFT(B, 3, 1));
|
||||||
|
// for (int kk = 0; kk < 16; ++kk) {
|
||||||
|
// EXPECT_EQ(A[kk], B[kk]);
|
||||||
|
// }
|
||||||
|
EXPECT_EQ(0, WebRtcSpl_ComplexIFFT(B, 3, 1));
|
||||||
|
// for (int kk = 0; kk < 16; ++kk) {
|
||||||
|
// EXPECT_EQ(A[kk], B[kk]);
|
||||||
|
// }
|
||||||
|
WebRtcSpl_ComplexBitReverse(B, 3);
|
||||||
|
for (int kk = 0; kk < 16; ++kk) {
|
||||||
|
//EXPECT_EQ(A[kk], B[kk]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
SplEnvironment* env = new SplEnvironment;
|
||||||
|
::testing::AddGlobalTestEnvironment(env);
|
||||||
|
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
@ -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 <gtest/gtest.h>
|
||||||
|
|
||||||
|
class SplTest: public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
SplTest();
|
||||||
|
virtual void SetUp();
|
||||||
|
virtual void TearDown();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBRTC_SPL_UNIT_TEST_H_
|
2
src/common_audio/vad/OWNERS
Normal file
2
src/common_audio/vad/OWNERS
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bjornv@webrtc.org
|
||||||
|
jan.skoglund@webrtc.org
|
159
src/common_audio/vad/main/interface/webrtc_vad.h
Normal file
159
src/common_audio/vad/main/interface/webrtc_vad.h
Normal file
@ -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_bytes : Size of the buffer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
WebRtc_Word16 WebRtcVad_get_version(char *version, size_t size_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_
|
48
src/common_audio/vad/main/source/vad.gypi
Normal file
48
src/common_audio/vad/main/source/vad.gypi
Normal file
@ -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.
|
||||||
|
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'vad',
|
||||||
|
'type': '<(library)',
|
||||||
|
'dependencies': [
|
||||||
|
'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:
|
80
src/common_audio/vad/main/source/vad_const.c
Normal file
80
src/common_audio/vad/main/source/vad_const.c
Normal file
@ -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};
|
59
src/common_audio/vad/main/source/vad_const.h
Normal file
59
src/common_audio/vad/main/source/vad_const.h
Normal file
@ -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 header file includes the declarations of the internally used constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_VAD_CONST_H_
|
||||||
|
#define WEBRTC_VAD_CONST_H_
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
// TODO(ajm): give these internal-linkage by moving to the appropriate file
|
||||||
|
// where possible, and otherwise tag with WebRtcVad_.
|
||||||
|
|
||||||
|
// Spectrum Weighting
|
||||||
|
extern const WebRtc_Word16 kSpectrumWeight[];
|
||||||
|
extern const WebRtc_Word16 kCompVar;
|
||||||
|
// Logarithm constant
|
||||||
|
extern const WebRtc_Word16 kLogConst;
|
||||||
|
extern const WebRtc_Word16 kLog10Const;
|
||||||
|
// Q15
|
||||||
|
extern const WebRtc_Word16 kNoiseUpdateConst;
|
||||||
|
extern const WebRtc_Word16 kSpeechUpdateConst;
|
||||||
|
// Q8
|
||||||
|
extern const WebRtc_Word16 kBackEta;
|
||||||
|
// Coefficients used by WebRtcVad_HpOutput, Q14
|
||||||
|
extern const WebRtc_Word16 kHpZeroCoefs[];
|
||||||
|
extern const WebRtc_Word16 kHpPoleCoefs[];
|
||||||
|
// Allpass filter coefficients, upper and lower, in Q15 resp. Q13
|
||||||
|
extern const WebRtc_Word16 kAllPassCoefsQ15[];
|
||||||
|
extern const WebRtc_Word16 kAllPassCoefsQ13[];
|
||||||
|
// Minimum difference between the two models, Q5
|
||||||
|
extern const WebRtc_Word16 kMinimumDifference[];
|
||||||
|
// Maximum value when updating the speech model, Q7
|
||||||
|
extern const WebRtc_Word16 kMaximumSpeech[];
|
||||||
|
// Minimum value for mean value
|
||||||
|
extern const WebRtc_Word16 kMinimumMean[];
|
||||||
|
// Upper limit of mean value for noise model, Q7
|
||||||
|
extern const WebRtc_Word16 kMaximumNoise[];
|
||||||
|
// Adjustment for division with two in WebRtcVad_SplitFilter
|
||||||
|
extern const WebRtc_Word16 kOffsetVector[];
|
||||||
|
// Start values for the Gaussian models, Q7
|
||||||
|
extern const WebRtc_Word16 kNoiseDataWeights[];
|
||||||
|
extern const WebRtc_Word16 kSpeechDataWeights[];
|
||||||
|
extern const WebRtc_Word16 kNoiseDataMeans[];
|
||||||
|
extern const WebRtc_Word16 kSpeechDataMeans[];
|
||||||
|
extern const WebRtc_Word16 kNoiseDataStds[];
|
||||||
|
extern const WebRtc_Word16 kSpeechDataStds[];
|
||||||
|
|
||||||
|
#endif // WEBRTC_VAD_CONST_H_
|
685
src/common_audio/vad/main/source/vad_core.c
Normal file
685
src/common_audio/vad/main/source/vad_core.c
Normal file
@ -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;
|
||||||
|
}
|
132
src/common_audio/vad/main/source/vad_core.h
Normal file
132
src/common_audio/vad/main/source/vad_core.h
Normal file
@ -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_
|
95
src/common_audio/vad/main/source/vad_defines.h
Normal file
95
src/common_audio/vad/main/source/vad_defines.h
Normal file
@ -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_
|
267
src/common_audio/vad/main/source/vad_filterbank.c
Normal file
267
src/common_audio/vad/main/source/vad_filterbank.c
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
143
src/common_audio/vad/main/source/vad_filterbank.h
Normal file
143
src/common_audio/vad/main/source/vad_filterbank.h
Normal file
@ -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_
|
70
src/common_audio/vad/main/source/vad_gmm.c
Normal file
70
src/common_audio/vad/main/source/vad_gmm.c
Normal file
@ -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
|
||||||
|
}
|
47
src/common_audio/vad/main/source/vad_gmm.h
Normal file
47
src/common_audio/vad/main/source/vad_gmm.h
Normal file
@ -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_
|
231
src/common_audio/vad/main/source/vad_sp.c
Normal file
231
src/common_audio/vad/main/source/vad_sp.c
Normal file
@ -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];
|
||||||
|
}
|
60
src/common_audio/vad/main/source/vad_sp.h
Normal file
60
src/common_audio/vad/main/source/vad_sp.h
Normal file
@ -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_
|
197
src/common_audio/vad/main/source/webrtc_vad.c
Normal file
197
src/common_audio/vad/main/source/webrtc_vad.c
Normal file
@ -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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "webrtc_vad.h"
|
||||||
|
#include "vad_core.h"
|
||||||
|
|
||||||
|
static const int kInitCheck = 42;
|
||||||
|
|
||||||
|
WebRtc_Word16 WebRtcVad_get_version(char *version, size_t size_bytes)
|
||||||
|
{
|
||||||
|
const char my_version[] = "VAD 1.2.0";
|
||||||
|
|
||||||
|
if (version == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size_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;
|
||||||
|
}
|
||||||
|
}
|
123
src/common_audio/vad/main/test/unit_test/unit_test.cc
Normal file
123
src/common_audio/vad/main/test/unit_test/unit_test.cc
Normal file
@ -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 <cstring>
|
||||||
|
#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();
|
||||||
|
}
|
28
src/common_audio/vad/main/test/unit_test/unit_test.h
Normal file
28
src/common_audio/vad/main/test/unit_test/unit_test.h
Normal file
@ -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 <gtest/gtest.h>
|
||||||
|
|
||||||
|
class VadTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
VadTest();
|
||||||
|
virtual void SetUp();
|
||||||
|
virtual void TearDown();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBRTC_VAD_UNIT_TEST_H_
|
595
src/common_types.h
Normal file
595
src/common_types.h
Normal file
@ -0,0 +1,595 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_COMMON_TYPES_H
|
||||||
|
#define WEBRTC_COMMON_TYPES_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#ifdef WEBRTC_EXPORT
|
||||||
|
#define WEBRTC_DLLEXPORT _declspec(dllexport)
|
||||||
|
#elif WEBRTC_DLL
|
||||||
|
#define WEBRTC_DLLEXPORT _declspec(dllimport)
|
||||||
|
#else
|
||||||
|
#define WEBRTC_DLLEXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class InStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int Read(void *buf,int len) = 0;
|
||||||
|
virtual int Rewind() {return -1;}
|
||||||
|
virtual ~InStream() {}
|
||||||
|
protected:
|
||||||
|
InStream() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OutStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool Write(const void *buf,int len) = 0;
|
||||||
|
virtual int Rewind() {return -1;}
|
||||||
|
virtual ~OutStream() {}
|
||||||
|
protected:
|
||||||
|
OutStream() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TraceModule
|
||||||
|
{
|
||||||
|
// not a module, triggered from the engine code
|
||||||
|
kTraceVoice = 0x0001,
|
||||||
|
// not a module, triggered from the engine code
|
||||||
|
kTraceVideo = 0x0002,
|
||||||
|
// not a module, triggered from the utility code
|
||||||
|
kTraceUtility = 0x0003,
|
||||||
|
kTraceRtpRtcp = 0x0004,
|
||||||
|
kTraceTransport = 0x0005,
|
||||||
|
kTraceSrtp = 0x0006,
|
||||||
|
kTraceAudioCoding = 0x0007,
|
||||||
|
kTraceAudioMixerServer = 0x0008,
|
||||||
|
kTraceAudioMixerClient = 0x0009,
|
||||||
|
kTraceFile = 0x000a,
|
||||||
|
kTraceAudioProcessing = 0x000b,
|
||||||
|
kTraceVideoCoding = 0x0010,
|
||||||
|
kTraceVideoMixer = 0x0011,
|
||||||
|
kTraceAudioDevice = 0x0012,
|
||||||
|
kTraceVideoRenderer = 0x0014,
|
||||||
|
kTraceVideoCapture = 0x0015,
|
||||||
|
kTraceVideoPreocessing = 0x0016
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TraceLevel
|
||||||
|
{
|
||||||
|
kTraceNone = 0x0000, // no trace
|
||||||
|
kTraceStateInfo = 0x0001,
|
||||||
|
kTraceWarning = 0x0002,
|
||||||
|
kTraceError = 0x0004,
|
||||||
|
kTraceCritical = 0x0008,
|
||||||
|
kTraceApiCall = 0x0010,
|
||||||
|
kTraceDefault = 0x00ff,
|
||||||
|
|
||||||
|
kTraceModuleCall = 0x0020,
|
||||||
|
kTraceMemory = 0x0100, // memory info
|
||||||
|
kTraceTimer = 0x0200, // timing info
|
||||||
|
kTraceStream = 0x0400, // "continuous" stream of data
|
||||||
|
|
||||||
|
// used for debug purposes
|
||||||
|
kTraceDebug = 0x0800, // debug
|
||||||
|
kTraceInfo = 0x1000, // debug info
|
||||||
|
|
||||||
|
kTraceAll = 0xffff
|
||||||
|
};
|
||||||
|
|
||||||
|
// External Trace API
|
||||||
|
class TraceCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Print(const TraceLevel level,
|
||||||
|
const char *traceString,
|
||||||
|
const int length) = 0;
|
||||||
|
protected:
|
||||||
|
virtual ~TraceCallback() {}
|
||||||
|
TraceCallback() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum FileFormats
|
||||||
|
{
|
||||||
|
kFileFormatWavFile = 1,
|
||||||
|
kFileFormatCompressedFile = 2,
|
||||||
|
kFileFormatAviFile = 3,
|
||||||
|
kFileFormatPreencodedFile = 4,
|
||||||
|
kFileFormatPcm16kHzFile = 7,
|
||||||
|
kFileFormatPcm8kHzFile = 8,
|
||||||
|
kFileFormatPcm32kHzFile = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum ProcessingTypes
|
||||||
|
{
|
||||||
|
kPlaybackPerChannel = 0,
|
||||||
|
kPlaybackAllChannelsMixed,
|
||||||
|
kRecordingPerChannel,
|
||||||
|
kRecordingAllChannelsMixed
|
||||||
|
};
|
||||||
|
|
||||||
|
// Encryption enums
|
||||||
|
enum CipherTypes
|
||||||
|
{
|
||||||
|
kCipherNull = 0,
|
||||||
|
kCipherAes128CounterMode = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AuthenticationTypes
|
||||||
|
{
|
||||||
|
kAuthNull = 0,
|
||||||
|
kAuthHmacSha1 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SecurityLevels
|
||||||
|
{
|
||||||
|
kNoProtection = 0,
|
||||||
|
kEncryption = 1,
|
||||||
|
kAuthentication = 2,
|
||||||
|
kEncryptionAndAuthentication = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
class Encryption
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void encrypt(
|
||||||
|
int channel_no,
|
||||||
|
unsigned char* in_data,
|
||||||
|
unsigned char* out_data,
|
||||||
|
int bytes_in,
|
||||||
|
int* bytes_out) = 0;
|
||||||
|
|
||||||
|
virtual void decrypt(
|
||||||
|
int channel_no,
|
||||||
|
unsigned char* in_data,
|
||||||
|
unsigned char* out_data,
|
||||||
|
int bytes_in,
|
||||||
|
int* bytes_out) = 0;
|
||||||
|
|
||||||
|
virtual void encrypt_rtcp(
|
||||||
|
int channel_no,
|
||||||
|
unsigned char* in_data,
|
||||||
|
unsigned char* out_data,
|
||||||
|
int bytes_in,
|
||||||
|
int* bytes_out) = 0;
|
||||||
|
|
||||||
|
virtual void decrypt_rtcp(
|
||||||
|
int channel_no,
|
||||||
|
unsigned char* in_data,
|
||||||
|
unsigned char* out_data,
|
||||||
|
int bytes_in,
|
||||||
|
int* bytes_out) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~Encryption() {}
|
||||||
|
Encryption() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// External transport callback interface
|
||||||
|
class Transport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int SendPacket(int channel, const void *data, int len) = 0;
|
||||||
|
virtual int SendRTCPPacket(int channel, const void *data, int len) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~Transport() {}
|
||||||
|
Transport() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================================================================
|
||||||
|
// Voice specific types
|
||||||
|
// ==================================================================
|
||||||
|
|
||||||
|
// Each codec supported can be described by this structure.
|
||||||
|
struct CodecInst
|
||||||
|
{
|
||||||
|
int pltype;
|
||||||
|
char plname[32];
|
||||||
|
int plfreq;
|
||||||
|
int pacsize;
|
||||||
|
int channels;
|
||||||
|
int rate;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FrameType
|
||||||
|
{
|
||||||
|
kFrameEmpty = 0,
|
||||||
|
kAudioFrameSpeech = 1,
|
||||||
|
kAudioFrameCN = 2,
|
||||||
|
kVideoFrameKey = 3, // independent frame
|
||||||
|
kVideoFrameDelta = 4, // depends on the previus frame
|
||||||
|
kVideoFrameGolden = 5, // depends on a old known previus frame
|
||||||
|
kVideoFrameAltRef = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
// RTP
|
||||||
|
enum {kRtpCsrcSize = 15}; // RFC 3550 page 13
|
||||||
|
|
||||||
|
enum RTPDirections
|
||||||
|
{
|
||||||
|
kRtpIncoming = 0,
|
||||||
|
kRtpOutgoing
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PayloadFrequencies
|
||||||
|
{
|
||||||
|
kFreq8000Hz = 8000,
|
||||||
|
kFreq16000Hz = 16000,
|
||||||
|
kFreq32000Hz = 32000
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VadModes // degree of bandwidth reduction
|
||||||
|
{
|
||||||
|
kVadConventional = 0, // lowest reduction
|
||||||
|
kVadAggressiveLow,
|
||||||
|
kVadAggressiveMid,
|
||||||
|
kVadAggressiveHigh // highest reduction
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetworkStatistics // NETEQ statistics
|
||||||
|
{
|
||||||
|
// current jitter buffer size in ms
|
||||||
|
WebRtc_UWord16 currentBufferSize;
|
||||||
|
// preferred (optimal) buffer size in ms
|
||||||
|
WebRtc_UWord16 preferredBufferSize;
|
||||||
|
// loss rate (network + late) in percent (in Q14)
|
||||||
|
WebRtc_UWord16 currentPacketLossRate;
|
||||||
|
// late loss rate in percent (in Q14)
|
||||||
|
WebRtc_UWord16 currentDiscardRate;
|
||||||
|
// fraction (of original stream) of synthesized speech inserted through
|
||||||
|
// expansion (in Q14)
|
||||||
|
WebRtc_UWord16 currentExpandRate;
|
||||||
|
// fraction of synthesized speech inserted through pre-emptive expansion
|
||||||
|
// (in Q14)
|
||||||
|
WebRtc_UWord16 currentPreemptiveRate;
|
||||||
|
// fraction of data removed through acceleration (in Q14)
|
||||||
|
WebRtc_UWord16 currentAccelerateRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JitterStatistics
|
||||||
|
{
|
||||||
|
// smallest Jitter Buffer size during call in ms
|
||||||
|
WebRtc_UWord32 jbMinSize;
|
||||||
|
// largest Jitter Buffer size during call in ms
|
||||||
|
WebRtc_UWord32 jbMaxSize;
|
||||||
|
// the average JB size, measured over time - ms
|
||||||
|
WebRtc_UWord32 jbAvgSize;
|
||||||
|
// number of times the Jitter Buffer changed (using Accelerate or
|
||||||
|
// Pre-emptive Expand)
|
||||||
|
WebRtc_UWord32 jbChangeCount;
|
||||||
|
// amount (in ms) of audio data received late
|
||||||
|
WebRtc_UWord32 lateLossMs;
|
||||||
|
// milliseconds removed to reduce jitter buffer size
|
||||||
|
WebRtc_UWord32 accelerateMs;
|
||||||
|
// milliseconds discarded through buffer flushing
|
||||||
|
WebRtc_UWord32 flushedMs;
|
||||||
|
// milliseconds of generated silence
|
||||||
|
WebRtc_UWord32 generatedSilentMs;
|
||||||
|
// milliseconds of synthetic audio data (non-background noise)
|
||||||
|
WebRtc_UWord32 interpolatedVoiceMs;
|
||||||
|
// milliseconds of synthetic audio data (background noise level)
|
||||||
|
WebRtc_UWord32 interpolatedSilentMs;
|
||||||
|
// count of tiny expansions in output audio
|
||||||
|
WebRtc_UWord32 countExpandMoreThan120ms;
|
||||||
|
// count of small expansions in output audio
|
||||||
|
WebRtc_UWord32 countExpandMoreThan250ms;
|
||||||
|
// count of medium expansions in output audio
|
||||||
|
WebRtc_UWord32 countExpandMoreThan500ms;
|
||||||
|
// count of long expansions in output audio
|
||||||
|
WebRtc_UWord32 countExpandMoreThan2000ms;
|
||||||
|
// duration of longest audio drop-out
|
||||||
|
WebRtc_UWord32 longestExpandDurationMs;
|
||||||
|
// count of times we got small network outage (inter-arrival time in
|
||||||
|
// [500, 1000) ms)
|
||||||
|
WebRtc_UWord32 countIAT500ms;
|
||||||
|
// count of times we got medium network outage (inter-arrival time in
|
||||||
|
// [1000, 2000) ms)
|
||||||
|
WebRtc_UWord32 countIAT1000ms;
|
||||||
|
// count of times we got large network outage (inter-arrival time >=
|
||||||
|
// 2000 ms)
|
||||||
|
WebRtc_UWord32 countIAT2000ms;
|
||||||
|
// longest packet inter-arrival time in ms
|
||||||
|
WebRtc_UWord32 longestIATms;
|
||||||
|
// min time incoming Packet "waited" to be played
|
||||||
|
WebRtc_UWord32 minPacketDelayMs;
|
||||||
|
// max time incoming Packet "waited" to be played
|
||||||
|
WebRtc_UWord32 maxPacketDelayMs;
|
||||||
|
// avg time incoming Packet "waited" to be played
|
||||||
|
WebRtc_UWord32 avgPacketDelayMs;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int min; // minumum
|
||||||
|
int max; // maximum
|
||||||
|
int average; // average
|
||||||
|
} StatVal;
|
||||||
|
|
||||||
|
typedef struct // All levels are reported in dBm0
|
||||||
|
{
|
||||||
|
StatVal speech_rx; // long-term speech levels on receiving side
|
||||||
|
StatVal speech_tx; // long-term speech levels on transmitting side
|
||||||
|
StatVal noise_rx; // long-term noise/silence levels on receiving side
|
||||||
|
StatVal noise_tx; // long-term noise/silence levels on transmitting side
|
||||||
|
} LevelStatistics;
|
||||||
|
|
||||||
|
typedef struct // All levels are reported in dB
|
||||||
|
{
|
||||||
|
StatVal erl; // Echo Return Loss
|
||||||
|
StatVal erle; // Echo Return Loss Enhancement
|
||||||
|
StatVal rerl; // RERL = ERL + ERLE
|
||||||
|
// Echo suppression inside EC at the point just before its NLP
|
||||||
|
StatVal a_nlp;
|
||||||
|
} EchoStatistics;
|
||||||
|
|
||||||
|
enum TelephoneEventDetectionMethods
|
||||||
|
{
|
||||||
|
kInBand = 0,
|
||||||
|
kOutOfBand = 1,
|
||||||
|
kInAndOutOfBand = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NsModes // type of Noise Suppression
|
||||||
|
{
|
||||||
|
kNsUnchanged = 0, // previously set mode
|
||||||
|
kNsDefault, // platform default
|
||||||
|
kNsConference, // conferencing default
|
||||||
|
kNsLowSuppression, // lowest suppression
|
||||||
|
kNsModerateSuppression,
|
||||||
|
kNsHighSuppression,
|
||||||
|
kNsVeryHighSuppression, // highest suppression
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AgcModes // type of Automatic Gain Control
|
||||||
|
{
|
||||||
|
kAgcUnchanged = 0, // previously set mode
|
||||||
|
kAgcDefault, // platform default
|
||||||
|
// adaptive mode for use when analog volume control exists (e.g. for
|
||||||
|
// PC softphone)
|
||||||
|
kAgcAdaptiveAnalog,
|
||||||
|
// scaling takes place in the digital domain (e.g. for conference servers
|
||||||
|
// and embedded devices)
|
||||||
|
kAgcAdaptiveDigital,
|
||||||
|
// can be used on embedded devices where the the capture signal is level
|
||||||
|
// is predictable
|
||||||
|
kAgcFixedDigital
|
||||||
|
};
|
||||||
|
|
||||||
|
// EC modes
|
||||||
|
enum EcModes // type of Echo Control
|
||||||
|
{
|
||||||
|
kEcUnchanged = 0, // previously set mode
|
||||||
|
kEcDefault, // platform default
|
||||||
|
kEcConference, // conferencing default (aggressive AEC)
|
||||||
|
kEcAec, // Acoustic Echo Cancellation
|
||||||
|
kEcAecm, // AEC mobile
|
||||||
|
};
|
||||||
|
|
||||||
|
// AECM modes
|
||||||
|
enum AecmModes // mode of AECM
|
||||||
|
{
|
||||||
|
kAecmQuietEarpieceOrHeadset = 0,
|
||||||
|
// Quiet earpiece or headset use
|
||||||
|
kAecmEarpiece, // most earpiece use
|
||||||
|
kAecmLoudEarpiece, // Loud earpiece or quiet speakerphone use
|
||||||
|
kAecmSpeakerphone, // most speakerphone use (default)
|
||||||
|
kAecmLoudSpeakerphone // Loud speakerphone
|
||||||
|
};
|
||||||
|
|
||||||
|
// AGC configuration
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short targetLeveldBOv;
|
||||||
|
unsigned short digitalCompressionGaindB;
|
||||||
|
bool limiterEnable;
|
||||||
|
} AgcConfig; // AGC configuration parameters
|
||||||
|
|
||||||
|
enum StereoChannel
|
||||||
|
{
|
||||||
|
kStereoLeft = 0,
|
||||||
|
kStereoRight,
|
||||||
|
kStereoBoth
|
||||||
|
};
|
||||||
|
|
||||||
|
// Audio device layers
|
||||||
|
enum AudioLayers
|
||||||
|
{
|
||||||
|
kAudioPlatformDefault = 0,
|
||||||
|
kAudioWindowsWave = 1,
|
||||||
|
kAudioWindowsCore = 2,
|
||||||
|
kAudioLinuxAlsa = 3,
|
||||||
|
kAudioLinuxPulse = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NetEqModes // NetEQ playout configurations
|
||||||
|
{
|
||||||
|
// Optimized trade-off between low delay and jitter robustness for two-way
|
||||||
|
// communication.
|
||||||
|
kNetEqDefault = 0,
|
||||||
|
// Improved jitter robustness at the cost of increased delay. Can be
|
||||||
|
// used in one-way communication.
|
||||||
|
kNetEqStreaming = 1,
|
||||||
|
// Optimzed for decodability of fax signals rather than for perceived audio
|
||||||
|
// quality.
|
||||||
|
kNetEqFax = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NetEqBgnModes // NetEQ Background Noise (BGN) configurations
|
||||||
|
{
|
||||||
|
// BGN is always on and will be generated when the incoming RTP stream
|
||||||
|
// stops (default).
|
||||||
|
kBgnOn = 0,
|
||||||
|
// The BGN is faded to zero (complete silence) after a few seconds.
|
||||||
|
kBgnFade = 1,
|
||||||
|
// BGN is not used at all. Silence is produced after speech extrapolation
|
||||||
|
// has faded.
|
||||||
|
kBgnOff = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OnHoldModes // On Hold direction
|
||||||
|
{
|
||||||
|
kHoldSendAndPlay = 0, // Put both sending and playing in on-hold state.
|
||||||
|
kHoldSendOnly, // Put only sending in on-hold state.
|
||||||
|
kHoldPlayOnly // Put only playing in on-hold state.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AmrMode
|
||||||
|
{
|
||||||
|
kRfc3267BwEfficient = 0,
|
||||||
|
kRfc3267OctetAligned = 1,
|
||||||
|
kRfc3267FileStorage = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================================================================
|
||||||
|
// Video specific types
|
||||||
|
// ==================================================================
|
||||||
|
|
||||||
|
// Raw video types
|
||||||
|
enum RawVideoType
|
||||||
|
{
|
||||||
|
kVideoI420 = 0,
|
||||||
|
kVideoYV12 = 1,
|
||||||
|
kVideoYUY2 = 2,
|
||||||
|
kVideoUYVY = 3,
|
||||||
|
kVideoIYUV = 4,
|
||||||
|
kVideoARGB = 5,
|
||||||
|
kVideoRGB24 = 6,
|
||||||
|
kVideoRGB565 = 7,
|
||||||
|
kVideoARGB4444 = 8,
|
||||||
|
kVideoARGB1555 = 9,
|
||||||
|
kVideoMJPEG = 10,
|
||||||
|
kVideoNV12 = 11,
|
||||||
|
kVideoNV21 = 12,
|
||||||
|
kVideoUnknown = 99
|
||||||
|
};
|
||||||
|
|
||||||
|
// Video codec
|
||||||
|
enum { kConfigParameterSize = 128};
|
||||||
|
enum { kPayloadNameSize = 32};
|
||||||
|
|
||||||
|
// H.263 specific
|
||||||
|
struct VideoCodecH263
|
||||||
|
{
|
||||||
|
char quality;
|
||||||
|
};
|
||||||
|
|
||||||
|
// H.264 specific
|
||||||
|
enum H264Packetization
|
||||||
|
{
|
||||||
|
kH264SingleMode = 0,
|
||||||
|
kH264NonInterleavedMode = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VideoCodecComplexity
|
||||||
|
{
|
||||||
|
kComplexityNormal = 0,
|
||||||
|
kComplexityHigh = 1,
|
||||||
|
kComplexityHigher = 2,
|
||||||
|
kComplexityMax = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VideoCodecProfile
|
||||||
|
{
|
||||||
|
kProfileBase = 0x00,
|
||||||
|
kProfileMain = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VideoCodecH264
|
||||||
|
{
|
||||||
|
H264Packetization packetization;
|
||||||
|
VideoCodecComplexity complexity;
|
||||||
|
VideoCodecProfile profile;
|
||||||
|
char level;
|
||||||
|
char quality;
|
||||||
|
|
||||||
|
bool useFMO;
|
||||||
|
|
||||||
|
unsigned char configParameters[kConfigParameterSize];
|
||||||
|
unsigned char configParametersSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
// VP8 specific
|
||||||
|
struct VideoCodecVP8
|
||||||
|
{
|
||||||
|
bool pictureLossIndicationOn;
|
||||||
|
bool feedbackModeOn;
|
||||||
|
VideoCodecComplexity complexity;
|
||||||
|
};
|
||||||
|
|
||||||
|
// MPEG-4 specific
|
||||||
|
struct VideoCodecMPEG4
|
||||||
|
{
|
||||||
|
unsigned char configParameters[kConfigParameterSize];
|
||||||
|
unsigned char configParametersSize;
|
||||||
|
char level;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unknown specific
|
||||||
|
struct VideoCodecGeneric
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// Video codec types
|
||||||
|
enum VideoCodecType
|
||||||
|
{
|
||||||
|
kVideoCodecH263,
|
||||||
|
kVideoCodecH264,
|
||||||
|
kVideoCodecVP8,
|
||||||
|
kVideoCodecMPEG4,
|
||||||
|
kVideoCodecI420,
|
||||||
|
kVideoCodecRED,
|
||||||
|
kVideoCodecULPFEC,
|
||||||
|
kVideoCodecUnknown
|
||||||
|
};
|
||||||
|
|
||||||
|
union VideoCodecUnion
|
||||||
|
{
|
||||||
|
VideoCodecH263 H263;
|
||||||
|
VideoCodecH264 H264;
|
||||||
|
VideoCodecVP8 VP8;
|
||||||
|
VideoCodecMPEG4 MPEG4;
|
||||||
|
VideoCodecGeneric Generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Common video codec properties
|
||||||
|
struct VideoCodec
|
||||||
|
{
|
||||||
|
VideoCodecType codecType;
|
||||||
|
char plName[kPayloadNameSize];
|
||||||
|
unsigned char plType;
|
||||||
|
|
||||||
|
unsigned short width;
|
||||||
|
unsigned short height;
|
||||||
|
|
||||||
|
unsigned int startBitrate;
|
||||||
|
unsigned int maxBitrate;
|
||||||
|
unsigned int minBitrate;
|
||||||
|
unsigned char maxFramerate;
|
||||||
|
|
||||||
|
VideoCodecUnion codecSpecific;
|
||||||
|
|
||||||
|
unsigned int qpMax;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // WEBRTC_COMMON_TYPES_H
|
2
src/modules/audio_processing/OWNERS
Normal file
2
src/modules/audio_processing/OWNERS
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
andrew@webrtc.org
|
||||||
|
bjornv@webrtc.org
|
@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_INTERFACE_ECHO_CANCELLATION_H_
|
||||||
|
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_INTERFACE_ECHO_CANCELLATION_H_
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
#define AEC_UNSPECIFIED_ERROR 12000
|
||||||
|
#define AEC_UNSUPPORTED_FUNCTION_ERROR 12001
|
||||||
|
#define AEC_UNINITIALIZED_ERROR 12002
|
||||||
|
#define AEC_NULL_POINTER_ERROR 12003
|
||||||
|
#define AEC_BAD_PARAMETER_ERROR 12004
|
||||||
|
|
||||||
|
// Warnings
|
||||||
|
#define AEC_BAD_PARAMETER_WARNING 12050
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kAecNlpConservative = 0,
|
||||||
|
kAecNlpModerate,
|
||||||
|
kAecNlpAggressive
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kAecFalse = 0,
|
||||||
|
kAecTrue
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WebRtc_Word16 nlpMode; // default kAecNlpModerate
|
||||||
|
WebRtc_Word16 skewMode; // default kAecFalse
|
||||||
|
WebRtc_Word16 metricsMode; // default kAecFalse
|
||||||
|
//float realSkew;
|
||||||
|
} AecConfig;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WebRtc_Word16 instant;
|
||||||
|
WebRtc_Word16 average;
|
||||||
|
WebRtc_Word16 max;
|
||||||
|
WebRtc_Word16 min;
|
||||||
|
} AecLevel;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AecLevel rerl;
|
||||||
|
AecLevel erl;
|
||||||
|
AecLevel erle;
|
||||||
|
AecLevel aNlp;
|
||||||
|
} AecMetrics;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocates the memory needed by the AEC. The memory needs to be initialized
|
||||||
|
* separately using the WebRtcAec_Init() function.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void **aecInst Pointer to the AEC instance to be created
|
||||||
|
* and initilized
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_Create(void **aecInst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function releases the memory allocated by WebRtcAec_Create().
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_Free(void *aecInst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes an AEC instance.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
* WebRtc_Word32 sampFreq Sampling frequency of data
|
||||||
|
* WebRtc_Word32 scSampFreq Soundcard sampling frequency
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_Init(void *aecInst,
|
||||||
|
WebRtc_Word32 sampFreq,
|
||||||
|
WebRtc_Word32 scSampFreq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inserts an 80 or 160 sample block of data into the farend buffer.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
* WebRtc_Word16 *farend In buffer containing one frame of
|
||||||
|
* farend signal for L band
|
||||||
|
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst,
|
||||||
|
const WebRtc_Word16 *farend,
|
||||||
|
WebRtc_Word16 nrOfSamples);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runs the echo canceller on an 80 or 160 sample blocks of data.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
* WebRtc_Word16 *nearend In buffer containing one frame of
|
||||||
|
* nearend+echo signal for L band
|
||||||
|
* WebRtc_Word16 *nearendH In buffer containing one frame of
|
||||||
|
* nearend+echo signal for H band
|
||||||
|
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
|
||||||
|
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
|
||||||
|
* system buffers
|
||||||
|
* WebRtc_Word16 skew Difference between number of samples played
|
||||||
|
* and recorded at the soundcard (for clock skew
|
||||||
|
* compensation)
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
|
||||||
|
* for L band
|
||||||
|
* WebRtc_Word16 *outH Out buffer, one frame of processed nearend
|
||||||
|
* for H band
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_Process(void *aecInst,
|
||||||
|
const WebRtc_Word16 *nearend,
|
||||||
|
const WebRtc_Word16 *nearendH,
|
||||||
|
WebRtc_Word16 *out,
|
||||||
|
WebRtc_Word16 *outH,
|
||||||
|
WebRtc_Word16 nrOfSamples,
|
||||||
|
WebRtc_Word16 msInSndCardBuf,
|
||||||
|
WebRtc_Word32 skew);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function enables the user to set certain parameters on-the-fly.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
* AecConfig config Config instance that contains all
|
||||||
|
* properties to be set
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the on-the-fly paramters.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* AecConfig *config Pointer to the config instance that
|
||||||
|
* all properties will be written to
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the current echo status of the nearend signal.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word16 *status 0: Almost certainly nearend single-talk
|
||||||
|
* 1: Might not be neared single-talk
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the current echo metrics for the session.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* AecMetrics *metrics Struct which will be filled out with the
|
||||||
|
* current echo metrics.
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the last error code.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecInst Pointer to the AEC instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 11000-11100: error code
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets a version string.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* char *versionStr Pointer to a string array
|
||||||
|
* WebRtc_Word16 len The maximum length of the string
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word8 *versionStr Pointer to a string array
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_INTERFACE_ECHO_CANCELLATION_H_ */
|
953
src/modules/audio_processing/aec/main/matlab/fullaec.m
Normal file
953
src/modules/audio_processing/aec/main/matlab/fullaec.m
Normal file
@ -0,0 +1,953 @@
|
|||||||
|
% Partitioned block frequency domain adaptive filtering NLMS and
|
||||||
|
% standard time-domain sample-based NLMS
|
||||||
|
%fid=fopen('aecFar-samsung.pcm', 'rb'); % Load far end
|
||||||
|
fid=fopen('aecFar.pcm', 'rb'); % Load far end
|
||||||
|
%fid=fopen(farFile, 'rb'); % Load far end
|
||||||
|
rrin=fread(fid,inf,'int16');
|
||||||
|
fclose(fid);
|
||||||
|
%rrin=loadsl('data/far_me2.pcm'); % Load far end
|
||||||
|
%fid=fopen('aecNear-samsung.pcm', 'rb'); % Load near end
|
||||||
|
fid=fopen('aecNear.pcm', 'rb'); % Load near end
|
||||||
|
%fid=fopen(nearFile, 'rb'); % Load near end
|
||||||
|
ssin=fread(fid,inf,'int16');
|
||||||
|
%ssin = [zeros(1024,1) ; ssin(1:end-1024)];
|
||||||
|
|
||||||
|
fclose(fid);
|
||||||
|
rand('state',13);
|
||||||
|
fs=16000;
|
||||||
|
mult=fs/8000;
|
||||||
|
%rrin=rrin(fs*0+1:round(fs*120));
|
||||||
|
%ssin=ssin(fs*0+1:round(fs*120));
|
||||||
|
if fs == 8000
|
||||||
|
cohRange = 2:3;
|
||||||
|
elseif fs==16000
|
||||||
|
cohRange = 2;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Flags
|
||||||
|
NLPon=1; % NLP
|
||||||
|
CNon=1; % Comfort noise
|
||||||
|
PLTon=1; % Plotting
|
||||||
|
|
||||||
|
M = 16; % Number of partitions
|
||||||
|
N = 64; % Partition length
|
||||||
|
L = M*N; % Filter length
|
||||||
|
if fs == 8000
|
||||||
|
mufb = 0.6;
|
||||||
|
else
|
||||||
|
mufb = 0.5;
|
||||||
|
end
|
||||||
|
%mufb=1;
|
||||||
|
VADtd=48;
|
||||||
|
alp = 0.1; % Power estimation factor alc = 0.1; % Coherence estimation factor
|
||||||
|
beta = 0.9; % Plotting factor
|
||||||
|
%% Changed a little %%
|
||||||
|
step = 0.3;%0.1875; % Downward step size
|
||||||
|
%%
|
||||||
|
if fs == 8000
|
||||||
|
threshold=2e-6; % DTrob threshold
|
||||||
|
else
|
||||||
|
%threshold=0.7e-6;
|
||||||
|
threshold=1.5e-6; end
|
||||||
|
|
||||||
|
if fs == 8000
|
||||||
|
echoBandRange = ceil(300*2/fs*N):floor(1800*2/fs*N);
|
||||||
|
%echoBandRange = ceil(1500*2/fs*N):floor(2500*2/fs*N);
|
||||||
|
else
|
||||||
|
echoBandRange = ceil(300*2/fs*N):floor(1800*2/fs*N);
|
||||||
|
%echoBandRange = ceil(300*2/fs*N):floor(1800*2/fs*N);
|
||||||
|
end
|
||||||
|
%echoBandRange = ceil(1600*2/fs*N):floor(1900*2/fs*N);
|
||||||
|
%echoBandRange = ceil(2000*2/fs*N):floor(4000*2/fs*N);
|
||||||
|
suppState = 1;
|
||||||
|
transCtr = 0;
|
||||||
|
|
||||||
|
Nt=1;
|
||||||
|
vt=1;
|
||||||
|
|
||||||
|
ramp = 1.0003; % Upward ramp
|
||||||
|
rampd = 0.999; % Downward ramp
|
||||||
|
cvt = 20; % Subband VAD threshold;
|
||||||
|
nnthres = 20; % Noise threshold
|
||||||
|
|
||||||
|
shh=logspace(-1.3,-2.2,N+1)';
|
||||||
|
sh=[shh;flipud(shh(2:end-1))]; % Suppression profile
|
||||||
|
|
||||||
|
len=length(ssin);
|
||||||
|
w=zeros(L,1); % Sample-based TD NLMS
|
||||||
|
WFb=zeros(N+1,M); % Block-based FD NLMS
|
||||||
|
WFbOld=zeros(N+1,M); % Block-based FD NLMS
|
||||||
|
YFb=zeros(N+1,M);
|
||||||
|
erfb=zeros(len,1);
|
||||||
|
erfb3=zeros(len,1);
|
||||||
|
|
||||||
|
ercn=zeros(len,1);
|
||||||
|
zm=zeros(N,1);
|
||||||
|
XFm=zeros(N+1,M);
|
||||||
|
YFm=zeros(N+1,M);
|
||||||
|
pn0=10*ones(N+1,1);
|
||||||
|
pn=zeros(N+1,1);
|
||||||
|
NN=len;
|
||||||
|
Nb=floor(NN/N)-M;
|
||||||
|
erifb=zeros(Nb+1,1)+0.1;
|
||||||
|
erifb3=zeros(Nb+1,1)+0.1;
|
||||||
|
ericn=zeros(Nb+1,1)+0.1;
|
||||||
|
dri=zeros(Nb+1,1)+0.1;
|
||||||
|
start=1;
|
||||||
|
xo=zeros(N,1);
|
||||||
|
do=xo;
|
||||||
|
eo=xo;
|
||||||
|
|
||||||
|
echoBands=zeros(Nb+1,1);
|
||||||
|
cohxdAvg=zeros(Nb+1,1);
|
||||||
|
cohxdSlow=zeros(Nb+1,N+1);
|
||||||
|
cohedSlow=zeros(Nb+1,N+1);
|
||||||
|
%overdriveM=zeros(Nb+1,N+1);
|
||||||
|
cohxdFastAvg=zeros(Nb+1,1);
|
||||||
|
cohxdAvgBad=zeros(Nb+1,1);
|
||||||
|
cohedAvg=zeros(Nb+1,1);
|
||||||
|
cohedFastAvg=zeros(Nb+1,1);
|
||||||
|
hnledAvg=zeros(Nb+1,1);
|
||||||
|
hnlxdAvg=zeros(Nb+1,1);
|
||||||
|
ovrdV=zeros(Nb+1,1);
|
||||||
|
dIdxV=zeros(Nb+1,1);
|
||||||
|
SLxV=zeros(Nb+1,1);
|
||||||
|
hnlSortQV=zeros(Nb+1,1);
|
||||||
|
hnlPrefAvgV=zeros(Nb+1,1);
|
||||||
|
mutInfAvg=zeros(Nb+1,1);
|
||||||
|
%overdrive=zeros(Nb+1,1);
|
||||||
|
hnled = zeros(N+1, 1);
|
||||||
|
weight=zeros(N+1,1);
|
||||||
|
hnlMax = zeros(N+1, 1);
|
||||||
|
hnl = zeros(N+1, 1);
|
||||||
|
overdrive = ones(1, N+1);
|
||||||
|
xfwm=zeros(N+1,M);
|
||||||
|
dfm=zeros(N+1,M);
|
||||||
|
WFbD=ones(N+1,1);
|
||||||
|
|
||||||
|
fbSupp = 0;
|
||||||
|
hnlLocalMin = 1;
|
||||||
|
cohxdLocalMin = 1;
|
||||||
|
hnlLocalMinV=zeros(Nb+1,1);
|
||||||
|
cohxdLocalMinV=zeros(Nb+1,1);
|
||||||
|
hnlMinV=zeros(Nb+1,1);
|
||||||
|
dkEnV=zeros(Nb+1,1);
|
||||||
|
ekEnV=zeros(Nb+1,1);
|
||||||
|
ovrd = 2;
|
||||||
|
ovrdPos = floor((N+1)/4);
|
||||||
|
ovrdSm = 2;
|
||||||
|
hnlMin = 1;
|
||||||
|
minCtr = 0;
|
||||||
|
SeMin = 0;
|
||||||
|
SdMin = 0;
|
||||||
|
SeLocalAvg = 0;
|
||||||
|
SeMinSm = 0;
|
||||||
|
divergeFact = 1;
|
||||||
|
dIdx = 1;
|
||||||
|
hnlMinCtr = 0;
|
||||||
|
hnlNewMin = 0;
|
||||||
|
divergeState = 0;
|
||||||
|
|
||||||
|
Sy=ones(N+1,1);
|
||||||
|
Sym=1e7*ones(N+1,1);
|
||||||
|
|
||||||
|
wins=[0;sqrt(hanning(2*N-1))];
|
||||||
|
ubufn=zeros(2*N,1);
|
||||||
|
ebuf=zeros(2*N,1);
|
||||||
|
ebuf2=zeros(2*N,1);
|
||||||
|
ebuf4=zeros(2*N,1);
|
||||||
|
mbuf=zeros(2*N,1);
|
||||||
|
|
||||||
|
cohedFast = zeros(N+1,1);
|
||||||
|
cohxdFast = zeros(N+1,1);
|
||||||
|
cohxd = zeros(N+1,1);
|
||||||
|
Se = zeros(N+1,1);
|
||||||
|
Sd = zeros(N+1,1);
|
||||||
|
Sx = zeros(N+1,1);
|
||||||
|
SxBad = zeros(N+1,1);
|
||||||
|
Sed = zeros(N+1,1);
|
||||||
|
Sxd = zeros(N+1,1);
|
||||||
|
SxdBad = zeros(N+1,1);
|
||||||
|
hnledp=[];
|
||||||
|
|
||||||
|
cohxdMax = 0;
|
||||||
|
|
||||||
|
%hh=waitbar(0,'Please wait...');
|
||||||
|
progressbar(0);
|
||||||
|
|
||||||
|
%spaces = ' ';
|
||||||
|
%spaces = repmat(spaces, 50, 1);
|
||||||
|
%spaces = ['[' ; spaces ; ']'];
|
||||||
|
%fprintf(1, spaces);
|
||||||
|
%fprintf(1, '\n');
|
||||||
|
|
||||||
|
for kk=1:Nb
|
||||||
|
pos = N * (kk-1) + start;
|
||||||
|
|
||||||
|
% FD block method
|
||||||
|
% ---------------------- Organize data
|
||||||
|
xk = rrin(pos:pos+N-1);
|
||||||
|
dk = ssin(pos:pos+N-1);
|
||||||
|
|
||||||
|
xx = [xo;xk];
|
||||||
|
xo = xk;
|
||||||
|
tmp = fft(xx);
|
||||||
|
XX = tmp(1:N+1);
|
||||||
|
|
||||||
|
dd = [do;dk]; % Overlap
|
||||||
|
do = dk;
|
||||||
|
tmp = fft(dd); % Frequency domain
|
||||||
|
DD = tmp(1:N+1);
|
||||||
|
|
||||||
|
% ------------------------ Power estimation
|
||||||
|
pn0 = (1 - alp) * pn0 + alp * real(XX.* conj(XX));
|
||||||
|
pn = pn0;
|
||||||
|
%pn = (1 - alp) * pn + alp * M * pn0;
|
||||||
|
if (CNon)
|
||||||
|
Yp = real(conj(DD).*DD); % Instantaneous power
|
||||||
|
Sy = (1 - alp) * Sy + alp * Yp; % Averaged power
|
||||||
|
|
||||||
|
mm = min(Sy,Sym);
|
||||||
|
diff = Sym - mm;
|
||||||
|
if (kk>50)
|
||||||
|
Sym = (mm + step*diff) * ramp; % Estimated background noise power
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% ---------------------- Filtering
|
||||||
|
XFm(:,1) = XX;
|
||||||
|
for mm=0:(M-1)
|
||||||
|
m=mm+1;
|
||||||
|
YFb(:,m) = XFm(:,m) .* WFb(:,m);
|
||||||
|
end
|
||||||
|
yfk = sum(YFb,2);
|
||||||
|
tmp = [yfk ; flipud(conj(yfk(2:N)))];
|
||||||
|
ykt = real(ifft(tmp));
|
||||||
|
ykfb = ykt(end-N+1:end);
|
||||||
|
|
||||||
|
% ---------------------- Error estimation
|
||||||
|
ekfb = dk - ykfb;
|
||||||
|
%if sum(abs(ekfb)) < sum(abs(dk))
|
||||||
|
%ekfb = dk - ykfb;
|
||||||
|
% erfb(pos:pos+N-1) = ekfb;
|
||||||
|
%else
|
||||||
|
%ekfb = dk;
|
||||||
|
% erfb(pos:pos+N-1) = dk;
|
||||||
|
%end
|
||||||
|
%(kk-1)*(N*2)+1
|
||||||
|
erfb(pos:pos+N-1) = ekfb;
|
||||||
|
tmp = fft([zm;ekfb]); % FD version for cancelling part (overlap-save)
|
||||||
|
Ek = tmp(1:N+1);
|
||||||
|
|
||||||
|
% ------------------------ Adaptation
|
||||||
|
Ek2 = Ek ./(M*pn + 0.001); % Normalized error
|
||||||
|
%Ek2 = Ek ./(pn + 0.001); % Normalized error
|
||||||
|
%Ek2 = Ek ./(100*pn + 0.001); % Normalized error
|
||||||
|
|
||||||
|
absEf = max(abs(Ek2), threshold);
|
||||||
|
absEf = ones(N+1,1)*threshold./absEf;
|
||||||
|
Ek2 = Ek2.*absEf;
|
||||||
|
|
||||||
|
mEk = mufb.*Ek2;
|
||||||
|
PP = conj(XFm).*(ones(M,1) * mEk')';
|
||||||
|
tmp = [PP ; flipud(conj(PP(2:N,:)))];
|
||||||
|
IFPP = real(ifft(tmp));
|
||||||
|
PH = IFPP(1:N,:);
|
||||||
|
tmp = fft([PH;zeros(N,M)]);
|
||||||
|
FPH = tmp(1:N+1,:);
|
||||||
|
WFb = WFb + FPH;
|
||||||
|
|
||||||
|
if mod(kk, 10*mult) == 0
|
||||||
|
WFbEn = sum(real(WFb.*conj(WFb)));
|
||||||
|
%WFbEn = sum(abs(WFb));
|
||||||
|
[tmp, dIdx] = max(WFbEn);
|
||||||
|
|
||||||
|
WFbD = sum(abs(WFb(:, dIdx)),2);
|
||||||
|
%WFbD = WFbD / (mean(WFbD) + 1e-10);
|
||||||
|
WFbD = min(max(WFbD, 0.5), 4);
|
||||||
|
end
|
||||||
|
dIdxV(kk) = dIdx;
|
||||||
|
|
||||||
|
% NLP
|
||||||
|
if (NLPon)
|
||||||
|
|
||||||
|
ee = [eo;ekfb];
|
||||||
|
eo = ekfb;
|
||||||
|
window = wins;
|
||||||
|
if fs == 8000
|
||||||
|
%gamma = 0.88;
|
||||||
|
gamma = 0.9;
|
||||||
|
else
|
||||||
|
%gamma = 0.92;
|
||||||
|
gamma = 0.93;
|
||||||
|
end
|
||||||
|
%gamma = 0.9;
|
||||||
|
|
||||||
|
tmp = fft(xx.*window);
|
||||||
|
xf = tmp(1:N+1);
|
||||||
|
tmp = fft(dd.*window);
|
||||||
|
df = tmp(1:N+1);
|
||||||
|
tmp = fft(ee.*window);
|
||||||
|
ef = tmp(1:N+1);
|
||||||
|
|
||||||
|
xfwm(:,1) = xf;
|
||||||
|
xf = xfwm(:,dIdx);
|
||||||
|
%fprintf(1,'%d: %f\n', kk, xf(4));
|
||||||
|
dfm(:,1) = df;
|
||||||
|
|
||||||
|
SxOld = Sx;
|
||||||
|
|
||||||
|
Se = gamma*Se + (1-gamma)*real(ef.*conj(ef));
|
||||||
|
Sd = gamma*Sd + (1-gamma)*real(df.*conj(df));
|
||||||
|
Sx = gamma*Sx + (1 - gamma)*real(xf.*conj(xf));
|
||||||
|
|
||||||
|
%xRatio = real(xfwm(:,1).*conj(xfwm(:,1))) ./ ...
|
||||||
|
% (real(xfwm(:,2).*conj(xfwm(:,2))) + 1e-10);
|
||||||
|
%xRatio = Sx ./ (SxOld + 1e-10);
|
||||||
|
%SLx = log(1/(N+1)*sum(xRatio)) - 1/(N+1)*sum(log(xRatio));
|
||||||
|
%SLxV(kk) = SLx;
|
||||||
|
|
||||||
|
%freqSm = 0.9;
|
||||||
|
%Sx = filter(freqSm, [1 -(1-freqSm)], Sx);
|
||||||
|
%Sx(end:1) = filter(freqSm, [1 -(1-freqSm)], Sx(end:1));
|
||||||
|
%Se = filter(freqSm, [1 -(1-freqSm)], Se);
|
||||||
|
%Se(end:1) = filter(freqSm, [1 -(1-freqSm)], Se(end:1));
|
||||||
|
%Sd = filter(freqSm, [1 -(1-freqSm)], Sd);
|
||||||
|
%Sd(end:1) = filter(freqSm, [1 -(1-freqSm)], Sd(end:1));
|
||||||
|
|
||||||
|
%SeFast = ef.*conj(ef);
|
||||||
|
%SdFast = df.*conj(df);
|
||||||
|
%SxFast = xf.*conj(xf);
|
||||||
|
%cohedFast = 0.9*cohedFast + 0.1*SeFast ./ (SdFast + 1e-10);
|
||||||
|
%cohedFast(find(cohedFast > 1)) = 1;
|
||||||
|
%cohedFast(find(cohedFast > 1)) = 1 ./ cohedFast(find(cohedFast>1));
|
||||||
|
%cohedFastAvg(kk) = mean(cohedFast(echoBandRange));
|
||||||
|
%cohedFastAvg(kk) = min(cohedFast);
|
||||||
|
|
||||||
|
%cohxdFast = 0.8*cohxdFast + 0.2*log(SdFast ./ (SxFast + 1e-10));
|
||||||
|
%cohxdFastAvg(kk) = mean(cohxdFast(echoBandRange));
|
||||||
|
|
||||||
|
% coherence
|
||||||
|
Sxd = gamma*Sxd + (1 - gamma)*xf.*conj(df);
|
||||||
|
Sed = gamma*Sed + (1-gamma)*ef.*conj(df);
|
||||||
|
|
||||||
|
%Sxd = filter(freqSm, [1 -(1-freqSm)], Sxd);
|
||||||
|
%Sxd(end:1) = filter(freqSm, [1 -(1-freqSm)], Sxd(end:1));
|
||||||
|
%Sed = filter(freqSm, [1 -(1-freqSm)], Sed);
|
||||||
|
%Sed(end:1) = filter(freqSm, [1 -(1-freqSm)], Sed(end:1));
|
||||||
|
|
||||||
|
cohed = real(Sed.*conj(Sed))./(Se.*Sd + 1e-10);
|
||||||
|
%cohedAvg(kk) = mean(cohed(echoBandRange));
|
||||||
|
%cohedAvg(kk) = cohed(6);
|
||||||
|
%cohedAvg(kk) = min(cohed);
|
||||||
|
|
||||||
|
cohxd = real(Sxd.*conj(Sxd))./(Sx.*Sd + 1e-10);
|
||||||
|
%freqSm = 0.5;
|
||||||
|
%cohxd(3:end) = filter(freqSm, [1 -(1-freqSm)], cohxd(3:end));
|
||||||
|
%cohxd(end:3) = filter(freqSm, [1 -(1-freqSm)], cohxd(end:3));
|
||||||
|
%cohxdAvg(kk) = mean(cohxd(echoBandRange));
|
||||||
|
%cohxdAvg(kk) = (cohxd(32));
|
||||||
|
%cohxdAvg(kk) = max(cohxd);
|
||||||
|
|
||||||
|
%xf = xfm(:,dIdx);
|
||||||
|
%SxBad = gamma*SxBad + (1 - gamma)*real(xf.*conj(xf));
|
||||||
|
%SxdBad = gamma*SxdBad + (1 - gamma)*xf.*conj(df);
|
||||||
|
%cohxdBad = real(SxdBad.*conj(SxdBad))./(SxBad.*Sd + 0.01);
|
||||||
|
%cohxdAvgBad(kk) = mean(cohxdBad);
|
||||||
|
|
||||||
|
%for j=1:N+1
|
||||||
|
% mutInf(j) = 0.9*mutInf(j) + 0.1*information(abs(xfm(j,:)), abs(dfm(j,:)));
|
||||||
|
%end
|
||||||
|
%mutInfAvg(kk) = mean(mutInf);
|
||||||
|
|
||||||
|
%hnled = cohedFast;
|
||||||
|
%xIdx = find(cohxd > 1 - cohed);
|
||||||
|
%hnled(xIdx) = 1 - cohxd(xIdx);
|
||||||
|
%hnled = 1 - max(cohxd, 1-cohedFast);
|
||||||
|
hnled = min(1 - cohxd, cohed);
|
||||||
|
%hnled = 1 - cohxd;
|
||||||
|
%hnled = max(1 - (cohxd + (1-cohedFast)), 0);
|
||||||
|
%hnled = 1 - max(cohxd, 1-cohed);
|
||||||
|
|
||||||
|
if kk > 1
|
||||||
|
cohxdSlow(kk,:) = 0.99*cohxdSlow(kk-1,:) + 0.01*cohxd';
|
||||||
|
cohedSlow(kk,:) = 0.99*cohedSlow(kk-1,:) + 0.01*(1-cohed)';
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if 0
|
||||||
|
%if kk > 50
|
||||||
|
%idx = find(hnled > 0.3);
|
||||||
|
hnlMax = hnlMax*0.9999;
|
||||||
|
%hnlMax(idx) = max(hnlMax(idx), hnled(idx));
|
||||||
|
hnlMax = max(hnlMax, hnled);
|
||||||
|
%overdrive(idx) = max(log(hnlMax(idx))/log(0.99), 1);
|
||||||
|
avgHnl = mean(hnlMax(echoBandRange));
|
||||||
|
if avgHnl > 0.3
|
||||||
|
overdrive = max(log(avgHnl)/log(0.99), 1);
|
||||||
|
end
|
||||||
|
weight(4:end) = max(hnlMax) - hnlMax(4:end);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%[hg, gidx] = max(hnled);
|
||||||
|
%fnrg = Sx(gidx) / (Sd(gidx) + 1e-10);
|
||||||
|
|
||||||
|
%[tmp, bidx] = find((Sx / Sd + 1e-10) > fnrg);
|
||||||
|
%hnled(bidx) = hg;
|
||||||
|
|
||||||
|
|
||||||
|
%cohed1 = mean(cohed(cohRange)); % range depends on bandwidth
|
||||||
|
%cohed1 = cohed1^2;
|
||||||
|
%echoBands(kk) = length(find(cohed(echoBandRange) < 0.25))/length(echoBandRange);
|
||||||
|
|
||||||
|
%if (fbSupp == 0)
|
||||||
|
% if (echoBands(kk) > 0.8)
|
||||||
|
% fbSupp = 1;
|
||||||
|
% end
|
||||||
|
%else
|
||||||
|
% if (echoBands(kk) < 0.6)
|
||||||
|
% fbSupp = 0;
|
||||||
|
% end
|
||||||
|
%end
|
||||||
|
%overdrive(kk) = 7.5*echoBands(kk) + 0.5;
|
||||||
|
|
||||||
|
% Factor by which to weight other bands
|
||||||
|
%if (cohed1 < 0.1)
|
||||||
|
% w = 0.8 - cohed1*10*0.4;
|
||||||
|
%else
|
||||||
|
% w = 0.4;
|
||||||
|
%end
|
||||||
|
|
||||||
|
% Weight coherence subbands
|
||||||
|
%hnled = w*cohed1 + (1 - w)*cohed;
|
||||||
|
%hnled = (hnled).^2;
|
||||||
|
%cohed(floor(N/2):end) = cohed(floor(N/2):end).^2;
|
||||||
|
%if fbSupp == 1
|
||||||
|
% cohed = zeros(size(cohed));
|
||||||
|
%end
|
||||||
|
%cohed = cohed.^overdrive(kk);
|
||||||
|
|
||||||
|
%hnled = gamma*hnled + (1 - gamma)*cohed;
|
||||||
|
% Additional hf suppression
|
||||||
|
%hnledp = [hnledp ; mean(hnled)];
|
||||||
|
%hnled(floor(N/2):end) = hnled(floor(N/2):end).^2;
|
||||||
|
%ef = ef.*((weight*(min(1 - hnled)).^2 + (1 - weight).*(1 - hnled)).^2);
|
||||||
|
|
||||||
|
cohedMean = mean(cohed(echoBandRange));
|
||||||
|
%aggrFact = 4*(1-mean(hnled(echoBandRange))) + 1;
|
||||||
|
%[hnlSort, hnlSortIdx] = sort(hnled(echoBandRange));
|
||||||
|
[hnlSort, hnlSortIdx] = sort(1-cohxd(echoBandRange));
|
||||||
|
[xSort, xSortIdx] = sort(Sx);
|
||||||
|
%aggrFact = (1-mean(hnled(echoBandRange)));
|
||||||
|
%hnlSortQ = hnlSort(qIdx);
|
||||||
|
hnlSortQ = mean(1 - cohxd(echoBandRange));
|
||||||
|
%hnlSortQ = mean(1 - cohxd);
|
||||||
|
|
||||||
|
[hnlSort2, hnlSortIdx2] = sort(hnled(echoBandRange));
|
||||||
|
%[hnlSort2, hnlSortIdx2] = sort(hnled);
|
||||||
|
hnlQuant = 0.75;
|
||||||
|
hnlQuantLow = 0.5;
|
||||||
|
qIdx = floor(hnlQuant*length(hnlSort2));
|
||||||
|
qIdxLow = floor(hnlQuantLow*length(hnlSort2));
|
||||||
|
hnlPrefAvg = hnlSort2(qIdx);
|
||||||
|
hnlPrefAvgLow = hnlSort2(qIdxLow);
|
||||||
|
%hnlPrefAvgLow = mean(hnled);
|
||||||
|
%hnlPrefAvg = max(hnlSort2);
|
||||||
|
%hnlPrefAvgLow = min(hnlSort2);
|
||||||
|
|
||||||
|
%hnlPref = hnled(echoBandRange);
|
||||||
|
%hnlPrefAvg = mean(hnlPref(xSortIdx((0.5*length(xSortIdx)):end)));
|
||||||
|
|
||||||
|
%hnlPrefAvg = min(hnlPrefAvg, hnlSortQ);
|
||||||
|
|
||||||
|
%hnlSortQIdx = hnlSortIdx(qIdx);
|
||||||
|
%SeQ = Se(qIdx + echoBandRange(1) - 1);
|
||||||
|
%SdQ = Sd(qIdx + echoBandRange(1) - 1);
|
||||||
|
%SeQ = Se(qIdxLow + echoBandRange(1) - 1);
|
||||||
|
%SdQ = Sd(qIdxLow + echoBandRange(1) - 1);
|
||||||
|
%propLow = length(find(hnlSort < 0.1))/length(hnlSort);
|
||||||
|
%aggrFact = min((1 - hnlSortQ)/2, 0.5);
|
||||||
|
%aggrTerm = 1/aggrFact;
|
||||||
|
|
||||||
|
%hnlg = mean(hnled(echoBandRange));
|
||||||
|
%hnlg = hnlSortQ;
|
||||||
|
%if suppState == 0
|
||||||
|
% if hnlg < 0.05
|
||||||
|
% suppState = 2;
|
||||||
|
% transCtr = 0;
|
||||||
|
% elseif hnlg < 0.75
|
||||||
|
% suppState = 1;
|
||||||
|
% transCtr = 0;
|
||||||
|
% end
|
||||||
|
%elseif suppState == 1
|
||||||
|
% if hnlg > 0.8
|
||||||
|
% suppState = 0;
|
||||||
|
% transCtr = 0;
|
||||||
|
% elseif hnlg < 0.05
|
||||||
|
% suppState = 2;
|
||||||
|
% transCtr = 0;
|
||||||
|
% end
|
||||||
|
%else
|
||||||
|
% if hnlg > 0.8
|
||||||
|
% suppState = 0;
|
||||||
|
% transCtr = 0;
|
||||||
|
% elseif hnlg > 0.25
|
||||||
|
% suppState = 1;
|
||||||
|
% transCtr = 0;
|
||||||
|
% end
|
||||||
|
%end
|
||||||
|
%if kk > 50
|
||||||
|
|
||||||
|
if cohedMean > 0.98 & hnlSortQ > 0.9
|
||||||
|
%if suppState == 1
|
||||||
|
% hnled = 0.5*hnled + 0.5*cohed;
|
||||||
|
% %hnlSortQ = 0.5*hnlSortQ + 0.5*cohedMean;
|
||||||
|
% hnlPrefAvg = 0.5*hnlPrefAvg + 0.5*cohedMean;
|
||||||
|
%else
|
||||||
|
% hnled = cohed;
|
||||||
|
% %hnlSortQ = cohedMean;
|
||||||
|
% hnlPrefAvg = cohedMean;
|
||||||
|
%end
|
||||||
|
suppState = 0;
|
||||||
|
elseif cohedMean < 0.95 | hnlSortQ < 0.8
|
||||||
|
%if suppState == 0
|
||||||
|
% hnled = 0.5*hnled + 0.5*cohed;
|
||||||
|
% %hnlSortQ = 0.5*hnlSortQ + 0.5*cohedMean;
|
||||||
|
% hnlPrefAvg = 0.5*hnlPrefAvg + 0.5*cohedMean;
|
||||||
|
%end
|
||||||
|
suppState = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if hnlSortQ < cohxdLocalMin & hnlSortQ < 0.75
|
||||||
|
cohxdLocalMin = hnlSortQ;
|
||||||
|
end
|
||||||
|
|
||||||
|
if cohxdLocalMin == 1
|
||||||
|
ovrd = 3;
|
||||||
|
hnled = 1-cohxd;
|
||||||
|
hnlPrefAvg = hnlSortQ;
|
||||||
|
hnlPrefAvgLow = hnlSortQ;
|
||||||
|
end
|
||||||
|
|
||||||
|
if suppState == 0
|
||||||
|
hnled = cohed;
|
||||||
|
hnlPrefAvg = cohedMean;
|
||||||
|
hnlPrefAvgLow = cohedMean;
|
||||||
|
end
|
||||||
|
|
||||||
|
%if hnlPrefAvg < hnlLocalMin & hnlPrefAvg < 0.6
|
||||||
|
if hnlPrefAvgLow < hnlLocalMin & hnlPrefAvgLow < 0.6
|
||||||
|
%hnlLocalMin = hnlPrefAvg;
|
||||||
|
%hnlMin = hnlPrefAvg;
|
||||||
|
hnlLocalMin = hnlPrefAvgLow;
|
||||||
|
hnlMin = hnlPrefAvgLow;
|
||||||
|
hnlNewMin = 1;
|
||||||
|
hnlMinCtr = 0;
|
||||||
|
%if hnlMinCtr == 0
|
||||||
|
% hnlMinCtr = hnlMinCtr + 1;
|
||||||
|
%else
|
||||||
|
% hnlMinCtr = 0;
|
||||||
|
% hnlMin = hnlLocalMin;
|
||||||
|
%SeLocalMin = SeQ;
|
||||||
|
%SdLocalMin = SdQ;
|
||||||
|
%SeLocalAvg = 0;
|
||||||
|
%minCtr = 0;
|
||||||
|
% ovrd = max(log(0.0001)/log(hnlMin), 2);
|
||||||
|
%divergeFact = hnlLocalMin;
|
||||||
|
end
|
||||||
|
|
||||||
|
if hnlNewMin == 1
|
||||||
|
hnlMinCtr = hnlMinCtr + 1;
|
||||||
|
end
|
||||||
|
if hnlMinCtr == 2
|
||||||
|
hnlNewMin = 0;
|
||||||
|
hnlMinCtr = 0;
|
||||||
|
%ovrd = max(log(0.0001)/log(hnlMin), 2);
|
||||||
|
ovrd = max(log(0.00001)/(log(hnlMin + 1e-10) + 1e-10), 3);
|
||||||
|
%ovrd = max(log(0.00000001)/(log(hnlMin + 1e-10) + 1e-10), 5);
|
||||||
|
%ovrd = max(log(0.0001)/log(hnlPrefAvg), 2);
|
||||||
|
%ovrd = max(log(0.001)/log(hnlMin), 2);
|
||||||
|
end
|
||||||
|
hnlLocalMin = min(hnlLocalMin + 0.0008/mult, 1);
|
||||||
|
cohxdLocalMin = min(cohxdLocalMin + 0.0004/mult, 1);
|
||||||
|
%divergeFact = hnlSortQ;
|
||||||
|
|
||||||
|
|
||||||
|
%if minCtr > 0 & hnlLocalMin < 1
|
||||||
|
% hnlMin = hnlLocalMin;
|
||||||
|
% %SeMin = 0.9*SeMin + 0.1*sqrt(SeLocalMin);
|
||||||
|
% SdMin = sqrt(SdLocalMin);
|
||||||
|
% %SeMin = sqrt(SeLocalMin)*hnlSortQ;
|
||||||
|
% SeMin = sqrt(SeLocalMin);
|
||||||
|
% %ovrd = log(100/SeMin)/log(hnlSortQ);
|
||||||
|
% %ovrd = log(100/SeMin)/log(hnlSortQ);
|
||||||
|
% ovrd = log(0.01)/log(hnlMin);
|
||||||
|
% ovrd = max(ovrd, 2);
|
||||||
|
% ovrdPos = hnlSortQIdx;
|
||||||
|
% %ovrd = max(ovrd, 1);
|
||||||
|
% %SeMin = sqrt(SeLocalAvg/5);
|
||||||
|
% minCtr = 0;
|
||||||
|
%else
|
||||||
|
% %SeLocalMin = 0.9*SeLocalMin +0.1*SeQ;
|
||||||
|
% SeLocalAvg = SeLocalAvg + SeQ;
|
||||||
|
% minCtr = minCtr + 1;
|
||||||
|
%end
|
||||||
|
|
||||||
|
if ovrd < ovrdSm
|
||||||
|
ovrdSm = 0.99*ovrdSm + 0.01*ovrd;
|
||||||
|
else
|
||||||
|
ovrdSm = 0.9*ovrdSm + 0.1*ovrd;
|
||||||
|
end
|
||||||
|
%end
|
||||||
|
|
||||||
|
%ekEn = sum(real(ekfb.^2));
|
||||||
|
%dkEn = sum(real(dk.^2));
|
||||||
|
ekEn = sum(Se);
|
||||||
|
dkEn = sum(Sd);
|
||||||
|
|
||||||
|
if divergeState == 0
|
||||||
|
if ekEn > dkEn
|
||||||
|
ef = df;
|
||||||
|
divergeState = 1;
|
||||||
|
%hnlPrefAvg = hnlSortQ;
|
||||||
|
%hnled = (1 - cohxd);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
%if ekEn*1.1 < dkEn
|
||||||
|
%if ekEn*1.26 < dkEn
|
||||||
|
if ekEn*1.05 < dkEn
|
||||||
|
divergeState = 0;
|
||||||
|
else
|
||||||
|
ef = df;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ekEn > dkEn*19.95
|
||||||
|
WFb=zeros(N+1,M); % Block-based FD NLMS
|
||||||
|
end
|
||||||
|
|
||||||
|
ekEnV(kk) = ekEn;
|
||||||
|
dkEnV(kk) = dkEn;
|
||||||
|
|
||||||
|
hnlLocalMinV(kk) = hnlLocalMin;
|
||||||
|
cohxdLocalMinV(kk) = cohxdLocalMin;
|
||||||
|
hnlMinV(kk) = hnlMin;
|
||||||
|
%cohxdMaxLocal = max(cohxdSlow(kk,:));
|
||||||
|
%if kk > 50
|
||||||
|
%cohxdMaxLocal = 1-hnlSortQ;
|
||||||
|
%if cohxdMaxLocal > 0.5
|
||||||
|
% %if cohxdMaxLocal > cohxdMax
|
||||||
|
% odScale = max(log(cohxdMaxLocal)/log(0.95), 1);
|
||||||
|
% %overdrive(7:end) = max(log(cohxdSlow(kk,7:end))/log(0.9), 1);
|
||||||
|
% cohxdMax = cohxdMaxLocal;
|
||||||
|
% end
|
||||||
|
%end
|
||||||
|
%end
|
||||||
|
%cohxdMax = cohxdMax*0.999;
|
||||||
|
|
||||||
|
%overdriveM(kk,:) = max(overdrive, 1);
|
||||||
|
%aggrFact = 0.25;
|
||||||
|
aggrFact = 0.3;
|
||||||
|
%aggrFact = 0.5*propLow;
|
||||||
|
%if fs == 8000
|
||||||
|
% wCurve = [0 ; 0 ; aggrFact*sqrt(linspace(0,1,N-1))' + 0.1];
|
||||||
|
%else
|
||||||
|
% wCurve = [0; 0; 0; aggrFact*sqrt(linspace(0,1,N-2))' + 0.1];
|
||||||
|
%end
|
||||||
|
wCurve = [0; aggrFact*sqrt(linspace(0,1,N))' + 0.1];
|
||||||
|
% For sync with C
|
||||||
|
%if fs == 8000
|
||||||
|
% wCurve = wCurve(2:end);
|
||||||
|
%else
|
||||||
|
% wCurve = wCurve(1:end-1);
|
||||||
|
%end
|
||||||
|
%weight = aggrFact*(sqrt(linspace(0,1,N+1)'));
|
||||||
|
%weight = aggrFact*wCurve;
|
||||||
|
weight = wCurve;
|
||||||
|
%weight = aggrFact*ones(N+1,1);
|
||||||
|
%weight = zeros(N+1,1);
|
||||||
|
%hnled = weight.*min(hnled) + (1 - weight).*hnled;
|
||||||
|
%hnled = weight.*min(mean(hnled(echoBandRange)), hnled) + (1 - weight).*hnled;
|
||||||
|
%hnled = weight.*min(hnlSortQ, hnled) + (1 - weight).*hnled;
|
||||||
|
|
||||||
|
%hnlSortQV(kk) = mean(hnled);
|
||||||
|
%hnlPrefAvgV(kk) = mean(hnled(echoBandRange));
|
||||||
|
|
||||||
|
hnled = weight.*min(hnlPrefAvg, hnled) + (1 - weight).*hnled;
|
||||||
|
|
||||||
|
%od = aggrFact*(sqrt(linspace(0,1,N+1)') + aggrTerm);
|
||||||
|
%od = 4*(sqrt(linspace(0,1,N+1)') + 1/4);
|
||||||
|
|
||||||
|
%ovrdFact = (ovrdSm - 1) / sqrt(ovrdPos/(N+1));
|
||||||
|
%ovrdFact = ovrdSm / sqrt(echoBandRange(floor(length(echoBandRange)/2))/(N+1));
|
||||||
|
%od = ovrdFact*sqrt(linspace(0,1,N+1))' + 1;
|
||||||
|
%od = ovrdSm*ones(N+1,1).*abs(WFb(:,dIdx))/(max(abs(WFb(:,dIdx)))+1e-10);
|
||||||
|
|
||||||
|
%od = ovrdSm*ones(N+1,1);
|
||||||
|
%od = ovrdSm*WFbD.*(sqrt(linspace(0,1,N+1))' + 1);
|
||||||
|
|
||||||
|
od = ovrdSm*(sqrt(linspace(0,1,N+1))' + 1);
|
||||||
|
%od = 4*(sqrt(linspace(0,1,N+1))' + 1);
|
||||||
|
|
||||||
|
%od = 2*ones(N+1,1);
|
||||||
|
%od = 2*ones(N+1,1);
|
||||||
|
%sshift = ((1-hnled)*2-1).^3+1;
|
||||||
|
sshift = ones(N+1,1);
|
||||||
|
|
||||||
|
hnled = hnled.^(od.*sshift);
|
||||||
|
|
||||||
|
%if hnlg > 0.75
|
||||||
|
%if (suppState ~= 0)
|
||||||
|
% transCtr = 0;
|
||||||
|
%end
|
||||||
|
% suppState = 0;
|
||||||
|
%elseif hnlg < 0.6 & hnlg > 0.2
|
||||||
|
% suppState = 1;
|
||||||
|
%elseif hnlg < 0.1
|
||||||
|
%hnled = zeros(N+1, 1);
|
||||||
|
%if (suppState ~= 2)
|
||||||
|
% transCtr = 0;
|
||||||
|
%end
|
||||||
|
% suppState = 2;
|
||||||
|
%else
|
||||||
|
% if (suppState ~= 2)
|
||||||
|
% transCtr = 0;
|
||||||
|
% end
|
||||||
|
% suppState = 2;
|
||||||
|
%end
|
||||||
|
%if suppState == 0
|
||||||
|
% hnled = ones(N+1, 1);
|
||||||
|
%elseif suppState == 2
|
||||||
|
% hnled = zeros(N+1, 1);
|
||||||
|
%end
|
||||||
|
%hnled(find(hnled < 0.1)) = 0;
|
||||||
|
%hnled = hnled.^2;
|
||||||
|
%if transCtr < 5
|
||||||
|
%hnl = 0.75*hnl + 0.25*hnled;
|
||||||
|
% transCtr = transCtr + 1;
|
||||||
|
%else
|
||||||
|
hnl = hnled;
|
||||||
|
%end
|
||||||
|
%hnled(find(hnled < 0.05)) = 0;
|
||||||
|
ef = ef.*(hnl);
|
||||||
|
|
||||||
|
%ef = ef.*(min(1 - cohxd, cohed).^2);
|
||||||
|
%ef = ef.*((1-cohxd).^2);
|
||||||
|
|
||||||
|
ovrdV(kk) = ovrdSm;
|
||||||
|
%ovrdV(kk) = dIdx;
|
||||||
|
%ovrdV(kk) = divergeFact;
|
||||||
|
%hnledAvg(kk) = 1-mean(1-cohedFast(echoBandRange));
|
||||||
|
hnledAvg(kk) = 1-mean(1-cohed(echoBandRange));
|
||||||
|
hnlxdAvg(kk) = 1-mean(cohxd(echoBandRange));
|
||||||
|
%hnlxdAvg(kk) = cohxd(5);
|
||||||
|
%hnlSortQV(kk) = mean(hnled);
|
||||||
|
hnlSortQV(kk) = hnlPrefAvgLow;
|
||||||
|
hnlPrefAvgV(kk) = hnlPrefAvg;
|
||||||
|
%hnlAvg(kk) = propLow;
|
||||||
|
%ef(N/2:end) = 0;
|
||||||
|
%ner = (sum(Sd) ./ (sum(Se.*(hnl.^2)) + 1e-10));
|
||||||
|
|
||||||
|
% Comfort noise
|
||||||
|
if (CNon)
|
||||||
|
snn=sqrt(Sym);
|
||||||
|
snn(1)=0; % Reject LF noise
|
||||||
|
Un=snn.*exp(j*2*pi.*[0;rand(N-1,1);0]);
|
||||||
|
|
||||||
|
% Weight comfort noise by suppression
|
||||||
|
Un = sqrt(1-hnled.^2).*Un;
|
||||||
|
Fmix = ef + Un;
|
||||||
|
else
|
||||||
|
Fmix = ef;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Overlap and add in time domain for smoothness
|
||||||
|
tmp = [Fmix ; flipud(conj(Fmix(2:N)))];
|
||||||
|
mixw = wins.*real(ifft(tmp));
|
||||||
|
mola = mbuf(end-N+1:end) + mixw(1:N);
|
||||||
|
mbuf = mixw;
|
||||||
|
ercn(pos:pos+N-1) = mola;
|
||||||
|
end % NLPon
|
||||||
|
|
||||||
|
% Filter update
|
||||||
|
%Ek2 = Ek ./(12*pn + 0.001); % Normalized error
|
||||||
|
%Ek2 = Ek2 * divergeFact;
|
||||||
|
%Ek2 = Ek ./(pn + 0.001); % Normalized error
|
||||||
|
%Ek2 = Ek ./(100*pn + 0.001); % Normalized error
|
||||||
|
|
||||||
|
%divergeIdx = find(abs(Ek) > abs(DD));
|
||||||
|
%divergeIdx = find(Se > Sd);
|
||||||
|
%threshMod = threshold*ones(N+1,1);
|
||||||
|
%if length(divergeIdx) > 0
|
||||||
|
%if sum(abs(Ek)) > sum(abs(DD))
|
||||||
|
%WFb(divergeIdx,:) = WFb(divergeIdx,:) .* repmat(sqrt(Sd(divergeIdx)./(Se(divergeIdx)+1e-10))),1,M);
|
||||||
|
%Ek2(divergeIdx) = Ek2(divergeIdx) .* sqrt(Sd(divergeIdx)./(Se(divergeIdx)+1e-10));
|
||||||
|
%Ek2(divergeIdx) = Ek2(divergeIdx) .* abs(DD(divergeIdx))./(abs(Ek(divergeIdx))+1e-10);
|
||||||
|
%WFb(divergeIdx,:) = WFbOld(divergeIdx,:);
|
||||||
|
%WFb = WFbOld;
|
||||||
|
%threshMod(divergeIdx) = threshMod(divergeIdx) .* abs(DD(divergeIdx))./(abs(Ek(divergeIdx))+1e-10);
|
||||||
|
% threshMod(divergeIdx) = threshMod(divergeIdx) .* sqrt(Sd(divergeIdx)./(Se(divergeIdx)+1e-10));
|
||||||
|
%end
|
||||||
|
|
||||||
|
%absEf = max(abs(Ek2), threshold);
|
||||||
|
%absEf = ones(N+1,1)*threshold./absEf;
|
||||||
|
%absEf = max(abs(Ek2), threshMod);
|
||||||
|
%absEf = threshMod./absEf;
|
||||||
|
%Ek2 = Ek2.*absEf;
|
||||||
|
|
||||||
|
%if sum(Se) <= sum(Sd)
|
||||||
|
|
||||||
|
% mEk = mufb.*Ek2;
|
||||||
|
% PP = conj(XFm).*(ones(M,1) * mEk')';
|
||||||
|
% tmp = [PP ; flipud(conj(PP(2:N,:)))];
|
||||||
|
% IFPP = real(ifft(tmp));
|
||||||
|
% PH = IFPP(1:N,:);
|
||||||
|
% tmp = fft([PH;zeros(N,M)]);
|
||||||
|
% FPH = tmp(1:N+1,:);
|
||||||
|
% %WFbOld = WFb;
|
||||||
|
% WFb = WFb + FPH;
|
||||||
|
|
||||||
|
%else
|
||||||
|
% WF = WFbOld;
|
||||||
|
%end
|
||||||
|
|
||||||
|
% Shift old FFTs
|
||||||
|
%for m=M:-1:2
|
||||||
|
% XFm(:,m) = XFm(:,m-1);
|
||||||
|
% YFm(:,m) = YFm(:,m-1);
|
||||||
|
%end
|
||||||
|
XFm(:,2:end) = XFm(:,1:end-1);
|
||||||
|
YFm(:,2:end) = YFm(:,1:end-1);
|
||||||
|
xfwm(:,2:end) = xfwm(:,1:end-1);
|
||||||
|
dfm(:,2:end) = dfm(:,1:end-1);
|
||||||
|
|
||||||
|
%if mod(kk, floor(Nb/50)) == 0
|
||||||
|
% fprintf(1, '.');
|
||||||
|
%end
|
||||||
|
|
||||||
|
if mod(kk, floor(Nb/100)) == 0
|
||||||
|
%if mod(kk, floor(Nb/500)) == 0
|
||||||
|
progressbar(kk/Nb);
|
||||||
|
%figure(5)
|
||||||
|
%plot(abs(WFb));
|
||||||
|
%legend('1','2','3','4','5','6','7','8','9','10','11','12');
|
||||||
|
%title(kk*N/fs);
|
||||||
|
%figure(6)
|
||||||
|
%plot(WFbD);
|
||||||
|
%figure(6)
|
||||||
|
%plot(threshMod)
|
||||||
|
%if length(divergeIdx) > 0
|
||||||
|
% plot(abs(DD))
|
||||||
|
% hold on
|
||||||
|
% plot(abs(Ek), 'r')
|
||||||
|
% hold off
|
||||||
|
%plot(min(sqrt(Sd./(Se+1e-10)),1))
|
||||||
|
%axis([0 N 0 1]);
|
||||||
|
%end
|
||||||
|
%figure(6)
|
||||||
|
%plot(cohedFast);
|
||||||
|
%axis([1 N+1 0 1]);
|
||||||
|
%plot(WFbEn);
|
||||||
|
|
||||||
|
%figure(7)
|
||||||
|
%plot(weight);
|
||||||
|
%plot([cohxd 1-cohed]);
|
||||||
|
%plot([cohxd 1-cohed 1-cohedFast hnled]);
|
||||||
|
%plot([cohxd cohxdFast/max(cohxdFast)]);
|
||||||
|
%legend('cohxd', '1-cohed', '1-cohedFast');
|
||||||
|
%axis([1 65 0 1]);
|
||||||
|
%pause(0.5);
|
||||||
|
%overdrive
|
||||||
|
end
|
||||||
|
end
|
||||||
|
progressbar(1);
|
||||||
|
|
||||||
|
%figure(2);
|
||||||
|
%plot([feat(:,1) feat(:,2)+1 feat(:,3)+2 mfeat+3]);
|
||||||
|
%plot([feat(:,1) mfeat+1]);
|
||||||
|
|
||||||
|
%figure(3);
|
||||||
|
%plot(10*log10([dri erifb erifb3 ericn]));
|
||||||
|
%legend('Near-end','Error','Post NLP','Final',4);
|
||||||
|
% Compensate for delay
|
||||||
|
%ercn=[ercn(N+1:end);zeros(N,1)];
|
||||||
|
%ercn_=[ercn_(N+1:end);zeros(N,1)];
|
||||||
|
|
||||||
|
%figure(11);
|
||||||
|
%plot(cohxdSlow);
|
||||||
|
|
||||||
|
%figure(12);
|
||||||
|
%surf(cohxdSlow);
|
||||||
|
%shading interp;
|
||||||
|
|
||||||
|
%figure(13);
|
||||||
|
%plot(overdriveM);
|
||||||
|
|
||||||
|
%figure(14);
|
||||||
|
%surf(overdriveM);
|
||||||
|
%shading interp;
|
||||||
|
|
||||||
|
figure(10);
|
||||||
|
t = (0:Nb)*N/fs;
|
||||||
|
rrinSubSamp = rrin(N*(1:(Nb+1)));
|
||||||
|
plot(t, rrinSubSamp/max(abs(rrinSubSamp)),'b');
|
||||||
|
hold on
|
||||||
|
plot(t, hnledAvg, 'r');
|
||||||
|
plot(t, hnlxdAvg, 'g');
|
||||||
|
plot(t, hnlSortQV, 'y');
|
||||||
|
plot(t, hnlLocalMinV, 'k');
|
||||||
|
plot(t, cohxdLocalMinV, 'c');
|
||||||
|
plot(t, hnlPrefAvgV, 'm');
|
||||||
|
%plot(t, cohxdAvg, 'r');
|
||||||
|
%plot(cohxdFastAvg, 'r');
|
||||||
|
%plot(cohxdAvgBad, 'k');
|
||||||
|
%plot(t, cohedAvg, 'k');
|
||||||
|
%plot(t, 1-cohedFastAvg, 'k');
|
||||||
|
%plot(ssin(N*(1:floor(length(ssin)/N)))/max(abs(ssin)));
|
||||||
|
%plot(echoBands,'r');
|
||||||
|
%plot(overdrive, 'g');
|
||||||
|
%plot(erfb(N*(1:floor(length(erfb)/N)))/max(abs(erfb)));
|
||||||
|
hold off
|
||||||
|
tightx;
|
||||||
|
|
||||||
|
figure(11)
|
||||||
|
plot(t, ovrdV);
|
||||||
|
tightx;
|
||||||
|
%plot(mfeat,'r');
|
||||||
|
%plot(1-cohxyp_,'r');
|
||||||
|
%plot(Hnlxydp,'y');
|
||||||
|
%plot(hnledp,'k');
|
||||||
|
%plot(Hnlxydp, 'c');
|
||||||
|
%plot(ccohpd_,'k');
|
||||||
|
%plot(supplot_, 'g');
|
||||||
|
%plot(ones(length(mfeat),1)*rr1_, 'k');
|
||||||
|
%plot(ones(length(mfeat),1)*rr2_, 'k');
|
||||||
|
%plot(N*(1:length(feat)), feat);
|
||||||
|
%plot(Sep_,'r');
|
||||||
|
%axis([1 floor(length(erfb)/N) -1 1])
|
||||||
|
%hold off
|
||||||
|
%plot(10*log10([Se_, Sx_, Seu_, real(sf_.*conj(sf_))]));
|
||||||
|
%legend('Se','Sx','Seu','S');
|
||||||
|
%figure(5)
|
||||||
|
%plot([ercn ercn_]);
|
||||||
|
|
||||||
|
figure(12)
|
||||||
|
plot(t, dIdxV);
|
||||||
|
%plot(t, SLxV);
|
||||||
|
tightx;
|
||||||
|
|
||||||
|
%figure(13)
|
||||||
|
%plot(t, [ekEnV dkEnV]);
|
||||||
|
%plot(t, dkEnV./(ekEnV+1e-10));
|
||||||
|
%tightx;
|
||||||
|
|
||||||
|
%close(hh);
|
||||||
|
%spclab(fs,ssin,erfb,ercn,'outxd.pcm');
|
||||||
|
%spclab(fs,rrin,ssin,erfb,1.78*ercn,'vqeOut-1.pcm');
|
||||||
|
%spclab(fs,erfb,'aecOutLp.pcm');
|
||||||
|
%spclab(fs,rrin,ssin,erfb,1.78*ercn,'aecOut25.pcm','vqeOut-1.pcm');
|
||||||
|
%spclab(fs,rrin,ssin,erfb,ercn,'aecOut-mba.pcm');
|
||||||
|
%spclab(fs,rrin,ssin,erfb,ercn,'aecOut.pcm');
|
||||||
|
%spclab(fs, ssin, erfb, ercn, 'out0.pcm');
|
46
src/modules/audio_processing/aec/main/source/aec.gypi
Normal file
46
src/modules/audio_processing/aec/main/source/aec.gypi
Normal file
@ -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.
|
||||||
|
|
||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'aec',
|
||||||
|
'type': '<(library)',
|
||||||
|
'dependencies': [
|
||||||
|
'<(webrtc_root)/common_audio/common_audio.gyp:spl',
|
||||||
|
'apm_util'
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'../interface',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': [
|
||||||
|
'../interface',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'sources': [
|
||||||
|
'../interface/echo_cancellation.h',
|
||||||
|
'echo_cancellation.c',
|
||||||
|
'aec_core.h',
|
||||||
|
'aec_core.c',
|
||||||
|
'aec_core_sse2.c',
|
||||||
|
'aec_rdft.h',
|
||||||
|
'aec_rdft.c',
|
||||||
|
'aec_rdft_sse2.c',
|
||||||
|
'resampler.h',
|
||||||
|
'resampler.c',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# tab-width:2
|
||||||
|
# indent-tabs-mode:nil
|
||||||
|
# End:
|
||||||
|
# vim: set expandtab tabstop=2 shiftwidth=2:
|
1430
src/modules/audio_processing/aec/main/source/aec_core.c
Normal file
1430
src/modules/audio_processing/aec/main/source/aec_core.c
Normal file
File diff suppressed because it is too large
Load Diff
176
src/modules/audio_processing/aec/main/source/aec_core.h
Normal file
176
src/modules/audio_processing/aec/main/source/aec_core.h
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specifies the interface for the AEC core.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
|
||||||
|
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "signal_processing_library.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
//#define UNCONSTR // time-unconstrained filter
|
||||||
|
//#define AEC_DEBUG // for recording files
|
||||||
|
|
||||||
|
#define FRAME_LEN 80
|
||||||
|
#define PART_LEN 64 // Length of partition
|
||||||
|
#define PART_LEN1 (PART_LEN + 1) // Unique fft coefficients
|
||||||
|
#define PART_LEN2 (PART_LEN * 2) // Length of partition * 2
|
||||||
|
#define NR_PART 12 // Number of partitions
|
||||||
|
#define FILT_LEN (PART_LEN * NR_PART) // Filter length
|
||||||
|
#define FILT_LEN2 (FILT_LEN * 2) // Double filter length
|
||||||
|
#define FAR_BUF_LEN (FILT_LEN2 * 2)
|
||||||
|
#define PREF_BAND_SIZE 24
|
||||||
|
|
||||||
|
#define BLOCKL_MAX FRAME_LEN
|
||||||
|
|
||||||
|
typedef float complex_t[2];
|
||||||
|
// For performance reasons, some arrays of complex numbers are replaced by twice
|
||||||
|
// as long arrays of float, all the real parts followed by all the imaginary
|
||||||
|
// ones (complex_t[SIZE] -> float[2][SIZE]). This allows SIMD optimizations and
|
||||||
|
// is better than two arrays (one for the real parts and one for the imaginary
|
||||||
|
// parts) as this other way would require two pointers instead of one and cause
|
||||||
|
// extra register spilling. This also allows the offsets to be calculated at
|
||||||
|
// compile time.
|
||||||
|
|
||||||
|
// Metrics
|
||||||
|
enum {offsetLevel = -100};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float sfrsum;
|
||||||
|
int sfrcounter;
|
||||||
|
float framelevel;
|
||||||
|
float frsum;
|
||||||
|
int frcounter;
|
||||||
|
float minlevel;
|
||||||
|
float averagelevel;
|
||||||
|
} power_level_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float instant;
|
||||||
|
float average;
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
float sum;
|
||||||
|
float hisum;
|
||||||
|
float himean;
|
||||||
|
int counter;
|
||||||
|
int hicounter;
|
||||||
|
} stats_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int farBufWritePos, farBufReadPos;
|
||||||
|
|
||||||
|
int knownDelay;
|
||||||
|
int inSamples, outSamples;
|
||||||
|
int delayEstCtr;
|
||||||
|
|
||||||
|
void *farFrBuf, *nearFrBuf, *outFrBuf;
|
||||||
|
|
||||||
|
void *nearFrBufH;
|
||||||
|
void *outFrBufH;
|
||||||
|
|
||||||
|
float xBuf[PART_LEN2]; // farend
|
||||||
|
float dBuf[PART_LEN2]; // nearend
|
||||||
|
float eBuf[PART_LEN2]; // error
|
||||||
|
|
||||||
|
float dBufH[PART_LEN2]; // nearend
|
||||||
|
|
||||||
|
float xPow[PART_LEN1];
|
||||||
|
float dPow[PART_LEN1];
|
||||||
|
float dMinPow[PART_LEN1];
|
||||||
|
float dInitMinPow[PART_LEN1];
|
||||||
|
float *noisePow;
|
||||||
|
|
||||||
|
float xfBuf[2][NR_PART * PART_LEN1]; // farend fft buffer
|
||||||
|
float wfBuf[2][NR_PART * PART_LEN1]; // filter fft
|
||||||
|
complex_t sde[PART_LEN1]; // cross-psd of nearend and error
|
||||||
|
complex_t sxd[PART_LEN1]; // cross-psd of farend and nearend
|
||||||
|
complex_t xfwBuf[NR_PART * PART_LEN1]; // farend windowed fft buffer
|
||||||
|
|
||||||
|
float sx[PART_LEN1], sd[PART_LEN1], se[PART_LEN1]; // far, near and error psd
|
||||||
|
float hNs[PART_LEN1];
|
||||||
|
float hNlFbMin, hNlFbLocalMin;
|
||||||
|
float hNlXdAvgMin;
|
||||||
|
int hNlNewMin, hNlMinCtr;
|
||||||
|
float overDrive, overDriveSm;
|
||||||
|
float targetSupp, minOverDrive;
|
||||||
|
float outBuf[PART_LEN];
|
||||||
|
int delayIdx;
|
||||||
|
|
||||||
|
short stNearState, echoState;
|
||||||
|
short divergeState;
|
||||||
|
|
||||||
|
int xfBufBlockPos;
|
||||||
|
|
||||||
|
short farBuf[FILT_LEN2 * 2];
|
||||||
|
|
||||||
|
short mult; // sampling frequency multiple
|
||||||
|
int sampFreq;
|
||||||
|
WebRtc_UWord32 seed;
|
||||||
|
|
||||||
|
float mu; // stepsize
|
||||||
|
float errThresh; // error threshold
|
||||||
|
|
||||||
|
int noiseEstCtr;
|
||||||
|
|
||||||
|
power_level_t farlevel;
|
||||||
|
power_level_t nearlevel;
|
||||||
|
power_level_t linoutlevel;
|
||||||
|
power_level_t nlpoutlevel;
|
||||||
|
|
||||||
|
int metricsMode;
|
||||||
|
int stateCounter;
|
||||||
|
stats_t erl;
|
||||||
|
stats_t erle;
|
||||||
|
stats_t aNlp;
|
||||||
|
stats_t rerl;
|
||||||
|
|
||||||
|
// Quantities to control H band scaling for SWB input
|
||||||
|
int freq_avg_ic; //initial bin for averaging nlp gain
|
||||||
|
int flag_Hband_cn; //for comfort noise
|
||||||
|
float cn_scale_Hband; //scale for comfort noise in H band
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
FILE *farFile;
|
||||||
|
FILE *nearFile;
|
||||||
|
FILE *outFile;
|
||||||
|
FILE *outLpFile;
|
||||||
|
#endif
|
||||||
|
} aec_t;
|
||||||
|
|
||||||
|
typedef void (*WebRtcAec_FilterFar_t)(aec_t *aec, float yf[2][PART_LEN1]);
|
||||||
|
extern WebRtcAec_FilterFar_t WebRtcAec_FilterFar;
|
||||||
|
typedef void (*WebRtcAec_ScaleErrorSignal_t)(aec_t *aec, float ef[2][PART_LEN1]);
|
||||||
|
extern WebRtcAec_ScaleErrorSignal_t WebRtcAec_ScaleErrorSignal;
|
||||||
|
typedef void (*WebRtcAec_FilterAdaptation_t)
|
||||||
|
(aec_t *aec, float *fft, float ef[2][PART_LEN1]);
|
||||||
|
extern WebRtcAec_FilterAdaptation_t WebRtcAec_FilterAdaptation;
|
||||||
|
typedef void (*WebRtcAec_OverdriveAndSuppress_t)
|
||||||
|
(aec_t *aec, float hNl[PART_LEN1], const float hNlFb, float efw[2][PART_LEN1]);
|
||||||
|
extern WebRtcAec_OverdriveAndSuppress_t WebRtcAec_OverdriveAndSuppress;
|
||||||
|
|
||||||
|
int WebRtcAec_CreateAec(aec_t **aec);
|
||||||
|
int WebRtcAec_FreeAec(aec_t *aec);
|
||||||
|
int WebRtcAec_InitAec(aec_t *aec, int sampFreq);
|
||||||
|
void WebRtcAec_InitAec_SSE2(void);
|
||||||
|
|
||||||
|
void WebRtcAec_InitMetrics(aec_t *aec);
|
||||||
|
void WebRtcAec_ProcessFrame(aec_t *aec, const short *farend,
|
||||||
|
const short *nearend, const short *nearendH,
|
||||||
|
short *out, short *outH,
|
||||||
|
int knownDelay);
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
|
||||||
|
|
429
src/modules/audio_processing/aec/main/source/aec_core_sse2.c
Normal file
429
src/modules/audio_processing/aec/main/source/aec_core_sse2.c
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The core AEC algorithm, SSE2 version of speed-critical functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#if defined(WEBRTC_USE_SSE2)
|
||||||
|
#include <emmintrin.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "aec_core.h"
|
||||||
|
#include "aec_rdft.h"
|
||||||
|
|
||||||
|
__inline static float MulRe(float aRe, float aIm, float bRe, float bIm)
|
||||||
|
{
|
||||||
|
return aRe * bRe - aIm * bIm;
|
||||||
|
}
|
||||||
|
|
||||||
|
__inline static float MulIm(float aRe, float aIm, float bRe, float bIm)
|
||||||
|
{
|
||||||
|
return aRe * bIm + aIm * bRe;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FilterFarSSE2(aec_t *aec, float yf[2][PART_LEN1])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < NR_PART; i++) {
|
||||||
|
int j;
|
||||||
|
int xPos = (i + aec->xfBufBlockPos) * PART_LEN1;
|
||||||
|
int pos = i * PART_LEN1;
|
||||||
|
// Check for wrap
|
||||||
|
if (i + aec->xfBufBlockPos >= NR_PART) {
|
||||||
|
xPos -= NR_PART*(PART_LEN1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vectorized code (four at once)
|
||||||
|
for (j = 0; j + 3 < PART_LEN1; j += 4) {
|
||||||
|
const __m128 xfBuf_re = _mm_loadu_ps(&aec->xfBuf[0][xPos + j]);
|
||||||
|
const __m128 xfBuf_im = _mm_loadu_ps(&aec->xfBuf[1][xPos + j]);
|
||||||
|
const __m128 wfBuf_re = _mm_loadu_ps(&aec->wfBuf[0][pos + j]);
|
||||||
|
const __m128 wfBuf_im = _mm_loadu_ps(&aec->wfBuf[1][pos + j]);
|
||||||
|
const __m128 yf_re = _mm_loadu_ps(&yf[0][j]);
|
||||||
|
const __m128 yf_im = _mm_loadu_ps(&yf[1][j]);
|
||||||
|
const __m128 a = _mm_mul_ps(xfBuf_re, wfBuf_re);
|
||||||
|
const __m128 b = _mm_mul_ps(xfBuf_im, wfBuf_im);
|
||||||
|
const __m128 c = _mm_mul_ps(xfBuf_re, wfBuf_im);
|
||||||
|
const __m128 d = _mm_mul_ps(xfBuf_im, wfBuf_re);
|
||||||
|
const __m128 e = _mm_sub_ps(a, b);
|
||||||
|
const __m128 f = _mm_add_ps(c, d);
|
||||||
|
const __m128 g = _mm_add_ps(yf_re, e);
|
||||||
|
const __m128 h = _mm_add_ps(yf_im, f);
|
||||||
|
_mm_storeu_ps(&yf[0][j], g);
|
||||||
|
_mm_storeu_ps(&yf[1][j], h);
|
||||||
|
}
|
||||||
|
// scalar code for the remaining items.
|
||||||
|
for (; j < PART_LEN1; j++) {
|
||||||
|
yf[0][j] += MulRe(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
|
||||||
|
aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
|
||||||
|
yf[1][j] += MulIm(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
|
||||||
|
aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ScaleErrorSignalSSE2(aec_t *aec, float ef[2][PART_LEN1])
|
||||||
|
{
|
||||||
|
const __m128 k1e_10f = _mm_set1_ps(1e-10f);
|
||||||
|
const __m128 kThresh = _mm_set1_ps(aec->errThresh);
|
||||||
|
const __m128 kMu = _mm_set1_ps(aec->mu);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
// vectorized code (four at once)
|
||||||
|
for (i = 0; i + 3 < PART_LEN1; i += 4) {
|
||||||
|
const __m128 xPow = _mm_loadu_ps(&aec->xPow[i]);
|
||||||
|
const __m128 ef_re_base = _mm_loadu_ps(&ef[0][i]);
|
||||||
|
const __m128 ef_im_base = _mm_loadu_ps(&ef[1][i]);
|
||||||
|
|
||||||
|
const __m128 xPowPlus = _mm_add_ps(xPow, k1e_10f);
|
||||||
|
__m128 ef_re = _mm_div_ps(ef_re_base, xPowPlus);
|
||||||
|
__m128 ef_im = _mm_div_ps(ef_im_base, xPowPlus);
|
||||||
|
const __m128 ef_re2 = _mm_mul_ps(ef_re, ef_re);
|
||||||
|
const __m128 ef_im2 = _mm_mul_ps(ef_im, ef_im);
|
||||||
|
const __m128 ef_sum2 = _mm_add_ps(ef_re2, ef_im2);
|
||||||
|
const __m128 absEf = _mm_sqrt_ps(ef_sum2);
|
||||||
|
const __m128 bigger = _mm_cmpgt_ps(absEf, kThresh);
|
||||||
|
__m128 absEfPlus = _mm_add_ps(absEf, k1e_10f);
|
||||||
|
const __m128 absEfInv = _mm_div_ps(kThresh, absEfPlus);
|
||||||
|
__m128 ef_re_if = _mm_mul_ps(ef_re, absEfInv);
|
||||||
|
__m128 ef_im_if = _mm_mul_ps(ef_im, absEfInv);
|
||||||
|
ef_re_if = _mm_and_ps(bigger, ef_re_if);
|
||||||
|
ef_im_if = _mm_and_ps(bigger, ef_im_if);
|
||||||
|
ef_re = _mm_andnot_ps(bigger, ef_re);
|
||||||
|
ef_im = _mm_andnot_ps(bigger, ef_im);
|
||||||
|
ef_re = _mm_or_ps(ef_re, ef_re_if);
|
||||||
|
ef_im = _mm_or_ps(ef_im, ef_im_if);
|
||||||
|
ef_re = _mm_mul_ps(ef_re, kMu);
|
||||||
|
ef_im = _mm_mul_ps(ef_im, kMu);
|
||||||
|
|
||||||
|
_mm_storeu_ps(&ef[0][i], ef_re);
|
||||||
|
_mm_storeu_ps(&ef[1][i], ef_im);
|
||||||
|
}
|
||||||
|
// scalar code for the remaining items.
|
||||||
|
for (; i < (PART_LEN1); i++) {
|
||||||
|
float absEf;
|
||||||
|
ef[0][i] /= (aec->xPow[i] + 1e-10f);
|
||||||
|
ef[1][i] /= (aec->xPow[i] + 1e-10f);
|
||||||
|
absEf = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]);
|
||||||
|
|
||||||
|
if (absEf > aec->errThresh) {
|
||||||
|
absEf = aec->errThresh / (absEf + 1e-10f);
|
||||||
|
ef[0][i] *= absEf;
|
||||||
|
ef[1][i] *= absEf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stepsize factor
|
||||||
|
ef[0][i] *= aec->mu;
|
||||||
|
ef[1][i] *= aec->mu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FilterAdaptationSSE2(aec_t *aec, float *fft, float ef[2][PART_LEN1]) {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < NR_PART; i++) {
|
||||||
|
int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
|
||||||
|
int pos = i * PART_LEN1;
|
||||||
|
// Check for wrap
|
||||||
|
if (i + aec->xfBufBlockPos >= NR_PART) {
|
||||||
|
xPos -= NR_PART * PART_LEN1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNCONSTR
|
||||||
|
for (j = 0; j < PART_LEN1; j++) {
|
||||||
|
aec->wfBuf[pos + j][0] += MulRe(aec->xfBuf[xPos + j][0],
|
||||||
|
-aec->xfBuf[xPos + j][1],
|
||||||
|
ef[j][0], ef[j][1]);
|
||||||
|
aec->wfBuf[pos + j][1] += MulIm(aec->xfBuf[xPos + j][0],
|
||||||
|
-aec->xfBuf[xPos + j][1],
|
||||||
|
ef[j][0], ef[j][1]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Process the whole array...
|
||||||
|
for (j = 0; j < PART_LEN; j+= 4) {
|
||||||
|
// Load xfBuf and ef.
|
||||||
|
const __m128 xfBuf_re = _mm_loadu_ps(&aec->xfBuf[0][xPos + j]);
|
||||||
|
const __m128 xfBuf_im = _mm_loadu_ps(&aec->xfBuf[1][xPos + j]);
|
||||||
|
const __m128 ef_re = _mm_loadu_ps(&ef[0][j]);
|
||||||
|
const __m128 ef_im = _mm_loadu_ps(&ef[1][j]);
|
||||||
|
// Calculate the product of conjugate(xfBuf) by ef.
|
||||||
|
// re(conjugate(a) * b) = aRe * bRe + aIm * bIm
|
||||||
|
// im(conjugate(a) * b)= aRe * bIm - aIm * bRe
|
||||||
|
const __m128 a = _mm_mul_ps(xfBuf_re, ef_re);
|
||||||
|
const __m128 b = _mm_mul_ps(xfBuf_im, ef_im);
|
||||||
|
const __m128 c = _mm_mul_ps(xfBuf_re, ef_im);
|
||||||
|
const __m128 d = _mm_mul_ps(xfBuf_im, ef_re);
|
||||||
|
const __m128 e = _mm_add_ps(a, b);
|
||||||
|
const __m128 f = _mm_sub_ps(c, d);
|
||||||
|
// Interleave real and imaginary parts.
|
||||||
|
const __m128 g = _mm_unpacklo_ps(e, f);
|
||||||
|
const __m128 h = _mm_unpackhi_ps(e, f);
|
||||||
|
// Store
|
||||||
|
_mm_storeu_ps(&fft[2*j + 0], g);
|
||||||
|
_mm_storeu_ps(&fft[2*j + 4], h);
|
||||||
|
}
|
||||||
|
// ... and fixup the first imaginary entry.
|
||||||
|
fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN],
|
||||||
|
-aec->xfBuf[1][xPos + PART_LEN],
|
||||||
|
ef[0][PART_LEN], ef[1][PART_LEN]);
|
||||||
|
|
||||||
|
aec_rdft_inverse_128(fft);
|
||||||
|
memset(fft + PART_LEN, 0, sizeof(float)*PART_LEN);
|
||||||
|
|
||||||
|
// fft scaling
|
||||||
|
{
|
||||||
|
float scale = 2.0f / PART_LEN2;
|
||||||
|
const __m128 scale_ps = _mm_load_ps1(&scale);
|
||||||
|
for (j = 0; j < PART_LEN; j+=4) {
|
||||||
|
const __m128 fft_ps = _mm_loadu_ps(&fft[j]);
|
||||||
|
const __m128 fft_scale = _mm_mul_ps(fft_ps, scale_ps);
|
||||||
|
_mm_storeu_ps(&fft[j], fft_scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aec_rdft_forward_128(fft);
|
||||||
|
|
||||||
|
{
|
||||||
|
float wt1 = aec->wfBuf[1][pos];
|
||||||
|
aec->wfBuf[0][pos + PART_LEN] += fft[1];
|
||||||
|
for (j = 0; j < PART_LEN; j+= 4) {
|
||||||
|
__m128 wtBuf_re = _mm_loadu_ps(&aec->wfBuf[0][pos + j]);
|
||||||
|
__m128 wtBuf_im = _mm_loadu_ps(&aec->wfBuf[1][pos + j]);
|
||||||
|
const __m128 fft0 = _mm_loadu_ps(&fft[2 * j + 0]);
|
||||||
|
const __m128 fft4 = _mm_loadu_ps(&fft[2 * j + 4]);
|
||||||
|
const __m128 fft_re = _mm_shuffle_ps(fft0, fft4, _MM_SHUFFLE(2, 0, 2 ,0));
|
||||||
|
const __m128 fft_im = _mm_shuffle_ps(fft0, fft4, _MM_SHUFFLE(3, 1, 3 ,1));
|
||||||
|
wtBuf_re = _mm_add_ps(wtBuf_re, fft_re);
|
||||||
|
wtBuf_im = _mm_add_ps(wtBuf_im, fft_im);
|
||||||
|
_mm_storeu_ps(&aec->wfBuf[0][pos + j], wtBuf_re);
|
||||||
|
_mm_storeu_ps(&aec->wfBuf[1][pos + j], wtBuf_im);
|
||||||
|
}
|
||||||
|
aec->wfBuf[1][pos] = wt1;
|
||||||
|
}
|
||||||
|
#endif // UNCONSTR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static __m128 mm_pow_ps(__m128 a, __m128 b)
|
||||||
|
{
|
||||||
|
// a^b = exp2(b * log2(a))
|
||||||
|
// exp2(x) and log2(x) are calculated using polynomial approximations.
|
||||||
|
__m128 log2_a, b_log2_a, a_exp_b;
|
||||||
|
|
||||||
|
// Calculate log2(x), x = a.
|
||||||
|
{
|
||||||
|
// To calculate log2(x), we decompose x like this:
|
||||||
|
// x = y * 2^n
|
||||||
|
// n is an integer
|
||||||
|
// y is in the [1.0, 2.0) range
|
||||||
|
//
|
||||||
|
// log2(x) = log2(y) + n
|
||||||
|
// n can be evaluated by playing with float representation.
|
||||||
|
// log2(y) in a small range can be approximated, this code uses an order
|
||||||
|
// five polynomial approximation. The coefficients have been
|
||||||
|
// estimated with the Remez algorithm and the resulting
|
||||||
|
// polynomial has a maximum relative error of 0.00086%.
|
||||||
|
|
||||||
|
// Compute n.
|
||||||
|
// This is done by masking the exponent, shifting it into the top bit of
|
||||||
|
// the mantissa, putting eight into the biased exponent (to shift/
|
||||||
|
// compensate the fact that the exponent has been shifted in the top/
|
||||||
|
// fractional part and finally getting rid of the implicit leading one
|
||||||
|
// from the mantissa by substracting it out.
|
||||||
|
static const ALIGN16_BEG int float_exponent_mask[4] ALIGN16_END =
|
||||||
|
{0x7F800000, 0x7F800000, 0x7F800000, 0x7F800000};
|
||||||
|
static const ALIGN16_BEG int eight_biased_exponent[4] ALIGN16_END =
|
||||||
|
{0x43800000, 0x43800000, 0x43800000, 0x43800000};
|
||||||
|
static const ALIGN16_BEG int implicit_leading_one[4] ALIGN16_END =
|
||||||
|
{0x43BF8000, 0x43BF8000, 0x43BF8000, 0x43BF8000};
|
||||||
|
static const int shift_exponent_into_top_mantissa = 8;
|
||||||
|
const __m128 two_n = _mm_and_ps(a, *((__m128 *)float_exponent_mask));
|
||||||
|
const __m128 n_1 = (__m128)_mm_srli_epi32((__m128i)two_n,
|
||||||
|
shift_exponent_into_top_mantissa);
|
||||||
|
const __m128 n_0 = _mm_or_ps(
|
||||||
|
(__m128)n_1, *((__m128 *)eight_biased_exponent));
|
||||||
|
const __m128 n = _mm_sub_ps(n_0, *((__m128 *)implicit_leading_one));
|
||||||
|
|
||||||
|
// Compute y.
|
||||||
|
static const ALIGN16_BEG int mantissa_mask[4] ALIGN16_END =
|
||||||
|
{0x007FFFFF, 0x007FFFFF, 0x007FFFFF, 0x007FFFFF};
|
||||||
|
static const ALIGN16_BEG int zero_biased_exponent_is_one[4] ALIGN16_END =
|
||||||
|
{0x3F800000, 0x3F800000, 0x3F800000, 0x3F800000};
|
||||||
|
const __m128 mantissa = _mm_and_ps(a, *((__m128 *)mantissa_mask));
|
||||||
|
const __m128 y = _mm_or_ps(
|
||||||
|
mantissa, *((__m128 *)zero_biased_exponent_is_one));
|
||||||
|
|
||||||
|
// Approximate log2(y) ~= (y - 1) * pol5(y).
|
||||||
|
// pol5(y) = C5 * y^5 + C4 * y^4 + C3 * y^3 + C2 * y^2 + C1 * y + C0
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END C5[4] =
|
||||||
|
{-3.4436006e-2f, -3.4436006e-2f, -3.4436006e-2f, -3.4436006e-2f};
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END C4[4] =
|
||||||
|
{3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f};
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END C3[4] =
|
||||||
|
{-1.2315303f, -1.2315303f, -1.2315303f, -1.2315303f};
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END C2[4] =
|
||||||
|
{2.5988452f, 2.5988452f, 2.5988452f, 2.5988452f};
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END C1[4] =
|
||||||
|
{-3.3241990f, -3.3241990f, -3.3241990f, -3.3241990f};
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END C0[4] =
|
||||||
|
{3.1157899f, 3.1157899f, 3.1157899f, 3.1157899f};
|
||||||
|
const __m128 pol5_y_0 = _mm_mul_ps(y, *((__m128 *)C5));
|
||||||
|
const __m128 pol5_y_1 = _mm_add_ps(pol5_y_0, *((__m128 *)C4));
|
||||||
|
const __m128 pol5_y_2 = _mm_mul_ps(pol5_y_1, y);
|
||||||
|
const __m128 pol5_y_3 = _mm_add_ps(pol5_y_2, *((__m128 *)C3));
|
||||||
|
const __m128 pol5_y_4 = _mm_mul_ps(pol5_y_3, y);
|
||||||
|
const __m128 pol5_y_5 = _mm_add_ps(pol5_y_4, *((__m128 *)C2));
|
||||||
|
const __m128 pol5_y_6 = _mm_mul_ps(pol5_y_5, y);
|
||||||
|
const __m128 pol5_y_7 = _mm_add_ps(pol5_y_6, *((__m128 *)C1));
|
||||||
|
const __m128 pol5_y_8 = _mm_mul_ps(pol5_y_7, y);
|
||||||
|
const __m128 pol5_y = _mm_add_ps(pol5_y_8, *((__m128 *)C0));
|
||||||
|
const __m128 y_minus_one = _mm_sub_ps(
|
||||||
|
y, *((__m128 *)zero_biased_exponent_is_one));
|
||||||
|
const __m128 log2_y = _mm_mul_ps(y_minus_one , pol5_y);
|
||||||
|
|
||||||
|
// Combine parts.
|
||||||
|
log2_a = _mm_add_ps(n, log2_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// b * log2(a)
|
||||||
|
b_log2_a = _mm_mul_ps(b, log2_a);
|
||||||
|
|
||||||
|
// Calculate exp2(x), x = b * log2(a).
|
||||||
|
{
|
||||||
|
// To calculate 2^x, we decompose x like this:
|
||||||
|
// x = n + y
|
||||||
|
// n is an integer, the value of x - 0.5 rounded down, therefore
|
||||||
|
// y is in the [0.5, 1.5) range
|
||||||
|
//
|
||||||
|
// 2^x = 2^n * 2^y
|
||||||
|
// 2^n can be evaluated by playing with float representation.
|
||||||
|
// 2^y in a small range can be approximated, this code uses an order two
|
||||||
|
// polynomial approximation. The coefficients have been estimated
|
||||||
|
// with the Remez algorithm and the resulting polynomial has a
|
||||||
|
// maximum relative error of 0.17%.
|
||||||
|
|
||||||
|
// To avoid over/underflow, we reduce the range of input to ]-127, 129].
|
||||||
|
static const ALIGN16_BEG float max_input[4] ALIGN16_END =
|
||||||
|
{129.f, 129.f, 129.f, 129.f};
|
||||||
|
static const ALIGN16_BEG float min_input[4] ALIGN16_END =
|
||||||
|
{-126.99999f, -126.99999f, -126.99999f, -126.99999f};
|
||||||
|
const __m128 x_min = _mm_min_ps(b_log2_a, *((__m128 *)max_input));
|
||||||
|
const __m128 x_max = _mm_max_ps(x_min, *((__m128 *)min_input));
|
||||||
|
// Compute n.
|
||||||
|
static const ALIGN16_BEG float half[4] ALIGN16_END =
|
||||||
|
{0.5f, 0.5f, 0.5f, 0.5f};
|
||||||
|
const __m128 x_minus_half = _mm_sub_ps(x_max, *((__m128 *)half));
|
||||||
|
const __m128i x_minus_half_floor = _mm_cvtps_epi32(x_minus_half);
|
||||||
|
// Compute 2^n.
|
||||||
|
static const ALIGN16_BEG int float_exponent_bias[4] ALIGN16_END =
|
||||||
|
{127, 127, 127, 127};
|
||||||
|
static const int float_exponent_shift = 23;
|
||||||
|
const __m128i two_n_exponent = _mm_add_epi32(
|
||||||
|
x_minus_half_floor, *((__m128i *)float_exponent_bias));
|
||||||
|
const __m128 two_n = (__m128)_mm_slli_epi32(
|
||||||
|
two_n_exponent, float_exponent_shift);
|
||||||
|
// Compute y.
|
||||||
|
const __m128 y = _mm_sub_ps(x_max, _mm_cvtepi32_ps(x_minus_half_floor));
|
||||||
|
// Approximate 2^y ~= C2 * y^2 + C1 * y + C0.
|
||||||
|
static const ALIGN16_BEG float C2[4] ALIGN16_END =
|
||||||
|
{3.3718944e-1f, 3.3718944e-1f, 3.3718944e-1f, 3.3718944e-1f};
|
||||||
|
static const ALIGN16_BEG float C1[4] ALIGN16_END =
|
||||||
|
{6.5763628e-1f, 6.5763628e-1f, 6.5763628e-1f, 6.5763628e-1f};
|
||||||
|
static const ALIGN16_BEG float C0[4] ALIGN16_END =
|
||||||
|
{1.0017247f, 1.0017247f, 1.0017247f, 1.0017247f};
|
||||||
|
const __m128 exp2_y_0 = _mm_mul_ps(y, *((__m128 *)C2));
|
||||||
|
const __m128 exp2_y_1 = _mm_add_ps(exp2_y_0, *((__m128 *)C1));
|
||||||
|
const __m128 exp2_y_2 = _mm_mul_ps(exp2_y_1, y);
|
||||||
|
const __m128 exp2_y = _mm_add_ps(exp2_y_2, *((__m128 *)C0));
|
||||||
|
|
||||||
|
// Combine parts.
|
||||||
|
a_exp_b = _mm_mul_ps(exp2_y, two_n);
|
||||||
|
}
|
||||||
|
return a_exp_b;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const float WebRtcAec_weightCurve[65];
|
||||||
|
extern const float WebRtcAec_overDriveCurve[65];
|
||||||
|
|
||||||
|
static void OverdriveAndSuppressSSE2(aec_t *aec, float hNl[PART_LEN1],
|
||||||
|
const float hNlFb,
|
||||||
|
float efw[2][PART_LEN1]) {
|
||||||
|
int i;
|
||||||
|
const __m128 vec_hNlFb = _mm_set1_ps(hNlFb);
|
||||||
|
const __m128 vec_one = _mm_set1_ps(1.0f);
|
||||||
|
const __m128 vec_minus_one = _mm_set1_ps(-1.0f);
|
||||||
|
const __m128 vec_overDriveSm = _mm_set1_ps(aec->overDriveSm);
|
||||||
|
// vectorized code (four at once)
|
||||||
|
for (i = 0; i + 3 < PART_LEN1; i+=4) {
|
||||||
|
// Weight subbands
|
||||||
|
__m128 vec_hNl = _mm_loadu_ps(&hNl[i]);
|
||||||
|
const __m128 vec_weightCurve = _mm_loadu_ps(&WebRtcAec_weightCurve[i]);
|
||||||
|
const __m128 bigger = _mm_cmpgt_ps(vec_hNl, vec_hNlFb);
|
||||||
|
const __m128 vec_weightCurve_hNlFb = _mm_mul_ps(
|
||||||
|
vec_weightCurve, vec_hNlFb);
|
||||||
|
const __m128 vec_one_weightCurve = _mm_sub_ps(vec_one, vec_weightCurve);
|
||||||
|
const __m128 vec_one_weightCurve_hNl = _mm_mul_ps(
|
||||||
|
vec_one_weightCurve, vec_hNl);
|
||||||
|
const __m128 vec_if0 = _mm_andnot_ps(bigger, vec_hNl);
|
||||||
|
const __m128 vec_if1 = _mm_and_ps(
|
||||||
|
bigger, _mm_add_ps(vec_weightCurve_hNlFb, vec_one_weightCurve_hNl));
|
||||||
|
vec_hNl = _mm_or_ps(vec_if0, vec_if1);
|
||||||
|
|
||||||
|
{
|
||||||
|
const __m128 vec_overDriveCurve = _mm_loadu_ps(
|
||||||
|
&WebRtcAec_overDriveCurve[i]);
|
||||||
|
const __m128 vec_overDriveSm_overDriveCurve = _mm_mul_ps(
|
||||||
|
vec_overDriveSm, vec_overDriveCurve);
|
||||||
|
vec_hNl = mm_pow_ps(vec_hNl, vec_overDriveSm_overDriveCurve);
|
||||||
|
_mm_storeu_ps(&hNl[i], vec_hNl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suppress error signal
|
||||||
|
{
|
||||||
|
__m128 vec_efw_re = _mm_loadu_ps(&efw[0][i]);
|
||||||
|
__m128 vec_efw_im = _mm_loadu_ps(&efw[1][i]);
|
||||||
|
vec_efw_re = _mm_mul_ps(vec_efw_re, vec_hNl);
|
||||||
|
vec_efw_im = _mm_mul_ps(vec_efw_im, vec_hNl);
|
||||||
|
|
||||||
|
// Ooura fft returns incorrect sign on imaginary component. It matters
|
||||||
|
// here because we are making an additive change with comfort noise.
|
||||||
|
vec_efw_im = _mm_mul_ps(vec_efw_im, vec_minus_one);
|
||||||
|
_mm_storeu_ps(&efw[0][i], vec_efw_re);
|
||||||
|
_mm_storeu_ps(&efw[1][i], vec_efw_im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// scalar code for the remaining items.
|
||||||
|
for (; i < PART_LEN1; i++) {
|
||||||
|
// Weight subbands
|
||||||
|
if (hNl[i] > hNlFb) {
|
||||||
|
hNl[i] = WebRtcAec_weightCurve[i] * hNlFb +
|
||||||
|
(1 - WebRtcAec_weightCurve[i]) * hNl[i];
|
||||||
|
}
|
||||||
|
hNl[i] = powf(hNl[i], aec->overDriveSm * WebRtcAec_overDriveCurve[i]);
|
||||||
|
|
||||||
|
// Suppress error signal
|
||||||
|
efw[0][i] *= hNl[i];
|
||||||
|
efw[1][i] *= hNl[i];
|
||||||
|
|
||||||
|
// Ooura fft returns incorrect sign on imaginary component. It matters
|
||||||
|
// here because we are making an additive change with comfort noise.
|
||||||
|
efw[1][i] *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRtcAec_InitAec_SSE2(void) {
|
||||||
|
WebRtcAec_FilterFar = FilterFarSSE2;
|
||||||
|
WebRtcAec_ScaleErrorSignal = ScaleErrorSignalSSE2;
|
||||||
|
WebRtcAec_FilterAdaptation = FilterAdaptationSSE2;
|
||||||
|
WebRtcAec_OverdriveAndSuppress = OverdriveAndSuppressSSE2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBRTC_USE_SSE2
|
587
src/modules/audio_processing/aec/main/source/aec_rdft.c
Normal file
587
src/modules/audio_processing/aec/main/source/aec_rdft.c
Normal file
@ -0,0 +1,587 @@
|
|||||||
|
/*
|
||||||
|
* http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
|
||||||
|
* Copyright Takuya OOURA, 1996-2001
|
||||||
|
*
|
||||||
|
* You may use, copy, modify and distribute this code for any purpose (include
|
||||||
|
* commercial use) and without fee. Please refer to this package when you modify
|
||||||
|
* this code.
|
||||||
|
*
|
||||||
|
* Changes by the WebRTC authors:
|
||||||
|
* - Trivial type modifications.
|
||||||
|
* - Minimal code subset to do rdft of length 128.
|
||||||
|
* - Optimizations because of known length.
|
||||||
|
*
|
||||||
|
* All changes are covered by the WebRTC license and IP grant:
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "aec_rdft.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "system_wrappers/interface/cpu_features_wrapper.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
// constants shared by all paths (C, SSE2).
|
||||||
|
float rdft_w[64];
|
||||||
|
// constants used by the C path.
|
||||||
|
float rdft_wk3ri_first[32];
|
||||||
|
float rdft_wk3ri_second[32];
|
||||||
|
// constants used by SSE2 but initialized in C path.
|
||||||
|
ALIGN16_BEG float ALIGN16_END rdft_wk1r[32];
|
||||||
|
ALIGN16_BEG float ALIGN16_END rdft_wk2r[32];
|
||||||
|
ALIGN16_BEG float ALIGN16_END rdft_wk3r[32];
|
||||||
|
ALIGN16_BEG float ALIGN16_END rdft_wk1i[32];
|
||||||
|
ALIGN16_BEG float ALIGN16_END rdft_wk2i[32];
|
||||||
|
ALIGN16_BEG float ALIGN16_END rdft_wk3i[32];
|
||||||
|
ALIGN16_BEG float ALIGN16_END cftmdl_wk1r[4];
|
||||||
|
|
||||||
|
static int ip[16];
|
||||||
|
|
||||||
|
static void bitrv2_32or128(int n, int *ip, float *a) {
|
||||||
|
// n is 32 or 128
|
||||||
|
int j, j1, k, k1, m, m2;
|
||||||
|
float xr, xi, yr, yi;
|
||||||
|
|
||||||
|
ip[0] = 0;
|
||||||
|
{
|
||||||
|
int l = n;
|
||||||
|
m = 1;
|
||||||
|
while ((m << 3) < l) {
|
||||||
|
l >>= 1;
|
||||||
|
for (j = 0; j < m; j++) {
|
||||||
|
ip[m + j] = ip[j] + l;
|
||||||
|
}
|
||||||
|
m <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m2 = 2 * m;
|
||||||
|
for (k = 0; k < m; k++) {
|
||||||
|
for (j = 0; j < k; j++) {
|
||||||
|
j1 = 2 * j + ip[k];
|
||||||
|
k1 = 2 * k + ip[j];
|
||||||
|
xr = a[j1];
|
||||||
|
xi = a[j1 + 1];
|
||||||
|
yr = a[k1];
|
||||||
|
yi = a[k1 + 1];
|
||||||
|
a[j1] = yr;
|
||||||
|
a[j1 + 1] = yi;
|
||||||
|
a[k1] = xr;
|
||||||
|
a[k1 + 1] = xi;
|
||||||
|
j1 += m2;
|
||||||
|
k1 += 2 * m2;
|
||||||
|
xr = a[j1];
|
||||||
|
xi = a[j1 + 1];
|
||||||
|
yr = a[k1];
|
||||||
|
yi = a[k1 + 1];
|
||||||
|
a[j1] = yr;
|
||||||
|
a[j1 + 1] = yi;
|
||||||
|
a[k1] = xr;
|
||||||
|
a[k1 + 1] = xi;
|
||||||
|
j1 += m2;
|
||||||
|
k1 -= m2;
|
||||||
|
xr = a[j1];
|
||||||
|
xi = a[j1 + 1];
|
||||||
|
yr = a[k1];
|
||||||
|
yi = a[k1 + 1];
|
||||||
|
a[j1] = yr;
|
||||||
|
a[j1 + 1] = yi;
|
||||||
|
a[k1] = xr;
|
||||||
|
a[k1 + 1] = xi;
|
||||||
|
j1 += m2;
|
||||||
|
k1 += 2 * m2;
|
||||||
|
xr = a[j1];
|
||||||
|
xi = a[j1 + 1];
|
||||||
|
yr = a[k1];
|
||||||
|
yi = a[k1 + 1];
|
||||||
|
a[j1] = yr;
|
||||||
|
a[j1 + 1] = yi;
|
||||||
|
a[k1] = xr;
|
||||||
|
a[k1 + 1] = xi;
|
||||||
|
}
|
||||||
|
j1 = 2 * k + m2 + ip[k];
|
||||||
|
k1 = j1 + m2;
|
||||||
|
xr = a[j1];
|
||||||
|
xi = a[j1 + 1];
|
||||||
|
yr = a[k1];
|
||||||
|
yi = a[k1 + 1];
|
||||||
|
a[j1] = yr;
|
||||||
|
a[j1 + 1] = yi;
|
||||||
|
a[k1] = xr;
|
||||||
|
a[k1 + 1] = xi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void makewt_32(void) {
|
||||||
|
const int nw = 32;
|
||||||
|
int j, nwh;
|
||||||
|
float delta, x, y;
|
||||||
|
|
||||||
|
ip[0] = nw;
|
||||||
|
ip[1] = 1;
|
||||||
|
nwh = nw >> 1;
|
||||||
|
delta = atanf(1.0f) / nwh;
|
||||||
|
rdft_w[0] = 1;
|
||||||
|
rdft_w[1] = 0;
|
||||||
|
rdft_w[nwh] = cosf(delta * nwh);
|
||||||
|
rdft_w[nwh + 1] = rdft_w[nwh];
|
||||||
|
for (j = 2; j < nwh; j += 2) {
|
||||||
|
x = cosf(delta * j);
|
||||||
|
y = sinf(delta * j);
|
||||||
|
rdft_w[j] = x;
|
||||||
|
rdft_w[j + 1] = y;
|
||||||
|
rdft_w[nw - j] = y;
|
||||||
|
rdft_w[nw - j + 1] = x;
|
||||||
|
}
|
||||||
|
bitrv2_32or128(nw, ip + 2, rdft_w);
|
||||||
|
|
||||||
|
// pre-calculate constants used by cft1st_128 and cftmdl_128...
|
||||||
|
cftmdl_wk1r[0] = rdft_w[2];
|
||||||
|
cftmdl_wk1r[1] = rdft_w[2];
|
||||||
|
cftmdl_wk1r[2] = rdft_w[2];
|
||||||
|
cftmdl_wk1r[3] = -rdft_w[2];
|
||||||
|
{
|
||||||
|
int k1;
|
||||||
|
|
||||||
|
for (k1 = 0, j = 0; j < 128; j += 16, k1 += 2) {
|
||||||
|
const int k2 = 2 * k1;
|
||||||
|
const float wk2r = rdft_w[k1 + 0];
|
||||||
|
const float wk2i = rdft_w[k1 + 1];
|
||||||
|
float wk1r, wk1i;
|
||||||
|
// ... scalar version.
|
||||||
|
wk1r = rdft_w[k2 + 0];
|
||||||
|
wk1i = rdft_w[k2 + 1];
|
||||||
|
rdft_wk3ri_first[k1 + 0] = wk1r - 2 * wk2i * wk1i;
|
||||||
|
rdft_wk3ri_first[k1 + 1] = 2 * wk2i * wk1r - wk1i;
|
||||||
|
wk1r = rdft_w[k2 + 2];
|
||||||
|
wk1i = rdft_w[k2 + 3];
|
||||||
|
rdft_wk3ri_second[k1 + 0] = wk1r - 2 * wk2r * wk1i;
|
||||||
|
rdft_wk3ri_second[k1 + 1] = 2 * wk2r * wk1r - wk1i;
|
||||||
|
// ... vector version.
|
||||||
|
rdft_wk1r[k2 + 0] = rdft_w[k2 + 0];
|
||||||
|
rdft_wk1r[k2 + 1] = rdft_w[k2 + 0];
|
||||||
|
rdft_wk1r[k2 + 2] = rdft_w[k2 + 2];
|
||||||
|
rdft_wk1r[k2 + 3] = rdft_w[k2 + 2];
|
||||||
|
rdft_wk2r[k2 + 0] = rdft_w[k1 + 0];
|
||||||
|
rdft_wk2r[k2 + 1] = rdft_w[k1 + 0];
|
||||||
|
rdft_wk2r[k2 + 2] = -rdft_w[k1 + 1];
|
||||||
|
rdft_wk2r[k2 + 3] = -rdft_w[k1 + 1];
|
||||||
|
rdft_wk3r[k2 + 0] = rdft_wk3ri_first[k1 + 0];
|
||||||
|
rdft_wk3r[k2 + 1] = rdft_wk3ri_first[k1 + 0];
|
||||||
|
rdft_wk3r[k2 + 2] = rdft_wk3ri_second[k1 + 0];
|
||||||
|
rdft_wk3r[k2 + 3] = rdft_wk3ri_second[k1 + 0];
|
||||||
|
rdft_wk1i[k2 + 0] = -rdft_w[k2 + 1];
|
||||||
|
rdft_wk1i[k2 + 1] = rdft_w[k2 + 1];
|
||||||
|
rdft_wk1i[k2 + 2] = -rdft_w[k2 + 3];
|
||||||
|
rdft_wk1i[k2 + 3] = rdft_w[k2 + 3];
|
||||||
|
rdft_wk2i[k2 + 0] = -rdft_w[k1 + 1];
|
||||||
|
rdft_wk2i[k2 + 1] = rdft_w[k1 + 1];
|
||||||
|
rdft_wk2i[k2 + 2] = -rdft_w[k1 + 0];
|
||||||
|
rdft_wk2i[k2 + 3] = rdft_w[k1 + 0];
|
||||||
|
rdft_wk3i[k2 + 0] = -rdft_wk3ri_first[k1 + 1];
|
||||||
|
rdft_wk3i[k2 + 1] = rdft_wk3ri_first[k1 + 1];
|
||||||
|
rdft_wk3i[k2 + 2] = -rdft_wk3ri_second[k1 + 1];
|
||||||
|
rdft_wk3i[k2 + 3] = rdft_wk3ri_second[k1 + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void makect_32(void) {
|
||||||
|
float *c = rdft_w + 32;
|
||||||
|
const int nc = 32;
|
||||||
|
int j, nch;
|
||||||
|
float delta;
|
||||||
|
|
||||||
|
ip[1] = nc;
|
||||||
|
nch = nc >> 1;
|
||||||
|
delta = atanf(1.0f) / nch;
|
||||||
|
c[0] = cosf(delta * nch);
|
||||||
|
c[nch] = 0.5f * c[0];
|
||||||
|
for (j = 1; j < nch; j++) {
|
||||||
|
c[j] = 0.5f * cosf(delta * j);
|
||||||
|
c[nc - j] = 0.5f * sinf(delta * j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cft1st_128_C(float *a) {
|
||||||
|
const int n = 128;
|
||||||
|
int j, k1, k2;
|
||||||
|
float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
|
||||||
|
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
|
||||||
|
|
||||||
|
x0r = a[0] + a[2];
|
||||||
|
x0i = a[1] + a[3];
|
||||||
|
x1r = a[0] - a[2];
|
||||||
|
x1i = a[1] - a[3];
|
||||||
|
x2r = a[4] + a[6];
|
||||||
|
x2i = a[5] + a[7];
|
||||||
|
x3r = a[4] - a[6];
|
||||||
|
x3i = a[5] - a[7];
|
||||||
|
a[0] = x0r + x2r;
|
||||||
|
a[1] = x0i + x2i;
|
||||||
|
a[4] = x0r - x2r;
|
||||||
|
a[5] = x0i - x2i;
|
||||||
|
a[2] = x1r - x3i;
|
||||||
|
a[3] = x1i + x3r;
|
||||||
|
a[6] = x1r + x3i;
|
||||||
|
a[7] = x1i - x3r;
|
||||||
|
wk1r = rdft_w[2];
|
||||||
|
x0r = a[8] + a[10];
|
||||||
|
x0i = a[9] + a[11];
|
||||||
|
x1r = a[8] - a[10];
|
||||||
|
x1i = a[9] - a[11];
|
||||||
|
x2r = a[12] + a[14];
|
||||||
|
x2i = a[13] + a[15];
|
||||||
|
x3r = a[12] - a[14];
|
||||||
|
x3i = a[13] - a[15];
|
||||||
|
a[8] = x0r + x2r;
|
||||||
|
a[9] = x0i + x2i;
|
||||||
|
a[12] = x2i - x0i;
|
||||||
|
a[13] = x0r - x2r;
|
||||||
|
x0r = x1r - x3i;
|
||||||
|
x0i = x1i + x3r;
|
||||||
|
a[10] = wk1r * (x0r - x0i);
|
||||||
|
a[11] = wk1r * (x0r + x0i);
|
||||||
|
x0r = x3i + x1r;
|
||||||
|
x0i = x3r - x1i;
|
||||||
|
a[14] = wk1r * (x0i - x0r);
|
||||||
|
a[15] = wk1r * (x0i + x0r);
|
||||||
|
k1 = 0;
|
||||||
|
for (j = 16; j < n; j += 16) {
|
||||||
|
k1 += 2;
|
||||||
|
k2 = 2 * k1;
|
||||||
|
wk2r = rdft_w[k1 + 0];
|
||||||
|
wk2i = rdft_w[k1 + 1];
|
||||||
|
wk1r = rdft_w[k2 + 0];
|
||||||
|
wk1i = rdft_w[k2 + 1];
|
||||||
|
wk3r = rdft_wk3ri_first[k1 + 0];
|
||||||
|
wk3i = rdft_wk3ri_first[k1 + 1];
|
||||||
|
x0r = a[j + 0] + a[j + 2];
|
||||||
|
x0i = a[j + 1] + a[j + 3];
|
||||||
|
x1r = a[j + 0] - a[j + 2];
|
||||||
|
x1i = a[j + 1] - a[j + 3];
|
||||||
|
x2r = a[j + 4] + a[j + 6];
|
||||||
|
x2i = a[j + 5] + a[j + 7];
|
||||||
|
x3r = a[j + 4] - a[j + 6];
|
||||||
|
x3i = a[j + 5] - a[j + 7];
|
||||||
|
a[j + 0] = x0r + x2r;
|
||||||
|
a[j + 1] = x0i + x2i;
|
||||||
|
x0r -= x2r;
|
||||||
|
x0i -= x2i;
|
||||||
|
a[j + 4] = wk2r * x0r - wk2i * x0i;
|
||||||
|
a[j + 5] = wk2r * x0i + wk2i * x0r;
|
||||||
|
x0r = x1r - x3i;
|
||||||
|
x0i = x1i + x3r;
|
||||||
|
a[j + 2] = wk1r * x0r - wk1i * x0i;
|
||||||
|
a[j + 3] = wk1r * x0i + wk1i * x0r;
|
||||||
|
x0r = x1r + x3i;
|
||||||
|
x0i = x1i - x3r;
|
||||||
|
a[j + 6] = wk3r * x0r - wk3i * x0i;
|
||||||
|
a[j + 7] = wk3r * x0i + wk3i * x0r;
|
||||||
|
wk1r = rdft_w[k2 + 2];
|
||||||
|
wk1i = rdft_w[k2 + 3];
|
||||||
|
wk3r = rdft_wk3ri_second[k1 + 0];
|
||||||
|
wk3i = rdft_wk3ri_second[k1 + 1];
|
||||||
|
x0r = a[j + 8] + a[j + 10];
|
||||||
|
x0i = a[j + 9] + a[j + 11];
|
||||||
|
x1r = a[j + 8] - a[j + 10];
|
||||||
|
x1i = a[j + 9] - a[j + 11];
|
||||||
|
x2r = a[j + 12] + a[j + 14];
|
||||||
|
x2i = a[j + 13] + a[j + 15];
|
||||||
|
x3r = a[j + 12] - a[j + 14];
|
||||||
|
x3i = a[j + 13] - a[j + 15];
|
||||||
|
a[j + 8] = x0r + x2r;
|
||||||
|
a[j + 9] = x0i + x2i;
|
||||||
|
x0r -= x2r;
|
||||||
|
x0i -= x2i;
|
||||||
|
a[j + 12] = -wk2i * x0r - wk2r * x0i;
|
||||||
|
a[j + 13] = -wk2i * x0i + wk2r * x0r;
|
||||||
|
x0r = x1r - x3i;
|
||||||
|
x0i = x1i + x3r;
|
||||||
|
a[j + 10] = wk1r * x0r - wk1i * x0i;
|
||||||
|
a[j + 11] = wk1r * x0i + wk1i * x0r;
|
||||||
|
x0r = x1r + x3i;
|
||||||
|
x0i = x1i - x3r;
|
||||||
|
a[j + 14] = wk3r * x0r - wk3i * x0i;
|
||||||
|
a[j + 15] = wk3r * x0i + wk3i * x0r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cftmdl_128_C(float *a) {
|
||||||
|
const int l = 8;
|
||||||
|
const int n = 128;
|
||||||
|
const int m = 32;
|
||||||
|
int j0, j1, j2, j3, k, k1, k2, m2;
|
||||||
|
float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
|
||||||
|
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
|
||||||
|
|
||||||
|
for (j0 = 0; j0 < l; j0 += 2) {
|
||||||
|
j1 = j0 + 8;
|
||||||
|
j2 = j0 + 16;
|
||||||
|
j3 = j0 + 24;
|
||||||
|
x0r = a[j0 + 0] + a[j1 + 0];
|
||||||
|
x0i = a[j0 + 1] + a[j1 + 1];
|
||||||
|
x1r = a[j0 + 0] - a[j1 + 0];
|
||||||
|
x1i = a[j0 + 1] - a[j1 + 1];
|
||||||
|
x2r = a[j2 + 0] + a[j3 + 0];
|
||||||
|
x2i = a[j2 + 1] + a[j3 + 1];
|
||||||
|
x3r = a[j2 + 0] - a[j3 + 0];
|
||||||
|
x3i = a[j2 + 1] - a[j3 + 1];
|
||||||
|
a[j0 + 0] = x0r + x2r;
|
||||||
|
a[j0 + 1] = x0i + x2i;
|
||||||
|
a[j2 + 0] = x0r - x2r;
|
||||||
|
a[j2 + 1] = x0i - x2i;
|
||||||
|
a[j1 + 0] = x1r - x3i;
|
||||||
|
a[j1 + 1] = x1i + x3r;
|
||||||
|
a[j3 + 0] = x1r + x3i;
|
||||||
|
a[j3 + 1] = x1i - x3r;
|
||||||
|
}
|
||||||
|
wk1r = rdft_w[2];
|
||||||
|
for (j0 = m; j0 < l + m; j0 += 2) {
|
||||||
|
j1 = j0 + 8;
|
||||||
|
j2 = j0 + 16;
|
||||||
|
j3 = j0 + 24;
|
||||||
|
x0r = a[j0 + 0] + a[j1 + 0];
|
||||||
|
x0i = a[j0 + 1] + a[j1 + 1];
|
||||||
|
x1r = a[j0 + 0] - a[j1 + 0];
|
||||||
|
x1i = a[j0 + 1] - a[j1 + 1];
|
||||||
|
x2r = a[j2 + 0] + a[j3 + 0];
|
||||||
|
x2i = a[j2 + 1] + a[j3 + 1];
|
||||||
|
x3r = a[j2 + 0] - a[j3 + 0];
|
||||||
|
x3i = a[j2 + 1] - a[j3 + 1];
|
||||||
|
a[j0 + 0] = x0r + x2r;
|
||||||
|
a[j0 + 1] = x0i + x2i;
|
||||||
|
a[j2 + 0] = x2i - x0i;
|
||||||
|
a[j2 + 1] = x0r - x2r;
|
||||||
|
x0r = x1r - x3i;
|
||||||
|
x0i = x1i + x3r;
|
||||||
|
a[j1 + 0] = wk1r * (x0r - x0i);
|
||||||
|
a[j1 + 1] = wk1r * (x0r + x0i);
|
||||||
|
x0r = x3i + x1r;
|
||||||
|
x0i = x3r - x1i;
|
||||||
|
a[j3 + 0] = wk1r * (x0i - x0r);
|
||||||
|
a[j3 + 1] = wk1r * (x0i + x0r);
|
||||||
|
}
|
||||||
|
k1 = 0;
|
||||||
|
m2 = 2 * m;
|
||||||
|
for (k = m2; k < n; k += m2) {
|
||||||
|
k1 += 2;
|
||||||
|
k2 = 2 * k1;
|
||||||
|
wk2r = rdft_w[k1 + 0];
|
||||||
|
wk2i = rdft_w[k1 + 1];
|
||||||
|
wk1r = rdft_w[k2 + 0];
|
||||||
|
wk1i = rdft_w[k2 + 1];
|
||||||
|
wk3r = rdft_wk3ri_first[k1 + 0];
|
||||||
|
wk3i = rdft_wk3ri_first[k1 + 1];
|
||||||
|
for (j0 = k; j0 < l + k; j0 += 2) {
|
||||||
|
j1 = j0 + 8;
|
||||||
|
j2 = j0 + 16;
|
||||||
|
j3 = j0 + 24;
|
||||||
|
x0r = a[j0 + 0] + a[j1 + 0];
|
||||||
|
x0i = a[j0 + 1] + a[j1 + 1];
|
||||||
|
x1r = a[j0 + 0] - a[j1 + 0];
|
||||||
|
x1i = a[j0 + 1] - a[j1 + 1];
|
||||||
|
x2r = a[j2 + 0] + a[j3 + 0];
|
||||||
|
x2i = a[j2 + 1] + a[j3 + 1];
|
||||||
|
x3r = a[j2 + 0] - a[j3 + 0];
|
||||||
|
x3i = a[j2 + 1] - a[j3 + 1];
|
||||||
|
a[j0 + 0] = x0r + x2r;
|
||||||
|
a[j0 + 1] = x0i + x2i;
|
||||||
|
x0r -= x2r;
|
||||||
|
x0i -= x2i;
|
||||||
|
a[j2 + 0] = wk2r * x0r - wk2i * x0i;
|
||||||
|
a[j2 + 1] = wk2r * x0i + wk2i * x0r;
|
||||||
|
x0r = x1r - x3i;
|
||||||
|
x0i = x1i + x3r;
|
||||||
|
a[j1 + 0] = wk1r * x0r - wk1i * x0i;
|
||||||
|
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
|
||||||
|
x0r = x1r + x3i;
|
||||||
|
x0i = x1i - x3r;
|
||||||
|
a[j3 + 0] = wk3r * x0r - wk3i * x0i;
|
||||||
|
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
|
||||||
|
}
|
||||||
|
wk1r = rdft_w[k2 + 2];
|
||||||
|
wk1i = rdft_w[k2 + 3];
|
||||||
|
wk3r = rdft_wk3ri_second[k1 + 0];
|
||||||
|
wk3i = rdft_wk3ri_second[k1 + 1];
|
||||||
|
for (j0 = k + m; j0 < l + (k + m); j0 += 2) {
|
||||||
|
j1 = j0 + 8;
|
||||||
|
j2 = j0 + 16;
|
||||||
|
j3 = j0 + 24;
|
||||||
|
x0r = a[j0 + 0] + a[j1 + 0];
|
||||||
|
x0i = a[j0 + 1] + a[j1 + 1];
|
||||||
|
x1r = a[j0 + 0] - a[j1 + 0];
|
||||||
|
x1i = a[j0 + 1] - a[j1 + 1];
|
||||||
|
x2r = a[j2 + 0] + a[j3 + 0];
|
||||||
|
x2i = a[j2 + 1] + a[j3 + 1];
|
||||||
|
x3r = a[j2 + 0] - a[j3 + 0];
|
||||||
|
x3i = a[j2 + 1] - a[j3 + 1];
|
||||||
|
a[j0 + 0] = x0r + x2r;
|
||||||
|
a[j0 + 1] = x0i + x2i;
|
||||||
|
x0r -= x2r;
|
||||||
|
x0i -= x2i;
|
||||||
|
a[j2 + 0] = -wk2i * x0r - wk2r * x0i;
|
||||||
|
a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
|
||||||
|
x0r = x1r - x3i;
|
||||||
|
x0i = x1i + x3r;
|
||||||
|
a[j1 + 0] = wk1r * x0r - wk1i * x0i;
|
||||||
|
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
|
||||||
|
x0r = x1r + x3i;
|
||||||
|
x0i = x1i - x3r;
|
||||||
|
a[j3 + 0] = wk3r * x0r - wk3i * x0i;
|
||||||
|
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cftfsub_128(float *a) {
|
||||||
|
int j, j1, j2, j3, l;
|
||||||
|
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
|
||||||
|
|
||||||
|
cft1st_128(a);
|
||||||
|
cftmdl_128(a);
|
||||||
|
l = 32;
|
||||||
|
for (j = 0; j < l; j += 2) {
|
||||||
|
j1 = j + l;
|
||||||
|
j2 = j1 + l;
|
||||||
|
j3 = j2 + l;
|
||||||
|
x0r = a[j] + a[j1];
|
||||||
|
x0i = a[j + 1] + a[j1 + 1];
|
||||||
|
x1r = a[j] - a[j1];
|
||||||
|
x1i = a[j + 1] - a[j1 + 1];
|
||||||
|
x2r = a[j2] + a[j3];
|
||||||
|
x2i = a[j2 + 1] + a[j3 + 1];
|
||||||
|
x3r = a[j2] - a[j3];
|
||||||
|
x3i = a[j2 + 1] - a[j3 + 1];
|
||||||
|
a[j] = x0r + x2r;
|
||||||
|
a[j + 1] = x0i + x2i;
|
||||||
|
a[j2] = x0r - x2r;
|
||||||
|
a[j2 + 1] = x0i - x2i;
|
||||||
|
a[j1] = x1r - x3i;
|
||||||
|
a[j1 + 1] = x1i + x3r;
|
||||||
|
a[j3] = x1r + x3i;
|
||||||
|
a[j3 + 1] = x1i - x3r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cftbsub_128(float *a) {
|
||||||
|
int j, j1, j2, j3, l;
|
||||||
|
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
|
||||||
|
|
||||||
|
cft1st_128(a);
|
||||||
|
cftmdl_128(a);
|
||||||
|
l = 32;
|
||||||
|
|
||||||
|
for (j = 0; j < l; j += 2) {
|
||||||
|
j1 = j + l;
|
||||||
|
j2 = j1 + l;
|
||||||
|
j3 = j2 + l;
|
||||||
|
x0r = a[j] + a[j1];
|
||||||
|
x0i = -a[j + 1] - a[j1 + 1];
|
||||||
|
x1r = a[j] - a[j1];
|
||||||
|
x1i = -a[j + 1] + a[j1 + 1];
|
||||||
|
x2r = a[j2] + a[j3];
|
||||||
|
x2i = a[j2 + 1] + a[j3 + 1];
|
||||||
|
x3r = a[j2] - a[j3];
|
||||||
|
x3i = a[j2 + 1] - a[j3 + 1];
|
||||||
|
a[j] = x0r + x2r;
|
||||||
|
a[j + 1] = x0i - x2i;
|
||||||
|
a[j2] = x0r - x2r;
|
||||||
|
a[j2 + 1] = x0i + x2i;
|
||||||
|
a[j1] = x1r - x3i;
|
||||||
|
a[j1 + 1] = x1i - x3r;
|
||||||
|
a[j3] = x1r + x3i;
|
||||||
|
a[j3 + 1] = x1i + x3r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rftfsub_128_C(float *a) {
|
||||||
|
const float *c = rdft_w + 32;
|
||||||
|
int j1, j2, k1, k2;
|
||||||
|
float wkr, wki, xr, xi, yr, yi;
|
||||||
|
|
||||||
|
for (j1 = 1, j2 = 2; j2 < 64; j1 += 1, j2 += 2) {
|
||||||
|
k2 = 128 - j2;
|
||||||
|
k1 = 32 - j1;
|
||||||
|
wkr = 0.5f - c[k1];
|
||||||
|
wki = c[j1];
|
||||||
|
xr = a[j2 + 0] - a[k2 + 0];
|
||||||
|
xi = a[j2 + 1] + a[k2 + 1];
|
||||||
|
yr = wkr * xr - wki * xi;
|
||||||
|
yi = wkr * xi + wki * xr;
|
||||||
|
a[j2 + 0] -= yr;
|
||||||
|
a[j2 + 1] -= yi;
|
||||||
|
a[k2 + 0] += yr;
|
||||||
|
a[k2 + 1] -= yi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rftbsub_128_C(float *a) {
|
||||||
|
const float *c = rdft_w + 32;
|
||||||
|
int j1, j2, k1, k2;
|
||||||
|
float wkr, wki, xr, xi, yr, yi;
|
||||||
|
|
||||||
|
a[1] = -a[1];
|
||||||
|
for (j1 = 1, j2 = 2; j2 < 64; j1 += 1, j2 += 2) {
|
||||||
|
k2 = 128 - j2;
|
||||||
|
k1 = 32 - j1;
|
||||||
|
wkr = 0.5f - c[k1];
|
||||||
|
wki = c[j1];
|
||||||
|
xr = a[j2 + 0] - a[k2 + 0];
|
||||||
|
xi = a[j2 + 1] + a[k2 + 1];
|
||||||
|
yr = wkr * xr + wki * xi;
|
||||||
|
yi = wkr * xi - wki * xr;
|
||||||
|
a[j2 + 0] = a[j2 + 0] - yr;
|
||||||
|
a[j2 + 1] = yi - a[j2 + 1];
|
||||||
|
a[k2 + 0] = yr + a[k2 + 0];
|
||||||
|
a[k2 + 1] = yi - a[k2 + 1];
|
||||||
|
}
|
||||||
|
a[65] = -a[65];
|
||||||
|
}
|
||||||
|
|
||||||
|
void aec_rdft_forward_128(float *a) {
|
||||||
|
const int n = 128;
|
||||||
|
float xi;
|
||||||
|
|
||||||
|
bitrv2_32or128(n, ip + 2, a);
|
||||||
|
cftfsub_128(a);
|
||||||
|
rftfsub_128(a);
|
||||||
|
xi = a[0] - a[1];
|
||||||
|
a[0] += a[1];
|
||||||
|
a[1] = xi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aec_rdft_inverse_128(float *a) {
|
||||||
|
const int n = 128;
|
||||||
|
|
||||||
|
a[1] = 0.5f * (a[0] - a[1]);
|
||||||
|
a[0] -= a[1];
|
||||||
|
rftbsub_128(a);
|
||||||
|
bitrv2_32or128(n, ip + 2, a);
|
||||||
|
cftbsub_128(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// code path selection
|
||||||
|
rft_sub_128_t cft1st_128;
|
||||||
|
rft_sub_128_t cftmdl_128;
|
||||||
|
rft_sub_128_t rftfsub_128;
|
||||||
|
rft_sub_128_t rftbsub_128;
|
||||||
|
|
||||||
|
void aec_rdft_init(void) {
|
||||||
|
cft1st_128 = cft1st_128_C;
|
||||||
|
cftmdl_128 = cftmdl_128_C;
|
||||||
|
rftfsub_128 = rftfsub_128_C;
|
||||||
|
rftbsub_128 = rftbsub_128_C;
|
||||||
|
if (WebRtc_GetCPUInfo(kSSE2)) {
|
||||||
|
#if defined(WEBRTC_USE_SSE2)
|
||||||
|
aec_rdft_init_sse2();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// init library constants.
|
||||||
|
makewt_32();
|
||||||
|
makect_32();
|
||||||
|
}
|
49
src/modules/audio_processing/aec/main/source/aec_rdft.h
Normal file
49
src/modules/audio_processing/aec/main/source/aec_rdft.h
Normal file
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_RDFT_H_
|
||||||
|
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_RDFT_H_
|
||||||
|
|
||||||
|
#ifdef _MSC_VER /* visual c++ */
|
||||||
|
# define ALIGN16_BEG __declspec(align(16))
|
||||||
|
# define ALIGN16_END
|
||||||
|
#else /* gcc or icc */
|
||||||
|
# define ALIGN16_BEG
|
||||||
|
# define ALIGN16_END __attribute__((aligned(16)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// constants shared by all paths (C, SSE2).
|
||||||
|
extern float rdft_w[64];
|
||||||
|
// constants used by the C path.
|
||||||
|
extern float rdft_wk3ri_first[32];
|
||||||
|
extern float rdft_wk3ri_second[32];
|
||||||
|
// constants used by SSE2 but initialized in C path.
|
||||||
|
extern float rdft_wk1r[32];
|
||||||
|
extern float rdft_wk2r[32];
|
||||||
|
extern float rdft_wk3r[32];
|
||||||
|
extern float rdft_wk1i[32];
|
||||||
|
extern float rdft_wk2i[32];
|
||||||
|
extern float rdft_wk3i[32];
|
||||||
|
extern float cftmdl_wk1r[4];
|
||||||
|
|
||||||
|
// code path selection function pointers
|
||||||
|
typedef void (*rft_sub_128_t)(float *a);
|
||||||
|
extern rft_sub_128_t rftfsub_128;
|
||||||
|
extern rft_sub_128_t rftbsub_128;
|
||||||
|
extern rft_sub_128_t cft1st_128;
|
||||||
|
extern rft_sub_128_t cftmdl_128;
|
||||||
|
|
||||||
|
// entry points
|
||||||
|
void aec_rdft_init(void);
|
||||||
|
void aec_rdft_init_sse2(void);
|
||||||
|
void aec_rdft_forward_128(float *a);
|
||||||
|
void aec_rdft_inverse_128(float *a);
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_RDFT_H_
|
397
src/modules/audio_processing/aec/main/source/aec_rdft_sse2.c
Normal file
397
src/modules/audio_processing/aec/main/source/aec_rdft_sse2.c
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#if defined(WEBRTC_USE_SSE2)
|
||||||
|
#include <emmintrin.h>
|
||||||
|
|
||||||
|
#include "aec_rdft.h"
|
||||||
|
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END k_swap_sign[4] =
|
||||||
|
{-1.f, 1.f, -1.f, 1.f};
|
||||||
|
|
||||||
|
static void cft1st_128_SSE2(float *a) {
|
||||||
|
const __m128 mm_swap_sign = _mm_load_ps(k_swap_sign);
|
||||||
|
int j, k2;
|
||||||
|
|
||||||
|
for (k2 = 0, j = 0; j < 128; j += 16, k2 += 4) {
|
||||||
|
__m128 a00v = _mm_loadu_ps(&a[j + 0]);
|
||||||
|
__m128 a04v = _mm_loadu_ps(&a[j + 4]);
|
||||||
|
__m128 a08v = _mm_loadu_ps(&a[j + 8]);
|
||||||
|
__m128 a12v = _mm_loadu_ps(&a[j + 12]);
|
||||||
|
__m128 a01v = _mm_shuffle_ps(a00v, a08v, _MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
__m128 a23v = _mm_shuffle_ps(a00v, a08v, _MM_SHUFFLE(3, 2, 3 ,2));
|
||||||
|
__m128 a45v = _mm_shuffle_ps(a04v, a12v, _MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
__m128 a67v = _mm_shuffle_ps(a04v, a12v, _MM_SHUFFLE(3, 2, 3 ,2));
|
||||||
|
|
||||||
|
const __m128 wk1rv = _mm_load_ps(&rdft_wk1r[k2]);
|
||||||
|
const __m128 wk1iv = _mm_load_ps(&rdft_wk1i[k2]);
|
||||||
|
const __m128 wk2rv = _mm_load_ps(&rdft_wk2r[k2]);
|
||||||
|
const __m128 wk2iv = _mm_load_ps(&rdft_wk2i[k2]);
|
||||||
|
const __m128 wk3rv = _mm_load_ps(&rdft_wk3r[k2]);
|
||||||
|
const __m128 wk3iv = _mm_load_ps(&rdft_wk3i[k2]);
|
||||||
|
__m128 x0v = _mm_add_ps(a01v, a23v);
|
||||||
|
const __m128 x1v = _mm_sub_ps(a01v, a23v);
|
||||||
|
const __m128 x2v = _mm_add_ps(a45v, a67v);
|
||||||
|
const __m128 x3v = _mm_sub_ps(a45v, a67v);
|
||||||
|
a01v = _mm_add_ps(x0v, x2v);
|
||||||
|
x0v = _mm_sub_ps(x0v, x2v);
|
||||||
|
__m128 x0w = _mm_shuffle_ps(x0v, x0v, _MM_SHUFFLE(2, 3, 0 ,1));
|
||||||
|
|
||||||
|
const __m128 a45_0v = _mm_mul_ps(wk2rv, x0v);
|
||||||
|
const __m128 a45_1v = _mm_mul_ps(wk2iv, x0w);
|
||||||
|
a45v = _mm_add_ps(a45_0v, a45_1v);
|
||||||
|
|
||||||
|
const __m128 x3w = _mm_shuffle_ps(x3v, x3v, _MM_SHUFFLE(2, 3, 0 ,1));
|
||||||
|
const __m128 x3s = _mm_mul_ps(mm_swap_sign, x3w);
|
||||||
|
x0v = _mm_add_ps(x1v, x3s);
|
||||||
|
x0w = _mm_shuffle_ps(x0v, x0v, _MM_SHUFFLE(2, 3, 0 ,1));
|
||||||
|
const __m128 a23_0v = _mm_mul_ps(wk1rv, x0v);
|
||||||
|
const __m128 a23_1v = _mm_mul_ps(wk1iv, x0w);
|
||||||
|
a23v = _mm_add_ps(a23_0v, a23_1v);
|
||||||
|
|
||||||
|
x0v = _mm_sub_ps(x1v, x3s);
|
||||||
|
x0w = _mm_shuffle_ps(x0v, x0v, _MM_SHUFFLE(2, 3, 0 ,1));
|
||||||
|
const __m128 a67_0v = _mm_mul_ps(wk3rv, x0v);
|
||||||
|
const __m128 a67_1v = _mm_mul_ps(wk3iv, x0w);
|
||||||
|
a67v = _mm_add_ps(a67_0v, a67_1v);
|
||||||
|
|
||||||
|
a00v = _mm_shuffle_ps(a01v, a23v, _MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
a04v = _mm_shuffle_ps(a45v, a67v, _MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
a08v = _mm_shuffle_ps(a01v, a23v, _MM_SHUFFLE(3, 2, 3 ,2));
|
||||||
|
a12v = _mm_shuffle_ps(a45v, a67v, _MM_SHUFFLE(3, 2, 3 ,2));
|
||||||
|
_mm_storeu_ps(&a[j + 0], a00v);
|
||||||
|
_mm_storeu_ps(&a[j + 4], a04v);
|
||||||
|
_mm_storeu_ps(&a[j + 8], a08v);
|
||||||
|
_mm_storeu_ps(&a[j + 12], a12v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cftmdl_128_SSE2(float *a) {
|
||||||
|
const int l = 8;
|
||||||
|
const __m128 mm_swap_sign = _mm_load_ps(k_swap_sign);
|
||||||
|
int j0, k, k1, k2;
|
||||||
|
|
||||||
|
__m128 wk1rv = _mm_load_ps(cftmdl_wk1r);
|
||||||
|
for (j0 = 0; j0 < l; j0 += 2) {
|
||||||
|
const __m128i a_00 = _mm_loadl_epi64((__m128i*)&a[j0 + 0]);
|
||||||
|
const __m128i a_08 = _mm_loadl_epi64((__m128i*)&a[j0 + 8]);
|
||||||
|
const __m128i a_32 = _mm_loadl_epi64((__m128i*)&a[j0 + 32]);
|
||||||
|
const __m128i a_40 = _mm_loadl_epi64((__m128i*)&a[j0 + 40]);
|
||||||
|
const __m128 a_00_32 = _mm_shuffle_ps((__m128)a_00, (__m128)a_32,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
const __m128 a_08_40 = _mm_shuffle_ps((__m128)a_08, (__m128)a_40,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
__m128 x0r0_0i0_0r1_x0i1 = _mm_add_ps(a_00_32, a_08_40);
|
||||||
|
const __m128 x1r0_1i0_1r1_x1i1 = _mm_sub_ps(a_00_32, a_08_40);
|
||||||
|
|
||||||
|
const __m128i a_16 = _mm_loadl_epi64((__m128i*)&a[j0 + 16]);
|
||||||
|
const __m128i a_24 = _mm_loadl_epi64((__m128i*)&a[j0 + 24]);
|
||||||
|
const __m128i a_48 = _mm_loadl_epi64((__m128i*)&a[j0 + 48]);
|
||||||
|
const __m128i a_56 = _mm_loadl_epi64((__m128i*)&a[j0 + 56]);
|
||||||
|
const __m128 a_16_48 = _mm_shuffle_ps((__m128)a_16, (__m128)a_48,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
const __m128 a_24_56 = _mm_shuffle_ps((__m128)a_24, (__m128)a_56,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
const __m128 x2r0_2i0_2r1_x2i1 = _mm_add_ps(a_16_48, a_24_56);
|
||||||
|
const __m128 x3r0_3i0_3r1_x3i1 = _mm_sub_ps(a_16_48, a_24_56);
|
||||||
|
|
||||||
|
const __m128 xx0 = _mm_add_ps(x0r0_0i0_0r1_x0i1, x2r0_2i0_2r1_x2i1);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 0], (__m128i)xx0);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 32],
|
||||||
|
_mm_shuffle_epi32((__m128i)xx0, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||||
|
const __m128 xx1 = _mm_sub_ps(x0r0_0i0_0r1_x0i1, x2r0_2i0_2r1_x2i1);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 16], (__m128i)xx1);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 48],
|
||||||
|
_mm_shuffle_epi32((__m128i)xx1, _MM_SHUFFLE(2, 3, 2, 3)));
|
||||||
|
a[j0 + 48] = -a[j0 + 48];
|
||||||
|
|
||||||
|
const __m128 x3i0_3r0_3i1_x3r1 = (__m128)
|
||||||
|
_mm_shuffle_epi32((__m128i)x3r0_3i0_3r1_x3i1, _MM_SHUFFLE(2, 3, 0, 1));
|
||||||
|
const __m128 x3_swapped = _mm_mul_ps(mm_swap_sign, x3i0_3r0_3i1_x3r1);
|
||||||
|
const __m128 x1_x3_add = _mm_add_ps(x1r0_1i0_1r1_x1i1, x3_swapped);
|
||||||
|
const __m128 x1_x3_sub = _mm_sub_ps(x1r0_1i0_1r1_x1i1, x3_swapped);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 8], (__m128i)x1_x3_add);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 24], (__m128i)x1_x3_sub);
|
||||||
|
|
||||||
|
const __m128 yy0 = _mm_shuffle_ps(x1_x3_add, x1_x3_sub,
|
||||||
|
_MM_SHUFFLE(2, 2, 2 ,2));
|
||||||
|
const __m128 yy1 = _mm_shuffle_ps(x1_x3_add, x1_x3_sub,
|
||||||
|
_MM_SHUFFLE(3, 3, 3 ,3));
|
||||||
|
const __m128 yy2 = _mm_mul_ps(mm_swap_sign, yy1);
|
||||||
|
const __m128 yy3 = _mm_add_ps(yy0, yy2);
|
||||||
|
const __m128 yy4 = _mm_mul_ps(wk1rv, yy3);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 40], (__m128i)yy4);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 56],
|
||||||
|
_mm_shuffle_epi32((__m128i)yy4, _MM_SHUFFLE(2, 3, 2, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
k1 = 0;
|
||||||
|
k = 64;
|
||||||
|
k1 += 2;
|
||||||
|
k2 = 2 * k1;
|
||||||
|
const __m128 wk2rv = _mm_load_ps(&rdft_wk2r[k2+0]);
|
||||||
|
const __m128 wk2iv = _mm_load_ps(&rdft_wk2i[k2+0]);
|
||||||
|
wk1rv = _mm_load_ps(&rdft_wk1r[k2+0]);
|
||||||
|
const __m128 wk1iv = _mm_load_ps(&rdft_wk1i[k2+0]);
|
||||||
|
const __m128 wk3rv = _mm_load_ps(&rdft_wk3r[k2+0]);
|
||||||
|
const __m128 wk3iv = _mm_load_ps(&rdft_wk3i[k2+0]);
|
||||||
|
for (j0 = k; j0 < l + k; j0 += 2) {
|
||||||
|
const __m128i a_00 = _mm_loadl_epi64((__m128i*)&a[j0 + 0]);
|
||||||
|
const __m128i a_08 = _mm_loadl_epi64((__m128i*)&a[j0 + 8]);
|
||||||
|
const __m128i a_32 = _mm_loadl_epi64((__m128i*)&a[j0 + 32]);
|
||||||
|
const __m128i a_40 = _mm_loadl_epi64((__m128i*)&a[j0 + 40]);
|
||||||
|
const __m128 a_00_32 = _mm_shuffle_ps((__m128)a_00, (__m128)a_32,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
const __m128 a_08_40 = _mm_shuffle_ps((__m128)a_08, (__m128)a_40,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
__m128 x0r0_0i0_0r1_x0i1 = _mm_add_ps(a_00_32, a_08_40);
|
||||||
|
const __m128 x1r0_1i0_1r1_x1i1 = _mm_sub_ps(a_00_32, a_08_40);
|
||||||
|
|
||||||
|
const __m128i a_16 = _mm_loadl_epi64((__m128i*)&a[j0 + 16]);
|
||||||
|
const __m128i a_24 = _mm_loadl_epi64((__m128i*)&a[j0 + 24]);
|
||||||
|
const __m128i a_48 = _mm_loadl_epi64((__m128i*)&a[j0 + 48]);
|
||||||
|
const __m128i a_56 = _mm_loadl_epi64((__m128i*)&a[j0 + 56]);
|
||||||
|
const __m128 a_16_48 = _mm_shuffle_ps((__m128)a_16, (__m128)a_48,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
const __m128 a_24_56 = _mm_shuffle_ps((__m128)a_24, (__m128)a_56,
|
||||||
|
_MM_SHUFFLE(1, 0, 1 ,0));
|
||||||
|
const __m128 x2r0_2i0_2r1_x2i1 = _mm_add_ps(a_16_48, a_24_56);
|
||||||
|
const __m128 x3r0_3i0_3r1_x3i1 = _mm_sub_ps(a_16_48, a_24_56);
|
||||||
|
|
||||||
|
const __m128 xx = _mm_add_ps(x0r0_0i0_0r1_x0i1, x2r0_2i0_2r1_x2i1);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 0], (__m128i)xx);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 32],
|
||||||
|
_mm_shuffle_epi32((__m128i)xx, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||||
|
|
||||||
|
const __m128 xx1 = _mm_sub_ps(x0r0_0i0_0r1_x0i1, x2r0_2i0_2r1_x2i1);
|
||||||
|
const __m128 xx2 = _mm_mul_ps(xx1 , wk2rv);
|
||||||
|
const __m128 xx3 = _mm_mul_ps(wk2iv,
|
||||||
|
(__m128)_mm_shuffle_epi32((__m128i)xx1, _MM_SHUFFLE(2, 3, 0, 1)));
|
||||||
|
const __m128 xx4 = _mm_add_ps(xx2, xx3);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 16], (__m128i)xx4);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 48],
|
||||||
|
_mm_shuffle_epi32((__m128i)xx4, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||||
|
|
||||||
|
const __m128 x3i0_3r0_3i1_x3r1 = (__m128)
|
||||||
|
_mm_shuffle_epi32((__m128i)x3r0_3i0_3r1_x3i1, _MM_SHUFFLE(2, 3, 0, 1));
|
||||||
|
const __m128 x3_swapped = _mm_mul_ps(mm_swap_sign, x3i0_3r0_3i1_x3r1);
|
||||||
|
const __m128 x1_x3_add = _mm_add_ps(x1r0_1i0_1r1_x1i1, x3_swapped);
|
||||||
|
const __m128 x1_x3_sub = _mm_sub_ps(x1r0_1i0_1r1_x1i1, x3_swapped);
|
||||||
|
|
||||||
|
const __m128 xx10 = _mm_mul_ps(x1_x3_add, wk1rv);
|
||||||
|
const __m128 xx11 = _mm_mul_ps(wk1iv,
|
||||||
|
(__m128)_mm_shuffle_epi32((__m128i)x1_x3_add, _MM_SHUFFLE(2, 3, 0, 1)));
|
||||||
|
const __m128 xx12 = _mm_add_ps(xx10, xx11);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 8], (__m128i)xx12);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 40],
|
||||||
|
_mm_shuffle_epi32((__m128i)xx12, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||||
|
|
||||||
|
const __m128 xx20 = _mm_mul_ps(x1_x3_sub, wk3rv);
|
||||||
|
const __m128 xx21 = _mm_mul_ps(wk3iv,
|
||||||
|
(__m128)_mm_shuffle_epi32((__m128i)x1_x3_sub, _MM_SHUFFLE(2, 3, 0, 1)));
|
||||||
|
const __m128 xx22 = _mm_add_ps(xx20, xx21);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 24], (__m128i)xx22);
|
||||||
|
_mm_storel_epi64((__m128i*)&a[j0 + 56],
|
||||||
|
_mm_shuffle_epi32((__m128i)xx22, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rftfsub_128_SSE2(float *a) {
|
||||||
|
const float *c = rdft_w + 32;
|
||||||
|
int j1, j2, k1, k2;
|
||||||
|
float wkr, wki, xr, xi, yr, yi;
|
||||||
|
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END k_half[4] =
|
||||||
|
{0.5f, 0.5f, 0.5f, 0.5f};
|
||||||
|
const __m128 mm_half = _mm_load_ps(k_half);
|
||||||
|
|
||||||
|
// Vectorized code (four at once).
|
||||||
|
// Note: commented number are indexes for the first iteration of the loop.
|
||||||
|
for (j1 = 1, j2 = 2; j2 + 7 < 64; j1 += 4, j2 += 8) {
|
||||||
|
// Load 'wk'.
|
||||||
|
const __m128 c_j1 = _mm_loadu_ps(&c[ j1]); // 1, 2, 3, 4,
|
||||||
|
const __m128 c_k1 = _mm_loadu_ps(&c[29 - j1]); // 28, 29, 30, 31,
|
||||||
|
const __m128 wkrt = _mm_sub_ps(mm_half, c_k1); // 28, 29, 30, 31,
|
||||||
|
const __m128 wkr_ =
|
||||||
|
_mm_shuffle_ps(wkrt, wkrt, _MM_SHUFFLE(0, 1, 2, 3)); // 31, 30, 29, 28,
|
||||||
|
const __m128 wki_ = c_j1; // 1, 2, 3, 4,
|
||||||
|
// Load and shuffle 'a'.
|
||||||
|
const __m128 a_j2_0 = _mm_loadu_ps(&a[0 + j2]); // 2, 3, 4, 5,
|
||||||
|
const __m128 a_j2_4 = _mm_loadu_ps(&a[4 + j2]); // 6, 7, 8, 9,
|
||||||
|
const __m128 a_k2_0 = _mm_loadu_ps(&a[122 - j2]); // 120, 121, 122, 123,
|
||||||
|
const __m128 a_k2_4 = _mm_loadu_ps(&a[126 - j2]); // 124, 125, 126, 127,
|
||||||
|
const __m128 a_j2_p0 = _mm_shuffle_ps(a_j2_0, a_j2_4,
|
||||||
|
_MM_SHUFFLE(2, 0, 2 ,0)); // 2, 4, 6, 8,
|
||||||
|
const __m128 a_j2_p1 = _mm_shuffle_ps(a_j2_0, a_j2_4,
|
||||||
|
_MM_SHUFFLE(3, 1, 3 ,1)); // 3, 5, 7, 9,
|
||||||
|
const __m128 a_k2_p0 = _mm_shuffle_ps(a_k2_4, a_k2_0,
|
||||||
|
_MM_SHUFFLE(0, 2, 0 ,2)); // 126, 124, 122, 120,
|
||||||
|
const __m128 a_k2_p1 = _mm_shuffle_ps(a_k2_4, a_k2_0,
|
||||||
|
_MM_SHUFFLE(1, 3, 1 ,3)); // 127, 125, 123, 121,
|
||||||
|
// Calculate 'x'.
|
||||||
|
const __m128 xr_ = _mm_sub_ps(a_j2_p0, a_k2_p0);
|
||||||
|
// 2-126, 4-124, 6-122, 8-120,
|
||||||
|
const __m128 xi_ = _mm_add_ps(a_j2_p1, a_k2_p1);
|
||||||
|
// 3-127, 5-125, 7-123, 9-121,
|
||||||
|
// Calculate product into 'y'.
|
||||||
|
// yr = wkr * xr - wki * xi;
|
||||||
|
// yi = wkr * xi + wki * xr;
|
||||||
|
const __m128 a_ = _mm_mul_ps(wkr_, xr_);
|
||||||
|
const __m128 b_ = _mm_mul_ps(wki_, xi_);
|
||||||
|
const __m128 c_ = _mm_mul_ps(wkr_, xi_);
|
||||||
|
const __m128 d_ = _mm_mul_ps(wki_, xr_);
|
||||||
|
const __m128 yr_ = _mm_sub_ps(a_, b_); // 2-126, 4-124, 6-122, 8-120,
|
||||||
|
const __m128 yi_ = _mm_add_ps(c_, d_); // 3-127, 5-125, 7-123, 9-121,
|
||||||
|
// Update 'a'.
|
||||||
|
// a[j2 + 0] -= yr;
|
||||||
|
// a[j2 + 1] -= yi;
|
||||||
|
// a[k2 + 0] += yr;
|
||||||
|
// a[k2 + 1] -= yi;
|
||||||
|
const __m128 a_j2_p0n = _mm_sub_ps(a_j2_p0, yr_); // 2, 4, 6, 8,
|
||||||
|
const __m128 a_j2_p1n = _mm_sub_ps(a_j2_p1, yi_); // 3, 5, 7, 9,
|
||||||
|
const __m128 a_k2_p0n = _mm_add_ps(a_k2_p0, yr_); // 126, 124, 122, 120,
|
||||||
|
const __m128 a_k2_p1n = _mm_sub_ps(a_k2_p1, yi_); // 127, 125, 123, 121,
|
||||||
|
// Shuffle in right order and store.
|
||||||
|
const __m128 a_j2_0n = _mm_unpacklo_ps(a_j2_p0n, a_j2_p1n);
|
||||||
|
// 2, 3, 4, 5,
|
||||||
|
const __m128 a_j2_4n = _mm_unpackhi_ps(a_j2_p0n, a_j2_p1n);
|
||||||
|
// 6, 7, 8, 9,
|
||||||
|
const __m128 a_k2_0nt = _mm_unpackhi_ps(a_k2_p0n, a_k2_p1n);
|
||||||
|
// 122, 123, 120, 121,
|
||||||
|
const __m128 a_k2_4nt = _mm_unpacklo_ps(a_k2_p0n, a_k2_p1n);
|
||||||
|
// 126, 127, 124, 125,
|
||||||
|
const __m128 a_k2_0n = _mm_shuffle_ps(a_k2_0nt, a_k2_0nt,
|
||||||
|
_MM_SHUFFLE(1, 0, 3 ,2)); // 120, 121, 122, 123,
|
||||||
|
const __m128 a_k2_4n = _mm_shuffle_ps(a_k2_4nt, a_k2_4nt,
|
||||||
|
_MM_SHUFFLE(1, 0, 3 ,2)); // 124, 125, 126, 127,
|
||||||
|
_mm_storeu_ps(&a[0 + j2], a_j2_0n);
|
||||||
|
_mm_storeu_ps(&a[4 + j2], a_j2_4n);
|
||||||
|
_mm_storeu_ps(&a[122 - j2], a_k2_0n);
|
||||||
|
_mm_storeu_ps(&a[126 - j2], a_k2_4n);
|
||||||
|
}
|
||||||
|
// Scalar code for the remaining items.
|
||||||
|
for (; j2 < 64; j1 += 1, j2 += 2) {
|
||||||
|
k2 = 128 - j2;
|
||||||
|
k1 = 32 - j1;
|
||||||
|
wkr = 0.5f - c[k1];
|
||||||
|
wki = c[j1];
|
||||||
|
xr = a[j2 + 0] - a[k2 + 0];
|
||||||
|
xi = a[j2 + 1] + a[k2 + 1];
|
||||||
|
yr = wkr * xr - wki * xi;
|
||||||
|
yi = wkr * xi + wki * xr;
|
||||||
|
a[j2 + 0] -= yr;
|
||||||
|
a[j2 + 1] -= yi;
|
||||||
|
a[k2 + 0] += yr;
|
||||||
|
a[k2 + 1] -= yi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rftbsub_128_SSE2(float *a) {
|
||||||
|
const float *c = rdft_w + 32;
|
||||||
|
int j1, j2, k1, k2;
|
||||||
|
float wkr, wki, xr, xi, yr, yi;
|
||||||
|
|
||||||
|
static const ALIGN16_BEG float ALIGN16_END k_half[4] =
|
||||||
|
{0.5f, 0.5f, 0.5f, 0.5f};
|
||||||
|
const __m128 mm_half = _mm_load_ps(k_half);
|
||||||
|
|
||||||
|
a[1] = -a[1];
|
||||||
|
// Vectorized code (four at once).
|
||||||
|
// Note: commented number are indexes for the first iteration of the loop.
|
||||||
|
for (j1 = 1, j2 = 2; j2 + 7 < 64; j1 += 4, j2 += 8) {
|
||||||
|
// Load 'wk'.
|
||||||
|
const __m128 c_j1 = _mm_loadu_ps(&c[ j1]); // 1, 2, 3, 4,
|
||||||
|
const __m128 c_k1 = _mm_loadu_ps(&c[29 - j1]); // 28, 29, 30, 31,
|
||||||
|
const __m128 wkrt = _mm_sub_ps(mm_half, c_k1); // 28, 29, 30, 31,
|
||||||
|
const __m128 wkr_ =
|
||||||
|
_mm_shuffle_ps(wkrt, wkrt, _MM_SHUFFLE(0, 1, 2, 3)); // 31, 30, 29, 28,
|
||||||
|
const __m128 wki_ = c_j1; // 1, 2, 3, 4,
|
||||||
|
// Load and shuffle 'a'.
|
||||||
|
const __m128 a_j2_0 = _mm_loadu_ps(&a[0 + j2]); // 2, 3, 4, 5,
|
||||||
|
const __m128 a_j2_4 = _mm_loadu_ps(&a[4 + j2]); // 6, 7, 8, 9,
|
||||||
|
const __m128 a_k2_0 = _mm_loadu_ps(&a[122 - j2]); // 120, 121, 122, 123,
|
||||||
|
const __m128 a_k2_4 = _mm_loadu_ps(&a[126 - j2]); // 124, 125, 126, 127,
|
||||||
|
const __m128 a_j2_p0 = _mm_shuffle_ps(a_j2_0, a_j2_4,
|
||||||
|
_MM_SHUFFLE(2, 0, 2 ,0)); // 2, 4, 6, 8,
|
||||||
|
const __m128 a_j2_p1 = _mm_shuffle_ps(a_j2_0, a_j2_4,
|
||||||
|
_MM_SHUFFLE(3, 1, 3 ,1)); // 3, 5, 7, 9,
|
||||||
|
const __m128 a_k2_p0 = _mm_shuffle_ps(a_k2_4, a_k2_0,
|
||||||
|
_MM_SHUFFLE(0, 2, 0 ,2)); // 126, 124, 122, 120,
|
||||||
|
const __m128 a_k2_p1 = _mm_shuffle_ps(a_k2_4, a_k2_0,
|
||||||
|
_MM_SHUFFLE(1, 3, 1 ,3)); // 127, 125, 123, 121,
|
||||||
|
// Calculate 'x'.
|
||||||
|
const __m128 xr_ = _mm_sub_ps(a_j2_p0, a_k2_p0);
|
||||||
|
// 2-126, 4-124, 6-122, 8-120,
|
||||||
|
const __m128 xi_ = _mm_add_ps(a_j2_p1, a_k2_p1);
|
||||||
|
// 3-127, 5-125, 7-123, 9-121,
|
||||||
|
// Calculate product into 'y'.
|
||||||
|
// yr = wkr * xr + wki * xi;
|
||||||
|
// yi = wkr * xi - wki * xr;
|
||||||
|
const __m128 a_ = _mm_mul_ps(wkr_, xr_);
|
||||||
|
const __m128 b_ = _mm_mul_ps(wki_, xi_);
|
||||||
|
const __m128 c_ = _mm_mul_ps(wkr_, xi_);
|
||||||
|
const __m128 d_ = _mm_mul_ps(wki_, xr_);
|
||||||
|
const __m128 yr_ = _mm_add_ps(a_, b_); // 2-126, 4-124, 6-122, 8-120,
|
||||||
|
const __m128 yi_ = _mm_sub_ps(c_, d_); // 3-127, 5-125, 7-123, 9-121,
|
||||||
|
// Update 'a'.
|
||||||
|
// a[j2 + 0] = a[j2 + 0] - yr;
|
||||||
|
// a[j2 + 1] = yi - a[j2 + 1];
|
||||||
|
// a[k2 + 0] = yr + a[k2 + 0];
|
||||||
|
// a[k2 + 1] = yi - a[k2 + 1];
|
||||||
|
const __m128 a_j2_p0n = _mm_sub_ps(a_j2_p0, yr_); // 2, 4, 6, 8,
|
||||||
|
const __m128 a_j2_p1n = _mm_sub_ps(yi_, a_j2_p1); // 3, 5, 7, 9,
|
||||||
|
const __m128 a_k2_p0n = _mm_add_ps(a_k2_p0, yr_); // 126, 124, 122, 120,
|
||||||
|
const __m128 a_k2_p1n = _mm_sub_ps(yi_, a_k2_p1); // 127, 125, 123, 121,
|
||||||
|
// Shuffle in right order and store.
|
||||||
|
const __m128 a_j2_0n = _mm_unpacklo_ps(a_j2_p0n, a_j2_p1n);
|
||||||
|
// 2, 3, 4, 5,
|
||||||
|
const __m128 a_j2_4n = _mm_unpackhi_ps(a_j2_p0n, a_j2_p1n);
|
||||||
|
// 6, 7, 8, 9,
|
||||||
|
const __m128 a_k2_0nt = _mm_unpackhi_ps(a_k2_p0n, a_k2_p1n);
|
||||||
|
// 122, 123, 120, 121,
|
||||||
|
const __m128 a_k2_4nt = _mm_unpacklo_ps(a_k2_p0n, a_k2_p1n);
|
||||||
|
// 126, 127, 124, 125,
|
||||||
|
const __m128 a_k2_0n = _mm_shuffle_ps(a_k2_0nt, a_k2_0nt,
|
||||||
|
_MM_SHUFFLE(1, 0, 3 ,2)); // 120, 121, 122, 123,
|
||||||
|
const __m128 a_k2_4n = _mm_shuffle_ps(a_k2_4nt, a_k2_4nt,
|
||||||
|
_MM_SHUFFLE(1, 0, 3 ,2)); // 124, 125, 126, 127,
|
||||||
|
_mm_storeu_ps(&a[0 + j2], a_j2_0n);
|
||||||
|
_mm_storeu_ps(&a[4 + j2], a_j2_4n);
|
||||||
|
_mm_storeu_ps(&a[122 - j2], a_k2_0n);
|
||||||
|
_mm_storeu_ps(&a[126 - j2], a_k2_4n);
|
||||||
|
}
|
||||||
|
// Scalar code for the remaining items.
|
||||||
|
for (; j2 < 64; j1 += 1, j2 += 2) {
|
||||||
|
k2 = 128 - j2;
|
||||||
|
k1 = 32 - j1;
|
||||||
|
wkr = 0.5f - c[k1];
|
||||||
|
wki = c[j1];
|
||||||
|
xr = a[j2 + 0] - a[k2 + 0];
|
||||||
|
xi = a[j2 + 1] + a[k2 + 1];
|
||||||
|
yr = wkr * xr + wki * xi;
|
||||||
|
yi = wkr * xi - wki * xr;
|
||||||
|
a[j2 + 0] = a[j2 + 0] - yr;
|
||||||
|
a[j2 + 1] = yi - a[j2 + 1];
|
||||||
|
a[k2 + 0] = yr + a[k2 + 0];
|
||||||
|
a[k2 + 1] = yi - a[k2 + 1];
|
||||||
|
}
|
||||||
|
a[65] = -a[65];
|
||||||
|
}
|
||||||
|
|
||||||
|
void aec_rdft_init_sse2(void) {
|
||||||
|
cft1st_128 = cft1st_128_SSE2;
|
||||||
|
cftmdl_128 = cftmdl_128_SSE2;
|
||||||
|
rftfsub_128 = rftfsub_128_SSE2;
|
||||||
|
rftbsub_128 = rftbsub_128_SSE2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBRTC_USE_SS2
|
824
src/modules/audio_processing/aec/main/source/echo_cancellation.c
Normal file
824
src/modules/audio_processing/aec/main/source/echo_cancellation.c
Normal file
@ -0,0 +1,824 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains the API functions for the AEC.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "echo_cancellation.h"
|
||||||
|
#include "aec_core.h"
|
||||||
|
#include "ring_buffer.h"
|
||||||
|
#include "resampler.h"
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUF_SIZE_FRAMES 50 // buffer size (frames)
|
||||||
|
// Maximum length of resampled signal. Must be an integer multiple of frames
|
||||||
|
// (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN
|
||||||
|
// The factor of 2 handles wb, and the + 1 is as a safety margin
|
||||||
|
#define MAX_RESAMP_LEN (5 * FRAME_LEN)
|
||||||
|
|
||||||
|
static const int bufSizeSamp = BUF_SIZE_FRAMES * FRAME_LEN; // buffer size (samples)
|
||||||
|
static const int sampMsNb = 8; // samples per ms in nb
|
||||||
|
// Target suppression levels for nlp modes
|
||||||
|
// log{0.001, 0.00001, 0.00000001}
|
||||||
|
static const float targetSupp[3] = {-6.9f, -11.5f, -18.4f};
|
||||||
|
static const float minOverDrive[3] = {1.0f, 2.0f, 5.0f};
|
||||||
|
static const int initCheck = 42;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int delayCtr;
|
||||||
|
int sampFreq;
|
||||||
|
int splitSampFreq;
|
||||||
|
int scSampFreq;
|
||||||
|
float sampFactor; // scSampRate / sampFreq
|
||||||
|
short nlpMode;
|
||||||
|
short autoOnOff;
|
||||||
|
short activity;
|
||||||
|
short skewMode;
|
||||||
|
short bufSizeStart;
|
||||||
|
//short bufResetCtr; // counts number of noncausal frames
|
||||||
|
int knownDelay;
|
||||||
|
|
||||||
|
// Stores the last frame added to the farend buffer
|
||||||
|
short farendOld[2][FRAME_LEN];
|
||||||
|
short initFlag; // indicates if AEC has been initialized
|
||||||
|
|
||||||
|
// Variables used for averaging far end buffer size
|
||||||
|
short counter;
|
||||||
|
short sum;
|
||||||
|
short firstVal;
|
||||||
|
short checkBufSizeCtr;
|
||||||
|
|
||||||
|
// Variables used for delay shifts
|
||||||
|
short msInSndCardBuf;
|
||||||
|
short filtDelay;
|
||||||
|
int timeForDelayChange;
|
||||||
|
int ECstartup;
|
||||||
|
int checkBuffSize;
|
||||||
|
int delayChange;
|
||||||
|
short lastDelayDiff;
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
FILE *bufFile;
|
||||||
|
FILE *delayFile;
|
||||||
|
FILE *skewFile;
|
||||||
|
FILE *preCompFile;
|
||||||
|
FILE *postCompFile;
|
||||||
|
#endif // AEC_DEBUG
|
||||||
|
|
||||||
|
// Structures
|
||||||
|
void *farendBuf;
|
||||||
|
void *resampler;
|
||||||
|
|
||||||
|
int skewFrCtr;
|
||||||
|
int resample; // if the skew is small enough we don't resample
|
||||||
|
int highSkewCtr;
|
||||||
|
float skew;
|
||||||
|
|
||||||
|
int lastError;
|
||||||
|
|
||||||
|
aec_t *aec;
|
||||||
|
} aecpc_t;
|
||||||
|
|
||||||
|
// Estimates delay to set the position of the farend buffer read pointer
|
||||||
|
// (controlled by knownDelay)
|
||||||
|
static int EstBufDelay(aecpc_t *aecInst, short msInSndCardBuf);
|
||||||
|
|
||||||
|
// Stuffs the farend buffer if the estimated delay is too large
|
||||||
|
static int DelayComp(aecpc_t *aecInst);
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_Create(void **aecInst)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc;
|
||||||
|
if (aecInst == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aecpc = malloc(sizeof(aecpc_t));
|
||||||
|
*aecInst = aecpc;
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WebRtcAec_CreateAec(&aecpc->aec) == -1) {
|
||||||
|
WebRtcAec_Free(aecpc);
|
||||||
|
aecpc = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WebRtcApm_CreateBuffer(&aecpc->farendBuf, bufSizeSamp) == -1) {
|
||||||
|
WebRtcAec_Free(aecpc);
|
||||||
|
aecpc = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WebRtcAec_CreateResampler(&aecpc->resampler) == -1) {
|
||||||
|
WebRtcAec_Free(aecpc);
|
||||||
|
aecpc = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aecpc->initFlag = 0;
|
||||||
|
aecpc->lastError = 0;
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
aecpc->aec->farFile = fopen("aecFar.pcm","wb");
|
||||||
|
aecpc->aec->nearFile = fopen("aecNear.pcm","wb");
|
||||||
|
aecpc->aec->outFile = fopen("aecOut.pcm","wb");
|
||||||
|
aecpc->aec->outLpFile = fopen("aecOutLp.pcm","wb");
|
||||||
|
|
||||||
|
aecpc->bufFile = fopen("aecBuf.dat", "wb");
|
||||||
|
aecpc->skewFile = fopen("aecSkew.dat", "wb");
|
||||||
|
aecpc->delayFile = fopen("aecDelay.dat", "wb");
|
||||||
|
aecpc->preCompFile = fopen("preComp.pcm", "wb");
|
||||||
|
aecpc->postCompFile = fopen("postComp.pcm", "wb");
|
||||||
|
#endif // AEC_DEBUG
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_Free(void *aecInst)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
fclose(aecpc->aec->farFile);
|
||||||
|
fclose(aecpc->aec->nearFile);
|
||||||
|
fclose(aecpc->aec->outFile);
|
||||||
|
fclose(aecpc->aec->outLpFile);
|
||||||
|
|
||||||
|
fclose(aecpc->bufFile);
|
||||||
|
fclose(aecpc->skewFile);
|
||||||
|
fclose(aecpc->delayFile);
|
||||||
|
fclose(aecpc->preCompFile);
|
||||||
|
fclose(aecpc->postCompFile);
|
||||||
|
#endif // AEC_DEBUG
|
||||||
|
|
||||||
|
WebRtcAec_FreeAec(aecpc->aec);
|
||||||
|
WebRtcApm_FreeBuffer(aecpc->farendBuf);
|
||||||
|
WebRtcAec_FreeResampler(aecpc->resampler);
|
||||||
|
free(aecpc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_Init(void *aecInst, WebRtc_Word32 sampFreq, WebRtc_Word32 scSampFreq)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
AecConfig aecConfig;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sampFreq != 8000 && sampFreq != 16000 && sampFreq != 32000) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aecpc->sampFreq = sampFreq;
|
||||||
|
|
||||||
|
if (scSampFreq < 1 || scSampFreq > 96000) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aecpc->scSampFreq = scSampFreq;
|
||||||
|
|
||||||
|
// Initialize echo canceller core
|
||||||
|
if (WebRtcAec_InitAec(aecpc->aec, aecpc->sampFreq) == -1) {
|
||||||
|
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize farend buffer
|
||||||
|
if (WebRtcApm_InitBuffer(aecpc->farendBuf) == -1) {
|
||||||
|
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WebRtcAec_InitResampler(aecpc->resampler, aecpc->scSampFreq) == -1) {
|
||||||
|
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aecpc->initFlag = initCheck; // indicates that initilisation has been done
|
||||||
|
|
||||||
|
if (aecpc->sampFreq == 32000) {
|
||||||
|
aecpc->splitSampFreq = 16000;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aecpc->splitSampFreq = sampFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
aecpc->skewFrCtr = 0;
|
||||||
|
aecpc->activity = 0;
|
||||||
|
|
||||||
|
aecpc->delayChange = 1;
|
||||||
|
aecpc->delayCtr = 0;
|
||||||
|
|
||||||
|
aecpc->sum = 0;
|
||||||
|
aecpc->counter = 0;
|
||||||
|
aecpc->checkBuffSize = 1;
|
||||||
|
aecpc->firstVal = 0;
|
||||||
|
|
||||||
|
aecpc->ECstartup = 1;
|
||||||
|
aecpc->bufSizeStart = 0;
|
||||||
|
aecpc->checkBufSizeCtr = 0;
|
||||||
|
aecpc->filtDelay = 0;
|
||||||
|
aecpc->timeForDelayChange =0;
|
||||||
|
aecpc->knownDelay = 0;
|
||||||
|
aecpc->lastDelayDiff = 0;
|
||||||
|
|
||||||
|
aecpc->skew = 0;
|
||||||
|
aecpc->resample = kAecFalse;
|
||||||
|
aecpc->highSkewCtr = 0;
|
||||||
|
aecpc->sampFactor = (aecpc->scSampFreq * 1.0f) / aecpc->splitSampFreq;
|
||||||
|
|
||||||
|
memset(&aecpc->farendOld[0][0], 0, 160);
|
||||||
|
|
||||||
|
// Default settings.
|
||||||
|
aecConfig.nlpMode = kAecNlpModerate;
|
||||||
|
aecConfig.skewMode = kAecFalse;
|
||||||
|
aecConfig.metricsMode = kAecFalse;
|
||||||
|
|
||||||
|
if (WebRtcAec_set_config(aecpc, aecConfig) == -1) {
|
||||||
|
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only buffer L band for farend
|
||||||
|
WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst, const WebRtc_Word16 *farend,
|
||||||
|
WebRtc_Word16 nrOfSamples)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
WebRtc_Word32 retVal = 0;
|
||||||
|
short newNrOfSamples;
|
||||||
|
short newFarend[MAX_RESAMP_LEN];
|
||||||
|
float skew;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (farend == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->initFlag != initCheck) {
|
||||||
|
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// number of samples == 160 for SWB input
|
||||||
|
if (nrOfSamples != 80 && nrOfSamples != 160) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
skew = aecpc->skew;
|
||||||
|
|
||||||
|
// TODO: Is this really a good idea?
|
||||||
|
if (!aecpc->ECstartup) {
|
||||||
|
DelayComp(aecpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
|
||||||
|
// Resample and get a new number of samples
|
||||||
|
newNrOfSamples = WebRtcAec_ResampleLinear(aecpc->resampler,
|
||||||
|
farend,
|
||||||
|
nrOfSamples,
|
||||||
|
skew,
|
||||||
|
newFarend);
|
||||||
|
WebRtcApm_WriteBuffer(aecpc->farendBuf, newFarend, newNrOfSamples);
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
fwrite(farend, 2, nrOfSamples, aecpc->preCompFile);
|
||||||
|
fwrite(newFarend, 2, newNrOfSamples, aecpc->postCompFile);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WebRtcApm_WriteBuffer(aecpc->farendBuf, farend, nrOfSamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_Process(void *aecInst, const WebRtc_Word16 *nearend,
|
||||||
|
const WebRtc_Word16 *nearendH, WebRtc_Word16 *out, WebRtc_Word16 *outH,
|
||||||
|
WebRtc_Word16 nrOfSamples, WebRtc_Word16 msInSndCardBuf, WebRtc_Word32 skew)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
WebRtc_Word32 retVal = 0;
|
||||||
|
short i;
|
||||||
|
short farend[FRAME_LEN];
|
||||||
|
short nmbrOfFilledBuffers;
|
||||||
|
short nBlocks10ms;
|
||||||
|
short nFrames;
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
short msInAECBuf;
|
||||||
|
#endif
|
||||||
|
// Limit resampling to doubling/halving of signal
|
||||||
|
const float minSkewEst = -0.5f;
|
||||||
|
const float maxSkewEst = 1.0f;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nearend == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->initFlag != initCheck) {
|
||||||
|
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// number of samples == 160 for SWB input
|
||||||
|
if (nrOfSamples != 80 && nrOfSamples != 160) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for valid pointers based on sampling rate
|
||||||
|
if (aecpc->sampFreq == 32000 && nearendH == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msInSndCardBuf < 0) {
|
||||||
|
msInSndCardBuf = 0;
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
|
||||||
|
retVal = -1;
|
||||||
|
}
|
||||||
|
else if (msInSndCardBuf > 500) {
|
||||||
|
msInSndCardBuf = 500;
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
|
||||||
|
retVal = -1;
|
||||||
|
}
|
||||||
|
msInSndCardBuf += 10;
|
||||||
|
aecpc->msInSndCardBuf = msInSndCardBuf;
|
||||||
|
|
||||||
|
if (aecpc->skewMode == kAecTrue) {
|
||||||
|
if (aecpc->skewFrCtr < 25) {
|
||||||
|
aecpc->skewFrCtr++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
|
||||||
|
if (retVal == -1) {
|
||||||
|
aecpc->skew = 0;
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
aecpc->skew /= aecpc->sampFactor*nrOfSamples;
|
||||||
|
|
||||||
|
if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) {
|
||||||
|
aecpc->resample = kAecFalse;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aecpc->resample = kAecTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->skew < minSkewEst) {
|
||||||
|
aecpc->skew = minSkewEst;
|
||||||
|
}
|
||||||
|
else if (aecpc->skew > maxSkewEst) {
|
||||||
|
aecpc->skew = maxSkewEst;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nFrames = nrOfSamples / FRAME_LEN;
|
||||||
|
nBlocks10ms = nFrames / aecpc->aec->mult;
|
||||||
|
|
||||||
|
if (aecpc->ECstartup) {
|
||||||
|
if (nearend != out) {
|
||||||
|
// Only needed if they don't already point to the same place.
|
||||||
|
memcpy(out, nearend, sizeof(short) * nrOfSamples);
|
||||||
|
}
|
||||||
|
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecpc->farendBuf) / FRAME_LEN;
|
||||||
|
|
||||||
|
// The AEC is in the start up mode
|
||||||
|
// AEC is disabled until the soundcard buffer and farend buffers are OK
|
||||||
|
|
||||||
|
// Mechanism to ensure that the soundcard buffer is reasonably stable.
|
||||||
|
if (aecpc->checkBuffSize) {
|
||||||
|
|
||||||
|
aecpc->checkBufSizeCtr++;
|
||||||
|
// Before we fill up the far end buffer we require the amount of data on the
|
||||||
|
// sound card to be stable (+/-8 ms) compared to the first value. This
|
||||||
|
// comparison is made during the following 4 consecutive frames. If it seems
|
||||||
|
// to be stable then we start to fill up the far end buffer.
|
||||||
|
|
||||||
|
if (aecpc->counter == 0) {
|
||||||
|
aecpc->firstVal = aecpc->msInSndCardBuf;
|
||||||
|
aecpc->sum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abs(aecpc->firstVal - aecpc->msInSndCardBuf) <
|
||||||
|
WEBRTC_SPL_MAX(0.2 * aecpc->msInSndCardBuf, sampMsNb)) {
|
||||||
|
aecpc->sum += aecpc->msInSndCardBuf;
|
||||||
|
aecpc->counter++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aecpc->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->counter*nBlocks10ms >= 6) {
|
||||||
|
// The farend buffer size is determined in blocks of 80 samples
|
||||||
|
// Use 75% of the average value of the soundcard buffer
|
||||||
|
aecpc->bufSizeStart = WEBRTC_SPL_MIN((int) (0.75 * (aecpc->sum *
|
||||||
|
aecpc->aec->mult) / (aecpc->counter * 10)), BUF_SIZE_FRAMES);
|
||||||
|
// buffersize has now been determined
|
||||||
|
aecpc->checkBuffSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->checkBufSizeCtr * nBlocks10ms > 50) {
|
||||||
|
// for really bad sound cards, don't disable echocanceller for more than 0.5 sec
|
||||||
|
aecpc->bufSizeStart = WEBRTC_SPL_MIN((int) (0.75 * (aecpc->msInSndCardBuf *
|
||||||
|
aecpc->aec->mult) / 10), BUF_SIZE_FRAMES);
|
||||||
|
aecpc->checkBuffSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if checkBuffSize changed in the if-statement above
|
||||||
|
if (!aecpc->checkBuffSize) {
|
||||||
|
// soundcard buffer is now reasonably stable
|
||||||
|
// When the far end buffer is filled with approximately the same amount of
|
||||||
|
// data as the amount on the sound card we end the start up phase and start
|
||||||
|
// to cancel echoes.
|
||||||
|
|
||||||
|
if (nmbrOfFilledBuffers == aecpc->bufSizeStart) {
|
||||||
|
aecpc->ECstartup = 0; // Enable the AEC
|
||||||
|
}
|
||||||
|
else if (nmbrOfFilledBuffers > aecpc->bufSizeStart) {
|
||||||
|
WebRtcApm_FlushBuffer(aecpc->farendBuf, WebRtcApm_get_buffer_size(aecpc->farendBuf) -
|
||||||
|
aecpc->bufSizeStart * FRAME_LEN);
|
||||||
|
aecpc->ECstartup = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// AEC is enabled
|
||||||
|
|
||||||
|
// Note only 1 block supported for nb and 2 blocks for wb
|
||||||
|
for (i = 0; i < nFrames; i++) {
|
||||||
|
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecpc->farendBuf) / FRAME_LEN;
|
||||||
|
|
||||||
|
// Check that there is data in the far end buffer
|
||||||
|
if (nmbrOfFilledBuffers > 0) {
|
||||||
|
// Get the next 80 samples from the farend buffer
|
||||||
|
WebRtcApm_ReadBuffer(aecpc->farendBuf, farend, FRAME_LEN);
|
||||||
|
|
||||||
|
// Always store the last frame for use when we run out of data
|
||||||
|
memcpy(&(aecpc->farendOld[i][0]), farend, FRAME_LEN * sizeof(short));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// We have no data so we use the last played frame
|
||||||
|
memcpy(farend, &(aecpc->farendOld[i][0]), FRAME_LEN * sizeof(short));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call buffer delay estimator when all data is extracted,
|
||||||
|
// i.e. i = 0 for NB and i = 1 for WB or SWB
|
||||||
|
if ((i == 0 && aecpc->splitSampFreq == 8000) ||
|
||||||
|
(i == 1 && (aecpc->splitSampFreq == 16000))) {
|
||||||
|
EstBufDelay(aecpc, aecpc->msInSndCardBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the AEC
|
||||||
|
WebRtcAec_ProcessFrame(aecpc->aec, farend, &nearend[FRAME_LEN * i], &nearendH[FRAME_LEN * i],
|
||||||
|
&out[FRAME_LEN * i], &outH[FRAME_LEN * i], aecpc->knownDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AEC_DEBUG
|
||||||
|
msInAECBuf = WebRtcApm_get_buffer_size(aecpc->farendBuf) / (sampMsNb*aecpc->aec->mult);
|
||||||
|
fwrite(&msInAECBuf, 2, 1, aecpc->bufFile);
|
||||||
|
fwrite(&(aecpc->knownDelay), sizeof(aecpc->knownDelay), 1, aecpc->delayFile);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->initFlag != initCheck) {
|
||||||
|
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.skewMode != kAecFalse && config.skewMode != kAecTrue) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aecpc->skewMode = config.skewMode;
|
||||||
|
|
||||||
|
if (config.nlpMode != kAecNlpConservative && config.nlpMode !=
|
||||||
|
kAecNlpModerate && config.nlpMode != kAecNlpAggressive) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aecpc->nlpMode = config.nlpMode;
|
||||||
|
aecpc->aec->targetSupp = targetSupp[aecpc->nlpMode];
|
||||||
|
aecpc->aec->minOverDrive = minOverDrive[aecpc->nlpMode];
|
||||||
|
|
||||||
|
if (config.metricsMode != kAecFalse && config.metricsMode != kAecTrue) {
|
||||||
|
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aecpc->aec->metricsMode = config.metricsMode;
|
||||||
|
if (aecpc->aec->metricsMode == kAecTrue) {
|
||||||
|
WebRtcAec_InitMetrics(aecpc->aec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->initFlag != initCheck) {
|
||||||
|
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
config->nlpMode = aecpc->nlpMode;
|
||||||
|
config->skewMode = aecpc->skewMode;
|
||||||
|
config->metricsMode = aecpc->aec->metricsMode;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->initFlag != initCheck) {
|
||||||
|
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = aecpc->aec->echoState;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics)
|
||||||
|
{
|
||||||
|
const float upweight = 0.7f;
|
||||||
|
float dtmp;
|
||||||
|
short stmp;
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metrics == NULL) {
|
||||||
|
aecpc->lastError = AEC_NULL_POINTER_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aecpc->initFlag != initCheck) {
|
||||||
|
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERL
|
||||||
|
metrics->erl.instant = (short) aecpc->aec->erl.instant;
|
||||||
|
|
||||||
|
if ((aecpc->aec->erl.himean > offsetLevel) && (aecpc->aec->erl.average > offsetLevel)) {
|
||||||
|
// Use a mix between regular average and upper part average
|
||||||
|
dtmp = upweight * aecpc->aec->erl.himean + (1 - upweight) * aecpc->aec->erl.average;
|
||||||
|
metrics->erl.average = (short) dtmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
metrics->erl.average = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics->erl.max = (short) aecpc->aec->erl.max;
|
||||||
|
|
||||||
|
if (aecpc->aec->erl.min < (offsetLevel * (-1))) {
|
||||||
|
metrics->erl.min = (short) aecpc->aec->erl.min;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
metrics->erl.min = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERLE
|
||||||
|
metrics->erle.instant = (short) aecpc->aec->erle.instant;
|
||||||
|
|
||||||
|
if ((aecpc->aec->erle.himean > offsetLevel) && (aecpc->aec->erle.average > offsetLevel)) {
|
||||||
|
// Use a mix between regular average and upper part average
|
||||||
|
dtmp = upweight * aecpc->aec->erle.himean + (1 - upweight) * aecpc->aec->erle.average;
|
||||||
|
metrics->erle.average = (short) dtmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
metrics->erle.average = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics->erle.max = (short) aecpc->aec->erle.max;
|
||||||
|
|
||||||
|
if (aecpc->aec->erle.min < (offsetLevel * (-1))) {
|
||||||
|
metrics->erle.min = (short) aecpc->aec->erle.min;
|
||||||
|
} else {
|
||||||
|
metrics->erle.min = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RERL
|
||||||
|
if ((metrics->erl.average > offsetLevel) && (metrics->erle.average > offsetLevel)) {
|
||||||
|
stmp = metrics->erl.average + metrics->erle.average;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stmp = offsetLevel;
|
||||||
|
}
|
||||||
|
metrics->rerl.average = stmp;
|
||||||
|
|
||||||
|
// No other statistics needed, but returned for completeness
|
||||||
|
metrics->rerl.instant = stmp;
|
||||||
|
metrics->rerl.max = stmp;
|
||||||
|
metrics->rerl.min = stmp;
|
||||||
|
|
||||||
|
// A_NLP
|
||||||
|
metrics->aNlp.instant = (short) aecpc->aec->aNlp.instant;
|
||||||
|
|
||||||
|
if ((aecpc->aec->aNlp.himean > offsetLevel) && (aecpc->aec->aNlp.average > offsetLevel)) {
|
||||||
|
// Use a mix between regular average and upper part average
|
||||||
|
dtmp = upweight * aecpc->aec->aNlp.himean + (1 - upweight) * aecpc->aec->aNlp.average;
|
||||||
|
metrics->aNlp.average = (short) dtmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
metrics->aNlp.average = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics->aNlp.max = (short) aecpc->aec->aNlp.max;
|
||||||
|
|
||||||
|
if (aecpc->aec->aNlp.min < (offsetLevel * (-1))) {
|
||||||
|
metrics->aNlp.min = (short) aecpc->aec->aNlp.min;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
metrics->aNlp.min = offsetLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
|
||||||
|
{
|
||||||
|
const char version[] = "AEC 2.5.0";
|
||||||
|
const short versionLen = (short)strlen(version) + 1; // +1 for null-termination
|
||||||
|
|
||||||
|
if (versionStr == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versionLen > len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(versionStr, version, versionLen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst)
|
||||||
|
{
|
||||||
|
aecpc_t *aecpc = aecInst;
|
||||||
|
|
||||||
|
if (aecpc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aecpc->lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int EstBufDelay(aecpc_t *aecpc, short msInSndCardBuf)
|
||||||
|
{
|
||||||
|
short delayNew, nSampFar, nSampSndCard;
|
||||||
|
short diff;
|
||||||
|
|
||||||
|
nSampFar = WebRtcApm_get_buffer_size(aecpc->farendBuf);
|
||||||
|
nSampSndCard = msInSndCardBuf * sampMsNb * aecpc->aec->mult;
|
||||||
|
|
||||||
|
delayNew = nSampSndCard - nSampFar;
|
||||||
|
|
||||||
|
// Account for resampling frame delay
|
||||||
|
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
|
||||||
|
delayNew -= kResamplingDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delayNew < FRAME_LEN) {
|
||||||
|
WebRtcApm_FlushBuffer(aecpc->farendBuf, FRAME_LEN);
|
||||||
|
delayNew += FRAME_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
aecpc->filtDelay = WEBRTC_SPL_MAX(0, (short)(0.8*aecpc->filtDelay + 0.2*delayNew));
|
||||||
|
|
||||||
|
diff = aecpc->filtDelay - aecpc->knownDelay;
|
||||||
|
if (diff > 224) {
|
||||||
|
if (aecpc->lastDelayDiff < 96) {
|
||||||
|
aecpc->timeForDelayChange = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aecpc->timeForDelayChange++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (diff < 96 && aecpc->knownDelay > 0) {
|
||||||
|
if (aecpc->lastDelayDiff > 224) {
|
||||||
|
aecpc->timeForDelayChange = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aecpc->timeForDelayChange++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aecpc->timeForDelayChange = 0;
|
||||||
|
}
|
||||||
|
aecpc->lastDelayDiff = diff;
|
||||||
|
|
||||||
|
if (aecpc->timeForDelayChange > 25) {
|
||||||
|
aecpc->knownDelay = WEBRTC_SPL_MAX((int)aecpc->filtDelay - 160, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DelayComp(aecpc_t *aecpc)
|
||||||
|
{
|
||||||
|
int nSampFar, nSampSndCard, delayNew, nSampAdd;
|
||||||
|
const int maxStuffSamp = 10 * FRAME_LEN;
|
||||||
|
|
||||||
|
nSampFar = WebRtcApm_get_buffer_size(aecpc->farendBuf);
|
||||||
|
nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->aec->mult;
|
||||||
|
delayNew = nSampSndCard - nSampFar;
|
||||||
|
|
||||||
|
// Account for resampling frame delay
|
||||||
|
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
|
||||||
|
delayNew -= kResamplingDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delayNew > FAR_BUF_LEN - FRAME_LEN*aecpc->aec->mult) {
|
||||||
|
// The difference of the buffersizes is larger than the maximum
|
||||||
|
// allowed known delay. Compensate by stuffing the buffer.
|
||||||
|
nSampAdd = (int)(WEBRTC_SPL_MAX((int)(0.5 * nSampSndCard - nSampFar),
|
||||||
|
FRAME_LEN));
|
||||||
|
nSampAdd = WEBRTC_SPL_MIN(nSampAdd, maxStuffSamp);
|
||||||
|
|
||||||
|
WebRtcApm_StuffBuffer(aecpc->farendBuf, nSampAdd);
|
||||||
|
aecpc->delayChange = 1; // the delay needs to be updated
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
233
src/modules/audio_processing/aec/main/source/resampler.c
Normal file
233
src/modules/audio_processing/aec/main/source/resampler.c
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Resamples a signal to an arbitrary rate. Used by the AEC to compensate for clock
|
||||||
|
* skew by resampling the farend signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "resampler.h"
|
||||||
|
#include "aec_core.h"
|
||||||
|
|
||||||
|
enum { kFrameBufferSize = FRAME_LEN * 4 };
|
||||||
|
enum { kEstimateLengthFrames = 400 };
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short buffer[kFrameBufferSize];
|
||||||
|
float position;
|
||||||
|
|
||||||
|
int deviceSampleRateHz;
|
||||||
|
int skewData[kEstimateLengthFrames];
|
||||||
|
int skewDataIndex;
|
||||||
|
float skewEstimate;
|
||||||
|
} resampler_t;
|
||||||
|
|
||||||
|
static int EstimateSkew(const int* rawSkew,
|
||||||
|
int size,
|
||||||
|
int absLimit,
|
||||||
|
float *skewEst);
|
||||||
|
|
||||||
|
int WebRtcAec_CreateResampler(void **resampInst)
|
||||||
|
{
|
||||||
|
resampler_t *obj = malloc(sizeof(resampler_t));
|
||||||
|
*resampInst = obj;
|
||||||
|
if (obj == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAec_InitResampler(void *resampInst, int deviceSampleRateHz)
|
||||||
|
{
|
||||||
|
resampler_t *obj = (resampler_t*) resampInst;
|
||||||
|
memset(obj->buffer, 0, sizeof(obj->buffer));
|
||||||
|
obj->position = 0.0;
|
||||||
|
|
||||||
|
obj->deviceSampleRateHz = deviceSampleRateHz;
|
||||||
|
memset(obj->skewData, 0, sizeof(obj->skewData));
|
||||||
|
obj->skewDataIndex = 0;
|
||||||
|
obj->skewEstimate = 0.0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAec_FreeResampler(void *resampInst)
|
||||||
|
{
|
||||||
|
resampler_t *obj = (resampler_t*) resampInst;
|
||||||
|
free(obj);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAec_ResampleLinear(void *resampInst,
|
||||||
|
const short *inspeech,
|
||||||
|
int size,
|
||||||
|
float skew,
|
||||||
|
short *outspeech)
|
||||||
|
{
|
||||||
|
resampler_t *obj = (resampler_t*) resampInst;
|
||||||
|
|
||||||
|
short *y;
|
||||||
|
float be, tnew, interp;
|
||||||
|
int tn, outsize, mm;
|
||||||
|
|
||||||
|
if (size < 0 || size > 2 * FRAME_LEN) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new frame data in lookahead
|
||||||
|
memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay],
|
||||||
|
inspeech,
|
||||||
|
size * sizeof(short));
|
||||||
|
|
||||||
|
// Sample rate ratio
|
||||||
|
be = 1 + skew;
|
||||||
|
|
||||||
|
// Loop over input frame
|
||||||
|
mm = 0;
|
||||||
|
y = &obj->buffer[FRAME_LEN]; // Point at current frame
|
||||||
|
|
||||||
|
tnew = be * mm + obj->position;
|
||||||
|
tn = (int) tnew;
|
||||||
|
|
||||||
|
while (tn < size) {
|
||||||
|
|
||||||
|
// Interpolation
|
||||||
|
interp = y[tn] + (tnew - tn) * (y[tn+1] - y[tn]);
|
||||||
|
|
||||||
|
if (interp > 32767) {
|
||||||
|
interp = 32767;
|
||||||
|
}
|
||||||
|
else if (interp < -32768) {
|
||||||
|
interp = -32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
outspeech[mm] = (short) interp;
|
||||||
|
mm++;
|
||||||
|
|
||||||
|
tnew = be * mm + obj->position;
|
||||||
|
tn = (int) tnew;
|
||||||
|
}
|
||||||
|
|
||||||
|
outsize = mm;
|
||||||
|
obj->position += outsize * be - size;
|
||||||
|
|
||||||
|
// Shift buffer
|
||||||
|
memmove(obj->buffer,
|
||||||
|
&obj->buffer[size],
|
||||||
|
(kFrameBufferSize - size) * sizeof(short));
|
||||||
|
|
||||||
|
return outsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRtcAec_GetSkew(void *resampInst, int rawSkew, float *skewEst)
|
||||||
|
{
|
||||||
|
resampler_t *obj = (resampler_t*)resampInst;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (obj->skewDataIndex < kEstimateLengthFrames) {
|
||||||
|
obj->skewData[obj->skewDataIndex] = rawSkew;
|
||||||
|
obj->skewDataIndex++;
|
||||||
|
}
|
||||||
|
else if (obj->skewDataIndex == kEstimateLengthFrames) {
|
||||||
|
err = EstimateSkew(obj->skewData,
|
||||||
|
kEstimateLengthFrames,
|
||||||
|
obj->deviceSampleRateHz,
|
||||||
|
skewEst);
|
||||||
|
obj->skewEstimate = *skewEst;
|
||||||
|
obj->skewDataIndex++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*skewEst = obj->skewEstimate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EstimateSkew(const int* rawSkew,
|
||||||
|
int size,
|
||||||
|
int deviceSampleRateHz,
|
||||||
|
float *skewEst)
|
||||||
|
{
|
||||||
|
const int absLimitOuter = (int)(0.04f * deviceSampleRateHz);
|
||||||
|
const int absLimitInner = (int)(0.0025f * deviceSampleRateHz);
|
||||||
|
int i = 0;
|
||||||
|
int n = 0;
|
||||||
|
float rawAvg = 0;
|
||||||
|
float err = 0;
|
||||||
|
float rawAbsDev = 0;
|
||||||
|
int upperLimit = 0;
|
||||||
|
int lowerLimit = 0;
|
||||||
|
float cumSum = 0;
|
||||||
|
float x = 0;
|
||||||
|
float x2 = 0;
|
||||||
|
float y = 0;
|
||||||
|
float xy = 0;
|
||||||
|
float xAvg = 0;
|
||||||
|
float denom = 0;
|
||||||
|
float skew = 0;
|
||||||
|
|
||||||
|
*skewEst = 0; // Set in case of error below.
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) {
|
||||||
|
n++;
|
||||||
|
rawAvg += rawSkew[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
assert(n > 0);
|
||||||
|
rawAvg /= n;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) {
|
||||||
|
err = rawSkew[i] - rawAvg;
|
||||||
|
rawAbsDev += err >= 0 ? err : -err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(n > 0);
|
||||||
|
rawAbsDev /= n;
|
||||||
|
upperLimit = (int)(rawAvg + 5 * rawAbsDev + 1); // +1 for ceiling.
|
||||||
|
lowerLimit = (int)(rawAvg - 5 * rawAbsDev - 1); // -1 for floor.
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if ((rawSkew[i] < absLimitInner && rawSkew[i] > -absLimitInner) ||
|
||||||
|
(rawSkew[i] < upperLimit && rawSkew[i] > lowerLimit)) {
|
||||||
|
n++;
|
||||||
|
cumSum += rawSkew[i];
|
||||||
|
x += n;
|
||||||
|
x2 += n*n;
|
||||||
|
y += cumSum;
|
||||||
|
xy += n * cumSum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
assert(n > 0);
|
||||||
|
xAvg = x / n;
|
||||||
|
denom = x2 - xAvg*x;
|
||||||
|
|
||||||
|
if (denom != 0) {
|
||||||
|
skew = (xy - xAvg*y) / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
*skewEst = skew;
|
||||||
|
return 0;
|
||||||
|
}
|
32
src/modules/audio_processing/aec/main/source/resampler.h
Normal file
32
src/modules/audio_processing/aec/main/source/resampler.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_RESAMPLER_H_
|
||||||
|
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_RESAMPLER_H_
|
||||||
|
|
||||||
|
enum { kResamplingDelay = 1 };
|
||||||
|
|
||||||
|
// Unless otherwise specified, functions return 0 on success and -1 on error
|
||||||
|
int WebRtcAec_CreateResampler(void **resampInst);
|
||||||
|
int WebRtcAec_InitResampler(void *resampInst, int deviceSampleRateHz);
|
||||||
|
int WebRtcAec_FreeResampler(void *resampInst);
|
||||||
|
|
||||||
|
// Estimates skew from raw measurement.
|
||||||
|
int WebRtcAec_GetSkew(void *resampInst, int rawSkew, float *skewEst);
|
||||||
|
|
||||||
|
// Resamples input using linear interpolation.
|
||||||
|
// Returns size of resampled array.
|
||||||
|
int WebRtcAec_ResampleLinear(void *resampInst,
|
||||||
|
const short *inspeech,
|
||||||
|
int size,
|
||||||
|
float skew,
|
||||||
|
short *outspeech);
|
||||||
|
|
||||||
|
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_RESAMPLER_H_
|
@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_INTERFACE_ECHO_CONTROL_MOBILE_H_
|
||||||
|
#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_INTERFACE_ECHO_CONTROL_MOBILE_H_
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AecmFalse = 0,
|
||||||
|
AecmTrue
|
||||||
|
};
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
#define AECM_UNSPECIFIED_ERROR 12000
|
||||||
|
#define AECM_UNSUPPORTED_FUNCTION_ERROR 12001
|
||||||
|
#define AECM_UNINITIALIZED_ERROR 12002
|
||||||
|
#define AECM_NULL_POINTER_ERROR 12003
|
||||||
|
#define AECM_BAD_PARAMETER_ERROR 12004
|
||||||
|
|
||||||
|
// Warnings
|
||||||
|
#define AECM_BAD_PARAMETER_WARNING 12100
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WebRtc_Word16 cngMode; // AECM_FALSE, AECM_TRUE (default)
|
||||||
|
WebRtc_Word16 echoMode; // 0, 1, 2, 3 (default), 4
|
||||||
|
} AecmConfig;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocates the memory needed by the AECM. The memory needs to be
|
||||||
|
* initialized separately using the WebRtcAecm_Init() function.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void **aecmInst Pointer to the AECM instance to be
|
||||||
|
* created and initialized
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_Create(void **aecmInst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function releases the memory allocated by WebRtcAecm_Create()
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_Free(void *aecmInst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes an AECM instance.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
* WebRtc_Word32 sampFreq Sampling frequency of data
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_Init(void* aecmInst,
|
||||||
|
WebRtc_Word32 sampFreq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inserts an 80 or 160 sample block of data into the farend buffer.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
* WebRtc_Word16 *farend In buffer containing one frame of
|
||||||
|
* farend signal
|
||||||
|
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_BufferFarend(void* aecmInst,
|
||||||
|
const WebRtc_Word16* farend,
|
||||||
|
WebRtc_Word16 nrOfSamples);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runs the AECM on an 80 or 160 sample blocks of data.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
* WebRtc_Word16 *nearendNoisy In buffer containing one frame of
|
||||||
|
* reference nearend+echo signal. If
|
||||||
|
* noise reduction is active, provide
|
||||||
|
* the noisy signal here.
|
||||||
|
* WebRtc_Word16 *nearendClean In buffer containing one frame of
|
||||||
|
* nearend+echo signal. If noise
|
||||||
|
* reduction is active, provide the
|
||||||
|
* clean signal here. Otherwise pass a
|
||||||
|
* NULL pointer.
|
||||||
|
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
|
||||||
|
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
|
||||||
|
* system buffers
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_Process(void* aecmInst,
|
||||||
|
const WebRtc_Word16* nearendNoisy,
|
||||||
|
const WebRtc_Word16* nearendClean,
|
||||||
|
WebRtc_Word16* out,
|
||||||
|
WebRtc_Word16 nrOfSamples,
|
||||||
|
WebRtc_Word16 msInSndCardBuf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function enables the user to set certain parameters on-the-fly
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
* AecmConfig config Config instance that contains all
|
||||||
|
* properties to be set
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_set_config(void* aecmInst,
|
||||||
|
AecmConfig config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function enables the user to set certain parameters on-the-fly
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* AecmConfig *config Pointer to the config instance that
|
||||||
|
* all properties will be written to
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst,
|
||||||
|
AecmConfig *config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function enables the user to set the echo path on-the-fly.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void* aecmInst Pointer to the AECM instance
|
||||||
|
* void* echo_path Pointer to the echo path to be set
|
||||||
|
* size_t size_bytes Size in bytes of the echo path
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_InitEchoPath(void* aecmInst,
|
||||||
|
const void* echo_path,
|
||||||
|
size_t size_bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function enables the user to get the currently used echo path
|
||||||
|
* on-the-fly
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void* aecmInst Pointer to the AECM instance
|
||||||
|
* void* echo_path Pointer to echo path
|
||||||
|
* size_t size_bytes Size in bytes of the echo path
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_GetEchoPath(void* aecmInst,
|
||||||
|
void* echo_path,
|
||||||
|
size_t size_bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function enables the user to get the echo path size in bytes
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* size_t return : size in bytes
|
||||||
|
*/
|
||||||
|
size_t WebRtcAecm_echo_path_size_bytes();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the last error code.
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* void *aecmInst Pointer to the AECM instance
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word32 return 11000-11100: error code
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_get_error_code(void *aecmInst);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets a version string
|
||||||
|
*
|
||||||
|
* Inputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* char *versionStr Pointer to a string array
|
||||||
|
* WebRtc_Word16 len The maximum length of the string
|
||||||
|
*
|
||||||
|
* Outputs Description
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* WebRtc_Word8 *versionStr Pointer to a string array
|
||||||
|
* WebRtc_Word32 return 0: OK
|
||||||
|
* -1: error
|
||||||
|
*/
|
||||||
|
WebRtc_Word32 WebRtcAecm_get_version(WebRtc_Word8 *versionStr,
|
||||||
|
WebRtc_Word16 len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_INTERFACE_ECHO_CONTROL_MOBILE_H_ */
|
447
src/modules/audio_processing/aecm/main/matlab/compsup.m
Normal file
447
src/modules/audio_processing/aecm/main/matlab/compsup.m
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
function [emicrophone,aaa]=compsup(microphone,TheFarEnd,avtime,samplingfreq);
|
||||||
|
% microphone = microphone signal
|
||||||
|
% aaa = nonlinearity input variable
|
||||||
|
% TheFarEnd = far end signal
|
||||||
|
% avtime = interval to compute suppression from (seconds)
|
||||||
|
% samplingfreq = sampling frequency
|
||||||
|
|
||||||
|
%if(nargin==6)
|
||||||
|
% fprintf(1,'suppress has received a delay sequence\n');
|
||||||
|
%end
|
||||||
|
|
||||||
|
|
||||||
|
Ap500=[ 1.00, -4.95, 9.801, -9.70299, 4.80298005, -0.9509900499];
|
||||||
|
Bp500=[ 0.662743088639636, -2.5841655608125, 3.77668102146288, -2.45182477425154, 0.596566274575251, 0.0];
|
||||||
|
|
||||||
|
|
||||||
|
Ap200=[ 1.00, -4.875, 9.50625, -9.26859375, 4.518439453125, -0.881095693359375];
|
||||||
|
Bp200=[ 0.862545460994275, -3.2832804496114, 4.67892032308828, -2.95798023879133, 0.699796870041299, 0.0];
|
||||||
|
|
||||||
|
maxDelay=0.4; %[s]
|
||||||
|
histLen=1; %[s]
|
||||||
|
|
||||||
|
|
||||||
|
% CONSTANTS THAT YOU CAN EXPERIMENT WITH
|
||||||
|
A_GAIN=10.0; % for the suppress case
|
||||||
|
oversampling = 2; % must be power of 2; minimum is 2; 4 works
|
||||||
|
% fine for support=64, but for support=128,
|
||||||
|
% 8 gives better results.
|
||||||
|
support=64; %512 % fft support (frequency resolution; at low
|
||||||
|
% settings you can hear more distortion
|
||||||
|
% (e.g. pitch that is left-over from far-end))
|
||||||
|
% 128 works well, 64 is ok)
|
||||||
|
|
||||||
|
lowlevel = mean(abs(microphone))*0.0001;
|
||||||
|
|
||||||
|
G_ol = 0; % Use overlapping sets of estimates
|
||||||
|
|
||||||
|
% ECHO SUPPRESSION SPECIFIC PARAMETERS
|
||||||
|
suppress_overdrive=1.0; % overdrive factor for suppression 1.4 is good
|
||||||
|
gamma_echo=1.0; % same as suppress_overdrive but at different place
|
||||||
|
de_echo_bound=0.0;
|
||||||
|
mLim=10; % rank of matrix G
|
||||||
|
%limBW = 1; % use bandwidth-limited response for G
|
||||||
|
if mLim > (support/2+1)
|
||||||
|
error('mLim in suppress.m too large\n');
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
dynrange=1.0000e-004;
|
||||||
|
|
||||||
|
% other, constants
|
||||||
|
hsupport = support/2;
|
||||||
|
hsupport1 = hsupport+1;
|
||||||
|
factor = 2 / oversampling;
|
||||||
|
updatel = support/oversampling;
|
||||||
|
win=sqrt(designwindow(0,support));
|
||||||
|
estLen = round(avtime * samplingfreq/updatel)
|
||||||
|
|
||||||
|
runningfmean =0.0;
|
||||||
|
|
||||||
|
mLim = floor(hsupport1/2);
|
||||||
|
V = sqrt(2/hsupport1)*cos(pi/hsupport1*(repmat((0:hsupport1-1) + 0.5, mLim, 1).* ...
|
||||||
|
repmat((0:mLim-1)' + 0.5, 1, hsupport1)));
|
||||||
|
|
||||||
|
fprintf(1,'updatel is %5.3f s\n', updatel/samplingfreq);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bandfirst=8; bandlast=25;
|
||||||
|
dosmooth=0; % to get rid of wavy bin counts (can be worse or better)
|
||||||
|
|
||||||
|
% compute some constants
|
||||||
|
blockLen = support/oversampling;
|
||||||
|
maxDelayb = floor(samplingfreq*maxDelay/updatel); % in blocks
|
||||||
|
histLenb = floor(samplingfreq*histLen/updatel); % in blocks
|
||||||
|
|
||||||
|
x0=TheFarEnd;
|
||||||
|
y0=microphone;
|
||||||
|
|
||||||
|
|
||||||
|
%input
|
||||||
|
tlength=min([length(microphone),length(TheFarEnd)]);
|
||||||
|
updateno=floor(tlength/updatel);
|
||||||
|
tlength=updatel*updateno;
|
||||||
|
updateno = updateno - oversampling + 1;
|
||||||
|
|
||||||
|
TheFarEnd =TheFarEnd(1:tlength);
|
||||||
|
microphone =microphone(1:tlength);
|
||||||
|
|
||||||
|
TheFarEnd =[zeros(hsupport,1);TheFarEnd(1:tlength)];
|
||||||
|
microphone =[zeros(hsupport,1);microphone(1:tlength)];
|
||||||
|
|
||||||
|
|
||||||
|
% signal length
|
||||||
|
n = min([floor(length(x0)/support)*support,floor(length(y0)/support)*support]);
|
||||||
|
nb = n/blockLen - oversampling + 1; % in blocks
|
||||||
|
|
||||||
|
% initialize space
|
||||||
|
win = sqrt([0 ; hanning(support-1)]);
|
||||||
|
sxAll2 = zeros(hsupport1,nb);
|
||||||
|
syAll2 = zeros(hsupport1,nb);
|
||||||
|
|
||||||
|
z500=zeros(5,maxDelayb+1);
|
||||||
|
z200=zeros(5,hsupport1);
|
||||||
|
|
||||||
|
bxspectrum=uint32(zeros(nb,1));
|
||||||
|
bxhist=uint32(zeros(maxDelayb+1,1));
|
||||||
|
byspectrum=uint32(zeros(nb,1));
|
||||||
|
bcount=zeros(1+maxDelayb,nb);
|
||||||
|
fcount=zeros(1+maxDelayb,nb);
|
||||||
|
fout=zeros(1+maxDelayb,nb);
|
||||||
|
delay=zeros(nb,1);
|
||||||
|
tdelay=zeros(nb,1);
|
||||||
|
nlgains=zeros(nb,1);
|
||||||
|
|
||||||
|
% create space (mainly for debugging)
|
||||||
|
emicrophone=zeros(tlength,1);
|
||||||
|
femicrophone=complex(zeros(hsupport1,updateno));
|
||||||
|
thefilter=zeros(hsupport1,updateno);
|
||||||
|
thelimiter=ones(hsupport1,updateno);
|
||||||
|
fTheFarEnd=complex(zeros(hsupport1,updateno));
|
||||||
|
afTheFarEnd=zeros(hsupport1,updateno);
|
||||||
|
fmicrophone=complex(zeros(hsupport1,updateno));
|
||||||
|
afmicrophone=zeros(hsupport1,updateno);
|
||||||
|
|
||||||
|
G = zeros(hsupport1, hsupport1);
|
||||||
|
zerovec = zeros(hsupport1,1);
|
||||||
|
zeromat = zeros(hsupport1);
|
||||||
|
|
||||||
|
% Reset sums
|
||||||
|
mmxs_a = zerovec;
|
||||||
|
mmys_a = zerovec;
|
||||||
|
s2xs_a = zerovec;
|
||||||
|
s2ys_a = zerovec;
|
||||||
|
Rxxs_a = zeromat;
|
||||||
|
Ryxs_a = zeromat;
|
||||||
|
count_a = 1;
|
||||||
|
|
||||||
|
mmxs_b = zerovec;
|
||||||
|
mmys_b = zerovec;
|
||||||
|
s2xs_b = zerovec;
|
||||||
|
s2ys_b = zerovec;
|
||||||
|
Rxxs_b = zeromat;
|
||||||
|
Ryxs_b = zeromat;
|
||||||
|
count_b = 1;
|
||||||
|
|
||||||
|
nog=0;
|
||||||
|
|
||||||
|
aaa=zeros(size(TheFarEnd));
|
||||||
|
|
||||||
|
% loop over signal blocks
|
||||||
|
fprintf(1,'.. Suppression; averaging G over %5.1f seconds; file length %5.1f seconds ..\n',avtime, length(microphone)/samplingfreq);
|
||||||
|
fprintf(1,'.. SUPPRESSING ONLY AFTER %5.1f SECONDS! ..\n',avtime);
|
||||||
|
fprintf(1,'.. 20 seconds is good ..\n');
|
||||||
|
hh = waitbar_j(0,'Please wait...');
|
||||||
|
|
||||||
|
|
||||||
|
for i=1:updateno
|
||||||
|
|
||||||
|
sb = (i-1)*updatel + 1;
|
||||||
|
se=sb+support-1;
|
||||||
|
|
||||||
|
% analysis FFTs
|
||||||
|
temp=fft(win .* TheFarEnd(sb:se));
|
||||||
|
fTheFarEnd(:,i)=temp(1:hsupport1);
|
||||||
|
xf=fTheFarEnd(:,i);
|
||||||
|
afTheFarEnd(:,i)= abs(fTheFarEnd(:,i));
|
||||||
|
|
||||||
|
temp=win .* microphone(sb:se);
|
||||||
|
|
||||||
|
temp=fft(win .* microphone(sb:se));
|
||||||
|
fmicrophone(:,i)=temp(1:hsupport1);
|
||||||
|
yf=fmicrophone(:,i);
|
||||||
|
afmicrophone(:,i)= abs(fmicrophone(:,i));
|
||||||
|
|
||||||
|
|
||||||
|
ener_orig = afmicrophone(:,i)'*afmicrophone(:,i);
|
||||||
|
if( ener_orig == 0)
|
||||||
|
afmicrophone(:,i)=lowlevel*ones(size(afmicrophone(:,i)));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
% use log domain (showed improved performance)
|
||||||
|
xxf= sqrt(real(xf.*conj(xf))+1e-20);
|
||||||
|
yyf= sqrt(real(yf.*conj(yf))+1e-20);
|
||||||
|
sxAll2(:,i) = 20*log10(xxf);
|
||||||
|
syAll2(:,i) = 20*log10(yyf);
|
||||||
|
|
||||||
|
mD=min(i-1,maxDelayb);
|
||||||
|
xthreshold = sum(sxAll2(:,i-mD:i),2)/(maxDelayb+1);
|
||||||
|
|
||||||
|
[yout, z200] = filter(Bp200,Ap200,syAll2(:,i),z200,2);
|
||||||
|
yout=yout/(maxDelayb+1);
|
||||||
|
ythreshold = mean(syAll2(:,i-mD:i),2);
|
||||||
|
|
||||||
|
|
||||||
|
bxspectrum(i)=getBspectrum(sxAll2(:,i),xthreshold,bandfirst,bandlast);
|
||||||
|
byspectrum(i)=getBspectrum(syAll2(:,i),yout,bandfirst,bandlast);
|
||||||
|
|
||||||
|
bxhist(end-mD:end)=bxspectrum(i-mD:i);
|
||||||
|
|
||||||
|
bcount(:,i)=hisser2( ...
|
||||||
|
byspectrum(i),flipud(bxhist),bandfirst,bandlast);
|
||||||
|
|
||||||
|
|
||||||
|
[fout(:,i), z500] = filter(Bp500,Ap500,bcount(:,i),z500,2);
|
||||||
|
fcount(:,i)=sum(bcount(:,max(1,i-histLenb+1):i),2); % using the history range
|
||||||
|
fout(:,i)=round(fout(:,i));
|
||||||
|
[value,delay(i)]=min(fout(:,i),[],1);
|
||||||
|
tdelay(i)=(delay(i)-1)*support/(samplingfreq*oversampling);
|
||||||
|
|
||||||
|
% compensate
|
||||||
|
|
||||||
|
idel = max(i - delay(i) + 1,1);
|
||||||
|
|
||||||
|
|
||||||
|
% echo suppression
|
||||||
|
|
||||||
|
noisyspec = afmicrophone(:,i);
|
||||||
|
|
||||||
|
% Estimate G using covariance matrices
|
||||||
|
|
||||||
|
% Cumulative estimates
|
||||||
|
xx = afTheFarEnd(:,idel);
|
||||||
|
yy = afmicrophone(:,i);
|
||||||
|
|
||||||
|
% Means
|
||||||
|
mmxs_a = mmxs_a + xx;
|
||||||
|
mmys_a = mmys_a + yy;
|
||||||
|
if (G_ol)
|
||||||
|
mmxs_b = mmxs_b + xx;
|
||||||
|
mmys_b = mmys_b + yy;
|
||||||
|
mmy = mean([mmys_a/count_a mmys_b/count_b],2);
|
||||||
|
mmx = mean([mmxs_a/count_a mmxs_b/count_b],2);
|
||||||
|
else
|
||||||
|
mmx = mmxs_a/count_a;
|
||||||
|
mmy = mmys_a/count_a;
|
||||||
|
end
|
||||||
|
count_a = count_a + 1;
|
||||||
|
count_b = count_b + 1;
|
||||||
|
|
||||||
|
% Mean removal
|
||||||
|
xxm = xx - mmx;
|
||||||
|
yym = yy - mmy;
|
||||||
|
|
||||||
|
% Variances
|
||||||
|
s2xs_a = s2xs_a + xxm .* xxm;
|
||||||
|
s2ys_a = s2ys_a + yym .* yym;
|
||||||
|
s2xs_b = s2xs_b + xxm .* xxm;
|
||||||
|
s2ys_b = s2ys_b + yym .* yym;
|
||||||
|
|
||||||
|
% Correlation matrices
|
||||||
|
Rxxs_a = Rxxs_a + xxm * xxm';
|
||||||
|
Ryxs_a = Ryxs_a + yym * xxm';
|
||||||
|
Rxxs_b = Rxxs_b + xxm * xxm';
|
||||||
|
Ryxs_b = Ryxs_b + yym * xxm';
|
||||||
|
|
||||||
|
|
||||||
|
% Gain matrix A
|
||||||
|
|
||||||
|
if mod(i, estLen) == 0
|
||||||
|
|
||||||
|
|
||||||
|
% Cumulative based estimates
|
||||||
|
Rxxf = Rxxs_a / (estLen - 1);
|
||||||
|
Ryxf = Ryxs_a / (estLen - 1);
|
||||||
|
|
||||||
|
% Variance normalization
|
||||||
|
s2x2 = s2xs_a / (estLen - 1);
|
||||||
|
s2x2 = sqrt(s2x2);
|
||||||
|
% Sx = diag(max(s2x2,dynrange*max(s2x2)));
|
||||||
|
Sx = diag(s2x2);
|
||||||
|
if (sum(s2x2) > 0)
|
||||||
|
iSx = inv(Sx);
|
||||||
|
else
|
||||||
|
iSx= Sx + 0.01;
|
||||||
|
end
|
||||||
|
|
||||||
|
s2y2 = s2ys_a / (estLen - 1);
|
||||||
|
s2y2 = sqrt(s2y2);
|
||||||
|
% Sy = diag(max(s2y2,dynrange*max(s2y2)));
|
||||||
|
Sy = diag(s2y2);
|
||||||
|
iSy = inv(Sy);
|
||||||
|
rx = iSx * Rxxf * iSx;
|
||||||
|
ryx = iSy * Ryxf * iSx;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dbd= 7; % Us less than the full matrix
|
||||||
|
|
||||||
|
% k x m
|
||||||
|
% Bandlimited structure on G
|
||||||
|
LSEon = 0; % Default is using MMSE
|
||||||
|
if (LSEon)
|
||||||
|
ryx = ryx*rx;
|
||||||
|
rx = rx*rx;
|
||||||
|
end
|
||||||
|
p = dbd-1;
|
||||||
|
gaj = min(min(hsupport1,2*p+1),min([p+(1:hsupport1); hsupport1+p+1-(1:hsupport1)]));
|
||||||
|
cgaj = [0 cumsum(gaj)];
|
||||||
|
|
||||||
|
G3 = zeros(hsupport1);
|
||||||
|
for kk=1:hsupport1
|
||||||
|
ki = max(0,kk-p-1);
|
||||||
|
if (sum(sum(rx(ki+1:ki+gaj(kk),ki+1:ki+gaj(kk))))>0)
|
||||||
|
G3(kk,ki+1:ki+gaj(kk)) = ryx(kk,ki+1:ki+gaj(kk))/rx(ki+1:ki+gaj(kk),ki+1:ki+gaj(kk));
|
||||||
|
else
|
||||||
|
G3(kk,ki+1:ki+gaj(kk)) = ryx(kk,ki+1:ki+gaj(kk));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% End Bandlimited structure
|
||||||
|
|
||||||
|
G = G3;
|
||||||
|
G(abs(G)<0.01)=0;
|
||||||
|
G = suppress_overdrive * Sy * G * iSx;
|
||||||
|
|
||||||
|
if 1
|
||||||
|
figure(32); mi=2;
|
||||||
|
surf(max(min(G,mi),-mi)); view(2)
|
||||||
|
title('Unscaled Masked Limited-bandwidth G');
|
||||||
|
end
|
||||||
|
pause(0.05);
|
||||||
|
|
||||||
|
% Reset sums
|
||||||
|
mmxs_a = zerovec;
|
||||||
|
mmys_a = zerovec;
|
||||||
|
s2xs_a = zerovec;
|
||||||
|
s2ys_a = zerovec;
|
||||||
|
Rxxs_a = zeromat;
|
||||||
|
Ryxs_a = zeromat;
|
||||||
|
count_a = 1;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if (G_ol)
|
||||||
|
% Gain matrix B
|
||||||
|
|
||||||
|
if ((mod((i-estLen/2), estLen) == 0) & i>estLen)
|
||||||
|
|
||||||
|
|
||||||
|
% Cumulative based estimates
|
||||||
|
Rxxf = Rxxs_b / (estLen - 1);
|
||||||
|
Ryxf = Ryxs_b / (estLen - 1);
|
||||||
|
|
||||||
|
% Variance normalization
|
||||||
|
s2x2 = s2xs_b / (estLen - 1);
|
||||||
|
s2x2 = sqrt(s2x2);
|
||||||
|
Sx = diag(max(s2x2,dynrange*max(s2x2)));
|
||||||
|
iSx = inv(Sx);
|
||||||
|
s2y2 = s2ys_b / (estLen - 1);
|
||||||
|
s2y2 = sqrt(s2y2);
|
||||||
|
Sy = diag(max(s2y2,dynrange*max(s2y2)));
|
||||||
|
iSy = inv(Sy);
|
||||||
|
rx = iSx * Rxxf * iSx;
|
||||||
|
ryx = iSy * Ryxf * iSx;
|
||||||
|
|
||||||
|
|
||||||
|
% Bandlimited structure on G
|
||||||
|
LSEon = 0; % Default is using MMSE
|
||||||
|
if (LSEon)
|
||||||
|
ryx = ryx*rx;
|
||||||
|
rx = rx*rx;
|
||||||
|
end
|
||||||
|
p = dbd-1;
|
||||||
|
gaj = min(min(hsupport1,2*p+1),min([p+(1:hsupport1); hsupport1+p+1-(1:hsupport1)]));
|
||||||
|
cgaj = [0 cumsum(gaj)];
|
||||||
|
|
||||||
|
G3 = zeros(hsupport1);
|
||||||
|
for kk=1:hsupport1
|
||||||
|
ki = max(0,kk-p-1);
|
||||||
|
G3(kk,ki+1:ki+gaj(kk)) = ryx(kk,ki+1:ki+gaj(kk))/rx(ki+1:ki+gaj(kk),ki+1:ki+gaj(kk));
|
||||||
|
end
|
||||||
|
% End Bandlimited structure
|
||||||
|
|
||||||
|
G = G3;
|
||||||
|
G(abs(G)<0.01)=0;
|
||||||
|
G = suppress_overdrive * Sy * G * iSx;
|
||||||
|
|
||||||
|
if 1
|
||||||
|
figure(32); mi=2;
|
||||||
|
surf(max(min(G,mi),-mi)); view(2)
|
||||||
|
title('Unscaled Masked Limited-bandwidth G');
|
||||||
|
end
|
||||||
|
pause(0.05);
|
||||||
|
|
||||||
|
|
||||||
|
% Reset sums
|
||||||
|
mmxs_b = zerovec;
|
||||||
|
mmys_b = zerovec;
|
||||||
|
s2xs_b = zerovec;
|
||||||
|
s2ys_b = zerovec;
|
||||||
|
Rxxs_b = zeromat;
|
||||||
|
Ryxs_b = zeromat;
|
||||||
|
count_b = 1;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
FECestimate2 = G*afTheFarEnd(:,idel);
|
||||||
|
|
||||||
|
% compute Wiener filter and suppressor function
|
||||||
|
thefilter(:,i) = (noisyspec - gamma_echo*FECestimate2) ./ noisyspec;
|
||||||
|
ix0 = find(thefilter(:,i)<de_echo_bound); % bounding trick 1
|
||||||
|
thefilter(ix0,i) = de_echo_bound; % bounding trick 2
|
||||||
|
ix0 = find(thefilter(:,i)>1); % bounding in reasonable range
|
||||||
|
thefilter(ix0,i) = 1;
|
||||||
|
|
||||||
|
% NONLINEARITY
|
||||||
|
nl_alpha=0.8; % memory; seems not very critical
|
||||||
|
nlSeverity=0.3; % nonlinearity severity: 0 does nothing; 1 suppresses all
|
||||||
|
thefmean=mean(thefilter(8:16,i));
|
||||||
|
if (thefmean<1)
|
||||||
|
disp('');
|
||||||
|
end
|
||||||
|
runningfmean = nl_alpha*runningfmean + (1-nl_alpha)*thefmean;
|
||||||
|
aaa(sb+20+1:sb+20+updatel)=10000*runningfmean* ones(updatel,1); % debug
|
||||||
|
slope0=1.0/(1.0-nlSeverity); %
|
||||||
|
thegain = max(0.0,min(1.0,slope0*(runningfmean-nlSeverity)));
|
||||||
|
% END NONLINEARITY
|
||||||
|
thefilter(:,i) = thegain*thefilter(:,i);
|
||||||
|
|
||||||
|
|
||||||
|
% Wiener filtering
|
||||||
|
femicrophone(:,i) = fmicrophone(:,i) .* thefilter(:,i);
|
||||||
|
thelimiter(:,i) = (noisyspec - A_GAIN*FECestimate2) ./ noisyspec;
|
||||||
|
index = find(thelimiter(:,i)>1.0);
|
||||||
|
thelimiter(index,i) = 1.0;
|
||||||
|
index = find(thelimiter(:,i)<0.0);
|
||||||
|
thelimiter(index,i) = 0.0;
|
||||||
|
|
||||||
|
if (rem(i,floor(updateno/20))==0)
|
||||||
|
fprintf(1,'.');
|
||||||
|
end
|
||||||
|
if mod(i,50)==0
|
||||||
|
waitbar_j(i/updateno,hh);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
% reconstruction; first make spectrum odd
|
||||||
|
temp=[femicrophone(:,i);flipud(conj(femicrophone(2:hsupport,i)))];
|
||||||
|
emicrophone(sb:se) = emicrophone(sb:se) + factor * win .* real(ifft(temp));
|
||||||
|
|
||||||
|
end
|
||||||
|
fprintf(1,'\n');
|
||||||
|
|
||||||
|
close(hh);
|
22
src/modules/audio_processing/aecm/main/matlab/getBspectrum.m
Normal file
22
src/modules/audio_processing/aecm/main/matlab/getBspectrum.m
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
function bspectrum=getBspectrum(ps,threshold,bandfirst,bandlast)
|
||||||
|
% function bspectrum=getBspectrum(ps,threshold,bandfirst,bandlast)
|
||||||
|
% compute binary spectrum using threshold spectrum as pivot
|
||||||
|
% bspectrum = binary spectrum (binary)
|
||||||
|
% ps=current power spectrum (float)
|
||||||
|
% threshold=threshold spectrum (float)
|
||||||
|
% bandfirst = first band considered
|
||||||
|
% bandlast = last band considered
|
||||||
|
|
||||||
|
% initialization stuff
|
||||||
|
if( length(ps)<bandlast | bandlast>32 | length(ps)~=length(threshold))
|
||||||
|
error('BinDelayEst:spectrum:invalid','Dimensionality error');
|
||||||
|
end
|
||||||
|
|
||||||
|
% get current binary spectrum
|
||||||
|
diff = ps - threshold;
|
||||||
|
bspectrum=uint32(0);
|
||||||
|
for(i=bandfirst:bandlast)
|
||||||
|
if( diff(i)>0 )
|
||||||
|
bspectrum = bitset(bspectrum,i);
|
||||||
|
end
|
||||||
|
end
|
21
src/modules/audio_processing/aecm/main/matlab/hisser2.m
Normal file
21
src/modules/audio_processing/aecm/main/matlab/hisser2.m
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
function bcount=hisser2(bs,bsr,bandfirst,bandlast)
|
||||||
|
% function bcount=hisser(bspectrum,bandfirst,bandlast)
|
||||||
|
% histogram for the binary spectra
|
||||||
|
% bcount= array of bit counts
|
||||||
|
% bs=binary spectrum (one int32 number each)
|
||||||
|
% bsr=reference binary spectra (one int32 number each)
|
||||||
|
% blockSize = histogram over blocksize blocks
|
||||||
|
% bandfirst = first band considered
|
||||||
|
% bandlast = last band considered
|
||||||
|
|
||||||
|
% weight all delays equally
|
||||||
|
maxDelay = length(bsr);
|
||||||
|
|
||||||
|
% compute counts (two methods; the first works better and is operational)
|
||||||
|
bcount=zeros(maxDelay,1);
|
||||||
|
for(i=1:maxDelay)
|
||||||
|
% the delay should have low count for low-near&high-far and high-near&low-far
|
||||||
|
bcount(i)= sum(bitget(bitxor(bs,bsr(i)),bandfirst:bandlast));
|
||||||
|
% the delay should have low count for low-near&high-far (works less well)
|
||||||
|
% bcount(i)= sum(bitget(bitand(bsr(i),bitxor(bs,bsr(i))),bandfirst:bandlast));
|
||||||
|
end
|
19
src/modules/audio_processing/aecm/main/matlab/main2.m
Normal file
19
src/modules/audio_processing/aecm/main/matlab/main2.m
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
fid=fopen('aecfar.pcm'); far=fread(fid,'short'); fclose(fid);
|
||||||
|
fid=fopen('aecnear.pcm'); mic=fread(fid,'short'); fclose(fid);
|
||||||
|
|
||||||
|
%fid=fopen('QA1far.pcm'); far=fread(fid,'short'); fclose(fid);
|
||||||
|
%fid=fopen('QA1near.pcm'); mic=fread(fid,'short'); fclose(fid);
|
||||||
|
|
||||||
|
start=0 * 8000+1;
|
||||||
|
stop= 30 * 8000;
|
||||||
|
microphone=mic(start:stop);
|
||||||
|
TheFarEnd=far(start:stop);
|
||||||
|
avtime=1;
|
||||||
|
|
||||||
|
% 16000 to make it compatible with the C-version
|
||||||
|
[emicrophone,tdel]=compsup(microphone,TheFarEnd,avtime,16000);
|
||||||
|
|
||||||
|
spclab(8000,TheFarEnd,microphone,emicrophone);
|
||||||
|
|
||||||
|
|
269
src/modules/audio_processing/aecm/main/matlab/matlab/AECMobile.m
Normal file
269
src/modules/audio_processing/aecm/main/matlab/matlab/AECMobile.m
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
function [femicrophone, aecmStructNew, enerNear, enerFar] = AECMobile(fmicrophone, afTheFarEnd, setupStruct, aecmStruct)
|
||||||
|
global NEARENDFFT;
|
||||||
|
global F;
|
||||||
|
|
||||||
|
aecmStructNew = aecmStruct;
|
||||||
|
|
||||||
|
% Magnitude spectrum of near end signal
|
||||||
|
afmicrophone = abs(fmicrophone);
|
||||||
|
%afmicrophone = NEARENDFFT(setupStruct.currentBlock,:)'/2^F(setupStruct.currentBlock,end);
|
||||||
|
% Near end energy level
|
||||||
|
ener_orig = afmicrophone'*afmicrophone;
|
||||||
|
if( ener_orig == 0)
|
||||||
|
lowlevel = 0.01;
|
||||||
|
afmicrophone = lowlevel*ones(size(afmicrophone));
|
||||||
|
end
|
||||||
|
%adiff = max(abs(afmicrophone - afTheFarEnd));
|
||||||
|
%if (adiff > 0)
|
||||||
|
% disp([setupStruct.currentBlock adiff])
|
||||||
|
%end
|
||||||
|
|
||||||
|
% Store the near end energy
|
||||||
|
%aecmStructNew.enerNear(setupStruct.currentBlock) = log(afmicrophone'*afmicrophone);
|
||||||
|
aecmStructNew.enerNear(setupStruct.currentBlock) = log(sum(afmicrophone));
|
||||||
|
% Store the far end energy
|
||||||
|
%aecmStructNew.enerFar(setupStruct.currentBlock) = log(afTheFarEnd'*afTheFarEnd);
|
||||||
|
aecmStructNew.enerFar(setupStruct.currentBlock) = log(sum(afTheFarEnd));
|
||||||
|
|
||||||
|
% Update subbands (We currently use all frequency bins, hence .useSubBand is turned off)
|
||||||
|
if aecmStructNew.useSubBand
|
||||||
|
internalIndex = 1;
|
||||||
|
for kk=1:setupStruct.subBandLength+1
|
||||||
|
ySubBand(kk) = mean(afmicrophone(internalIndex:internalIndex+setupStruct.numInBand(kk)-1).^aecmStructNew.bandFactor);
|
||||||
|
xSubBand(kk) = mean(afTheFarEnd(internalIndex:internalIndex+setupStruct.numInBand(kk)-1).^aecmStructNew.bandFactor);
|
||||||
|
internalIndex = internalIndex + setupStruct.numInBand(kk);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ySubBand = afmicrophone.^aecmStructNew.bandFactor;
|
||||||
|
xSubBand = afTheFarEnd.^aecmStructNew.bandFactor;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Estimated echo energy
|
||||||
|
if (aecmStructNew.bandFactor == 1)
|
||||||
|
%aecmStructNew.enerEcho(setupStruct.currentBlock) = log((aecmStructNew.H.*xSubBand)'*(aecmStructNew.H.*xSubBand));
|
||||||
|
%aecmStructNew.enerEchoStored(setupStruct.currentBlock) = log((aecmStructNew.HStored.*xSubBand)'*(aecmStructNew.HStored.*xSubBand));
|
||||||
|
aecmStructNew.enerEcho(setupStruct.currentBlock) = log(sum(aecmStructNew.H.*xSubBand));
|
||||||
|
aecmStructNew.enerEchoStored(setupStruct.currentBlock) = log(sum(aecmStructNew.HStored.*xSubBand));
|
||||||
|
elseif (aecmStructNew.bandFactor == 2)
|
||||||
|
aecmStructNew.enerEcho(setupStruct.currentBlock) = log(aecmStructNew.H'*xSubBand);
|
||||||
|
aecmStructNew.enerEchoStored(setupStruct.currentBlock) = log(aecmStructNew.HStored'*xSubBand);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Last 100 blocks of data, used for plotting
|
||||||
|
n100 = max(1,setupStruct.currentBlock-99):setupStruct.currentBlock;
|
||||||
|
enerError = aecmStructNew.enerNear(n100)-aecmStructNew.enerEcho(n100);
|
||||||
|
enerErrorStored = aecmStructNew.enerNear(n100)-aecmStructNew.enerEchoStored(n100);
|
||||||
|
|
||||||
|
% Store the far end sub band. This is needed if we use LSE instead of NLMS
|
||||||
|
aecmStructNew.X = [xSubBand aecmStructNew.X(:,1:end-1)];
|
||||||
|
|
||||||
|
% Update energy levels, which control the VAD
|
||||||
|
if ((aecmStructNew.enerFar(setupStruct.currentBlock) < aecmStructNew.energyMin) & (aecmStructNew.enerFar(setupStruct.currentBlock) >= aecmStruct.FAR_ENERGY_MIN))
|
||||||
|
aecmStructNew.energyMin = aecmStructNew.enerFar(setupStruct.currentBlock);
|
||||||
|
%aecmStructNew.energyMin = max(aecmStructNew.energyMin,12);
|
||||||
|
aecmStructNew.energyMin = max(aecmStructNew.energyMin,aecmStruct.FAR_ENERGY_MIN);
|
||||||
|
aecmStructNew.energyLevel = (aecmStructNew.energyMax-aecmStructNew.energyMin)*aecmStructNew.energyThres+aecmStructNew.energyMin;
|
||||||
|
aecmStructNew.energyLevelMSE = (aecmStructNew.energyMax-aecmStructNew.energyMin)*aecmStructNew.energyThresMSE+aecmStructNew.energyMin;
|
||||||
|
end
|
||||||
|
if (aecmStructNew.enerFar(setupStruct.currentBlock) > aecmStructNew.energyMax)
|
||||||
|
aecmStructNew.energyMax = aecmStructNew.enerFar(setupStruct.currentBlock);
|
||||||
|
aecmStructNew.energyLevel = (aecmStructNew.energyMax-aecmStructNew.energyMin)*aecmStructNew.energyThres+aecmStructNew.energyMin;
|
||||||
|
aecmStructNew.energyLevelMSE = (aecmStructNew.energyMax-aecmStructNew.energyMin)*aecmStructNew.energyThresMSE+aecmStructNew.energyMin;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Calculate current energy error in near end (estimated echo vs. near end)
|
||||||
|
dE = aecmStructNew.enerNear(setupStruct.currentBlock)-aecmStructNew.enerEcho(setupStruct.currentBlock);
|
||||||
|
|
||||||
|
%%%%%%%%
|
||||||
|
% Calculate step size used in LMS algorithm, based on current far end energy and near end energy error (dE)
|
||||||
|
%%%%%%%%
|
||||||
|
if setupStruct.stepSize_flag
|
||||||
|
[mu, aecmStructNew] = calcStepSize(aecmStructNew.enerFar(setupStruct.currentBlock), dE, aecmStructNew, setupStruct.currentBlock, 1);
|
||||||
|
else
|
||||||
|
mu = 0.25;
|
||||||
|
end
|
||||||
|
aecmStructNew.muLog(setupStruct.currentBlock) = mu; % Store the step size
|
||||||
|
|
||||||
|
% Estimate Echo Spectral Shape
|
||||||
|
[U, aecmStructNew.H] = fallerEstimator(ySubBand,aecmStructNew.X,aecmStructNew.H,mu);
|
||||||
|
|
||||||
|
%%%%%
|
||||||
|
% Determine if we should store or restore the channel
|
||||||
|
%%%%%
|
||||||
|
if ((setupStruct.currentBlock <= aecmStructNew.convLength) | (~setupStruct.channelUpdate_flag))
|
||||||
|
aecmStructNew.HStored = aecmStructNew.H; % Store what you have after startup
|
||||||
|
elseif ((setupStruct.currentBlock > aecmStructNew.convLength) & (setupStruct.channelUpdate_flag))
|
||||||
|
if ((aecmStructNew.enerFar(setupStruct.currentBlock) < aecmStructNew.energyLevelMSE) & (aecmStructNew.enerFar(setupStruct.currentBlock-1) >= aecmStructNew.energyLevelMSE))
|
||||||
|
xxx = aecmStructNew.countMseH;
|
||||||
|
if (xxx > 20)
|
||||||
|
mseStored = mean(abs(aecmStructNew.enerEchoStored(setupStruct.currentBlock-xxx:setupStruct.currentBlock-1)-aecmStructNew.enerNear(setupStruct.currentBlock-xxx:setupStruct.currentBlock-1)));
|
||||||
|
mseLatest = mean(abs(aecmStructNew.enerEcho(setupStruct.currentBlock-xxx:setupStruct.currentBlock-1)-aecmStructNew.enerNear(setupStruct.currentBlock-xxx:setupStruct.currentBlock-1)));
|
||||||
|
%fprintf('Stored: %4f Latest: %4f\n', mseStored, mseLatest) % Uncomment if you want to display the MSE values
|
||||||
|
if ((mseStored < 0.8*mseLatest) & (aecmStructNew.mseHStoredOld < 0.8*aecmStructNew.mseHLatestOld))
|
||||||
|
aecmStructNew.H = aecmStructNew.HStored;
|
||||||
|
fprintf('Restored H at block %d\n',setupStruct.currentBlock)
|
||||||
|
elseif (((0.8*mseStored > mseLatest) & (mseLatest < aecmStructNew.mseHThreshold) & (aecmStructNew.mseHLatestOld < aecmStructNew.mseHThreshold)) | (mseStored == Inf))
|
||||||
|
aecmStructNew.HStored = aecmStructNew.H;
|
||||||
|
fprintf('Stored new H at block %d\n',setupStruct.currentBlock)
|
||||||
|
end
|
||||||
|
aecmStructNew.mseHStoredOld = mseStored;
|
||||||
|
aecmStructNew.mseHLatestOld = mseLatest;
|
||||||
|
end
|
||||||
|
elseif ((aecmStructNew.enerFar(setupStruct.currentBlock) >= aecmStructNew.energyLevelMSE) & (aecmStructNew.enerFar(setupStruct.currentBlock-1) < aecmStructNew.energyLevelMSE))
|
||||||
|
aecmStructNew.countMseH = 1;
|
||||||
|
elseif (aecmStructNew.enerFar(setupStruct.currentBlock) >= aecmStructNew.energyLevelMSE)
|
||||||
|
aecmStructNew.countMseH = aecmStructNew.countMseH + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%%%%%
|
||||||
|
% Check delay (calculate the delay offset (if we can))
|
||||||
|
% The algorithm is not tuned and should be used with care. It runs separately from Bastiaan's algorithm.
|
||||||
|
%%%%%
|
||||||
|
yyy = 31; % Correlation buffer length (currently unfortunately hard coded)
|
||||||
|
dxxx = 25; % Maximum offset (currently unfortunately hard coded)
|
||||||
|
if (setupStruct.currentBlock > aecmStructNew.convLength)
|
||||||
|
if (aecmStructNew.enerFar(setupStruct.currentBlock-(yyy+2*dxxx-1):setupStruct.currentBlock) > aecmStructNew.energyLevelMSE)
|
||||||
|
for xxx = -dxxx:dxxx
|
||||||
|
aecmStructNew.delayLatestS(xxx+dxxx+1) = sum(sign(aecmStructNew.enerEcho(setupStruct.currentBlock-(yyy+dxxx-xxx)+1:setupStruct.currentBlock+xxx-dxxx)-mean(aecmStructNew.enerEcho(setupStruct.currentBlock-(yyy++dxxx-xxx)+1:setupStruct.currentBlock+xxx-dxxx))).*sign(aecmStructNew.enerNear(setupStruct.currentBlock-yyy-dxxx+1:setupStruct.currentBlock-dxxx)-mean(aecmStructNew.enerNear(setupStruct.currentBlock-yyy-dxxx+1:setupStruct.currentBlock-dxxx))));
|
||||||
|
end
|
||||||
|
aecmStructNew.newDelayCurve = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ((setupStruct.currentBlock > 2*aecmStructNew.convLength) & ~rem(setupStruct.currentBlock,yyy*2) & aecmStructNew.newDelayCurve)
|
||||||
|
[maxV,maxP] = max(aecmStructNew.delayLatestS);
|
||||||
|
if ((maxP > 2) & (maxP < 2*dxxx))
|
||||||
|
maxVLeft = aecmStructNew.delayLatestS(max(1,maxP-4));
|
||||||
|
maxVRight = aecmStructNew.delayLatestS(min(2*dxxx+1,maxP+4));
|
||||||
|
%fprintf('Max %d, Left %d, Right %d\n',maxV,maxVLeft,maxVRight) % Uncomment if you want to see max value
|
||||||
|
if ((maxV > 24) & (maxVLeft < maxV - 10) & (maxVRight < maxV - 10))
|
||||||
|
aecmStructNew.feedbackDelay = maxP-dxxx-1;
|
||||||
|
aecmStructNew.newDelayCurve = 0;
|
||||||
|
aecmStructNew.feedbackDelayUpdate = 1;
|
||||||
|
fprintf('Feedback Update at block %d\n',setupStruct.currentBlock)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% End of "Check delay"
|
||||||
|
%%%%%%%%
|
||||||
|
|
||||||
|
%%%%%
|
||||||
|
% Calculate suppression gain, based on far end energy and near end energy error (dE)
|
||||||
|
if (setupStruct.supGain_flag)
|
||||||
|
[gamma_echo, aecmStructNew.cntIn, aecmStructNew.cntOut] = calcFilterGain(aecmStructNew.enerFar(setupStruct.currentBlock), dE, aecmStructNew, setupStruct.currentBlock, aecmStructNew.convLength, aecmStructNew.cntIn, aecmStructNew.cntOut);
|
||||||
|
else
|
||||||
|
gamma_echo = 1;
|
||||||
|
end
|
||||||
|
aecmStructNew.gammaLog(setupStruct.currentBlock) = gamma_echo; % Store the gain
|
||||||
|
gamma_use = gamma_echo;
|
||||||
|
|
||||||
|
% Use the stored channel
|
||||||
|
U = aecmStructNew.HStored.*xSubBand;
|
||||||
|
|
||||||
|
% compute Wiener filter and suppressor function
|
||||||
|
Iy = find(ySubBand);
|
||||||
|
subBandFilter = zeros(size(ySubBand));
|
||||||
|
if (aecmStructNew.bandFactor == 2)
|
||||||
|
subBandFilter(Iy) = (1 - gamma_use*sqrt(U(Iy)./ySubBand(Iy))); % For Faller
|
||||||
|
else
|
||||||
|
subBandFilter(Iy) = (1 - gamma_use*(U(Iy)./ySubBand(Iy))); % For COV
|
||||||
|
end
|
||||||
|
ix0 = find(subBandFilter < 0); % bounding trick 1
|
||||||
|
subBandFilter(ix0) = 0;
|
||||||
|
ix0 = find(subBandFilter > 1); % bounding trick 1
|
||||||
|
subBandFilter(ix0) = 1;
|
||||||
|
|
||||||
|
% Interpolate back to normal frequency bins if we use sub bands
|
||||||
|
if aecmStructNew.useSubBand
|
||||||
|
thefilter = interp1(setupStruct.centerFreq,subBandFilter,linspace(0,setupStruct.samplingfreq/2,setupStruct.hsupport1)','nearest');
|
||||||
|
testfilter = interp1(setupStruct.centerFreq,subBandFilter,linspace(0,setupStruct.samplingfreq/2,1000),'nearest');
|
||||||
|
thefilter(end) = subBandFilter(end);
|
||||||
|
|
||||||
|
internalIndex = 1;
|
||||||
|
for kk=1:setupStruct.subBandLength+1
|
||||||
|
internalIndex:internalIndex+setupStruct.numInBand(kk)-1;
|
||||||
|
thefilter(internalIndex:internalIndex+setupStruct.numInBand(kk)-1) = subBandFilter(kk);
|
||||||
|
internalIndex = internalIndex + setupStruct.numInBand(kk);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
thefilter = subBandFilter;
|
||||||
|
testfilter = subBandFilter;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Bound the filter
|
||||||
|
ix0 = find(thefilter < setupStruct.de_echo_bound); % bounding trick 1
|
||||||
|
thefilter(ix0) = setupStruct.de_echo_bound; % bounding trick 2
|
||||||
|
ix0 = find(thefilter > 1); % bounding in reasonable range
|
||||||
|
thefilter(ix0) = 1;
|
||||||
|
|
||||||
|
%%%%
|
||||||
|
% NLP
|
||||||
|
%%%%
|
||||||
|
thefmean = mean(thefilter(8:16));
|
||||||
|
if (thefmean < 1)
|
||||||
|
disp('');
|
||||||
|
end
|
||||||
|
aecmStructNew.runningfmean = setupStruct.nl_alpha*aecmStructNew.runningfmean + (1-setupStruct.nl_alpha)*thefmean;
|
||||||
|
slope0 = 1.0/(1.0 - setupStruct.nlSeverity); %
|
||||||
|
thegain = max(0.0, min(1.0, slope0*(aecmStructNew.runningfmean - setupStruct.nlSeverity)));
|
||||||
|
if ~setupStruct.nlp_flag
|
||||||
|
thegain = 1;
|
||||||
|
end
|
||||||
|
% END NONLINEARITY
|
||||||
|
thefilter = thegain*thefilter;
|
||||||
|
|
||||||
|
%%%%
|
||||||
|
% The suppression
|
||||||
|
%%%%
|
||||||
|
femicrophone = fmicrophone .* thefilter;
|
||||||
|
% Store the output energy (used for plotting)
|
||||||
|
%aecmStructNew.enerOut(setupStruct.currentBlock) = log(abs(femicrophone)'*abs(femicrophone));
|
||||||
|
aecmStructNew.enerOut(setupStruct.currentBlock) = log(sum(abs(femicrophone)));
|
||||||
|
|
||||||
|
if aecmStructNew.plotIt
|
||||||
|
figure(13)
|
||||||
|
subplot(311)
|
||||||
|
%plot(n100,enerFar(n100),'b-',n100,enerNear(n100),'k--',n100,enerEcho(n100),'r-',[n100(1) n100(end)],[1 1]*vadThNew,'b:',[n100(1) n100(end)],[1 1]*((energyMax-energyMin)/4+energyMin),'r-.',[n100(1) n100(end)],[1 1]*vadNearThNew,'g:',[n100(1) n100(end)],[1 1]*energyMax,'r-.',[n100(1) n100(end)],[1 1]*energyMin,'r-.','LineWidth',2)
|
||||||
|
plot(n100,aecmStructNew.enerFar(n100),'b-',n100,aecmStructNew.enerNear(n100),'k--',n100,aecmStructNew.enerOut(n100),'r-.',n100,aecmStructNew.enerEcho(n100),'r-',n100,aecmStructNew.enerEchoStored(n100),'c-',[n100(1) n100(end)],[1 1]*((aecmStructNew.energyMax-aecmStructNew.energyMin)/4+aecmStructNew.energyMin),'g-.',[n100(1) n100(end)],[1 1]*aecmStructNew.energyMax,'g-.',[n100(1) n100(end)],[1 1]*aecmStructNew.energyMin,'g-.','LineWidth',2)
|
||||||
|
%title(['Frame ',int2str(i),' av ',int2str(setupStruct.updateno),' State = ',int2str(speechState),' \mu = ',num2str(mu)])
|
||||||
|
title(['\gamma = ',num2str(gamma_echo),' \mu = ',num2str(mu)])
|
||||||
|
subplot(312)
|
||||||
|
%plot(n100,enerError,'b-',[n100(1) n100(end)],[1 1]*vadNearTh,'r:',[n100(1) n100(end)],[-1.5 -1.5]*vadNearTh,'r:','LineWidth',2)
|
||||||
|
%plot(n100,enerError,'b-',[n100(1) n100(end)],[1 1],'r:',[n100(1) n100(end)],[-2 -2],'r:','LineWidth',2)
|
||||||
|
plot(n100,enerError,'b-',n100,enerErrorStored,'c-',[n100(1) n100(end)],[1 1]*aecmStructNew.varMean,'k--',[n100(1) n100(end)],[1 1],'r:',[n100(1) n100(end)],[-2 -2],'r:','LineWidth',2)
|
||||||
|
% Plot mu
|
||||||
|
%plot(n100,log2(aecmStructNew.muLog(n100)),'b-','LineWidth',2)
|
||||||
|
%plot(n100,log2(aecmStructNew.HGain(n100)),'b-',[n100(1) n100(end)],[1 1]*log2(sum(aecmStructNew.HStored)),'r:','LineWidth',2)
|
||||||
|
title(['Block ',int2str(setupStruct.currentBlock),' av ',int2str(setupStruct.updateno)])
|
||||||
|
subplot(313)
|
||||||
|
%plot(n100,enerVar(n100),'b-',[n100(1) n100(end)],[1 1],'r:',[n100(1) n100(end)],[-2 -2],'r:','LineWidth',2)
|
||||||
|
%plot(n100,enerVar(n100),'b-','LineWidth',2)
|
||||||
|
% Plot correlation curve
|
||||||
|
|
||||||
|
%plot(-25:25,aecmStructNew.delayStored/max(aecmStructNew.delayStored),'c-',-25:25,aecmStructNew.delayLatest/max(aecmStructNew.delayLatest),'r-',-25:25,(max(aecmStructNew.delayStoredS)-aecmStructNew.delayStoredS)/(max(aecmStructNew.delayStoredS)-min(aecmStructNew.delayStoredS)),'c:',-25:25,(max(aecmStructNew.delayLatestS)-aecmStructNew.delayLatestS)/(max(aecmStructNew.delayLatestS)-min(aecmStructNew.delayLatestS)),'r:','LineWidth',2)
|
||||||
|
%plot(-25:25,aecmStructNew.delayStored,'c-',-25:25,aecmStructNew.delayLatest,'r-',-25:25,(max(aecmStructNew.delayStoredS)-aecmStructNew.delayStoredS)/(max(aecmStructNew.delayStoredS)-min(aecmStructNew.delayStoredS)),'c:',-25:25,(max(aecmStructNew.delayLatestS)-aecmStructNew.delayLatestS)/(max(aecmStructNew.delayLatestS)-min(aecmStructNew.delayLatestS)),'r:','LineWidth',2)
|
||||||
|
%plot(-25:25,aecmStructNew.delayLatest,'r-',-25:25,(50-aecmStructNew.delayLatestS)/100,'r:','LineWidth',2)
|
||||||
|
plot(-25:25,aecmStructNew.delayLatestS,'r:','LineWidth',2)
|
||||||
|
%plot(-25:25,aecmStructNew.delayStored,'c-',-25:25,aecmStructNew.delayLatest,'r-','LineWidth',2)
|
||||||
|
plot(0:32,aecmStruct.HStored,'bo-','LineWidth',2)
|
||||||
|
%title(['\gamma | In = ',int2str(aecmStructNew.muStruct.countInInterval),' | Out High = ',int2str(aecmStructNew.muStruct.countOutHighInterval),' | Out Low = ',int2str(aecmStructNew.muStruct.countOutLowInterval)])
|
||||||
|
pause(1)
|
||||||
|
%if ((setupStruct.currentBlock == 860) | (setupStruct.currentBlock == 420) | (setupStruct.currentBlock == 960))
|
||||||
|
if 0%(setupStruct.currentBlock == 960)
|
||||||
|
figure(60)
|
||||||
|
plot(n100,aecmStructNew.enerNear(n100),'k--',n100,aecmStructNew.enerEcho(n100),'k:','LineWidth',2)
|
||||||
|
legend('Near End','Estimated Echo')
|
||||||
|
title('Signal Energy witH offset compensation')
|
||||||
|
figure(61)
|
||||||
|
subplot(211)
|
||||||
|
stem(sign(aecmStructNew.enerNear(n100)-mean(aecmStructNew.enerNear(n100))))
|
||||||
|
title('Near End Energy Pattern (around mean value)')
|
||||||
|
subplot(212)
|
||||||
|
stem(sign(aecmStructNew.enerEcho(n100)-mean(aecmStructNew.enerEcho(n100))))
|
||||||
|
title('Estimated Echo Energy Pattern (around mean value)')
|
||||||
|
pause
|
||||||
|
end
|
||||||
|
drawnow%,pause
|
||||||
|
elseif ~rem(setupStruct.currentBlock,100)
|
||||||
|
fprintf('Block %d of %d\n',setupStruct.currentBlock,setupStruct.updateno)
|
||||||
|
end
|
98
src/modules/audio_processing/aecm/main/matlab/matlab/align.m
Normal file
98
src/modules/audio_processing/aecm/main/matlab/matlab/align.m
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
function [delayStructNew] = align(xf, yf, delayStruct, i, trueDelay);
|
||||||
|
|
||||||
|
%%%%%%%
|
||||||
|
% Bastiaan's algorithm copied
|
||||||
|
%%%%%%%
|
||||||
|
Ap500 = [1.00, -4.95, 9.801, -9.70299, 4.80298005, -0.9509900499];
|
||||||
|
Bp500 = [0.662743088639636, -2.5841655608125, 3.77668102146288, -2.45182477425154, 0.596566274575251, 0.0];
|
||||||
|
Ap200 = [1.00, -4.875, 9.50625, -9.26859375, 4.518439453125, -0.881095693359375];
|
||||||
|
Bp200 = [0.862545460994275, -3.2832804496114, 4.67892032308828, -2.95798023879133, 0.699796870041299, 0.0];
|
||||||
|
|
||||||
|
oldMethod = 1; % Turn on or off the old method. The new one is Bastiaan's August 2008 updates
|
||||||
|
THReSHoLD = 2.0; % ADJUSTABLE threshold factor; 4.0 seems good
|
||||||
|
%%%%%%%%%%%%%%%%%%%
|
||||||
|
% use log domain (showed improved performance)
|
||||||
|
xxf = sqrt(real(xf.*conj(xf))+1e-20);
|
||||||
|
yyf = sqrt(real(yf.*conj(yf))+1e-20);
|
||||||
|
delayStruct.sxAll2(:,i) = 20*log10(xxf);
|
||||||
|
delayStruct.syAll2(:,i) = 20*log10(yyf);
|
||||||
|
|
||||||
|
mD = min(i-1,delayStruct.maxDelayb);
|
||||||
|
if oldMethod
|
||||||
|
factor = 1.0;
|
||||||
|
histLenb = 250;
|
||||||
|
xthreshold = factor*median(delayStruct.sxAll2(:,i-mD:i),2);
|
||||||
|
ythreshold = factor*median(delayStruct.syAll2(:,i-mD:i),2);
|
||||||
|
else
|
||||||
|
xthreshold = sum(delayStruct.sxAll2(:,i-mD:i),2)/(delayStruct.maxDelayb+1);
|
||||||
|
|
||||||
|
[yout, delayStruct.z200] = filter(Bp200, Ap200, delayStruct.syAll2(:,i), delayStruct.z200, 2);
|
||||||
|
yout = yout/(delayStruct.maxDelayb+1);
|
||||||
|
ythreshold = mean(delayStruct.syAll2(:,i-mD:i),2);
|
||||||
|
ythreshold = yout;
|
||||||
|
end
|
||||||
|
|
||||||
|
delayStruct.bxspectrum(i) = getBspectrum(delayStruct.sxAll2(:,i), xthreshold, delayStruct.bandfirst, delayStruct.bandlast);
|
||||||
|
delayStruct.byspectrum(i) = getBspectrum(delayStruct.syAll2(:,i), ythreshold, delayStruct.bandfirst, delayStruct.bandlast);
|
||||||
|
|
||||||
|
delayStruct.bxhist(end-mD:end) = delayStruct.bxspectrum(i-mD:i);
|
||||||
|
|
||||||
|
delayStruct.bcount(:,i) = hisser2(delayStruct.byspectrum(i), flipud(delayStruct.bxhist), delayStruct.bandfirst, delayStruct.bandlast);
|
||||||
|
[delayStruct.fout(:,i), delayStruct.z500] = filter(Bp500, Ap500, delayStruct.bcount(:,i), delayStruct.z500, 2);
|
||||||
|
if oldMethod
|
||||||
|
%delayStruct.new(:,i) = sum(delayStruct.bcount(:,max(1,i-histLenb+1):i),2); % using the history range
|
||||||
|
tmpVec = [delayStruct.fout(1,i)*ones(2,1); delayStruct.fout(:,i); delayStruct.fout(end,i)*ones(2,1)]; % using the history range
|
||||||
|
tmpVec = filter(ones(1,5), 1, tmpVec);
|
||||||
|
delayStruct.new(:,i) = tmpVec(5:end);
|
||||||
|
%delayStruct.new(:,i) = delayStruct.fout(:,i); % using the history range
|
||||||
|
else
|
||||||
|
[delayStruct.fout(:,i), delayStruct.z500] = filter(Bp500, Ap500, delayStruct.bcount(:,i), delayStruct.z500, 2);
|
||||||
|
% NEW CODE
|
||||||
|
delayStruct.new(:,i) = filter([-1,-2,1,4,1,-2,-1], 1, delayStruct.fout(:,i)); %remv smth component
|
||||||
|
delayStruct.new(1:end-3,i) = delayStruct.new(1+3:end,i);
|
||||||
|
delayStruct.new(1:6,i) = 0.0;
|
||||||
|
delayStruct.new(end-6:end,i) = 0.0; % ends are no good
|
||||||
|
end
|
||||||
|
[valuen, tempdelay] = min(delayStruct.new(:,i)); % find minimum
|
||||||
|
if oldMethod
|
||||||
|
threshold = valuen + (max(delayStruct.new(:,i)) - valuen)/4;
|
||||||
|
thIndex = find(delayStruct.new(:,i) <= threshold);
|
||||||
|
if (i > 1)
|
||||||
|
delayDiff = abs(delayStruct.delay(i-1)-tempdelay+1);
|
||||||
|
if (delayStruct.oneGoodEstimate & (max(diff(thIndex)) > 1) & (delayDiff < 10))
|
||||||
|
% We consider this minimum to be significant, hence update the delay
|
||||||
|
delayStruct.delay(i) = tempdelay;
|
||||||
|
elseif (~delayStruct.oneGoodEstimate & (max(diff(thIndex)) > 1))
|
||||||
|
delayStruct.delay(i) = tempdelay;
|
||||||
|
if (i > histLenb)
|
||||||
|
delayStruct.oneGoodEstimate = 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
delayStruct.delay(i) = delayStruct.delay(i-1);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
delayStruct.delay(i) = tempdelay;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
threshold = THReSHoLD*std(delayStruct.new(:,i)); % set updata threshold
|
||||||
|
if ((-valuen > threshold) | (i < delayStruct.smlength)) % see if you want to update delay
|
||||||
|
delayStruct.delay(i) = tempdelay;
|
||||||
|
else
|
||||||
|
delayStruct.delay(i) = delayStruct.delay(i-1);
|
||||||
|
end
|
||||||
|
% END NEW CODE
|
||||||
|
end
|
||||||
|
delayStructNew = delayStruct;
|
||||||
|
|
||||||
|
% administrative and plotting stuff
|
||||||
|
if( 0)
|
||||||
|
figure(10);
|
||||||
|
plot([1:length(delayStructNew.new(:,i))],delayStructNew.new(:,i),trueDelay*[1 1],[min(delayStructNew.new(:,i)),max(delayStructNew.new(:,i))],'r',[1 length(delayStructNew.new(:,i))],threshold*[1 1],'r:', 'LineWidth',2);
|
||||||
|
%plot([1:length(delayStructNew.bcount(:,i))],delayStructNew.bcount(:,i),trueDelay*[1 1],[min(delayStructNew.bcount(:,i)),max(delayStructNew.bcount(:,i))],'r','LineWidth',2);
|
||||||
|
%plot([thedelay,thedelay],[min(fcount(:,i)),max(fcount(:,i))],'r');
|
||||||
|
%title(sprintf('bin count and known delay at time %5.1f s\n',(i-1)*(support/(fs*oversampling))));
|
||||||
|
title(delayStructNew.oneGoodEstimate)
|
||||||
|
xlabel('delay in frames');
|
||||||
|
%hold off;
|
||||||
|
drawnow
|
||||||
|
end
|
@ -0,0 +1,88 @@
|
|||||||
|
function [gam, cntIn2, cntOut2] = calcFilterGain(energy, dE, aecmStruct, t, T, cntIn, cntOut)
|
||||||
|
|
||||||
|
defaultLevel = 1.2;
|
||||||
|
cntIn2 = cntIn;
|
||||||
|
cntOut2 = cntOut;
|
||||||
|
if (t < T)
|
||||||
|
gam = 1;
|
||||||
|
else
|
||||||
|
dE1 = -5;
|
||||||
|
dE2 = 1;
|
||||||
|
gamMid = 0.2;
|
||||||
|
gam = max(0,min((energy - aecmStruct.energyMin)/(aecmStruct.energyLevel - aecmStruct.energyMin), 1-(1-gamMid)*(aecmStruct.energyMax-energy)/(aecmStruct.energyMax-aecmStruct.energyLevel)));
|
||||||
|
|
||||||
|
dEOffset = -0.5;
|
||||||
|
dEWidth = 1.5;
|
||||||
|
%gam2 = max(1,2-((dE-dEOffset)/(dE2-dEOffset)).^2);
|
||||||
|
gam2 = 1+(abs(dE-dEOffset)<(dE2-dEOffset));
|
||||||
|
|
||||||
|
gam = gam*gam2;
|
||||||
|
|
||||||
|
|
||||||
|
if (energy < aecmStruct.energyLevel)
|
||||||
|
gam = 0;
|
||||||
|
else
|
||||||
|
gam = defaultLevel;
|
||||||
|
end
|
||||||
|
dEVec = aecmStruct.enerNear(t-63:t)-aecmStruct.enerEcho(t-63:t);
|
||||||
|
%dEVec = aecmStruct.enerNear(t-20:t)-aecmStruct.enerEcho(t-20:t);
|
||||||
|
numCross = 0;
|
||||||
|
currentState = 0;
|
||||||
|
for ii=1:64
|
||||||
|
if (currentState == 0)
|
||||||
|
currentState = (dEVec(ii) > dE2) - (dEVec(ii) < -2);
|
||||||
|
elseif ((currentState == 1) & (dEVec(ii) < -2))
|
||||||
|
numCross = numCross + 1;
|
||||||
|
currentState = -1;
|
||||||
|
elseif ((currentState == -1) & (dEVec(ii) > dE2))
|
||||||
|
numCross = numCross + 1;
|
||||||
|
currentState = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
gam = max(0, gam - numCross/25);
|
||||||
|
gam = 1;
|
||||||
|
|
||||||
|
ener_A = 1;
|
||||||
|
ener_B = 0.8;
|
||||||
|
ener_C = aecmStruct.energyLevel + (aecmStruct.energyMax-aecmStruct.energyLevel)/5;
|
||||||
|
dE_A = 4;%2;
|
||||||
|
dE_B = 3.6;%1.8;
|
||||||
|
dE_C = 0.9*dEWidth;
|
||||||
|
dE_D = 1;
|
||||||
|
timeFactorLength = 10;
|
||||||
|
ddE = abs(dE-dEOffset);
|
||||||
|
if (energy < aecmStruct.energyLevel)
|
||||||
|
gam = 0;
|
||||||
|
else
|
||||||
|
gam = 1;
|
||||||
|
gam2 = max(0, min(ener_B*(energy-aecmStruct.energyLevel)/(ener_C-aecmStruct.energyLevel), ener_B+(ener_A-ener_B)*(energy-ener_C)/(aecmStruct.energyMax-ener_C)));
|
||||||
|
if (ddE < dEWidth)
|
||||||
|
% Update counters
|
||||||
|
cntIn2 = cntIn2 + 1;
|
||||||
|
if (cntIn2 > 2)
|
||||||
|
cntOut2 = 0;
|
||||||
|
end
|
||||||
|
gam3 = max(dE_D, min(dE_A-(dE_A-dE_B)*(ddE/dE_C), dE_D+(dE_B-dE_D)*(dEWidth-ddE)/(dEWidth-dE_C)));
|
||||||
|
gam3 = dE_A;
|
||||||
|
else
|
||||||
|
% Update counters
|
||||||
|
cntOut2 = cntOut2 + 1;
|
||||||
|
if (cntOut2 > 2)
|
||||||
|
cntIn2 = 0;
|
||||||
|
end
|
||||||
|
%gam2 = 1;
|
||||||
|
gam3 = dE_D;
|
||||||
|
end
|
||||||
|
timeFactor = min(1, cntIn2/timeFactorLength);
|
||||||
|
gam = gam*(1-timeFactor) + timeFactor*gam2*gam3;
|
||||||
|
end
|
||||||
|
%gam = gam/floor(numCross/2+1);
|
||||||
|
end
|
||||||
|
if isempty(gam)
|
||||||
|
numCross
|
||||||
|
timeFactor
|
||||||
|
cntIn2
|
||||||
|
cntOut2
|
||||||
|
gam2
|
||||||
|
gam3
|
||||||
|
end
|
@ -0,0 +1,105 @@
|
|||||||
|
function [mu, aecmStructNew] = calcStepSize(energy, dE, aecmStruct, t, logscale)
|
||||||
|
|
||||||
|
if (nargin < 4)
|
||||||
|
t = 1;
|
||||||
|
logscale = 1;
|
||||||
|
elseif (nargin == 4)
|
||||||
|
logscale = 1;
|
||||||
|
end
|
||||||
|
T = aecmStruct.convLength;
|
||||||
|
|
||||||
|
if logscale
|
||||||
|
currentMuMax = aecmStruct.MU_MIN + (aecmStruct.MU_MAX-aecmStruct.MU_MIN)*min(t,T)/T;
|
||||||
|
if (aecmStruct.energyMin >= aecmStruct.energyMax)
|
||||||
|
mu = aecmStruct.MU_MIN;
|
||||||
|
else
|
||||||
|
mu = (energy - aecmStruct.energyMin)/(aecmStruct.energyMax - aecmStruct.energyMin)*(currentMuMax-aecmStruct.MU_MIN) + aecmStruct.MU_MIN;
|
||||||
|
end
|
||||||
|
mu = 2^mu;
|
||||||
|
if (energy < aecmStruct.energyLevel)
|
||||||
|
mu = 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
muMin = 0;
|
||||||
|
muMax = 0.5;
|
||||||
|
currentMuMax = muMin + (muMax-muMin)*min(t,T)/T;
|
||||||
|
if (aecmStruct.energyMin >= aecmStruct.energyMax)
|
||||||
|
mu = muMin;
|
||||||
|
else
|
||||||
|
mu = (energy - aecmStruct.energyMin)/(aecmStruct.energyMax - aecmStruct.energyMin)*(currentMuMax-muMin) + muMin;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dE2 = 1;
|
||||||
|
dEOffset = -0.5;
|
||||||
|
offBoost = 5;
|
||||||
|
if (mu > 0)
|
||||||
|
if (abs(dE-aecmStruct.ENERGY_DEV_OFFSET) > aecmStruct.ENERGY_DEV_TOL)
|
||||||
|
aecmStruct.muStruct.countInInterval = 0;
|
||||||
|
else
|
||||||
|
aecmStruct.muStruct.countInInterval = aecmStruct.muStruct.countInInterval + 1;
|
||||||
|
end
|
||||||
|
if (dE < aecmStruct.ENERGY_DEV_OFFSET - aecmStruct.ENERGY_DEV_TOL)
|
||||||
|
aecmStruct.muStruct.countOutLowInterval = aecmStruct.muStruct.countOutLowInterval + 1;
|
||||||
|
else
|
||||||
|
aecmStruct.muStruct.countOutLowInterval = 0;
|
||||||
|
end
|
||||||
|
if (dE > aecmStruct.ENERGY_DEV_OFFSET + aecmStruct.ENERGY_DEV_TOL)
|
||||||
|
aecmStruct.muStruct.countOutHighInterval = aecmStruct.muStruct.countOutHighInterval + 1;
|
||||||
|
else
|
||||||
|
aecmStruct.muStruct.countOutHighInterval = 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
muVar = 2^min(-3,5/50*aecmStruct.muStruct.countInInterval-3);
|
||||||
|
muOff = 2^max(offBoost,min(0,offBoost*(aecmStruct.muStruct.countOutLowInterval-aecmStruct.muStruct.minOutLowInterval)/(aecmStruct.muStruct.maxOutLowInterval-aecmStruct.muStruct.minOutLowInterval)));
|
||||||
|
|
||||||
|
muLow = 1/64;
|
||||||
|
muVar = 1;
|
||||||
|
if (t < 2*T)
|
||||||
|
muDT = 1;
|
||||||
|
muVar = 1;
|
||||||
|
mdEVec = 0;
|
||||||
|
numCross = 0;
|
||||||
|
else
|
||||||
|
muDT = min(1,max(muLow,1-(1-muLow)*(dE-aecmStruct.ENERGY_DEV_OFFSET)/aecmStruct.ENERGY_DEV_TOL));
|
||||||
|
dEVec = aecmStruct.enerNear(t-63:t)-aecmStruct.enerEcho(t-63:t);
|
||||||
|
%dEVec = aecmStruct.enerNear(t-20:t)-aecmStruct.enerEcho(t-20:t);
|
||||||
|
numCross = 0;
|
||||||
|
currentState = 0;
|
||||||
|
for ii=1:64
|
||||||
|
if (currentState == 0)
|
||||||
|
currentState = (dEVec(ii) > dE2) - (dEVec(ii) < -2);
|
||||||
|
elseif ((currentState == 1) & (dEVec(ii) < -2))
|
||||||
|
numCross = numCross + 1;
|
||||||
|
currentState = -1;
|
||||||
|
elseif ((currentState == -1) & (dEVec(ii) > dE2))
|
||||||
|
numCross = numCross + 1;
|
||||||
|
currentState = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%logicDEVec = (dEVec > dE2) - (dEVec < -2);
|
||||||
|
%numCross = sum(abs(diff(logicDEVec)));
|
||||||
|
%mdEVec = mean(abs(dEVec-dEOffset));
|
||||||
|
%mdEVec = mean(abs(dEVec-mean(dEVec)));
|
||||||
|
%mdEVec = max(dEVec)-min(dEVec);
|
||||||
|
%if (mdEVec > 4)%1.5)
|
||||||
|
% muVar = 0;
|
||||||
|
%end
|
||||||
|
muVar = 2^(-floor(numCross/2));
|
||||||
|
muVar = 2^(-numCross);
|
||||||
|
end
|
||||||
|
%muVar = 1;
|
||||||
|
|
||||||
|
|
||||||
|
% if (eStd > (dE2-dEOffset))
|
||||||
|
% muVar = 1/8;
|
||||||
|
% else
|
||||||
|
% muVar = 1;
|
||||||
|
% end
|
||||||
|
|
||||||
|
%mu = mu*muDT*muVar*muOff;
|
||||||
|
mu = mu*muDT*muVar;
|
||||||
|
mu = min(mu,0.25);
|
||||||
|
aecmStructNew = aecmStruct;
|
||||||
|
%aecmStructNew.varMean = mdEVec;
|
||||||
|
aecmStructNew.varMean = numCross;
|
@ -0,0 +1,42 @@
|
|||||||
|
function [U, Hnew] = fallerEstimator(Y, X, H, mu)
|
||||||
|
|
||||||
|
% Near end signal is stacked frame by frame columnwise in matrix Y and far end in X
|
||||||
|
%
|
||||||
|
% Possible estimation procedures are
|
||||||
|
% 1) LSE
|
||||||
|
% 2) NLMS
|
||||||
|
% 3) Separated numerator and denomerator filters
|
||||||
|
regParam = 1;
|
||||||
|
[numFreqs, numFrames] = size(Y);
|
||||||
|
[numFreqs, Q] = size(X);
|
||||||
|
U = zeros(numFreqs, 1);
|
||||||
|
|
||||||
|
if ((nargin == 3) | (nargin == 5))
|
||||||
|
dtd = 0;
|
||||||
|
end
|
||||||
|
if (nargin == 4)
|
||||||
|
dtd = H;
|
||||||
|
end
|
||||||
|
Emax = 7;
|
||||||
|
dEH = Emax-sum(sum(H));
|
||||||
|
nu = 2*mu;
|
||||||
|
% if (nargin < 5)
|
||||||
|
% H = zeros(numFreqs, Q);
|
||||||
|
% for kk = 1:numFreqs
|
||||||
|
% Xmatrix = hankel(X(kk,1:Q),X(kk,Q:end));
|
||||||
|
% y = Y(kk,1:end-Q+1)';
|
||||||
|
% H(kk,:) = (y'*Xmatrix')*inv(Xmatrix*Xmatrix'+regParam);
|
||||||
|
% U(kk,1) = H(kk,:)*Xmatrix(:,1);
|
||||||
|
% end
|
||||||
|
% else
|
||||||
|
for kk = 1:numFreqs
|
||||||
|
x = X(kk,1:Q)';
|
||||||
|
y = Y(kk,1);
|
||||||
|
Htmp = mu*(y-H(kk,:)*x)/(x'*x+regParam)*x;
|
||||||
|
%Htmp = (mu*(y-H(kk,:)*x)/(x'*x+regParam) - nu/dEH)*x;
|
||||||
|
H(kk,:) = H(kk,:) + Htmp';
|
||||||
|
U(kk,1) = H(kk,:)*x;
|
||||||
|
end
|
||||||
|
% end
|
||||||
|
|
||||||
|
Hnew = H;
|
@ -0,0 +1,22 @@
|
|||||||
|
function bspectrum=getBspectrum(ps,threshold,bandfirst,bandlast)
|
||||||
|
% function bspectrum=getBspectrum(ps,threshold,bandfirst,bandlast)
|
||||||
|
% compute binary spectrum using threshold spectrum as pivot
|
||||||
|
% bspectrum = binary spectrum (binary)
|
||||||
|
% ps=current power spectrum (float)
|
||||||
|
% threshold=threshold spectrum (float)
|
||||||
|
% bandfirst = first band considered
|
||||||
|
% bandlast = last band considered
|
||||||
|
|
||||||
|
% initialization stuff
|
||||||
|
if( length(ps)<bandlast | bandlast>32 | length(ps)~=length(threshold))
|
||||||
|
error('BinDelayEst:spectrum:invalid','Dimensionality error');
|
||||||
|
end
|
||||||
|
|
||||||
|
% get current binary spectrum
|
||||||
|
diff = ps - threshold;
|
||||||
|
bspectrum=uint32(0);
|
||||||
|
for(i=bandfirst:bandlast)
|
||||||
|
if( diff(i)>0 )
|
||||||
|
bspectrum = bitset(bspectrum,i);
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,21 @@
|
|||||||
|
function bcount=hisser2(bs,bsr,bandfirst,bandlast)
|
||||||
|
% function bcount=hisser(bspectrum,bandfirst,bandlast)
|
||||||
|
% histogram for the binary spectra
|
||||||
|
% bcount= array of bit counts
|
||||||
|
% bs=binary spectrum (one int32 number each)
|
||||||
|
% bsr=reference binary spectra (one int32 number each)
|
||||||
|
% blockSize = histogram over blocksize blocks
|
||||||
|
% bandfirst = first band considered
|
||||||
|
% bandlast = last band considered
|
||||||
|
|
||||||
|
% weight all delays equally
|
||||||
|
maxDelay = length(bsr);
|
||||||
|
|
||||||
|
% compute counts (two methods; the first works better and is operational)
|
||||||
|
bcount=zeros(maxDelay,1);
|
||||||
|
for(i=1:maxDelay)
|
||||||
|
% the delay should have low count for low-near&high-far and high-near&low-far
|
||||||
|
bcount(i)= sum(bitget(bitxor(bs,bsr(i)),bandfirst:bandlast));
|
||||||
|
% the delay should have low count for low-near&high-far (works less well)
|
||||||
|
% bcount(i)= sum(bitget(bitand(bsr(i),bitxor(bs,bsr(i))),bandfirst:bandlast));
|
||||||
|
end
|
@ -0,0 +1,283 @@
|
|||||||
|
useHTC = 1; % Set this if you want to run a single file and set file names below. Otherwise use simEnvironment to run from several scenarios in a row
|
||||||
|
delayCompensation_flag = 0; % Set this flag to one if you want to turn on the delay compensation/enhancement
|
||||||
|
global FARENDFFT;
|
||||||
|
global NEARENDFFT;
|
||||||
|
global F;
|
||||||
|
|
||||||
|
if useHTC
|
||||||
|
% fid=fopen('./htcTouchHd/nb/aecFar.pcm'); xFar=fread(fid,'short'); fclose(fid);
|
||||||
|
% fid=fopen('./htcTouchHd/nb/aecNear.pcm'); yNear=fread(fid,'short'); fclose(fid);
|
||||||
|
% fid=fopen('./samsungBlackjack/nb/aecFar.pcm'); xFar=fread(fid,'short'); fclose(fid);
|
||||||
|
% fid=fopen('./samsungBlackjack/nb/aecNear.pcm'); yNear=fread(fid,'short'); fclose(fid);
|
||||||
|
% fid=fopen('aecFarPoor.pcm'); xFar=fread(fid,'short'); fclose(fid);
|
||||||
|
% fid=fopen('aecNearPoor.pcm'); yNear=fread(fid,'short'); fclose(fid);
|
||||||
|
% fid=fopen('out_aes.pcm'); outAES=fread(fid,'short'); fclose(fid);
|
||||||
|
fid=fopen('aecFar4.pcm'); xFar=fread(fid,'short'); fclose(fid);
|
||||||
|
fid=fopen('aecNear4.pcm'); yNear=fread(fid,'short'); fclose(fid);
|
||||||
|
yNearSpeech = zeros(size(xFar));
|
||||||
|
fs = 8000;
|
||||||
|
frameSize = 64;
|
||||||
|
% frameSize = 128;
|
||||||
|
fs = 16000;
|
||||||
|
% frameSize = 256;
|
||||||
|
%F = load('fftValues.txt');
|
||||||
|
%FARENDFFT = F(:,1:33);
|
||||||
|
%NEARENDFFT = F(:,34:66);
|
||||||
|
|
||||||
|
else
|
||||||
|
loadFileFar = [speakerType, '_s_',scenario,'_far_b.wav'];
|
||||||
|
[xFar,fs,nbits] = wavread(loadFileFar);
|
||||||
|
xFar = xFar*2^(nbits-1);
|
||||||
|
loadFileNear = [speakerType, '_s_',scenario,'_near_b.wav'];
|
||||||
|
[yNear,fs,nbits] = wavread(loadFileNear);
|
||||||
|
yNear = yNear*2^(nbits-1);
|
||||||
|
loadFileNearSpeech = [speakerType, '_s_',scenario,'_nearSpeech_b.wav'];
|
||||||
|
[yNearSpeech,fs,nbits] = wavread(loadFileNearSpeech);
|
||||||
|
yNearSpeech = yNearSpeech*2^(nbits-1);
|
||||||
|
frameSize = 256;
|
||||||
|
end
|
||||||
|
|
||||||
|
dtRegions = [];
|
||||||
|
|
||||||
|
% General settings for the AECM
|
||||||
|
setupStruct = struct(...
|
||||||
|
'stepSize_flag', 1,... % This flag turns on the step size calculation. If turned off, mu = 0.25.
|
||||||
|
'supGain_flag', 0,... % This flag turns on the suppression gain calculation. If turned off, gam = 1.
|
||||||
|
'channelUpdate_flag', 0,... % This flag turns on the channel update. If turned off, H is updated for convLength and then kept constant.
|
||||||
|
'nlp_flag', 0,... % Turn on/off NLP
|
||||||
|
'withVAD_flag', 0,... % Turn on/off NLP
|
||||||
|
'useSubBand', 0,... % Set to 1 if to use subBands
|
||||||
|
'useDelayEstimation', 1,... % Set to 1 if to use delay estimation
|
||||||
|
'support', frameSize,... % # of samples per frame
|
||||||
|
'samplingfreq',fs,... % Sampling frequency
|
||||||
|
'oversampling', 2,... % Overlap between blocks/frames
|
||||||
|
'updatel', 0,... % # of samples between blocks
|
||||||
|
'hsupport1', 0,... % # of bins in frequency domain
|
||||||
|
'factor', 0,... % synthesis window amplification
|
||||||
|
'tlength', 0,... % # of samples of entire file
|
||||||
|
'updateno', 0,... % # of updates
|
||||||
|
'nb', 1,... % # of blocks
|
||||||
|
'currentBlock', 0,... %
|
||||||
|
'win', zeros(frameSize,1),...% Window to apply for fft and synthesis
|
||||||
|
'avtime', 1,... % Time (in sec.) to perform averaging
|
||||||
|
'estLen', 0,... % Averaging in # of blocks
|
||||||
|
'A_GAIN', 10.0,... %
|
||||||
|
'suppress_overdrive', 1.0,... % overdrive factor for suppression 1.4 is good
|
||||||
|
'gamma_echo', 1.0,... % same as suppress_overdrive but at different place
|
||||||
|
'de_echo_bound', 0.0,... %
|
||||||
|
'nl_alpha', 0.4,... % memory; seems not very critical
|
||||||
|
'nlSeverity', 0.2,... % nonlinearity severity: 0 does nothing; 1 suppresses all
|
||||||
|
'numInBand', [],... % # of frequency bins in resp. subBand
|
||||||
|
'centerFreq', [],... % Center frequency of resp. subBand
|
||||||
|
'dtRegions', dtRegions,... % Regions where we have DT
|
||||||
|
'subBandLength', frameSize/2);%All bins
|
||||||
|
%'subBandLength', 11); %Something's wrong when subBandLength even
|
||||||
|
%'nl_alpha', 0.8,... % memory; seems not very critical
|
||||||
|
|
||||||
|
delayStruct = struct(...
|
||||||
|
'bandfirst', 8,...
|
||||||
|
'bandlast', 25,...
|
||||||
|
'smlength', 600,...
|
||||||
|
'maxDelay', 0.4,...
|
||||||
|
'oneGoodEstimate', 0,...
|
||||||
|
'delayAdjust', 0,...
|
||||||
|
'maxDelayb', 0);
|
||||||
|
% More parameters in delayStruct are constructed in "updateSettings" below
|
||||||
|
|
||||||
|
% Make struct settings
|
||||||
|
[setupStruct, delayStruct] = updateSettings(yNear, xFar, setupStruct, delayStruct);
|
||||||
|
setupStruct.numInBand = ones(setupStruct.hsupport1,1);
|
||||||
|
|
||||||
|
Q = 1; % Time diversity in channel
|
||||||
|
% General settings for the step size calculation
|
||||||
|
muStruct = struct(...
|
||||||
|
'countInInterval', 0,...
|
||||||
|
'countOutHighInterval', 0,...
|
||||||
|
'countOutLowInterval', 0,...
|
||||||
|
'minInInterval', 50,...
|
||||||
|
'minOutHighInterval', 10,...
|
||||||
|
'minOutLowInterval', 10,...
|
||||||
|
'maxOutLowInterval', 50);
|
||||||
|
% General settings for the AECM
|
||||||
|
aecmStruct = struct(...
|
||||||
|
'plotIt', 0,... % Set to 0 to turn off plotting
|
||||||
|
'useSubBand', 0,...
|
||||||
|
'bandFactor', 1,...
|
||||||
|
'H', zeros(setupStruct.subBandLength+1,Q),...
|
||||||
|
'HStored', zeros(setupStruct.subBandLength+1,Q),...
|
||||||
|
'X', zeros(setupStruct.subBandLength+1,Q),...
|
||||||
|
'energyThres', 0.28,...
|
||||||
|
'energyThresMSE', 0.4,...
|
||||||
|
'energyMin', inf,...
|
||||||
|
'energyMax', -inf,...
|
||||||
|
'energyLevel', 0,...
|
||||||
|
'energyLevelMSE', 0,...
|
||||||
|
'convLength', 100,...
|
||||||
|
'gammaLog', ones(setupStruct.updateno,1),...
|
||||||
|
'muLog', ones(setupStruct.updateno,1),...
|
||||||
|
'enerFar', zeros(setupStruct.updateno,1),...
|
||||||
|
'enerNear', zeros(setupStruct.updateno,1),...
|
||||||
|
'enerEcho', zeros(setupStruct.updateno,1),...
|
||||||
|
'enerEchoStored', zeros(setupStruct.updateno,1),...
|
||||||
|
'enerOut', zeros(setupStruct.updateno,1),...
|
||||||
|
'runningfmean', 0,...
|
||||||
|
'muStruct', muStruct,...
|
||||||
|
'varMean', 0,...
|
||||||
|
'countMseH', 0,...
|
||||||
|
'mseHThreshold', 1.1,...
|
||||||
|
'mseHStoredOld', inf,...
|
||||||
|
'mseHLatestOld', inf,...
|
||||||
|
'delayLatestS', zeros(1,51),...
|
||||||
|
'feedbackDelay', 0,...
|
||||||
|
'feedbackDelayUpdate', 0,...
|
||||||
|
'cntIn', 0,...
|
||||||
|
'cntOut', 0,...
|
||||||
|
'FAR_ENERGY_MIN', 1,...
|
||||||
|
'ENERGY_DEV_OFFSET', 0.5,...
|
||||||
|
'ENERGY_DEV_TOL', 1.5,...
|
||||||
|
'MU_MIN', -16,...
|
||||||
|
'MU_MAX', -2,...
|
||||||
|
'newDelayCurve', 0);
|
||||||
|
|
||||||
|
% Adjust speech signals
|
||||||
|
xFar = [zeros(setupStruct.hsupport1-1,1);xFar(1:setupStruct.tlength)];
|
||||||
|
yNear = [zeros(setupStruct.hsupport1-1,1);yNear(1:setupStruct.tlength)];
|
||||||
|
yNearSpeech = [zeros(setupStruct.hsupport1-1,1);yNearSpeech(1:setupStruct.tlength)];
|
||||||
|
xFar = xFar(1:setupStruct.tlength);
|
||||||
|
yNear = yNear(1:setupStruct.tlength);
|
||||||
|
|
||||||
|
% Set figure settings
|
||||||
|
if aecmStruct.plotIt
|
||||||
|
figure(13)
|
||||||
|
set(gcf,'doublebuffer','on')
|
||||||
|
end
|
||||||
|
%%%%%%%%%%
|
||||||
|
% Here starts the algorithm
|
||||||
|
% Dividing into frames and then estimating the near end speech
|
||||||
|
%%%%%%%%%%
|
||||||
|
fTheFarEnd = complex(zeros(setupStruct.hsupport1,1));
|
||||||
|
afTheFarEnd = zeros(setupStruct.hsupport1,setupStruct.updateno+1);
|
||||||
|
fFar = zeros(setupStruct.hsupport1,setupStruct.updateno+1);
|
||||||
|
fmicrophone = complex(zeros(setupStruct.hsupport1,1));
|
||||||
|
afmicrophone = zeros(setupStruct.hsupport1,setupStruct.updateno+1);
|
||||||
|
fNear = zeros(setupStruct.hsupport1,setupStruct.updateno+1);
|
||||||
|
femicrophone = complex(zeros(setupStruct.hsupport1,1));
|
||||||
|
emicrophone = zeros(setupStruct.tlength,1);
|
||||||
|
|
||||||
|
if (setupStruct.useDelayEstimation == 2)
|
||||||
|
delSamples = [1641 1895 2032 1895 2311 2000 2350 2222 NaN 2332 2330 2290 2401 2415 NaN 2393 2305 2381 2398];
|
||||||
|
delBlocks = round(delSamples/setupStruct.updatel);
|
||||||
|
delStarts = floor([25138 46844 105991 169901 195739 218536 241803 333905 347703 362660 373753 745135 765887 788078 806257 823835 842443 860139 881869]/setupStruct.updatel);
|
||||||
|
else
|
||||||
|
delStarts = [];
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1:setupStruct.updateno
|
||||||
|
setupStruct.currentBlock = i;
|
||||||
|
|
||||||
|
sb = (i-1)*setupStruct.updatel + 1;
|
||||||
|
se = sb + setupStruct.support - 1;
|
||||||
|
|
||||||
|
%%%%%%%
|
||||||
|
% Analysis FFTs
|
||||||
|
%%%%%%%
|
||||||
|
% Far end signal
|
||||||
|
temp = fft(setupStruct.win .* xFar(sb:se))/frameSize;
|
||||||
|
fTheFarEnd = temp(1:setupStruct.hsupport1);
|
||||||
|
afTheFarEnd(:,i) = abs(fTheFarEnd);
|
||||||
|
fFar(:,i) = fTheFarEnd;
|
||||||
|
% Near end signal
|
||||||
|
temp = fft(setupStruct.win .* yNear(sb:se))/frameSize;%,pause
|
||||||
|
fmicrophone = temp(1:setupStruct.hsupport1);
|
||||||
|
afmicrophone(:,i) = abs(fmicrophone);
|
||||||
|
fNear(:,i) = fmicrophone;
|
||||||
|
%abs(fmicrophone),pause
|
||||||
|
% The true near end speaker (if we have such info)
|
||||||
|
temp = fft(setupStruct.win .* yNearSpeech(sb:se));
|
||||||
|
aftrueSpeech = abs(temp(1:setupStruct.hsupport1));
|
||||||
|
|
||||||
|
if(i == 1000)
|
||||||
|
%break;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Perform delay estimation
|
||||||
|
if (setupStruct.useDelayEstimation == 1)
|
||||||
|
% Delay Estimation
|
||||||
|
delayStruct = align(fTheFarEnd, fmicrophone, delayStruct, i);
|
||||||
|
%delayStruct.delay(i) = 39;%19;
|
||||||
|
idel = max(i - delayStruct.delay(i) + 1,1);
|
||||||
|
|
||||||
|
if delayCompensation_flag
|
||||||
|
% If we have a new delay estimate from Bastiaan's alg. update the offset
|
||||||
|
if (delayStruct.delay(i) ~= delayStruct.delay(max(1,i-1)))
|
||||||
|
delayStruct.delayAdjust = delayStruct.delayAdjust + delayStruct.delay(i) - delayStruct.delay(i-1);
|
||||||
|
end
|
||||||
|
% Store the compensated delay
|
||||||
|
delayStruct.delayNew(i) = delayStruct.delay(i) - delayStruct.delayAdjust;
|
||||||
|
if (delayStruct.delayNew(i) < 1)
|
||||||
|
% Something's wrong
|
||||||
|
pause,break
|
||||||
|
end
|
||||||
|
% Compensate with the offset estimate
|
||||||
|
idel = idel + delayStruct.delayAdjust;
|
||||||
|
end
|
||||||
|
if 0%aecmStruct.plotIt
|
||||||
|
figure(1)
|
||||||
|
plot(1:i,delayStruct.delay(1:i),'k:',1:i,delayStruct.delayNew(1:i),'k--','LineWidth',2),drawnow
|
||||||
|
end
|
||||||
|
elseif (setupStruct.useDelayEstimation == 2)
|
||||||
|
% Use "manual delay"
|
||||||
|
delIndex = find(delStarts<i);
|
||||||
|
if isempty(delIndex)
|
||||||
|
idel = i;
|
||||||
|
else
|
||||||
|
idel = i - delBlocks(max(delIndex));
|
||||||
|
if isnan(idel)
|
||||||
|
idel = i - delBlocks(max(delIndex)-1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
% No delay estimation
|
||||||
|
%idel = max(i - 18, 1);
|
||||||
|
idel = max(i - 50, 1);
|
||||||
|
end
|
||||||
|
|
||||||
|
%%%%%%%%
|
||||||
|
% This is the AECM algorithm
|
||||||
|
%
|
||||||
|
% Output is the new frequency domain signal (hopefully) echo compensated
|
||||||
|
%%%%%%%%
|
||||||
|
[femicrophone, aecmStruct] = AECMobile(fmicrophone, afTheFarEnd(:,idel), setupStruct, aecmStruct);
|
||||||
|
%[femicrophone, aecmStruct] = AECMobile(fmicrophone, FARENDFFT(idel,:)'/2^F(idel,end-1), setupStruct, aecmStruct);
|
||||||
|
|
||||||
|
if aecmStruct.feedbackDelayUpdate
|
||||||
|
% If the feedback tells us there is a new offset out there update the enhancement
|
||||||
|
delayStruct.delayAdjust = delayStruct.delayAdjust + aecmStruct.feedbackDelay;
|
||||||
|
aecmStruct.feedbackDelayUpdate = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
% reconstruction; first make spectrum odd
|
||||||
|
temp = [femicrophone; flipud(conj(femicrophone(2:(setupStruct.hsupport1-1))))];
|
||||||
|
emicrophone(sb:se) = emicrophone(sb:se) + setupStruct.factor * setupStruct.win .* real(ifft(temp))*frameSize;
|
||||||
|
if max(isnan(emicrophone(sb:se)))
|
||||||
|
% Something's wrong with the output at block i
|
||||||
|
i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if useHTC
|
||||||
|
fid=fopen('aecOutMatlabC.pcm','w');fwrite(fid,int16(emicrophone),'short');fclose(fid);
|
||||||
|
%fid=fopen('farendFFT.txt','w');fwrite(fid,int16(afTheFarEnd(:)),'short');fclose(fid);
|
||||||
|
%fid=fopen('farendFFTreal.txt','w');fwrite(fid,int16(imag(fFar(:))),'short');fclose(fid);
|
||||||
|
%fid=fopen('farendFFTimag.txt','w');fwrite(fid,int16(real(fFar(:))),'short');fclose(fid);
|
||||||
|
%fid=fopen('nearendFFT.txt','w');fwrite(fid,int16(afmicrophone(:)),'short');fclose(fid);
|
||||||
|
%fid=fopen('nearendFFTreal.txt','w');fwrite(fid,int16(real(fNear(:))),'short');fclose(fid);
|
||||||
|
%fid=fopen('nearendFFTimag.txt','w');fwrite(fid,int16(imag(fNear(:))),'short');fclose(fid);
|
||||||
|
end
|
||||||
|
if useHTC
|
||||||
|
%spclab(setupStruct.samplingfreq,xFar,yNear,emicrophone)
|
||||||
|
else
|
||||||
|
spclab(setupStruct.samplingfreq,xFar,yNear,emicrophone,yNearSpeech)
|
||||||
|
end
|
@ -0,0 +1,15 @@
|
|||||||
|
speakerType = 'fm';
|
||||||
|
%for k=2:5
|
||||||
|
%for k=[2 4 5]
|
||||||
|
for k=3
|
||||||
|
scenario = int2str(k);
|
||||||
|
fprintf('Current scenario: %d\n',k)
|
||||||
|
mainProgram
|
||||||
|
%saveFile = [speakerType, '_s_',scenario,'_delayEst_v2_vad_man.wav'];
|
||||||
|
%wavwrite(emic,fs,nbits,saveFile);
|
||||||
|
%saveFile = ['P:\Engineering_share\BjornV\AECM\',speakerType, '_s_',scenario,'_delayEst_v2_vad_man.pcm'];
|
||||||
|
%saveFile = [speakerType, '_s_',scenario,'_adaptMu_adaptGamma_withVar_gammFilt_HSt.pcm'];
|
||||||
|
saveFile = ['scenario_',scenario,'_090417_backupH_nlp.pcm'];
|
||||||
|
fid=fopen(saveFile,'w');fwrite(fid,int16(emicrophone),'short');fclose(fid);
|
||||||
|
%pause
|
||||||
|
end
|
@ -0,0 +1,94 @@
|
|||||||
|
function [setupStructNew, delayStructNew] = updateSettings(microphone, TheFarEnd, setupStruct, delayStruct);
|
||||||
|
|
||||||
|
% other, constants
|
||||||
|
setupStruct.hsupport1 = setupStruct.support/2 + 1;
|
||||||
|
setupStruct.factor = 2 / setupStruct.oversampling;
|
||||||
|
setupStruct.updatel = setupStruct.support/setupStruct.oversampling;
|
||||||
|
setupStruct.estLen = round(setupStruct.avtime * setupStruct.samplingfreq/setupStruct.updatel);
|
||||||
|
|
||||||
|
% compute some constants
|
||||||
|
blockLen = setupStruct.support/setupStruct.oversampling;
|
||||||
|
delayStruct.maxDelayb = floor(setupStruct.samplingfreq*delayStruct.maxDelay/setupStruct.updatel); % in blocks
|
||||||
|
|
||||||
|
%input
|
||||||
|
tlength = min([length(microphone),length(TheFarEnd)]);
|
||||||
|
updateno = floor(tlength/setupStruct.updatel);
|
||||||
|
setupStruct.tlength = setupStruct.updatel*updateno;
|
||||||
|
setupStruct.updateno = updateno - setupStruct.oversampling + 1;
|
||||||
|
|
||||||
|
% signal length
|
||||||
|
n = floor(min([length(TheFarEnd), length(microphone)])/setupStruct.support)*setupStruct.support;
|
||||||
|
setupStruct.nb = n/blockLen - setupStruct.oversampling + 1; % in blocks
|
||||||
|
|
||||||
|
setupStruct.win = sqrt([0 ; hanning(setupStruct.support-1)]);
|
||||||
|
|
||||||
|
% Construct filterbank in Bark-scale
|
||||||
|
|
||||||
|
K = setupStruct.subBandLength; %Something's wrong when K even
|
||||||
|
erbs = 21.4*log10(0.00437*setupStruct.samplingfreq/2+1);
|
||||||
|
fe = (10.^((0:K)'*erbs/K/21.4)-1)/0.00437;
|
||||||
|
setupStruct.centerFreq = fe;
|
||||||
|
H = diag(ones(1,K-1))+diag(ones(1,K-2),-1);
|
||||||
|
Hinv = inv(H);
|
||||||
|
aty = 2*Hinv(end,:)*fe(2:end-1);
|
||||||
|
boundary = aty - (setupStruct.samplingfreq/2 + fe(end-1))/2;
|
||||||
|
if rem(K,2)
|
||||||
|
x1 = min([fe(2)/2, -boundary]);
|
||||||
|
else
|
||||||
|
x1 = max([0, boundary]);
|
||||||
|
end
|
||||||
|
%x1
|
||||||
|
g = fe(2:end-1);
|
||||||
|
g(1) = g(1) - x1/2;
|
||||||
|
x = 2*Hinv*g;
|
||||||
|
x = [x1;x];
|
||||||
|
%figure(42), clf
|
||||||
|
xy = zeros((K+1)*4,1);
|
||||||
|
yy = zeros((K+1)*4,1);
|
||||||
|
xy(1:4) = [fe(1) fe(1) x(1) x(1)]';
|
||||||
|
yy(1:4) = [0 1 1 0]'/x(1);
|
||||||
|
for kk=2:K
|
||||||
|
xy((kk-1)*4+(1:4)) = [x(kk-1) x(kk-1) x(kk) x(kk)]';
|
||||||
|
yy((kk-1)*4+(1:4)) = [0 1 1 0]'/(x(kk)-x(kk-1));
|
||||||
|
end
|
||||||
|
xy(end-3:end) = [x(K) x(K) fe(end) fe(end)]';
|
||||||
|
yy(end-3:end) = [0 1 1 0]'/(fe(end)*2-2*x(K));
|
||||||
|
%plot(xy,yy,'LineWidth',2)
|
||||||
|
%fill(xy,yy,'y')
|
||||||
|
|
||||||
|
x = [0;x];
|
||||||
|
xk = x*setupStruct.hsupport1/setupStruct.samplingfreq*2;
|
||||||
|
%setupStruct.erbBoundaries = xk;
|
||||||
|
numInBand = zeros(length(xk),1);
|
||||||
|
xh = (0:setupStruct.hsupport1-1);
|
||||||
|
|
||||||
|
for kk=1:length(xk)
|
||||||
|
if (kk==length(xk))
|
||||||
|
numInBand(kk) = length(find(xh>=xk(kk)));
|
||||||
|
else
|
||||||
|
numInBand(kk) = length(intersect(find(xh>=xk(kk)),find(xh<xk(kk+1))));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setupStruct.numInBand = numInBand;
|
||||||
|
|
||||||
|
setupStructNew = setupStruct;
|
||||||
|
|
||||||
|
delayStructNew = struct(...
|
||||||
|
'sxAll2',zeros(setupStructNew.hsupport1,setupStructNew.nb),...
|
||||||
|
'syAll2',zeros(setupStructNew.hsupport1,setupStructNew.nb),...
|
||||||
|
'z200',zeros(5,setupStructNew.hsupport1),...
|
||||||
|
'z500',zeros(5,delayStruct.maxDelayb+1),...
|
||||||
|
'bxspectrum',uint32(zeros(setupStructNew.nb,1)),...
|
||||||
|
'byspectrum',uint32(zeros(setupStructNew.nb,1)),...
|
||||||
|
'bandfirst',delayStruct.bandfirst,'bandlast',delayStruct.bandlast,...
|
||||||
|
'bxhist',uint32(zeros(delayStruct.maxDelayb+1,1)),...
|
||||||
|
'bcount',zeros(1+delayStruct.maxDelayb,setupStructNew.nb),...
|
||||||
|
'fout',zeros(1+delayStruct.maxDelayb,setupStructNew.nb),...
|
||||||
|
'new',zeros(1+delayStruct.maxDelayb,setupStructNew.nb),...
|
||||||
|
'smlength',delayStruct.smlength,...
|
||||||
|
'maxDelay', delayStruct.maxDelay,...
|
||||||
|
'maxDelayb', delayStruct.maxDelayb,...
|
||||||
|
'oneGoodEstimate', 0,...
|
||||||
|
'delayAdjust', 0,...
|
||||||
|
'delayNew',zeros(setupStructNew.nb,1),...
|
||||||
|
'delay',zeros(setupStructNew.nb,1));
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user