Added unit test for a filter bank function in iSAC-Fix, with some optimization
in the assembly code. Review URL: https://webrtc-codereview.appspot.com/754004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2670 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
36b95b4753
commit
afdcc2c845
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
|
||||
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Arguments:
|
||||
* io: Input/output, in Q0.
|
||||
* len: Input, sample length.
|
||||
* coefficient: Input.
|
||||
* state: Input/output, filter state, in Q4.
|
||||
*/
|
||||
void WebRtcIsacfix_HighpassFilterFixDec32(int16_t *io,
|
||||
int16_t len,
|
||||
const int16_t *coefficient,
|
||||
int32_t *state);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_ */
|
@ -21,6 +21,10 @@
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/********************* Coefficient Tables ************************/
|
||||
|
||||
/* HPstcoeff_in_Q14 = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */
|
||||
@ -41,4 +45,8 @@ extern const int16_t WebRtcIsacfix_kUpperApFactorsQ15[2];
|
||||
/* The lower channel all-pass filter factors */
|
||||
extern const int16_t WebRtcIsacfix_kLowerApFactorsQ15[2];
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_ */
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "codec.h"
|
||||
#include "filterbank_internal.h"
|
||||
#include "filterbank_tables.h"
|
||||
#include "settings.h"
|
||||
|
||||
@ -49,11 +50,10 @@ static void AllpassFilter2FixDec16(WebRtc_Word16 *InOut16, //Q0
|
||||
}
|
||||
|
||||
|
||||
static void HighpassFilterFixDec32(
|
||||
WebRtc_Word16 *io, /* Q0:input Q0: Output */
|
||||
WebRtc_Word16 len, /* length of input, Input */
|
||||
const WebRtc_Word16 *coeff, /* Coeff: [Q30hi Q30lo Q30hi Q30lo Q35hi Q35lo Q35hi Q35lo] */
|
||||
WebRtc_Word32 *state) /* Q4:filter state Input/Output */
|
||||
void WebRtcIsacfix_HighpassFilterFixDec32(int16_t *io,
|
||||
int16_t len,
|
||||
const int16_t *coefficient,
|
||||
int32_t *state)
|
||||
{
|
||||
int k;
|
||||
WebRtc_Word32 a1 = 0, b1 = 0, c = 0, in = 0;
|
||||
@ -66,34 +66,36 @@ static void HighpassFilterFixDec32(
|
||||
|
||||
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||
{
|
||||
int tmp_coeff = 0;
|
||||
int tmp_coeff0 = 0;
|
||||
int tmp_coeff1 = 0;
|
||||
__asm __volatile(
|
||||
"ldr %[tmp_coeff], [%[coeff]]\n\t"
|
||||
"smmulr %[a2], %[tmp_coeff], %[state0]\n\t"
|
||||
"ldr %[tmp_coeff], [%[coeff], #4]\n\t"
|
||||
"smmulr %[b2], %[tmp_coeff], %[state1]\n\t"
|
||||
"ldr %[tmp_coeff], [%[coeff], #8]\n\t"
|
||||
"smmulr %[a1], %[tmp_coeff], %[state0]\n\t"
|
||||
"ldr %[tmp_coeff], [%[coeff], #12]\n\t"
|
||||
"smmulr %[b1], %[tmp_coeff], %[state1]\n\t"
|
||||
"ldr %[tmp_coeff0], [%[coeff]]\n\t"
|
||||
"ldr %[tmp_coeff1], [%[coeff], #4]\n\t"
|
||||
"smmulr %[a2], %[tmp_coeff0], %[state0]\n\t"
|
||||
"smmulr %[b2], %[tmp_coeff1], %[state1]\n\t"
|
||||
"ldr %[tmp_coeff0], [%[coeff], #8]\n\t"
|
||||
"ldr %[tmp_coeff1], [%[coeff], #12]\n\t"
|
||||
"smmulr %[a1], %[tmp_coeff0], %[state0]\n\t"
|
||||
"smmulr %[b1], %[tmp_coeff1], %[state1]\n\t"
|
||||
:[a2]"+r"(a2),
|
||||
[b2]"+r"(b2),
|
||||
[a1]"+r"(a1),
|
||||
[b1]"+r"(b1),
|
||||
[tmp_coeff]"+r"(tmp_coeff)
|
||||
:[coeff]"r"(coeff),
|
||||
[tmp_coeff0]"+r"(tmp_coeff0),
|
||||
[tmp_coeff1]"+r"(tmp_coeff1)
|
||||
:[coeff]"r"(coefficient),
|
||||
[state0]"r"(state0),
|
||||
[state1]"r"(state1)
|
||||
);
|
||||
}
|
||||
#else
|
||||
/* Q35 * Q4 = Q39 ; shift 32 bit => Q7 */
|
||||
a1 = WEBRTC_SPL_MUL_32_32_RSFT32(coeff[5], coeff[4], state0);
|
||||
b1 = WEBRTC_SPL_MUL_32_32_RSFT32(coeff[7], coeff[6], state1);
|
||||
a1 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[5], coefficient[4], state0);
|
||||
b1 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[7], coefficient[6], state1);
|
||||
|
||||
/* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */
|
||||
a2 = WEBRTC_SPL_MUL_32_32_RSFT32(coeff[1], coeff[0], state0);
|
||||
b2 = WEBRTC_SPL_MUL_32_32_RSFT32(coeff[3], coeff[2], state1);
|
||||
a2 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[1], coefficient[0], state0);
|
||||
b2 = WEBRTC_SPL_MUL_32_32_RSFT32(coefficient[3], coefficient[2], state1);
|
||||
#endif
|
||||
|
||||
c = ((WebRtc_Word32)in) + WEBRTC_SPL_RSHIFT_W32(a1+b1, 7); // Q0
|
||||
@ -127,7 +129,7 @@ void WebRtcIsacfix_SplitAndFilter1(WebRtc_Word16 *pin,
|
||||
|
||||
|
||||
/* High pass filter */
|
||||
HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
|
||||
|
||||
|
||||
/* First Channel */
|
||||
@ -197,7 +199,7 @@ void WebRtcIsacfix_SplitAndFilter2(WebRtc_Word16 *pin,
|
||||
|
||||
|
||||
/* High pass filter */
|
||||
HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
|
||||
|
||||
|
||||
/* First Channel */
|
||||
@ -284,8 +286,8 @@ void WebRtcIsacfix_FilterAndCombine1(WebRtc_Word16 *tempin_ch1,
|
||||
}
|
||||
|
||||
/* High pass filter */
|
||||
HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
|
||||
HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
|
||||
|
||||
for (k=0;k<FRAMESAMPLES;k++) {
|
||||
out16[k] = in[k];
|
||||
@ -341,8 +343,8 @@ void WebRtcIsacfix_FilterAndCombine2(WebRtc_Word16 *tempin_ch1,
|
||||
}
|
||||
|
||||
/* High pass filter */
|
||||
HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
|
||||
HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
|
||||
|
||||
for (k=0;k<len;k++) {
|
||||
out16[k] = in[k];
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <typedefs.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h"
|
||||
#include "modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h"
|
||||
#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
|
||||
#include "system_wrappers/interface/cpu_features_wrapper.h"
|
||||
|
||||
@ -66,3 +68,29 @@ TEST_F(IsacUnitTest, CalculateResidualEnergyTest) {
|
||||
CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyNeon);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(IsacUnitTest, HighpassFilterFixDec32Test) {
|
||||
const int kSamples = 20;
|
||||
int16_t in[kSamples];
|
||||
int32_t state[2] = {12345, 987654};
|
||||
#ifdef WEBRTC_ARCH_ARM_V7A
|
||||
int32_t out[kSamples] = {-1040, -1035, -22875, -1397, -27604, 20018, 7917,
|
||||
-1279, -8552, -14494, -7558, -23537, -27258, -30554, -32768, -3432, -32768,
|
||||
25215, -27536, 22436};
|
||||
#else
|
||||
int32_t out[kSamples] = {-1040, -1035, -22875, -1397, -27604, 20017, 7915,
|
||||
-1280, -8554, -14496, -7561, -23541, -27263, -30560, -32768, -3441, -32768,
|
||||
25203, -27550, 22419};
|
||||
#endif
|
||||
|
||||
for(int i = 0; i < kSamples; i++) {
|
||||
in[i] = WEBRTC_SPL_WORD32_MAX / (i + 1);
|
||||
}
|
||||
|
||||
WebRtcIsacfix_HighpassFilterFixDec32(in, kSamples,
|
||||
WebRtcIsacfix_kHPStCoeffOut1Q30, state);
|
||||
|
||||
for(int i = 0; i < kSamples; i++) {
|
||||
EXPECT_EQ(out[i], in[i]);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user