| /* |
| * Copyright (c) 2011 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. |
| */ |
| |
| /* |
| * pitch_estimatorfilter.c |
| * |
| * Pitch filter functions |
| * |
| */ |
| |
| #include <string.h> |
| |
| #include "pitch_estimator.h" |
| |
| |
| /* 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. |
| */ |
| 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}, |
| {-240, 693, -1622, 4634, 14809, -2782, 1262, -587, 212}, |
| {-125, 358, -817, 2144, 15982, -1668, 721, -329, 118}, |
| { 0, 0, -1, 1, 16380, 1, -1, 0, 0}, |
| { 118, -329, 721, -1668, 15982, 2144, -817, 358, -125}, |
| { 212, -587, 1262, -2782, 14809, 4634, -1622, 693, -240}, |
| { 271, -743, 1570, -3320, 12963, 7301, -2292, 953, -325} |
| }; |
| |
| |
| |
| |
| 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); |
| |
| 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; |
| 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_Word32 tmpW32; |
| |
| if (type==4) |
| sign = -1; |
| |
| /* 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 */ |
| oldLagQ7 = pfp->oldlagQ7; |
| oldGainQ12 = pfp->oldgainQ12; |
| |
| if (type==4) { |
| /* make output more periodic */ |
| /* Fixed 1.3 = 21299 in Q14 */ |
| for (k=0;k<PITCH_SUBFRAMES;k++) |
| gainsQ12[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(gainsQ12[k], Gain, 14); |
| } |
| |
| /* 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))) { |
| oldLagQ7 = lagsQ7[0]; |
| oldGainQ12 = gainsQ12[0]; |
| } |
| |
| ind=0; |
| for (k=0;k<PITCH_SUBFRAMES;k++) { |
| |
| /* Calculate interpolation steps */ |
| lagdeltaQ7 = lagsQ7[k]-oldLagQ7; |
| lagdeltaQ7 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(lagdeltaQ7,DivFactor,15); |
| curLagQ7 = oldLagQ7; |
| gaindeltaQ12 = gainsQ12[k]-oldGainQ12; |
| gaindeltaQ12 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(gaindeltaQ12,DivFactor,15); |
| |
| curGainQ12 = oldGainQ12; |
| oldLagQ7 = lagsQ7[k]; |
| oldGainQ12 = gainsQ12[k]; |
| |
| |
| for (n=0;n<PITCH_SUBFRAME_LEN;n++) { |
| |
| if (cnt == 0) { /* Update parameters */ |
| |
| curGainQ12 += gaindeltaQ12; |
| curLagQ7 += lagdeltaQ7; |
| indW16 = (WebRtc_Word16)CalcLrIntQ(curLagQ7,7); |
| tmpW16 = WEBRTC_SPL_LSHIFT_W16(indW16,7); |
| tmpW16 -= curLagQ7; |
| frcQQ = WEBRTC_SPL_RSHIFT_W16(tmpW16,4); |
| frcQQ += 4; |
| |
| if(frcQQ==PITCH_FRACS) |
| frcQQ=0; |
| fracoeffQQ = kIntrpCoef[frcQQ]; |
| |
| cnt=12; |
| } |
| |
| /* shift low pass filter state */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) |
| inystateQQ[m] = inystateQQ[m-1]; |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - (indW16 + 2); |
| |
| tmpW32=0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| tmpW32 += WEBRTC_SPL_MUL_16_16(ubufQQ[pos2+m], fracoeffQQ[m]); |
| |
| /* Saturate to avoid overflow in tmpW16 */ |
| tmpW32 = WEBRTC_SPL_SAT(536862719, tmpW32, -536879104); |
| tmpW32 += 8192; |
| tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32,14); |
| |
| inystateQQ[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(curGainQ12, tmpW16,12); /* Multiply with gain */ |
| |
| /* Low pass filter */ |
| tmpW32=0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| tmpW32 += WEBRTC_SPL_MUL_16_16(inystateQQ[m], kDampFilter[m]); |
| |
| /* 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 = indatQQ[ind] - WEBRTC_SPL_MUL_16_16(sign, tmpW16); |
| outdatQQ[ind] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmpW32); |
| tmpW32 = indatQQ[ind] + (WebRtc_Word32)outdatQQ[ind]; |
| ubufQQ[pos] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmpW32); |
| |
| ind++; |
| cnt--; |
| } |
| } |
| |
| |
| /* Export buffer and states */ |
| memcpy(pfp->ubufQQ, 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)); |
| |
| pfp->oldlagQ7 = oldLagQ7; |
| pfp->oldgainQ12 = oldGainQ12; |
| |
| if (type==2) { |
| /* Filter look-ahead segment */ |
| for (n=0;n<QLOOKAHEAD;n++) { |
| /* shift low pass filter state */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) |
| inystateQQ[m] = inystateQQ[m-1]; |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos2= pos - (indW16 + 2); |
| |
| tmpW32=0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| tmpW32 += WEBRTC_SPL_MUL_16_16(ubufQQ[pos2+m], fracoeffQQ[m]); |
| |
| if (tmpW32<536862720) {//536870912) |
| tmpW32 += 8192; |
| tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32,14); |
| } else |
| tmpW16= 32767; |
| inystateQQ[0] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(curGainQ12, tmpW16,12); /* Multiply with gain */ |
| |
| /* Low pass filter */ |
| tmpW32=0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| tmpW32 += WEBRTC_SPL_MUL_16_16(inystateQQ[m], kDampFilter[m]); |
| if (tmpW32<1073725440) { //1073741824) |
| tmpW32 += 16384; |
| tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32,15); |
| } else |
| tmpW16 = 32767; |
| |
| /* Subtract from input and update buffer */ |
| tmpW32 = indatQQ[ind] - (WebRtc_Word32)tmpW16; |
| outdatQQ[ind] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmpW32); |
| tmpW32 = indatQQ[ind] + (WebRtc_Word32)outdatQQ[ind]; |
| ubufQQ[pos] = (WebRtc_Word16)WebRtcSpl_SatW32ToW16(tmpW32); |
| |
| ind++; |
| } |
| |
| } |
| |
| |
| } |
| |
| |
| void WebRtcIsacfix_PitchFilterGains(const WebRtc_Word16 *indatQ0, |
| PitchFiltstr *pfp, |
| WebRtc_Word16 *lagsQ7, |
| WebRtc_Word16 *gainsQ12) |
| { |
| int k, n, m, ind; |
| |
| WebRtc_Word16 ubufQQ[PITCH_INTBUFFSIZE]; |
| WebRtc_Word16 oldLagQ7,lagdeltaQ7, curLagQ7; |
| WebRtc_Word16 DivFactor = 6553; |
| const WebRtc_Word16 *fracoeffQQ = NULL; |
| WebRtc_Word16 scale; |
| WebRtc_Word16 cnt=0, pos, pos3QQ, frcQQ, indW16 = 0, tmpW16; |
| WebRtc_Word32 tmpW32, tmp2W32, csum1QQ, esumxQQ; |
| |
| /* Set up buffer and states */ |
| memcpy(ubufQQ, pfp->ubufQQ, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), PITCH_BUFFSIZE)); |
| 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))) { |
| oldLagQ7 = lagsQ7[0]; |
| } |
| |
| ind=0; |
| scale=0; |
| for (k=0;k<PITCH_SUBFRAMES;k++) { |
| |
| /* Calculate interpolation steps */ |
| lagdeltaQ7 = lagsQ7[k]-oldLagQ7; |
| lagdeltaQ7 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(lagdeltaQ7,DivFactor,15); |
| curLagQ7 = oldLagQ7; |
| oldLagQ7 = lagsQ7[k]; |
| |
| csum1QQ=1; |
| esumxQQ=1; |
| |
| for (n=0;n<PITCH_SUBFRAME_LEN;n++) { |
| |
| if (cnt == 0) { /* Update parameters */ |
| curLagQ7 += lagdeltaQ7; |
| indW16 = (WebRtc_Word16)CalcLrIntQ(curLagQ7,7); |
| tmpW16 = WEBRTC_SPL_LSHIFT_W16(indW16,7); |
| tmpW16 -= curLagQ7; |
| frcQQ = WEBRTC_SPL_RSHIFT_W16(tmpW16,4); |
| frcQQ += 4; |
| |
| if(frcQQ==PITCH_FRACS) |
| frcQQ=0; |
| fracoeffQQ = kIntrpCoef[frcQQ]; |
| |
| cnt=12; |
| } |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos3QQ = pos - (indW16 + 4); |
| |
| tmpW32=0; |
| for (m=0;m<PITCH_FRACORDER;m++){ |
| tmpW32 += WEBRTC_SPL_MUL_16_16(ubufQQ[pos3QQ+m], fracoeffQQ[m]); |
| } |
| |
| /* 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 (csum1QQ<esumxQQ) { |
| tmp2W32=WebRtcSpl_DivResultInQ31(csum1QQ,esumxQQ); |
| |
| /* Gain should be half the correlation */ |
| tmpW32=WEBRTC_SPL_RSHIFT_W32(tmp2W32,20); |
| } else |
| tmpW32=4096; |
| gainsQ12[k]=(WebRtc_Word16)WEBRTC_SPL_SAT(PITCH_MAX_GAIN_Q12, tmpW32, 0); |
| |
| } |
| |
| /* Export buffer and states */ |
| memcpy(pfp->ubufQQ, 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]; |
| |
| } |