1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h" 12 13 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 14 #include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h" 15 #include "webrtc/modules/audio_coding/codecs/isac/fix/source/structs.h" 16 #include "webrtc/system_wrappers/include/compile_assert_c.h" 17 18 // Number of segments in a pitch subframe. 19 static const int kSegments = 5; 20 21 // A division factor of 1/5 in Q15. 22 static const int16_t kDivFactor = 6553; 23 24 // Interpolation coefficients; generated by design_pitch_filter.m. 25 // Coefficients are stored in Q14. 26 static const int16_t kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = { 27 {-367, 1090, -2706, 9945, 10596, -3318, 1626, -781, 287}, 28 {-325, 953, -2292, 7301, 12963, -3320, 1570, -743, 271}, 29 {-240, 693, -1622, 4634, 14809, -2782, 1262, -587, 212}, 30 {-125, 358, -817, 2144, 15982, -1668, 721, -329, 118}, 31 { 0, 0, -1, 1, 16380, 1, -1, 0, 0}, 32 { 118, -329, 721, -1668, 15982, 2144, -817, 358, -125}, 33 { 212, -587, 1262, -2782, 14809, 4634, -1622, 693, -240}, 34 { 271, -743, 1570, -3320, 12963, 7301, -2292, 953, -325} 35 }; 36 37 static __inline size_t CalcLrIntQ(int16_t fixVal, 38 int16_t qDomain) { 39 int32_t roundVal = 1 << (qDomain - 1); 40 41 return (fixVal + roundVal) >> qDomain; 42 } 43 44 void WebRtcIsacfix_PitchFilter(int16_t* indatQQ, // Q10 if type is 1 or 4, 45 // Q0 if type is 2. 46 int16_t* outdatQQ, 47 PitchFiltstr* pfp, 48 int16_t* lagsQ7, 49 int16_t* gainsQ12, 50 int16_t type) { 51 int k, ind, cnt; 52 int16_t sign = 1; 53 int16_t inystateQQ[PITCH_DAMPORDER]; 54 int16_t ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD]; 55 const int16_t Gain = 21299; // 1.3 in Q14 56 int16_t oldLagQ7; 57 int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12; 58 size_t indW32 = 0, frcQQ = 0; 59 const int16_t* fracoeffQQ = NULL; 60 61 // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM(). 62 COMPILE_ASSERT(PITCH_FRACORDER == 9); 63 COMPILE_ASSERT(PITCH_DAMPORDER == 5); 64 65 // Set up buffer and states. 66 memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ)); 67 memcpy(inystateQQ, pfp->ystateQQ, sizeof(inystateQQ)); 68 69 // Get old lag and gain value from memory. 70 oldLagQ7 = pfp->oldlagQ7; 71 oldGainQ12 = pfp->oldgainQ12; 72 73 if (type == 4) { 74 sign = -1; 75 76 // Make output more periodic. 77 for (k = 0; k < PITCH_SUBFRAMES; k++) { 78 gainsQ12[k] = (int16_t)(gainsQ12[k] * Gain >> 14); 79 } 80 } 81 82 // No interpolation if pitch lag step is big. 83 if (((lagsQ7[0] * 3 >> 1) < oldLagQ7) || (lagsQ7[0] > (oldLagQ7 * 3 >> 1))) { 84 oldLagQ7 = lagsQ7[0]; 85 oldGainQ12 = gainsQ12[0]; 86 } 87 88 ind = 0; 89 90 for (k = 0; k < PITCH_SUBFRAMES; k++) { 91 // Calculate interpolation steps. 92 lagdeltaQ7 = lagsQ7[k] - oldLagQ7; 93 lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 94 lagdeltaQ7, kDivFactor, 15); 95 curLagQ7 = oldLagQ7; 96 gaindeltaQ12 = gainsQ12[k] - oldGainQ12; 97 gaindeltaQ12 = (int16_t)(gaindeltaQ12 * kDivFactor >> 15); 98 99 curGainQ12 = oldGainQ12; 100 oldLagQ7 = lagsQ7[k]; 101 oldGainQ12 = gainsQ12[k]; 102 103 // Each frame has 4 60-sample pitch subframes, and each subframe has 5 104 // 12-sample segments. Each segment need to be processed with 105 // newly-updated parameters, so we break the pitch filtering into 106 // two for-loops (5 x 12) below. It's also why kDivFactor = 0.2 (in Q15). 107 for (cnt = 0; cnt < kSegments; cnt++) { 108 // Update parameters for each segment. 109 curGainQ12 += gaindeltaQ12; 110 curLagQ7 += lagdeltaQ7; 111 indW32 = CalcLrIntQ(curLagQ7, 7); 112 frcQQ = ((indW32 << 7) + 64 - curLagQ7) >> 4; 113 114 if (frcQQ == PITCH_FRACS) { 115 frcQQ = 0; 116 } 117 fracoeffQQ = kIntrpCoef[frcQQ]; 118 119 // Pitch filtering. 120 WebRtcIsacfix_PitchFilterCore(PITCH_SUBFRAME_LEN / kSegments, curGainQ12, 121 indW32, sign, inystateQQ, ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind); 122 } 123 } 124 125 // Export buffer and states. 126 memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ)); 127 memcpy(pfp->ystateQQ, inystateQQ, sizeof(pfp->ystateQQ)); 128 129 pfp->oldlagQ7 = oldLagQ7; 130 pfp->oldgainQ12 = oldGainQ12; 131 132 if (type == 2) { 133 // Filter look-ahead segment. 134 WebRtcIsacfix_PitchFilterCore(QLOOKAHEAD, curGainQ12, indW32, 1, inystateQQ, 135 ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind); 136 } 137 } 138 139 140 void WebRtcIsacfix_PitchFilterGains(const int16_t* indatQ0, 141 PitchFiltstr* pfp, 142 int16_t* lagsQ7, 143 int16_t* gainsQ12) { 144 int k, n, m; 145 size_t ind, pos, pos3QQ; 146 147 int16_t ubufQQ[PITCH_INTBUFFSIZE]; 148 int16_t oldLagQ7, lagdeltaQ7, curLagQ7; 149 const int16_t* fracoeffQQ = NULL; 150 int16_t scale; 151 int16_t cnt = 0, tmpW16; 152 size_t frcQQ, indW16 = 0; 153 int32_t tmpW32, tmp2W32, csum1QQ, esumxQQ; 154 155 // Set up buffer and states. 156 memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ)); 157 oldLagQ7 = pfp->oldlagQ7; 158 159 // No interpolation if pitch lag step is big. 160 if (((lagsQ7[0] * 3 >> 1) < oldLagQ7) || (lagsQ7[0] > (oldLagQ7 * 3 >> 1))) { 161 oldLagQ7 = lagsQ7[0]; 162 } 163 164 ind = 0; 165 pos = ind + PITCH_BUFFSIZE; 166 scale = 0; 167 for (k = 0; k < PITCH_SUBFRAMES; k++) { 168 169 // Calculate interpolation steps. 170 lagdeltaQ7 = lagsQ7[k] - oldLagQ7; 171 lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 172 lagdeltaQ7, kDivFactor, 15); 173 curLagQ7 = oldLagQ7; 174 oldLagQ7 = lagsQ7[k]; 175 176 csum1QQ = 1; 177 esumxQQ = 1; 178 179 // Same as function WebRtcIsacfix_PitchFilter(), we break the pitch 180 // filtering into two for-loops (5 x 12) below. 181 for (cnt = 0; cnt < kSegments; cnt++) { 182 // Update parameters for each segment. 183 curLagQ7 += lagdeltaQ7; 184 indW16 = CalcLrIntQ(curLagQ7, 7); 185 frcQQ = ((indW16 << 7) + 64 - curLagQ7) >> 4; 186 187 if (frcQQ == PITCH_FRACS) { 188 frcQQ = 0; 189 } 190 fracoeffQQ = kIntrpCoef[frcQQ]; 191 192 pos3QQ = pos - (indW16 + 4); 193 194 for (n = 0; n < PITCH_SUBFRAME_LEN / kSegments; n++) { 195 // Filter to get fractional pitch. 196 197 tmpW32 = 0; 198 for (m = 0; m < PITCH_FRACORDER; m++) { 199 tmpW32 += ubufQQ[pos3QQ + m] * fracoeffQQ[m]; 200 } 201 202 // Subtract from input and update buffer. 203 ubufQQ[pos] = indatQ0[ind]; 204 205 tmp2W32 = WEBRTC_SPL_MUL_16_32_RSFT14(indatQ0[ind], tmpW32); 206 tmpW32 += 8192; 207 tmpW16 = tmpW32 >> 14; 208 tmpW32 = tmpW16 * tmpW16; 209 210 if ((tmp2W32 > 1073700000) || (csum1QQ > 1073700000) || 211 (tmpW32 > 1073700000) || (esumxQQ > 1073700000)) { // 2^30 212 scale++; 213 csum1QQ >>= 1; 214 esumxQQ >>= 1; 215 } 216 csum1QQ += tmp2W32 >> scale; 217 esumxQQ += tmpW32 >> scale; 218 219 ind++; 220 pos++; 221 pos3QQ++; 222 } 223 } 224 225 if (csum1QQ < esumxQQ) { 226 tmp2W32 = WebRtcSpl_DivResultInQ31(csum1QQ, esumxQQ); 227 228 // Gain should be half the correlation. 229 tmpW32 = tmp2W32 >> 20; 230 } else { 231 tmpW32 = 4096; 232 } 233 gainsQ12[k] = (int16_t)WEBRTC_SPL_SAT(PITCH_MAX_GAIN_Q12, tmpW32, 0); 234 } 235 236 // Export buffer and states. 237 memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ)); 238 pfp->oldlagQ7 = lagsQ7[PITCH_SUBFRAMES - 1]; 239 pfp->oldgainQ12 = gainsQ12[PITCH_SUBFRAMES - 1]; 240 241 } 242