From a15ea4965ef07f6aa074339f206383028e3b8898 Mon Sep 17 00:00:00 2001 From: "kma@webrtc.org" Date: Thu, 16 Aug 2012 15:43:57 +0000 Subject: [PATCH] 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 --- .../codecs/isac/fix/source/codec.h | 22 ++--- .../codecs/isac/fix/source/isacfix.c | 15 ++-- .../codecs/isac/fix/source/isacfix.gypi | 3 +- .../isac/fix/source/lpc_masking_model.c | 17 ++-- .../isac/fix/source/lpc_masking_model.h | 31 +++++-- .../isac/fix/source/lpc_masking_model_neon.S | 18 ++-- .../codecs/isac/fix/test/isacfix_unittest.cc | 82 +++++++++++-------- 7 files changed, 110 insertions(+), 78 deletions(-) diff --git a/src/modules/audio_coding/codecs/isac/fix/source/codec.h b/src/modules/audio_coding/codecs/isac/fix/source/codec.h index 9c129b73e..1b4f98723 100644 --- a/src/modules/audio_coding/codecs/isac/fix/source/codec.h +++ b/src/modules/audio_coding/codecs/isac/fix/source/codec.h @@ -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_ */ diff --git a/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c index 20f7bf149..8786b121b 100644 --- a/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c +++ b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.c @@ -15,15 +15,16 @@ * */ -#include "isacfix.h" +#include "modules/audio_coding/codecs/isac/fix/interface/isacfix.h" #include -#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) { diff --git a/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi index a9e7f5092..0255a73ef 100644 --- a/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi +++ b/src/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi @@ -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', ], }, ], diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c index ae5c90a88..4be438eb5 100644 --- a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c +++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.c @@ -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, diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h index 189e0e030..e06a20779 100644 --- a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h +++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h @@ -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 diff --git a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S index 507f43eaf..20b60d0f4 100644 --- a/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S +++ b/src/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_neon.S @@ -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} diff --git a/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc b/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc index abb87b3c5..64f5dfed5 100644 --- a/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc +++ b/src/modules/audio_coding/codecs/isac/fix/test/isacfix_unittest.cc @@ -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 }