/* * 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. */ /* * entropy_coding.c * * This file contains all functions used to arithmetically * encode the iSAC bistream. * */ #include #include "arith_routins.h" #include "spectrum_ar_model_tables.h" #include "pitch_gain_tables.h" #include "pitch_lag_tables.h" #include "entropy_coding.h" #include "lpc_tables.h" #include "settings.h" #include "signal_processing_library.h" /* This function implements the fix-point correspondant function to lrint. FLP: (WebRtc_Word32)floor(flt+.499999999999) FIP: (fixVal+roundVal)>>qDomain where roundVal = 2^(qDomain-1) = 1<<(qDomain-1) */ 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; } /* __inline WebRtc_UWord32 stepwise(WebRtc_Word32 dinQ10) { WebRtc_Word32 ind, diQ10, dtQ10; diQ10 = dinQ10; if (diQ10 < DPMIN_Q10) diQ10 = DPMIN_Q10; if (diQ10 >= DPMAX_Q10) diQ10 = DPMAX_Q10 - 1; dtQ10 = diQ10 - DPMIN_Q10;*/ /* Q10 + Q10 = Q10 */ /* ind = (dtQ10 * 5) >> 10; */ /* 2^10 / 5 = 0.2 in Q10 */ /* Q10 -> Q0 */ /* return rpointsFIX_Q10[ind]; } */ /* logN(x) = logN(2)*log2(x) = 0.6931*log2(x). Output in Q8. */ /* The input argument X to logN(X) is 2^17 times higher than the input floating point argument Y to log(Y), since the X value is a Q17 value. This can be compensated for after the call, by subraction a value Z for each Q-step. One Q-step means that X gets 2 thimes higher, i.e. Z = logN(2)*256 = 0.693147180559*256 = 177.445678 should be subtracted (since logN() returns a Q8 value). For a X value in Q17, the value 177.445678*17 = 3017 should be subtracted */ static WebRtc_Word16 CalcLogN(WebRtc_Word32 arg) { WebRtc_Word16 zeros, log2, frac, logN; zeros=WebRtcSpl_NormU32(arg); frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(WEBRTC_SPL_LSHIFT_W32(arg, zeros)&0x7FFFFFFF, 23); log2=(WebRtc_Word16)(WEBRTC_SPL_LSHIFT_W32(31-zeros, 8)+frac); // log2(x) in Q8 logN=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(log2,22713,15); //Q8*Q15 log(2) = 0.693147 = 22713 in Q15 logN=logN+11; //Scalar compensation which minimizes the (log(x)-logN(x))^2 error over all x. return logN; } /* expN(x) = 2^(a*x), where a = log2(e) ~= 1.442695 Input: Q8 (WebRtc_Word16) Output: Q17 (WebRtc_Word32) a = log2(e) = log2(exp(1)) ~= 1.442695 ==> a = 23637 in Q14 (1.442688) To this value, 700 is added or subtracted in order to get an average error nearer zero, instead of always same-sign. */ static WebRtc_Word32 CalcExpN(WebRtc_Word16 x) { WebRtc_Word16 ax, axINT, axFRAC; WebRtc_Word16 exp16; WebRtc_Word32 exp; if (x>=0) { // ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637-700, 14); //Q8 ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637, 14); //Q8 axINT = WEBRTC_SPL_RSHIFT_W16(ax, 8); //Q0 axFRAC = ax&0x00FF; exp16 = WEBRTC_SPL_LSHIFT_W32(1, axINT); //Q0 axFRAC = axFRAC+256; //Q8 exp = WEBRTC_SPL_MUL_16_16(exp16, axFRAC); // Q0*Q8 = Q8 exp = WEBRTC_SPL_LSHIFT_W32(exp, 9); //Q17 } else { // ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637+700, 14); //Q8 ax=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637, 14); //Q8 ax = -ax; axINT = 1 + WEBRTC_SPL_RSHIFT_W16(ax, 8); //Q0 axFRAC = 0x00FF - (ax&0x00FF); exp16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(32768, axINT); //Q15 axFRAC = axFRAC+256; //Q8 exp = WEBRTC_SPL_MUL_16_16(exp16, axFRAC); // Q15*Q8 = Q23 exp = WEBRTC_SPL_RSHIFT_W32(exp, 6); //Q17 } return exp; } /* compute correlation from power spectrum */ static void CalcCorrelation(WebRtc_Word32 *PSpecQ12, WebRtc_Word32 *CorrQ7) { WebRtc_Word32 summ[FRAMESAMPLES/8]; WebRtc_Word32 diff[FRAMESAMPLES/8]; WebRtc_Word32 sum; int k, n; for (k = 0; k < FRAMESAMPLES/8; k++) { summ[k] = WEBRTC_SPL_RSHIFT_W32(PSpecQ12[k] + PSpecQ12[FRAMESAMPLES/4-1 - k] + 16, 5); diff[k] = WEBRTC_SPL_RSHIFT_W32(PSpecQ12[k] - PSpecQ12[FRAMESAMPLES/4-1 - k] + 16, 5); } sum = 2; for (n = 0; n < FRAMESAMPLES/8; n++) sum += summ[n]; CorrQ7[0] = sum; for (k = 0; k < AR_ORDER; k += 2) { sum = 0; for (n = 0; n < FRAMESAMPLES/8; n++) sum += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], diff[n]) + 256, 9); CorrQ7[k+1] = sum; } for (k=1; k400000){ tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3); round = 32; shftVal = 6; } else { tmpGain = gainQ10; round = 256; shftVal = 9; } for (k = 1; k < AR_ORDER+1; k++) { sum = 16384; for (n = k; n < AR_ORDER+1; n++) sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]); /* Q24 */ sum = WEBRTC_SPL_RSHIFT_W32(sum, 15); CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round, shftVal); } sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7); for (n = 0; n < FRAMESAMPLES/8; n++) CurveQ16[n] = sum; for (k = 1; k < AR_ORDER; k += 2) { for (n = 0; n < FRAMESAMPLES/8; n++) CurveQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], CorrQ11[k+1]) + 2, 2); } CS_ptrQ9 = WebRtcIsacfix_kCos[0]; /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */ sh=WebRtcSpl_NormW32(CorrQ11[1]); if (CorrQ11[1]==0) /* Use next correlation */ sh=WebRtcSpl_NormW32(CorrQ11[2]); if (sh<9) shftVal = 9 - sh; else shftVal = 0; for (n = 0; n < FRAMESAMPLES/8; n++) diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2); for (k = 2; k < AR_ORDER; k += 2) { CS_ptrQ9 = WebRtcIsacfix_kCos[k]; for (n = 0; n < FRAMESAMPLES/8; n++) diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k+1], shftVal)) + 2, 2); } for (k=0; k400000){ tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3); round = 32; shftVal = 6; } else { tmpGain = gainQ10; round = 256; shftVal = 9; } for (k = 1; k < AR_ORDER+1; k++) { sum = 16384; for (n = k; n < AR_ORDER+1; n++) sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]); /* Q24 */ sum = WEBRTC_SPL_RSHIFT_W32(sum, 15); CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round, shftVal); } sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7); for (n = 0; n < FRAMESAMPLES/8; n++) summQ16[n] = sum; for (k = 1; k < (AR_ORDER); k += 2) { for (n = 0; n < FRAMESAMPLES/8; n++) summQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_32_16(CorrQ11[k+1],WebRtcIsacfix_kCos[k][n]) + 2, 2); } CS_ptrQ9 = WebRtcIsacfix_kCos[0]; /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */ sh=WebRtcSpl_NormW32(CorrQ11[1]); if (CorrQ11[1]==0) /* Use next correlation */ sh=WebRtcSpl_NormW32(CorrQ11[2]); if (sh<9) shftVal = 9 - sh; else shftVal = 0; for (n = 0; n < FRAMESAMPLES/8; n++) diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2); for (k = 2; k < AR_ORDER; k += 2) { CS_ptrQ9 = WebRtcIsacfix_kCos[k]; for (n = 0; n < FRAMESAMPLES/8; n++) diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k+1], shftVal)) + 2, 2); } in_sqrt = summQ16[0] + WEBRTC_SPL_LSHIFT_W32(diffQ16[0], shftVal); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = WEBRTC_SPL_LSHIFT_W32(1, WEBRTC_SPL_RSHIFT_W16(WebRtcSpl_GetSizeInBits(in_sqrt), 1)); for (k = 0; k < FRAMESAMPLES/8; k++) { in_sqrt = summQ16[k] + WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal); i = 10; /* make in_sqrt positive to prohibit sqrt of negative values */ if(in_sqrt<0) in_sqrt=-in_sqrt; newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1); do { res = newRes; newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1); } while (newRes != res && i-- > 0); CurveQ8[k] = (WebRtc_Word16)newRes; } for (k = FRAMESAMPLES/8; k < FRAMESAMPLES/4; k++) { in_sqrt = summQ16[FRAMESAMPLES/4-1 - k] - WEBRTC_SPL_LSHIFT_W32(diffQ16[FRAMESAMPLES/4-1 - k], shftVal); i = 10; /* make in_sqrt positive to prohibit sqrt of negative values */ if(in_sqrt<0) in_sqrt=-in_sqrt; newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1); do { res = newRes; newRes = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_DIV(in_sqrt, res) + res, 1); } while (newRes != res && i-- > 0); CurveQ8[k] = (WebRtc_Word16)newRes; } } /* generate array of dither samples in Q7 */ static void GenerateDitherQ7(WebRtc_Word16 *bufQ7, WebRtc_UWord32 seed, WebRtc_Word16 length, WebRtc_Word16 AvgPitchGain_Q12) { int k; WebRtc_Word16 dither1_Q7, dither2_Q7, dither_gain_Q14, shft; if (AvgPitchGain_Q12 < 614) /* this threshold should be equal to that in decode_spec() */ { for (k = 0; k < length-2; k += 3) { /* new random unsigned WebRtc_Word32 */ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515; /* fixed-point dither sample between -64 and 64 (Q7) */ dither1_Q7 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)seed + 16777216, 25); // * 128/4294967295 /* new random unsigned WebRtc_Word32 */ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515; /* fixed-point dither sample between -64 and 64 */ dither2_Q7 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(seed + 16777216, 25); shft = (WebRtc_Word16)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 15); if (shft < 5) { bufQ7[k] = dither1_Q7; bufQ7[k+1] = dither2_Q7; bufQ7[k+2] = 0; } else if (shft < 10) { bufQ7[k] = dither1_Q7; bufQ7[k+1] = 0; bufQ7[k+2] = dither2_Q7; } else { bufQ7[k] = 0; bufQ7[k+1] = dither1_Q7; bufQ7[k+2] = dither2_Q7; } } } else { dither_gain_Q14 = (WebRtc_Word16)(22528 - WEBRTC_SPL_MUL(10, AvgPitchGain_Q12)); /* dither on half of the coefficients */ for (k = 0; k < length-1; k += 2) { /* new random unsigned WebRtc_Word32 */ seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515; /* fixed-point dither sample between -64 and 64 */ dither1_Q7 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)seed + 16777216, 25); /* dither sample is placed in either even or odd index */ shft = (WebRtc_Word16)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 1); /* either 0 or 1 */ bufQ7[k + shft] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(dither_gain_Q14, dither1_Q7) + 8192, 14); bufQ7[k + 1 - shft] = 0; } } } /* * function to decode the complex spectrum from the bitstream * returns the total number of bytes in the stream */ WebRtc_Word16 WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata, WebRtc_Word16 *frQ7, WebRtc_Word16 *fiQ7, WebRtc_Word16 AvgPitchGain_Q12) { WebRtc_Word16 data[FRAMESAMPLES]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES/4]; WebRtc_Word16 ARCoefQ12[AR_ORDER+1]; WebRtc_Word16 RCQ15[AR_ORDER]; WebRtc_Word16 gainQ10; WebRtc_Word32 gain2_Q10; WebRtc_Word16 len; int k; /* create dither signal */ GenerateDitherQ7(data, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* Dither is output in vector 'Data' */ /* decode model parameters */ if (WebRtcIsacfix_DecodeRcCoef(streamdata, RCQ15) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12); if (WebRtcIsacfix_DecodeGain2(streamdata, &gain2_Q10) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; /* compute inverse AR power spectrum */ CalcInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* arithmetic decoding of spectrum */ /* 'data' input and output. Input = Dither */ len = WebRtcIsacfix_DecLogisticMulti2(data, streamdata, invARSpec2_Q16, (WebRtc_Word16)FRAMESAMPLES); if (len<1) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; /* subtract dither and scale down spectral samples with low SNR */ if (AvgPitchGain_Q12 <= 614) { for (k = 0; k < FRAMESAMPLES; k += 4) { gainQ10 = WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)30, 10), (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(invARSpec2_Q16[k>>2] + (WebRtc_UWord32)2195456, 16)); *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[ k ], gainQ10) + 512, 10); *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+1], gainQ10) + 512, 10); *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+2], gainQ10) + 512, 10); *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+3], gainQ10) + 512, 10); } } else { for (k = 0; k < FRAMESAMPLES; k += 4) { gainQ10 = WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)36, 10), (WebRtc_Word16)WEBRTC_SPL_RSHIFT_U32(invARSpec2_Q16[k>>2] + (WebRtc_UWord32)2654208, 16)); *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[ k ], gainQ10) + 512, 10); *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+1], gainQ10) + 512, 10); *frQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+2], gainQ10) + 512, 10); *fiQ7++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+3], gainQ10) + 512, 10); } } return len; } int WebRtcIsacfix_EncodeSpec(const WebRtc_Word16 *fr, const WebRtc_Word16 *fi, Bitstr_enc *streamdata, WebRtc_Word16 AvgPitchGain_Q12) { WebRtc_Word16 dataQ7[FRAMESAMPLES]; WebRtc_Word32 PSpec[FRAMESAMPLES/4]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES/4]; WebRtc_Word32 CorrQ7[AR_ORDER+1]; WebRtc_Word32 CorrQ7_norm[AR_ORDER+1]; WebRtc_Word16 RCQ15[AR_ORDER]; WebRtc_Word16 ARCoefQ12[AR_ORDER+1]; WebRtc_Word32 gain2_Q10; WebRtc_Word16 val; WebRtc_Word32 nrg; WebRtc_UWord32 sum; WebRtc_Word16 lft_shft; WebRtc_Word16 status; int k, n, j; /* create dither_float signal */ GenerateDitherQ7(dataQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* add dither and quantize, and compute power spectrum */ /* Vector dataQ7 contains Dither in Q7 */ for (k = 0; k < FRAMESAMPLES; k += 4) { val = ((*fr++ + dataQ7[k] + 64) & 0xFF80) - dataQ7[k]; /* Data = Dither */ dataQ7[k] = val; /* New value in Data */ sum = WEBRTC_SPL_UMUL(val, val); val = ((*fi++ + dataQ7[k+1] + 64) & 0xFF80) - dataQ7[k+1]; /* Data = Dither */ dataQ7[k+1] = val; /* New value in Data */ sum += WEBRTC_SPL_UMUL(val, val); val = ((*fr++ + dataQ7[k+2] + 64) & 0xFF80) - dataQ7[k+2]; /* Data = Dither */ dataQ7[k+2] = val; /* New value in Data */ sum += WEBRTC_SPL_UMUL(val, val); val = ((*fi++ + dataQ7[k+3] + 64) & 0xFF80) - dataQ7[k+3]; /* Data = Dither */ dataQ7[k+3] = val; /* New value in Data */ sum += WEBRTC_SPL_UMUL(val, val); PSpec[k>>2] = WEBRTC_SPL_RSHIFT_U32(sum, 2); } /* compute correlation from power spectrum */ CalcCorrelation(PSpec, CorrQ7); /* find AR coefficients */ /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */ lft_shft = WebRtcSpl_NormW32(CorrQ7[0]) - 18; if (lft_shft > 0) { for (k=0; k AR coefficients */ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12); /* compute ARCoef' * Corr * ARCoef in Q19 */ nrg = 0; for (j = 0; j <= AR_ORDER; j++) { for (n = 0; n <= j; n++) nrg += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(ARCoefQ12[j], WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CorrQ7_norm[j-n], ARCoefQ12[n]) + 256, 9)) + 4, 3); for (n = j+1; n <= AR_ORDER; n++) nrg += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(ARCoefQ12[j], WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CorrQ7_norm[n-j], ARCoefQ12[n]) + 256, 9)) + 4, 3); } if (lft_shft > 0) nrg = WEBRTC_SPL_RSHIFT_W32(nrg, lft_shft); else nrg = WEBRTC_SPL_LSHIFT_W32(nrg, -lft_shft); if(nrg>131072) gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES >> 2, nrg); /* also shifts 31 bits to the left! */ else gain2_Q10 = WEBRTC_SPL_RSHIFT_W32(FRAMESAMPLES, 2); /* quantize & code gain2_Q10 */ if (WebRtcIsacfix_EncodeGain2(&gain2_Q10, streamdata)) return -1; /* compute inverse AR magnitude spectrum */ CalcRootInvArSpec(ARCoefQ12, gain2_Q10, invARSpecQ8); /* arithmetic coding of spectrum */ status = WebRtcIsacfix_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (WebRtc_Word16)FRAMESAMPLES); if ( status ) return( status ); return 0; } /* Matlab's LAR definition */ static void Rc2LarFix(const WebRtc_Word16 *rcQ15, WebRtc_Word32 *larQ17, WebRtc_Word16 order) { /* This is a piece-wise implemenetation of a rc2lar-function (all values in the comment are Q15 values and are based on [0 24956/32768 30000/32768 32500/32768], i.e. [0.76159667968750 0.91552734375000 0.99182128906250] x0 x1 a k x0(again) b ================================================================================== 0.00 0.76: 0 2.625997508581 0 0 0.76 0.91: 2.000012018559 7.284502668663 0.761596679688 -3.547841027073 0.91 0.99: 3.121320351712 31.115835041229 0.915527343750 -25.366077452148 0.99 1.00: 5.495270168700 686.663805654056 0.991821289063 -675.552510708011 The implementation is y(x)= a + (x-x0)*k, but this can be simplified to y(x) = a-x0*k + x*k = b + x*k, where b = a-x0*k akx=[0 2.625997508581 0 2.000012018559 7.284502668663 0.761596679688 3.121320351712 31.115835041229 0.915527343750 5.495270168700 686.663805654056 0.991821289063]; b = akx(:,1) - akx(:,3).*akx(:,2) [ 0.0 -3.547841027073 -25.366077452148 -675.552510708011] */ int k; WebRtc_Word16 rc; WebRtc_Word32 larAbsQ17; for (k = 0; k < order; k++) { rc = WEBRTC_SPL_ABS_W16(rcQ15[k]); //Q15 /* Calculate larAbsQ17 in Q17 from rc in Q15 */ if (rc<24956) { //0.7615966 in Q15 // (Q15*Q13)>>11 = Q17 larAbsQ17 = WEBRTC_SPL_MUL_16_16_RSFT(rc, 21512, 11); } else if (rc<30000) { //0.91552734375 in Q15 // Q17 + (Q15*Q12)>>10 = Q17 larAbsQ17 = -465024 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 29837, 10); } else if (rc<32500) { //0.99182128906250 in Q15 // Q17 + (Q15*Q10)>>8 = Q17 larAbsQ17 = -3324784 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 31863, 8); } else { // Q17 + (Q15*Q5)>>3 = Q17 larAbsQ17 = -88546020 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 21973, 3); } if (rcQ15[k]>0) { larQ17[k] = larAbsQ17; } else { larQ17[k] = -larAbsQ17; } } } static void Lar2RcFix(const WebRtc_Word32 *larQ17, WebRtc_Word16 *rcQ15, WebRtc_Word16 order) { /* This is a piece-wise implemenetation of a lar2rc-function See comment in Rc2LarFix() about details. */ int k; WebRtc_Word16 larAbsQ11; WebRtc_Word32 rc; for (k = 0; k < order; k++) { larAbsQ11 = (WebRtc_Word16) WEBRTC_SPL_ABS_W32(WEBRTC_SPL_RSHIFT_W32(larQ17[k]+32,6)); //Q11 if (larAbsQ11<4097) { //2.000012018559 in Q11 // Q11*Q16>>12 = Q15 rc = WEBRTC_SPL_MUL_16_16_RSFT(larAbsQ11, 24957, 12); } else if (larAbsQ11<6393) { //3.121320351712 in Q11 // (Q11*Q17 + Q13)>>13 = Q15 rc = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(larAbsQ11, 17993) + 130738688), 13); } else if (larAbsQ11<11255) { //5.495270168700 in Q11 // (Q11*Q19 + Q30)>>15 = Q15 rc = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(larAbsQ11, 16850) + 875329820), 15); } else { // (Q11*Q24>>16 + Q19)>>4 = Q15 rc = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16_RSFT(larAbsQ11, 24433, 16)) + 515804), 4); } if (larQ17[k]<=0) { rc = -rc; } rcQ15[k] = (WebRtc_Word16) rc; // Q15 } } static void Poly2LarFix(WebRtc_Word16 *lowbandQ15, WebRtc_Word16 orderLo, WebRtc_Word16 *hibandQ15, WebRtc_Word16 orderHi, WebRtc_Word16 Nsub, WebRtc_Word32 *larsQ17) { int k, n; WebRtc_Word32 *outpQ17; WebRtc_Word16 orderTot; WebRtc_Word32 larQ17[MAX_ORDER]; // Size 7+6 is enough orderTot = (orderLo + orderHi); outpQ17 = larsQ17; for (k = 0; k < Nsub; k++) { Rc2LarFix(lowbandQ15, larQ17, orderLo); for (n = 0; n < orderLo; n++) outpQ17[n] = larQ17[n]; //Q17 Rc2LarFix(hibandQ15, larQ17, orderHi); for (n = 0; n < orderHi; n++) outpQ17[n + orderLo] = larQ17[n]; //Q17; outpQ17 += orderTot; lowbandQ15 += orderLo; hibandQ15 += orderHi; } } static void Lar2polyFix(WebRtc_Word32 *larsQ17, WebRtc_Word16 *lowbandQ15, WebRtc_Word16 orderLo, WebRtc_Word16 *hibandQ15, WebRtc_Word16 orderHi, WebRtc_Word16 Nsub) { int k, n; WebRtc_Word16 orderTot; WebRtc_Word16 *outplQ15, *outphQ15; WebRtc_Word32 *inpQ17; WebRtc_Word16 rcQ15[7+6]; orderTot = (orderLo + orderHi); outplQ15 = lowbandQ15; outphQ15 = hibandQ15; inpQ17 = larsQ17; for (k = 0; k < Nsub; k++) { /* gains not handled here as in the FLP version */ /* Low band */ Lar2RcFix(&inpQ17[0], rcQ15, orderLo); for (n = 0; n < orderLo; n++) outplQ15[n] = rcQ15[n]; // Refl. coeffs /* High band */ Lar2RcFix(&inpQ17[orderLo], rcQ15, orderHi); for (n = 0; n < orderHi; n++) outphQ15[n] = rcQ15[n]; // Refl. coeffs inpQ17 += orderTot; outplQ15 += orderLo; outphQ15 += orderHi; } } int WebRtcIsacfix_DecodeLpc(WebRtc_Word32 *gain_lo_hiQ17, WebRtc_Word16 *LPCCoef_loQ15, WebRtc_Word16 *LPCCoef_hiQ15, Bitstr_dec *streamdata, WebRtc_Word16 *outmodel) { WebRtc_Word32 larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_GAIN+KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES int err; err = WebRtcIsacfix_DecodeLpcCoef(streamdata, larsQ17, gain_lo_hiQ17, outmodel); if (err<0) // error check return -ISAC_RANGE_ERROR_DECODE_LPC; Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES); return 0; } /* decode & dequantize LPC Coef */ int WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata, WebRtc_Word32 *LPCCoefQ17, WebRtc_Word32 *gain_lo_hiQ17, WebRtc_Word16 *outmodel) { int j, k, n; int err; WebRtc_Word16 pos, pos2, posg, poss, offsg, offss, offs2; WebRtc_Word16 gainpos; WebRtc_Word16 model; WebRtc_Word16 index_QQ[KLT_ORDER_SHAPE]; WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN]; WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN]; WebRtc_Word16 tmpcoeffs_sQ10[KLT_ORDER_SHAPE]; WebRtc_Word32 tmpcoeffs_sQ17[KLT_ORDER_SHAPE]; WebRtc_Word32 tmpcoeffs2_sQ18[KLT_ORDER_SHAPE]; WebRtc_Word32 sumQQ; WebRtc_Word16 sumQQ16; WebRtc_Word32 tmp32; /* entropy decoding of model number */ err = WebRtcIsacfix_DecHistOneStepMulti(&model, streamdata, WebRtcIsacfix_kModelCdfPtr, WebRtcIsacfix_kModelInitIndex, 1); if (err<0) // error check return err; /* entropy decoding of quantization indices */ err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfShapePtr[model], WebRtcIsacfix_kInitIndexShape[model], KLT_ORDER_SHAPE); if (err<0) // error check return err; /* find quantization levels for coefficients */ for (k=0; k>(16-5) = Q21 pos++; pos2++; } tmpcoeffs2_gQ21[posg] = sumQQ; //Q21 posg++; offs2 += 2; } offs2 = 0; for (k=0; k>7 = Q18 pos++; pos2++; } tmpcoeffs2_sQ18[poss] = sumQQ; //Q18 poss++; offs2 += LPC_SHAPE_ORDER; } offsg += 2; offss += LPC_SHAPE_ORDER; } /* right transform */ // Transpose matrix offsg = 0; offss = 0; posg = 0; poss = 0; for (j=0; j>(16-1) = Q21 pos += 2; pos2 += SUBFRAMES; } tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4); posg++; } poss = offss; for (k=0; k>16 = Q17 pos += LPC_SHAPE_ORDER; pos2 += SUBFRAMES; } tmpcoeffs_sQ17[poss] = sumQQ; poss++; } offsg += 2; offss += LPC_SHAPE_ORDER; } /* scaling, mean addition, and gain restoration */ gainpos = 0; posg = 0;poss = 0;pos=0; for (k=0; k>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16 tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17 LPCCoefQ17[pos] = tmp32; } /* hi band LAR coeffs */ for (n=0; n>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13 tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17 LPCCoefQ17[pos] = tmp32; } } *outmodel=model; return 0; } /* estimate codel length of LPC Coef */ static int EstCodeLpcCoef(WebRtc_Word32 *LPCCoefQ17, WebRtc_Word32 *gain_lo_hiQ17, WebRtc_Word16 *model, WebRtc_Word32 *sizeQ11, Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData, transcode_obj *transcodingParam) { int j, k, n; WebRtc_Word16 posQQ, pos2QQ, gainpos; WebRtc_Word16 pos, pos2, poss, posg, offsg, offss, offs2; WebRtc_Word16 index_gQQ[KLT_ORDER_GAIN], index_sQQ[KLT_ORDER_SHAPE]; WebRtc_Word16 index_ovr_gQQ[KLT_ORDER_GAIN], index_ovr_sQQ[KLT_ORDER_SHAPE]; WebRtc_Word32 BitsQQ; WebRtc_Word16 tmpcoeffs_gQ6[KLT_ORDER_GAIN]; WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN]; WebRtc_Word32 tmpcoeffs_sQ17[KLT_ORDER_SHAPE]; WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN]; WebRtc_Word32 tmpcoeffs2_sQ17[KLT_ORDER_SHAPE]; WebRtc_Word32 sumQQ; WebRtc_Word32 tmp32; WebRtc_Word16 sumQQ16; int status = 0; /* write LAR coefficients to statistics file */ /* Save data for creation of multiple bitstreams (and transcoding) */ if (encData != NULL) { for (k=0; kLPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k]; } } /* log gains, mean removal and scaling */ posg = 0;poss = 0;pos=0; gainpos=0; for (k=0; k>(16-1) = Q17 pos++; pos2 += LPC_SHAPE_ORDER; } tmpcoeffs2_sQ17[poss] = sumQQ; //Q17 poss++; } offsg += 2; offss += LPC_SHAPE_ORDER; } /* right transform */ offsg = 0; offss = 0; offs2 = 0; for (j=0; j>(16-1) = Q21 pos += 2; pos2++; } tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4); posg++; } poss = offss; for (k=0; k>(16-1) = Q17 pos += LPC_SHAPE_ORDER; pos2++; } tmpcoeffs_sQ17[poss] = sumQQ; poss++; } offs2 += SUBFRAMES; offsg += 2; offss += LPC_SHAPE_ORDER; } /* quantize coefficients */ BitsQQ = 0; for (k=0; k WebRtcIsacfix_kMaxIndGain[k]) { index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k]; } index_ovr_gQQ[k] = WebRtcIsacfix_kOffsetGain[0][k]+index_gQQ[k]; posQQ = WebRtcIsacfix_kOfLevelsGain[0] + index_ovr_gQQ[k]; /* Save data for creation of multiple bitstreams */ if (encData != NULL) { encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k]; } /* determine number of bits */ sumQQ = WebRtcIsacfix_kCodeLenGainQ11[posQQ]; //Q11 BitsQQ += sumQQ; } for (k=0; k WebRtcIsacfix_kMaxIndShape[k]) index_sQQ[k] = WebRtcIsacfix_kMaxIndShape[k]; index_ovr_sQQ[k] = WebRtcIsacfix_kOffsetShape[0][k]+index_sQQ[k]; posQQ = WebRtcIsacfix_kOfLevelsShape[0] + index_ovr_sQQ[k]; sumQQ = WebRtcIsacfix_kCodeLenShapeQ11[posQQ]; //Q11 BitsQQ += sumQQ; } *model = 0; *sizeQ11=BitsQQ; /* entropy coding of model number */ status = WebRtcIsacfix_EncHistMulti(streamdata, model, WebRtcIsacfix_kModelCdfPtr, 1); if (status < 0) { return status; } /* entropy coding of quantization indices - shape only */ status = WebRtcIsacfix_EncHistMulti(streamdata, index_sQQ, WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE); if (status < 0) { return status; } /* Save data for creation of multiple bitstreams */ if (encData != NULL) { for (k=0; kLPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_sQQ[k]; } } /* save the state of the bitstream object 'streamdata' for the possible bit-rate reduction */ transcodingParam->full = streamdata->full; transcodingParam->stream_index = streamdata->stream_index; transcodingParam->streamval = streamdata->streamval; transcodingParam->W_upper = streamdata->W_upper; transcodingParam->beforeLastWord = streamdata->stream[streamdata->stream_index-1]; transcodingParam->lastWord = streamdata->stream[streamdata->stream_index]; /* entropy coding of index */ status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN); if (status < 0) { return status; } /* find quantization levels for shape coefficients */ for (k=0; k>(16-1) = Q17 pos++; pos2++; } tmpcoeffs2_sQ17[poss] = sumQQ; poss++; offs2 += LPC_SHAPE_ORDER; } offss += LPC_SHAPE_ORDER; } /* right transform */ // Transpose matrix offss = 0; poss = 0; for (j=0; j>(16-1) = Q17 pos += LPC_SHAPE_ORDER; pos2 += SUBFRAMES; } tmpcoeffs_sQ17[poss] = sumQQ; poss++; } offss += LPC_SHAPE_ORDER; } /* scaling, mean addition, and gain restoration */ poss = 0;pos=0; for (k=0; k>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16 tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17 LPCCoefQ17[pos] = tmp32; } /* hi band LAR coeffs */ for (n=0; n>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13 tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17 LPCCoefQ17[pos] = tmp32; } } //to update tmpcoeffs_gQ17 to the proper state for (k=0; k>(16-1) = Q17 pos++; pos2++; } tmpcoeffs2_gQ21[posg] = WEBRTC_SPL_LSHIFT_W32(sumQQ, 4); //Q17<<4 = Q21 posg++; offs2 += 2; } offsg += 2; } /* right transform */ // Transpose matrix offsg = 0; posg = 0; for (j=0; j>(16-1) = Q21 pos += 2; pos2 += SUBFRAMES; } tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4); posg++; } offsg += 2; } /* scaling, mean addition, and gain restoration */ posg = 0; gainpos = 0; for (k=0; k<2*SUBFRAMES; k++) { sumQQ16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9 sumQQ16 += WebRtcIsacfix_kMeansGainQ8[0][posg]; sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out gain_lo_hiQ17[gainpos] = sumQQ; //Q17 gainpos++; pos++;posg++; } return 0; } int WebRtcIsacfix_EstCodeLpcGain(WebRtc_Word32 *gain_lo_hiQ17, Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData) { int j, k, n; WebRtc_Word16 posQQ, pos2QQ, gainpos; WebRtc_Word16 pos, pos2, posg, offsg, offs2; WebRtc_Word16 index_gQQ[KLT_ORDER_GAIN]; WebRtc_Word16 tmpcoeffs_gQ6[KLT_ORDER_GAIN]; WebRtc_Word32 tmpcoeffs_gQ17[KLT_ORDER_GAIN]; WebRtc_Word32 tmpcoeffs2_gQ21[KLT_ORDER_GAIN]; WebRtc_Word32 sumQQ; int status = 0; /* write LAR coefficients to statistics file */ /* Save data for creation of multiple bitstreams (and transcoding) */ if (encData != NULL) { for (k=0; kLPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k]; } } /* log gains, mean removal and scaling */ posg = 0; pos = 0; gainpos = 0; for (k=0; k>(16-1) = Q21 pos += 2; pos2++; } tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4); posg++; } offsg += 2; offs2 += SUBFRAMES; } /* quantize coefficients */ for (k=0; k WebRtcIsacfix_kMaxIndGain[k]) { index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k]; } /* Save data for creation of multiple bitstreams */ if (encData != NULL) { encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k]; } } /* entropy coding of index */ status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN); if (status < 0) { return status; } return 0; } int WebRtcIsacfix_EncodeLpc(WebRtc_Word32 *gain_lo_hiQ17, WebRtc_Word16 *LPCCoef_loQ15, WebRtc_Word16 *LPCCoef_hiQ15, WebRtc_Word16 *model, WebRtc_Word32 *sizeQ11, Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData, transcode_obj *transcodeParam) { int status = 0; WebRtc_Word32 larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES // = (6+12)*6 == 108 Poly2LarFix(LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES, larsQ17); status = EstCodeLpcCoef(larsQ17, gain_lo_hiQ17, model, sizeQ11, streamdata, encData, transcodeParam); if (status < 0) { return (status); } Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES); return 0; } /* decode & dequantize RC */ int WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata, WebRtc_Word16 *RCQ15) { int k, err; WebRtc_Word16 index[AR_ORDER]; /* entropy decoding of quantization indices */ err = WebRtcIsacfix_DecHistOneStepMulti(index, streamdata, WebRtcIsacfix_kRcCdfPtr, WebRtcIsacfix_kRcInitInd, AR_ORDER); if (err<0) // error check return err; /* find quantization levels for reflection coefficients */ for (k=0; k WebRtcIsacfix_kRcBound[index[k]]) { while (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k] + 1]) index[k]++; } else { while (RCQ15[k] < WebRtcIsacfix_kRcBound[--index[k]]) ; } RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]); } /* entropy coding of quantization indices */ status = WebRtcIsacfix_EncHistMulti(streamdata, index, WebRtcIsacfix_kRcCdfPtr, AR_ORDER); /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */ return status; } /* decode & dequantize squared Gain */ int WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata, WebRtc_Word32 *gainQ10) { int err; WebRtc_Word16 index; /* entropy decoding of quantization index */ err = WebRtcIsacfix_DecHistOneStepMulti( &index, streamdata, WebRtcIsacfix_kGainPtr, WebRtcIsacfix_kGainInitInd, 1); /* error check */ if (err<0) { return err; } /* find quantization level */ *gainQ10 = WebRtcIsacfix_kGain2Lev[index]; return 0; } /* quantize & code squared Gain */ int WebRtcIsacfix_EncodeGain2(WebRtc_Word32 *gainQ10, Bitstr_enc *streamdata) { WebRtc_Word16 index; int status = 0; /* find quantization index */ index = WebRtcIsacfix_kGainInitInd[0]; if (*gainQ10 > WebRtcIsacfix_kGain2Bound[index]) { while (*gainQ10 > WebRtcIsacfix_kGain2Bound[index + 1]) index++; } else { while (*gainQ10 < WebRtcIsacfix_kGain2Bound[--index]) ; } /* dequantize */ *gainQ10 = WebRtcIsacfix_kGain2Lev[index]; /* entropy coding of quantization index */ status = WebRtcIsacfix_EncHistMulti(streamdata, &index, WebRtcIsacfix_kGainPtr, 1); /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */ return status; } /* code and decode Pitch Gains and Lags functions */ /* decode & dequantize Pitch Gains */ int WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata, WebRtc_Word16 *PitchGains_Q12) { int err; WebRtc_Word16 index_comb; const WebRtc_UWord16 *pitch_gain_cdf_ptr[1]; /* entropy decoding of quantization indices */ *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf; err = WebRtcIsacfix_DecHistBisectMulti(&index_comb, streamdata, pitch_gain_cdf_ptr, WebRtcIsacfix_kCdfTableSizeGain, 1); /* error check, Q_mean_Gain.. tables are of size 144 */ if ((err<0) || (index_comb<0) || (index_comb>144)) return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN; /* unquantize back to pitch gains by table look-up */ PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb]; PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb]; PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb]; PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb]; return 0; } /* quantize & code Pitch Gains */ int WebRtcIsacfix_EncodePitchGain(WebRtc_Word16 *PitchGains_Q12, Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData) { int k,j; WebRtc_Word16 SQ15[PITCH_SUBFRAMES]; WebRtc_Word16 index[3]; WebRtc_Word16 index_comb; const WebRtc_UWord16 *pitch_gain_cdf_ptr[1]; WebRtc_Word32 CQ17; int status = 0; /* get the approximate arcsine (almost linear)*/ for (k=0; k>14); // Rounding and scaling with stepsize (=1/0.125=8) /* check that the index is not outside the boundaries of the table */ if (index[k] < WebRtcIsacfix_kLowerlimiGain[k]) index[k] = WebRtcIsacfix_kLowerlimiGain[k]; else if (index[k] > WebRtcIsacfix_kUpperlimitGain[k]) index[k] = WebRtcIsacfix_kUpperlimitGain[k]; index[k] -= WebRtcIsacfix_kLowerlimiGain[k]; } /* calculate unique overall index */ index_comb = (WebRtc_Word16)(WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[0], index[0]) + WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[1], index[1]) + index[2]); /* unquantize back to pitch gains by table look-up */ // (Y) PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb]; PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb]; PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb]; PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb]; /* entropy coding of quantization pitch gains */ *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf; status = WebRtcIsacfix_EncHistMulti(streamdata, &index_comb, pitch_gain_cdf_ptr, 1); if (status < 0) { return status; } /* Save data for creation of multiple bitstreams */ if (encData != NULL) { encData->pitchGain_index[encData->startIdx] = index_comb; } return 0; } /* Pitch LAG */ /* decode & dequantize Pitch Lags */ int WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata, WebRtc_Word16 *PitchGain_Q12, WebRtc_Word16 *PitchLags_Q7) { int k, err; WebRtc_Word16 index[PITCH_SUBFRAMES]; const WebRtc_Word16 *mean_val2Q10, *mean_val4Q10; const WebRtc_Word16 *lower_limit; const WebRtc_UWord16 *init_index; const WebRtc_UWord16 *cdf_size; const WebRtc_UWord16 **cdf; WebRtc_Word32 meangainQ12; WebRtc_Word32 CQ11, CQ10,tmp32a,tmp32b; WebRtc_Word16 shft,tmp16a,tmp16c; meangainQ12=0; for (k = 0; k < 4; k++) meangainQ12 += PitchGain_Q12[k]; meangainQ12 = WEBRTC_SPL_RSHIFT_W32(meangainQ12, 2); // Get average /* voicing classificiation */ if (meangainQ12 <= 819) { // mean_gain < 0.2 shft = -1; // StepSize=2.0; cdf = WebRtcIsacfix_kPitchLagPtrLo; cdf_size = WebRtcIsacfix_kPitchLagSizeLo; mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo; mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo; lower_limit = WebRtcIsacfix_kLowerLimitLo; init_index = WebRtcIsacfix_kInitIndLo; } else if (meangainQ12 <= 1638) { // mean_gain < 0.4 shft = 0; // StepSize=1.0; cdf = WebRtcIsacfix_kPitchLagPtrMid; cdf_size = WebRtcIsacfix_kPitchLagSizeMid; mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid; mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid; lower_limit = WebRtcIsacfix_kLowerLimitMid; init_index = WebRtcIsacfix_kInitIndMid; } else { shft = 1; // StepSize=0.5; cdf = WebRtcIsacfix_kPitchLagPtrHi; cdf_size = WebRtcIsacfix_kPitchLagSizeHi; mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi; mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi; lower_limit = WebRtcIsacfix_kLowerLimitHi; init_index = WebRtcIsacfix_kInitIndHi; } /* entropy decoding of quantization indices */ err = WebRtcIsacfix_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1); if ((err<0) || (index[0]<0)) // error check return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG; err = WebRtcIsacfix_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3); if (err<0) // error check return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG; /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */ CQ11 = ((WebRtc_Word32)index[0] + lower_limit[0]); // Q0 CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11 for (k=0; kmeanGain[encData->startIdx] = meangainQ12; } /* voicing classificiation */ if (meangainQ12 <= 819) { // mean_gain < 0.2 shft = -1; // StepSize=2.0; cdf = WebRtcIsacfix_kPitchLagPtrLo; mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo; mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo; lower_limit = WebRtcIsacfix_kLowerLimitLo; upper_limit = WebRtcIsacfix_kUpperLimitLo; } else if (meangainQ12 <= 1638) { // mean_gain < 0.4 shft = 0; // StepSize=1.0; cdf = WebRtcIsacfix_kPitchLagPtrMid; mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid; mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid; lower_limit = WebRtcIsacfix_kLowerLimitMid; upper_limit = WebRtcIsacfix_kUpperLimitMid; } else { shft = 1; // StepSize=0.5; cdf = WebRtcIsacfix_kPitchLagPtrHi; mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi; mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi; lower_limit = WebRtcIsacfix_kLowerLimitHi; upper_limit = WebRtcIsacfix_kUpperLimitHi; } /* find quantization index */ for (k=0; k<4; k++) { /* transform */ CQ17=0; for (j=0; j upper_limit[k]) index[k] = upper_limit[k]; index[k] -= lower_limit[k]; /* Save data for creation of multiple bitstreams */ if(encData != NULL) { encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k]; } } /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */ CQ11 = (index[0] + lower_limit[0]); // Q0 CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11 for (k=0; k>(16-1) = Q21 pos += 2; pos2++; } tmpcoeffs_gQ17[posg] = WEBRTC_SPL_RSHIFT_W32(sumQQ, 4); posg++; } offsg += 2; offs2 += SUBFRAMES; } /* quantize coefficients */ for (k=0; k WebRtcIsacfix_kMaxIndGain[k]) { index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k]; } } }