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