Added isac WebRtcIsacfix_CalculateResidualEnergy() into dynamic Neon detection for

Android NDK platform.
Review URL: https://webrtc-codereview.appspot.com/722009

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2621 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
kma@webrtc.org 2012-08-16 15:43:57 +00:00
parent fd80070aa7
commit a15ea4965e
7 changed files with 110 additions and 78 deletions

View File

@ -46,7 +46,7 @@ int WebRtcIsacfix_EncodeStoredData(ISACFIX_EncInst_t *ISACenc_obj,
int BWnumber,
float scale);
/************************** initialization functions *************************/
/* initialization functions */
void WebRtcIsacfix_InitMaskingEnc(MaskFiltstr_enc *maskdata);
void WebRtcIsacfix_InitMaskingDec(MaskFiltstr_dec *maskdata);
@ -62,7 +62,7 @@ void WebRtcIsacfix_InitPitchAnalysis(PitchAnalysisStruct *State);
void WebRtcIsacfix_InitPlc( PLCstr *State );
/**************************** transform functions ****************************/
/* transform functions */
void WebRtcIsacfix_InitTransform();
@ -82,9 +82,7 @@ void WebRtcIsacfix_Spec2Time(WebRtc_Word16 *inreQ7,
/***************************** filterbank functions **************************/
/* filterbank functions */
void WebRtcIsacfix_SplitAndFilter1(WebRtc_Word16 *in,
WebRtc_Word16 *LP16,
@ -111,8 +109,7 @@ void WebRtcIsacfix_FilterAndCombine2(WebRtc_Word16 *tempin_ch1,
#endif
/************************* normalized lattice filters ************************/
/* normalized lattice filters */
void WebRtcIsacfix_NormLatticeFilterMa(WebRtc_Word16 orderCoef,
WebRtc_Word32 *stateGQ15,
@ -130,6 +127,10 @@ void WebRtcIsacfix_NormLatticeFilterAr(WebRtc_Word16 orderCoef,
WebRtc_Word16 lo_hi,
WebRtc_Word16 *lat_outQ0);
/* TODO(kma): Remove the following functions into individual header files. */
/* Internal functions in both C and ARM Neon versions */
int WebRtcIsacfix_AutocorrC(WebRtc_Word32* __restrict r,
const WebRtc_Word16* __restrict x,
WebRtc_Word16 N,
@ -143,7 +144,6 @@ void WebRtcIsacfix_FilterMaLoopC(int16_t input0,
int32_t* ptr1,
int32_t* ptr2);
// Functions for ARM-Neon platforms, in place of the above two generic C ones.
#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
int WebRtcIsacfix_AutocorrNeon(WebRtc_Word32* __restrict r,
const WebRtc_Word16* __restrict x,
@ -159,10 +159,7 @@ void WebRtcIsacfix_FilterMaLoopNeon(int16_t input0,
int32_t* ptr2);
#endif
/**** Function pointers associated with
**** WebRtcIsacfix_AutocorrC() / WebRtcIsacfix_AutocorrNeon()
**** and WebRtcIsacfix_FilterMaLoopC() / WebRtcIsacfix_FilterMaLoopNeon().
****/
/* Function pointers associated with the above functions. */
typedef int (*AutocorrFix)(WebRtc_Word32* __restrict r,
const WebRtc_Word16* __restrict x,
@ -179,5 +176,4 @@ typedef void (*FilterMaLoopFix)(int16_t input0,
int32_t* ptr2);
extern FilterMaLoopFix WebRtcIsacfix_FilterMaLoopFix;
#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_CODEC_H_ */

View File

@ -15,15 +15,16 @@
*
*/
#include "isacfix.h"
#include "modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
#include <stdlib.h>
#include "bandwidth_estimator.h"
#include "codec.h"
#include "modules/audio_coding/codecs/isac/fix/source/bandwidth_estimator.h"
#include "modules/audio_coding/codecs/isac/fix/source/codec.h"
#include "modules/audio_coding/codecs/isac/fix/source/entropy_coding.h"
#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
#include "modules/audio_coding/codecs/isac/fix/source/structs.h"
#include "system_wrappers/interface/cpu_features_wrapper.h"
#include "entropy_coding.h"
#include "structs.h"
/**************************************************************************
@ -179,6 +180,8 @@ WebRtc_Word16 WebRtcIsacfix_FreeInternal(ISACFIX_MainStruct *ISAC_main_inst)
static void WebRtcIsacfix_InitNeon(void) {
WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrNeon;
WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopNeon;
WebRtcIsacfix_CalculateResidualEnergy =
WebRtcIsacfix_CalculateResidualEnergyNeon;
}
#endif
@ -263,6 +266,8 @@ WebRtc_Word16 WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
// Initiaze function pointers.
WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC;
WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC;
WebRtcIsacfix_CalculateResidualEnergy =
WebRtcIsacfix_CalculateResidualEnergyC;
#ifdef WEBRTC_DETECT_ARM_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {

View File

@ -97,8 +97,9 @@
'<(webrtc_root)/common_audio/common_audio.gyp:signal_processing',
],
'sources': [
'lattice_neon.S',
'filters_neon.c',
'lattice_neon.S',
'lpc_masking_model_neon.S',
],
},
],

View File

@ -464,19 +464,19 @@ static __inline WebRtc_Word16 exp2_Q10_T(WebRtc_Word16 x) { // Both in and out
}
// Declare a function pointer.
// Declare function pointers.
AutocorrFix WebRtcIsacfix_AutocorrFix;
CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
#ifndef WEBRTC_ARCH_ARM_NEON
/* This routine calculates the residual energy for LPC.
* Formula as shown in comments inside.
*/
int32_t WebRtcIsacfix_CalculateResidualEnergy(int lpc_order,
int32_t q_val_corr,
int q_val_polynomial,
int16_t* a_polynomial,
int32_t* corr_coeffs,
int* q_val_residual_energy) {
int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
int32_t q_val_corr,
int q_val_polynomial,
int16_t* a_polynomial,
int32_t* corr_coeffs,
int* q_val_residual_energy) {
int i = 0, j = 0;
int shift_internal = 0, shift_norm = 0;
int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
@ -537,7 +537,6 @@ int32_t WebRtcIsacfix_CalculateResidualEnergy(int lpc_order,
return residual_energy;
}
#endif
void WebRtcIsacfix_GetLpcCoef(WebRtc_Word16 *inLoQ0,
WebRtc_Word16 *inHiQ0,

View File

@ -24,13 +24,6 @@ extern "C" {
#include "structs.h"
int32_t WebRtcIsacfix_CalculateResidualEnergy(int lpc_order,
int32_t q_val_corr,
int q_offset,
int16_t* a_polynomial,
int32_t* corr_coeffs,
int* q_val_residual_energy);
void WebRtcIsacfix_GetVars(const WebRtc_Word16 *input,
const WebRtc_Word16 *pitchGains_Q12,
WebRtc_UWord32 *oldEnergy,
@ -45,6 +38,30 @@ void WebRtcIsacfix_GetLpcCoef(WebRtc_Word16 *inLoQ0,
WebRtc_Word16 *lo_coeffQ15,
WebRtc_Word16 *hi_coeffQ15);
typedef int32_t (*CalculateResidualEnergy)(int lpc_order,
int32_t q_val_corr,
int q_val_polynomial,
int16_t* a_polynomial,
int32_t* corr_coeffs,
int* q_val_residual_energy);
extern CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
int32_t q_val_corr,
int q_val_polynomial,
int16_t* a_polynomial,
int32_t* corr_coeffs,
int* q_val_residual_energy);
#if (defined WEBRTC_DETECT_ARM_NEON) || (defined WEBRTC_ARCH_ARM_NEON)
int32_t WebRtcIsacfix_CalculateResidualEnergyNeon(int lpc_order,
int32_t q_val_corr,
int q_val_polynomial,
int16_t* a_polynomial,
int32_t* corr_coeffs,
int* q_val_residual_energy);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -8,23 +8,23 @@
@ be found in the AUTHORS file in the root of the source tree.
@
@ Contains a function for WebRtcIsacfix_CalculateResidualEnergy() in
@ Contains a function for WebRtcIsacfix_CalculateResidualEnergyNeon() in
@ iSAC codec, optimized for ARM Neon platform. Reference code in
@ lpc_masking_model.c.
.arch armv7-a
.fpu neon
.global WebRtcIsacfix_CalculateResidualEnergy
.global WebRtcIsacfix_CalculateResidualEnergyNeon
.align 2
@ int32_t WebRtcIsacfix_CalculateResidualEnergy(int lpc_order,
@ int32_t q_val_corr,
@ int q_val_polynomial,
@ int16_t* a_polynomial,
@ int32_t* corr_coeffs,
@ int* q_val_residual_energy);
@ int32_t WebRtcIsacfix_CalculateResidualEnergyNeon(int lpc_order,
@ int32_t q_val_corr,
@ int q_val_polynomial,
@ int16_t* a_polynomial,
@ int32_t* corr_coeffs,
@ int* q_val_residual_energy);
WebRtcIsacfix_CalculateResidualEnergy:
WebRtcIsacfix_CalculateResidualEnergyNeon:
.fnstart
.save {r4-r11}
push {r4-r11}

View File

@ -11,44 +11,58 @@
#include "gtest/gtest.h"
#include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
#include "system_wrappers/interface/cpu_features_wrapper.h"
class IsacUnitTest : public testing::Test {
protected:
// Pass a function pointer to the Tester function.
void CalculateResidualEnergyTester(CalculateResidualEnergy
CalculateResidualEnergyFunction) {
const int kIntOrder = 10;
const int32_t kInt32QDomain = 5;
const int kIntShift = 11;
int16_t a[kIntOrder + 1] = {32760, 122, 7, 0, -32760, -3958,
-48, 18745, 498, 9, 23456};
int32_t corr[kIntOrder + 1] = {11443647, -27495, 0,
98745, -11443600, 1, 1, 498, 9, 888, 23456};
int q_shift_residual = 0;
int32_t residual_energy = 0;
// Test the code path where (residual_energy >= 0x10000).
residual_energy = CalculateResidualEnergyFunction(kIntOrder,
kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
EXPECT_EQ(1789023310, residual_energy);
EXPECT_EQ(2, q_shift_residual);
// Test the code path where (residual_energy < 0x10000)
// and ((energy & 0x8000) != 0).
for(int i = 0; i < kIntOrder + 1; i++) {
a[i] = 24575 >> i;
corr[i] = i;
}
residual_energy = CalculateResidualEnergyFunction(kIntOrder,
kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
EXPECT_EQ(1595279092, residual_energy);
EXPECT_EQ(26, q_shift_residual);
// Test the code path where (residual_energy <= 0x7fff).
for(int i = 0; i < kIntOrder + 1; i++) {
a[i] = 2457 >> i;
}
residual_energy = CalculateResidualEnergyFunction(kIntOrder,
kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
EXPECT_EQ(2029266944, residual_energy);
EXPECT_EQ(33, q_shift_residual);
}
};
TEST_F(IsacUnitTest, CalculateResidualEnergyTest) {
const int kIntOrder = 10;
const int32_t kInt32QDomain = 5;
const int kIntShift = 11;
int16_t a[kIntOrder + 1] = {32760, 122, 7, 0, -32760, -3958,
-48, 18745, 498, 9, 23456};
int32_t corr[kIntOrder + 1] = {11443647, -27495, 0,
98745, -11443600, 1, 1, 498, 9, 888, 23456};
int q_shift_residual = 0;
int32_t residual_energy = 0;
// Test the code path where (residual_energy >= 0x10000).
residual_energy = WebRtcIsacfix_CalculateResidualEnergy(kIntOrder,
kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
EXPECT_EQ(1789023310, residual_energy);
EXPECT_EQ(2, q_shift_residual);
// Test the code path where (residual_energy < 0x10000)
// and ((energy & 0x8000) != 0).
for(int i = 0; i < kIntOrder + 1; i++) {
a[i] = 24575 >> i;
corr[i] = i;
CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyC);
#ifdef WEBRTC_DETECT_ARM_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyNeon);
}
residual_energy = WebRtcIsacfix_CalculateResidualEnergy(kIntOrder,
kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
EXPECT_EQ(1595279092, residual_energy);
EXPECT_EQ(26, q_shift_residual);
// Test the code path where (residual_energy <= 0x7fff).
for(int i = 0; i < kIntOrder + 1; i++) {
a[i] = 2457 >> i;
}
residual_energy = WebRtcIsacfix_CalculateResidualEnergy(kIntOrder,
kInt32QDomain, kIntShift, a, corr, &q_shift_residual);
EXPECT_EQ(2029266944, residual_energy);
EXPECT_EQ(33, q_shift_residual);
#elif defined(WEBRTC_ARCH_ARM_NEON)
CalculateResidualEnergyTester(WebRtcIsacfix_CalculateResidualEnergyNeon);
#endif
}