From c3b2683bf4444b8668d7061dc293b87c8c74556a Mon Sep 17 00:00:00 2001 From: "kma@webrtc.org" Date: Fri, 1 Jun 2012 17:00:07 +0000 Subject: [PATCH] Refactored the pitch filter function in iSAC-fix. One important purpose is to prepare the function for assembly optimization in ARM platforms. Note that, (1) The main change is a new function PitchFilter() replacing a couple of common code blocks. Next step will be the assembly coding of this function in ARM. (2) Resulted code is not bit exact with the original. The only reason is replacing two saturation blocks (lines 197 and 208) for the case of "type == 2" with the general case (line 147 and 159). The change makes the code more consistent, and I think the original code might just be a bug. I raised the issue in an email to Turaj and Bjorn last week. Listening test might be needed. I will send the resulted files to Turaj for this purpose. (3) I used Astyle to make the code more stylish, but didn't try extra effort to correct all the code style details. Local code style consistency was considered for new code. So this is not a full and final refactor project (will leave that to future refactoring). Review URL: https://webrtc-codereview.appspot.com/573009 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2344 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../codecs/iSAC/fix/source/pitch_filter.c | 445 +++++++++--------- 1 file changed, 217 insertions(+), 228 deletions(-) diff --git a/src/modules/audio_coding/codecs/iSAC/fix/source/pitch_filter.c b/src/modules/audio_coding/codecs/iSAC/fix/source/pitch_filter.c index 87af1533ba..99fdce62d0 100644 --- a/src/modules/audio_coding/codecs/iSAC/fix/source/pitch_filter.c +++ b/src/modules/audio_coding/codecs/iSAC/fix/source/pitch_filter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * 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 @@ -9,25 +9,30 @@ */ /* - * pitch_estimatorfilter.c + * pitch_filter.c * * Pitch filter functions * */ -#include +#include "common_audio/signal_processing/include/signal_processing_library.h" +#include "modules/audio_coding/codecs/iSAC/fix/source/pitch_estimator.h" +#include "modules/audio_coding/codecs/iSAC/fix/source/settings.h" +#include "modules/audio_coding/codecs/iSAC/fix/source/structs.h" -#include "pitch_estimator.h" +// Number of segments in a pitch subframe. +static const int kSegments = 5; +// A division factor of 1/5 in Q15. +static const WebRtc_Word16 kDivFactor = 6553; -/* Filter coefficicients in Q15 */ +// Filter coefficicients in Q15. static const WebRtc_Word16 kDampFilter[PITCH_DAMPORDER] = { -2294, 8192, 20972, 8192, -2294 }; -/* Interpolation coefficients; generated by design_pitch_filter.m. - * Coefficients are stored in Q14. - */ +// Interpolation coefficients; generated by design_pitch_filter.m. +// Coefficients are stored in Q14. static const WebRtc_Word16 kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = { {-367, 1090, -2706, 9945, 10596, -3318, 1626, -781, 287}, {-325, 953, -2292, 7301, 12963, -3320, 1570, -743, 271}, @@ -39,293 +44,277 @@ static const WebRtc_Word16 kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = { { 271, -743, 1570, -3320, 12963, 7301, -2292, 953, -325} }; - - - -static __inline WebRtc_Word32 CalcLrIntQ(WebRtc_Word32 fixVal, WebRtc_Word16 qDomain) { +static __inline WebRtc_Word32 CalcLrIntQ(WebRtc_Word32 fixVal, + WebRtc_Word16 qDomain) { WebRtc_Word32 intgr; WebRtc_Word32 roundVal; - roundVal = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, qDomain-1); - intgr = WEBRTC_SPL_RSHIFT_W32(fixVal+roundVal, qDomain); + roundVal = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, qDomain - 1); + intgr = WEBRTC_SPL_RSHIFT_W32(fixVal + roundVal, qDomain); return intgr; } -void WebRtcIsacfix_PitchFilter(WebRtc_Word16 *indatQQ, /* Q10 if type is 1 or 4, Q0 if type is 2 */ - WebRtc_Word16 *outdatQQ, - PitchFiltstr *pfp, - WebRtc_Word16 *lagsQ7, - WebRtc_Word16 *gainsQ12, - WebRtc_Word16 type) -{ - int k, n, m, ind; +// Pitch filtering. +// TODO(Turaj): Add descriptions of input and output parameters. +static void PitchFilter(int loopNumber, + WebRtc_Word16 gain, + int index, + WebRtc_Word16 sign, + WebRtc_Word16* inputState, + WebRtc_Word16* outputBuf2, + const WebRtc_Word16* coefficient, + WebRtc_Word16* inputBuf, + WebRtc_Word16* outputBuf, + int* index2) { + int i = 0, j = 0; // Loop counters. + WebRtc_Word16* ubufQQpos2 = &outputBuf2[PITCH_BUFFSIZE - (index + 2)]; + WebRtc_Word16 tmpW16 = 0; + + for (i = 0; i < loopNumber; i++) { + WebRtc_Word32 tmpW32 = 0; + + // Filter to get fractional pitch. + for (j = 0; j < PITCH_FRACORDER; j++) { + tmpW32 += WEBRTC_SPL_MUL_16_16(ubufQQpos2[*index2 + j], coefficient[j]); + } + + // Saturate to avoid overflow in tmpW16. + tmpW32 = WEBRTC_SPL_SAT(536862719, tmpW32, -536879104); + tmpW32 += 8192; + tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 14); + + // Shift low pass filter state. + memmove(&inputState[1], &inputState[0], + (PITCH_DAMPORDER - 1) * sizeof(WebRtc_Word16)); + inputState[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( + gain, tmpW16, 12); + + // Low pass filter. + tmpW32 = 0; + // TODO(kma): Define a static inline function WebRtcSpl_DotProduct() + // in spl_inl.h to replace this and other similar loops. + for (j = 0; j < PITCH_DAMPORDER; j++) { + tmpW32 += WEBRTC_SPL_MUL_16_16(inputState[j], kDampFilter[j]); + } + + // Saturate to avoid overflow in tmpW16. + tmpW32 = WEBRTC_SPL_SAT(1073725439, tmpW32, -1073758208); + tmpW32 += 16384; + tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 15); + + // Subtract from input and update buffer. + tmpW32 = inputBuf[*index2] - WEBRTC_SPL_MUL_16_16(sign, tmpW16); + outputBuf[*index2] = WebRtcSpl_SatW32ToW16(tmpW32); + tmpW32 = inputBuf[*index2] + outputBuf[*index2]; + outputBuf2[*index2 + PITCH_BUFFSIZE] = WebRtcSpl_SatW32ToW16(tmpW32); + + (*index2)++; + } +} + +void WebRtcIsacfix_PitchFilter(WebRtc_Word16* indatQQ, // Q10 if type is 1 or 4, + // Q0 if type is 2. + WebRtc_Word16* outdatQQ, + PitchFiltstr* pfp, + WebRtc_Word16* lagsQ7, + WebRtc_Word16* gainsQ12, + WebRtc_Word16 type) { + int k, ind, cnt; WebRtc_Word16 sign = 1; WebRtc_Word16 inystateQQ[PITCH_DAMPORDER]; - WebRtc_Word16 ubufQQ[PITCH_INTBUFFSIZE+QLOOKAHEAD]; - WebRtc_Word16 Gain = 21299; /* 1.3 in Q14 */ - WebRtc_Word16 DivFactor = 6553; /* 0.2 in Q15 */ - WebRtc_Word16 oldLagQ7, oldGainQ12, - lagdeltaQ7, curLagQ7, - gaindeltaQ12, curGainQ12; - WebRtc_Word16 tmpW16, indW16=0, frcQQ, cnt=0, pos, pos2; - const WebRtc_Word16 *fracoeffQQ=NULL; + WebRtc_Word16 ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD]; + const WebRtc_Word16 Gain = 21299; // 1.3 in Q14 + WebRtc_Word16 oldLagQ7; + WebRtc_Word16 oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12; + int indW32 = 0, frcQQ = 0; WebRtc_Word32 tmpW32; + const WebRtc_Word16* fracoeffQQ = NULL; - if (type==4) - sign = -1; + // Set up buffer and states. + memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ)); + memcpy(inystateQQ, pfp->ystateQQ, sizeof(inystateQQ)); - /* Set up buffer and states */ - memcpy(ubufQQ, pfp->ubufQQ, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_BUFFSIZE)); - memcpy(inystateQQ, pfp->ystateQQ, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_DAMPORDER)); - - /* Get old lag and gain value from memory */ + // Get old lag and gain value from memory. oldLagQ7 = pfp->oldlagQ7; oldGainQ12 = pfp->oldgainQ12; - if (type==4) { - /* make output more periodic */ - /* Fixed 1.3 = 21299 in Q14 */ - for (k=0;k WEBRTC_SPL_RSHIFT_W16(WEBRTC_SPL_MUL_16_16(oldLagQ7, 3), 1))) { + // No interpolation if pitch lag step is big. + if ((WEBRTC_SPL_MUL_16_16_RSFT(lagsQ7[0], 3, 1) < oldLagQ7) || + (lagsQ7[0] > WEBRTC_SPL_MUL_16_16_RSFT(oldLagQ7, 3, 1))) { oldLagQ7 = lagsQ7[0]; oldGainQ12 = gainsQ12[0]; } - ind=0; - for (k=0;k0;m--) - inystateQQ[m] = inystateQQ[m-1]; - - /* Filter to get fractional pitch */ - pos = ind + PITCH_BUFFSIZE; - pos2 = pos - (indW16 + 2); - - tmpW32=0; - for (m=0;mubufQQ, ubufQQ+PITCH_FRAME_LEN, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_BUFFSIZE)); - memcpy(pfp->ystateQQ, inystateQQ, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_DAMPORDER)); + // Export buffer and states. + memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ)); + memcpy(pfp->ystateQQ, inystateQQ, sizeof(pfp->ystateQQ)); pfp->oldlagQ7 = oldLagQ7; pfp->oldgainQ12 = oldGainQ12; - if (type==2) { - /* Filter look-ahead segment */ - for (n=0;n0;m--) - inystateQQ[m] = inystateQQ[m-1]; - - /* Filter to get fractional pitch */ - pos = ind + PITCH_BUFFSIZE; - pos2= pos - (indW16 + 2); - - tmpW32=0; - for (m=0;mubufQQ, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_BUFFSIZE)); + // Set up buffer and states. + memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ)); oldLagQ7 = pfp->oldlagQ7; - /* No interpolation if pitch lag step is big */ - if ((WEBRTC_SPL_RSHIFT_W16(WEBRTC_SPL_MUL_16_16(lagsQ7[0], 3), 1) < oldLagQ7) || - (lagsQ7[0] > WEBRTC_SPL_RSHIFT_W16(WEBRTC_SPL_MUL_16_16(oldLagQ7, 3), 1))) { + // No interpolation if pitch lag step is big. + if ((WEBRTC_SPL_MUL_16_16_RSFT(lagsQ7[0], 3, 1) < oldLagQ7) || + (lagsQ7[0] > WEBRTC_SPL_MUL_16_16_RSFT(oldLagQ7, 3, 1))) { oldLagQ7 = lagsQ7[0]; } - ind=0; - scale=0; - for (k=0;k 1073700000) || (csum1QQ > 1073700000) || + (tmpW32 > 1073700000) || (esumxQQ > 1073700000)) { // 2^30 + scale++; + csum1QQ = WEBRTC_SPL_RSHIFT_W32(csum1QQ, 1); + esumxQQ = WEBRTC_SPL_RSHIFT_W32(esumxQQ, 1); + } + tmp2W32 = WEBRTC_SPL_RSHIFT_W32(tmp2W32, scale); + csum1QQ += tmp2W32; + tmpW32 = WEBRTC_SPL_RSHIFT_W32(tmpW32, scale); + esumxQQ += tmpW32; + + ind++; + pos++; + pos3QQ++; } - - /* Subtract from input and update buffer */ - ubufQQ[pos] = indatQ0[ind]; - - tmp2W32 = WEBRTC_SPL_MUL_16_32_RSFT14(indatQ0[ind], tmpW32); - tmpW32 += 8192; - tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32,14); - tmpW32 = WEBRTC_SPL_MUL_16_16(tmpW16, tmpW16); - - if ((tmp2W32>1073700000) || (csum1QQ>1073700000) || (tmpW32>1073700000) || (esumxQQ>1073700000)) {//2^30 - scale++; - csum1QQ = WEBRTC_SPL_RSHIFT_W32(csum1QQ,1); - esumxQQ = WEBRTC_SPL_RSHIFT_W32(esumxQQ,1); - } - tmp2W32 = WEBRTC_SPL_RSHIFT_W32(tmp2W32,scale); - csum1QQ += tmp2W32; - tmpW32 = WEBRTC_SPL_RSHIFT_W32(tmpW32,scale); - esumxQQ += tmpW32; - - ind++; - cnt--; } - if (csum1QQubufQQ, ubufQQ+PITCH_FRAME_LEN, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_BUFFSIZE)); - pfp->oldlagQ7 = lagsQ7[PITCH_SUBFRAMES-1]; - pfp->oldgainQ12 = gainsQ12[PITCH_SUBFRAMES-1]; + // Export buffer and states. + memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ)); + pfp->oldlagQ7 = lagsQ7[PITCH_SUBFRAMES - 1]; + pfp->oldgainQ12 = gainsQ12[PITCH_SUBFRAMES - 1]; }