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:
kma@webrtc.org 2012-08-27 23:54:13 +00:00
parent 36b95b4753
commit afdcc2c845
4 changed files with 100 additions and 26 deletions

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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];

View File

@ -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]);
}
}