/* * 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 header file defines all of the functions used to arithmetically * encode the iSAC bistream * */ #include "entropy_coding.h" #include "settings.h" #include "arith_routines.h" #include "signal_processing_library.h" #include "spl_inl.h" #include "spectrum_ar_model_tables.h" #include "lpc_tables.h" #include "pitch_gain_tables.h" #include "pitch_lag_tables.h" #include "encode_lpc_swb.h" #include "lpc_shape_swb12_tables.h" #include "lpc_shape_swb16_tables.h" #include "lpc_gain_swb_tables.h" #include #include static const WebRtc_UWord16 WebRtcIsac_kLpcVecPerSegmentUb12 = 5; static const WebRtc_UWord16 WebRtcIsac_kLpcVecPerSegmentUb16 = 4; /* coefficients for the stepwise rate estimation */ const WebRtc_Word32 WebRtcIsac_kRPointsQ10[100] = { 14495, 14295, 14112, 13944, 13788, 13643, 13459, 13276, 13195, 13239, 13243, 13191, 13133, 13216, 13263, 13330, 13316, 13242, 13191, 13106, 12942, 12669, 12291, 11840, 11361, 10795, 10192, 9561, 8934, 8335, 7750, 7161, 6589, 6062, 5570, 5048, 4548, 4069, 3587, 3143, 2717, 2305, 1915, 1557, 1235, 963, 720, 541, 423, 366, 369, 435, 561, 750, 1001, 1304, 1626, 1989, 2381, 2793, 3219, 3656, 4134, 4612, 5106, 5629, 6122, 6644, 7216, 7801, 8386, 8987, 9630, 10255, 10897, 11490, 11950, 12397, 12752, 12999, 13175, 13258, 13323, 13290, 13296, 13335, 13113, 13255, 13347, 13355, 13298, 13247, 13313, 13155, 13267, 13313, 13374, 13446, 13525, 13609}; /* cdf array for encoder bandwidth (12 vs 16 kHz) indicator */ static const WebRtc_UWord16 WebRtcIsac_kOneBitEqualProbCdf[3] = { 0, 32768, 65535}; /* pointer to cdf array for encoder bandwidth (12 vs 16 kHz) indicator */ static const WebRtc_UWord16 *WebRtcIsac_kOneBitEqualProbCdf_ptr[1] = {WebRtcIsac_kOneBitEqualProbCdf}; /* initial cdf index for decoder of encoded bandwidth (12 vs 16 kHz) indicator */ static const WebRtc_UWord16 WebRtcIsac_kOneBitEqualProbInitIndex[1] = {1}; /* coefficients for the stepwise rate estimation */ const WebRtc_Word32 acnQ10 = 426; const WebRtc_Word32 bcnQ10 = -581224; const WebRtc_Word32 ccnQ10 = 722631; const WebRtc_Word32 lbcnQ10 = -402874; #define DPMIN_Q10 -10240 // -10.00 in Q10 #define DPMAX_Q10 10240 // 10.00 in Q10 #define MINBITS_Q10 10240 /* 10.0 in Q10 */ #define IS_SWB_12KHZ 1 #if defined(WEBRTC_LINUX) extern long int lrint(double x); /* Note! This declaration is missing in math.h, that is why it is declared as extern*/ #define WebRtcIsac_lrint lrint #elif defined(WEBRTC_MAC) extern long int lrint(double x); /* Note! This declaration is missing in math.h, that is why it is declared as extern*/ #define WebRtcIsac_lrint lrint #elif defined(X64) static __inline WebRtc_Word32 WebRtcIsac_lrint(double flt) { WebRtc_Word32 intgr; intgr = (WebRtc_Word32)floor(flt+.499999999999); return intgr ; } #elif defined(WEBRTC_TARGET_PC) static __inline WebRtc_Word32 WebRtcIsac_lrint(double flt) { WebRtc_Word32 intgr; _asm { fld flt fistp intgr } ; return intgr ; } #else // Do a slow but correct implementation of lrint static __inline WebRtc_Word32 WebRtcIsac_lrint(double flt) { WebRtc_Word32 intgr; intgr = (WebRtc_Word32)floor(flt+.499999999999); return intgr ; } #endif __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 WebRtcIsac_kRPointsQ10[ind]; } __inline short log2_Q10_B( int x ) { int zeros; short frac; zeros = WebRtcSpl_NormU32( x ); frac = ((unsigned int)(x << zeros) & 0x7FFFFFFF) >> 21; return (short) (((31 - zeros) << 10) + frac); } /* compute correlation from power spectrum */ static void WebRtcIsac_FindCorrelation(WebRtc_Word32 *PSpecQ12, WebRtc_Word32 *CorrQ7) { WebRtc_Word32 summ[FRAMESAMPLES/8]; WebRtc_Word32 diff[FRAMESAMPLES/8]; const WebRtc_Word16 *CS_ptrQ9; WebRtc_Word32 sum; int k, n; for (k = 0; k < FRAMESAMPLES/8; k++) { summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES_QUARTER-1 - k] + 16) >> 5; diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES_QUARTER-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; CS_ptrQ9 = WebRtcIsac_kCos[k]; for (n = 0; n < FRAMESAMPLES/8; n++) sum += (CS_ptrQ9[n] * diff[n] + 256) >> 9; CorrQ7[k+1] = sum; } for (k=1; k> 9; CorrQ7[k+1] = sum; } } /* compute inverse AR power spectrum */ /* Changed to the function used in iSAC FIX for compatibility reasons */ static void WebRtcIsac_FindInvArSpec(const WebRtc_Word16 *ARCoefQ12, const WebRtc_Word32 gainQ10, WebRtc_Word32 *CurveQ16) { WebRtc_Word32 CorrQ11[AR_ORDER+1]; WebRtc_Word32 sum, tmpGain; WebRtc_Word32 diffQ16[FRAMESAMPLES/8]; const WebRtc_Word16 *CS_ptrQ9; int k, n; WebRtc_Word16 round, shftVal = 0, sh; sum = 0; for (n = 0; n < AR_ORDER+1; n++) sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]); /* Q24 */ sum = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(sum, 6), 65) + 32768, 16); /* result in Q8 */ CorrQ11[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, gainQ10) + 256, 9); /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */ if(gainQ10>400000){ 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) { //CS_ptrQ9 = WebRtcIsac_kCos[k]; for (n = 0; n < FRAMESAMPLES/8; n++) CurveQ16[n] += WEBRTC_SPL_RSHIFT_W32( WEBRTC_SPL_MUL(WebRtcIsac_kCos[k][n], CorrQ11[k+1]) + 2, 2); } CS_ptrQ9 = WebRtcIsac_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 = WebRtcIsac_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; k>25); // * 128/4294967295 /* new random unsigned int */ seed = (seed * 196314165) + 907633515; /* fixed-point dither sample between -64 and 64 */ dither2_Q7 = (WebRtc_Word16)(((int)seed + 16777216)>>25); shft = (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 - 10 * AvgPitchGain_Q12); /* dither on half of the coefficients */ for (k = 0; k < length-1; k += 2) { /* new random unsigned int */ seed = (seed * 196314165) + 907633515; /* fixed-point dither sample between -64 and 64 */ dither1_Q7 = (WebRtc_Word16)(((int)seed + 16777216)>>25); /* dither sample is placed in either even or odd index */ shft = (seed >> 25) & 1; /* either 0 or 1 */ bufQ7[k + shft] = (((dither_gain_Q14 * dither1_Q7) + 8192)>>14); bufQ7[k + 1 - shft] = 0; } } } /****************************************************************************** * GenerateDitherQ7LbUB() * * generate array of dither samples in Q7 There are less zeros in dither * vector compared to GenerateDitherQ7Lb. * * A uniform random number generator with the range of [-64 64] is employed * but the generated dithers are scaled by 0.35, a heuristic scaling. * * Input: * -seed : the initial seed for the random number generator. * -length : the number of dither values to be generated. * * Output: * -bufQ7 : pointer to a buffer where dithers are written to. */ static void GenerateDitherQ7LbUB( WebRtc_Word16 *bufQ7, WebRtc_UWord32 seed, int length) { int k; for (k = 0; k < length; k++) { /* new random unsigned int */ seed = (seed * 196314165) + 907633515; /* fixed-point dither sample between -64 and 64 (Q7) */ // * 128/4294967295 bufQ7[k] = (WebRtc_Word16)(((int)seed + 16777216)>>25); // scale by 0.35 bufQ7[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(bufQ7[k], 2048, 13); } } /* * function to decode the complex spectrum from the bit stream * returns the total number of bytes in the stream */ int WebRtcIsac_DecodeSpecLb(Bitstr *streamdata, double *fr, double *fi, WebRtc_Word16 AvgPitchGain_Q12) { WebRtc_Word16 DitherQ7[FRAMESAMPLES]; WebRtc_Word16 data[FRAMESAMPLES]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER]; WebRtc_Word16 ARCoefQ12[AR_ORDER+1]; WebRtc_Word16 RCQ15[AR_ORDER]; WebRtc_Word16 gainQ10; WebRtc_Word32 gain2_Q10, res; WebRtc_Word32 in_sqrt; WebRtc_Word32 newRes; int k, len, i; /* create dither signal */ GenerateDitherQ7Lb(DitherQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* decode model parameters */ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12); if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; /* compute inverse AR power spectrum */ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1); for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { in_sqrt = invARSpec2_Q16[k]; i = 10; /* Negative values make no sense for a real sqrt-function. */ if (in_sqrt<0) in_sqrt=-in_sqrt; newRes = (in_sqrt / res + res) >> 1; do { res = newRes; newRes = (in_sqrt / res + res) >> 1; } while (newRes != res && i-- > 0); invARSpecQ8[k] = (WebRtc_Word16)newRes; } /* arithmetic decoding of spectrum */ if ((len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7, FRAMESAMPLES, !IS_SWB_12KHZ)) <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(30 << 10, (WebRtc_Word16)((invARSpec2_Q16[k>>2] + (32768 + (33 << 16))) >> 16)); *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0; *fi++ = (double)((data[k+1] * gainQ10 + 512) >> 10) / 128.0; *fr++ = (double)((data[k+2] * gainQ10 + 512) >> 10) / 128.0; *fi++ = (double)((data[k+3] * gainQ10 + 512) >> 10) / 128.0; } } else { for (k = 0; k < FRAMESAMPLES; k += 4) { gainQ10 = WebRtcSpl_DivW32W16ResW16(36 << 10, (WebRtc_Word16)((invARSpec2_Q16[k>>2] + (32768 + (40 << 16))) >> 16)); *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0; *fi++ = (double)((data[k+1] * gainQ10 + 512) >> 10) / 128.0; *fr++ = (double)((data[k+2] * gainQ10 + 512) >> 10) / 128.0; *fi++ = (double)((data[k+3] * gainQ10 + 512) >> 10) / 128.0; } } return len; } /****************************************************************************** * WebRtcIsac_DecodeSpecUB16() * Decode real and imaginary part of the DFT coefficients, given a bit-stream. * This function is called when the codec is in 0-16 kHz bandwidth. * The decoded DFT coefficient can be transformed to time domain by * WebRtcIsac_Time2Spec(). * * Input: * - streamdata : pointer to a stucture containg the encoded * data and theparameters needed for entropy * coding. * * Output: * -*fr : pointer to a buffer where the real part of DFT * coefficients are written to. * -*fi : pointer to a buffer where the imaginary part * of DFT coefficients are written to. * * Return value : < 0 if an error occures * 0 if succeeded. */ int WebRtcIsac_DecodeSpecUB16( Bitstr* streamdata, double* fr, double* fi) { WebRtc_Word16 DitherQ7[FRAMESAMPLES]; WebRtc_Word16 data[FRAMESAMPLES]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER]; WebRtc_Word16 ARCoefQ12[AR_ORDER+1]; WebRtc_Word16 RCQ15[AR_ORDER]; WebRtc_Word32 gain2_Q10, res; WebRtc_Word32 in_sqrt; WebRtc_Word32 newRes; int k, len, i, j; /* create dither signal */ GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES); /* decode model parameters */ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12); if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; /* compute inverse AR power spectrum */ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1); for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { in_sqrt = invARSpec2_Q16[k]; i = 10; /* Negative values make no sense for a real sqrt-function. */ if (in_sqrt<0) in_sqrt=-in_sqrt; newRes = (in_sqrt / res + res) >> 1; do { res = newRes; newRes = (in_sqrt / res + res) >> 1; } while (newRes != res && i-- > 0); invARSpecQ8[k] = (WebRtc_Word16)newRes; } /* arithmetic decoding of spectrum */ if ((len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7, FRAMESAMPLES, !IS_SWB_12KHZ)) <1) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; /* re-arrange DFT coefficients and scale down */ for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++) { fr[j] = (double)data[ k ] / 128.0; fi[j] = (double)data[k+1] / 128.0; fr[(FRAMESAMPLES_HALF) - 1 - j] = (double)data[k+2] / 128.0; fi[(FRAMESAMPLES_HALF) - 1 - j] = (double)data[k+3] / 128.0; } return len; } /****************************************************************************** * WebRtcIsac_DecodeSpecUB12() * Decode real and imaginary part of the DFT coefficients, given a bit-stream. * This function is called when the codec is in 0-12 kHz bandwidth. * The decoded DFT coefficient can be transformed to time domain by * WebRtcIsac_Time2Spec(). * * Input: * - streamdata : pointer to a stucture containg the encoded * data and theparameters needed for entropy * coding. * * Output: * -*fr : pointer to a buffer where the real part of DFT * coefficients are written to. * -*fi : pointer to a buffer where the imaginary part * of DFT coefficients are written to. * * Return value : < 0 if an error occures * 0 if succeeded. */ int WebRtcIsac_DecodeSpecUB12( Bitstr *streamdata, double *fr, double *fi) { WebRtc_Word16 DitherQ7[FRAMESAMPLES]; WebRtc_Word16 data[FRAMESAMPLES]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER]; WebRtc_Word16 ARCoefQ12[AR_ORDER+1]; WebRtc_Word16 RCQ15[AR_ORDER]; WebRtc_Word32 gain2_Q10; WebRtc_Word32 res; WebRtc_Word32 in_sqrt; WebRtc_Word32 newRes; int k, len, i; /* create dither signal */ GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES); /* decode model parameters */ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12); if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0) return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; /* compute inverse AR power spectrum */ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1); for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { in_sqrt = invARSpec2_Q16[k]; i = 10; /* Negative values make no sense for a real sqrt-function. */ if (in_sqrt<0) in_sqrt=-in_sqrt; newRes = (in_sqrt / res + res) >> 1; do { res = newRes; newRes = (in_sqrt / res + res) >> 1; } while (newRes != res && i-- > 0); invARSpecQ8[k] = (WebRtc_Word16)newRes; } /* arithmetic decoding of spectrum */ if ((len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7, (FRAMESAMPLES_HALF), IS_SWB_12KHZ)) < 1) { return -ISAC_RANGE_ERROR_DECODE_SPECTRUM; } for (k = 0, i = 0; k < FRAMESAMPLES_HALF; k += 4) { fr[i] = (double)data[ k ] / 128.0; fi[i] = (double)data[k+1] / 128.0; i++; fr[i] = (double)data[k+2] / 128.0; fi[i] = (double)data[k+3] / 128.0; i++; } // The second half of real and imaginary coefficients is zero. This is // due to using the old FFT module which requires two signals as input // while in 0-12 kHz mode we only have 8-12 kHz band, and the second signal // is set to zero memset(&fr[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER * sizeof(double)); memset(&fi[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER * sizeof(double)); return len; } int WebRtcIsac_EncodeSpecLb(const WebRtc_Word16 *fr, const WebRtc_Word16 *fi, Bitstr *streamdata, WebRtc_Word16 AvgPitchGain_Q12) { WebRtc_Word16 ditherQ7[FRAMESAMPLES]; WebRtc_Word16 dataQ7[FRAMESAMPLES]; WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER]; 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, res; WebRtc_UWord32 sum; WebRtc_Word32 in_sqrt; WebRtc_Word32 newRes; WebRtc_Word16 err; int lft_shft; int k, n, j, i; /* create dither_float signal */ GenerateDitherQ7Lb(ditherQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* add dither and quantize, and compute power spectrum */ for (k = 0; k < FRAMESAMPLES; k += 4) { val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k]; dataQ7[k] = val; sum = val * val; val = ((*fi++ + ditherQ7[k+1] + 64) & 0xFF80) - ditherQ7[k+1]; dataQ7[k+1] = val; sum += val * val; val = ((*fr++ + ditherQ7[k+2] + 64) & 0xFF80) - ditherQ7[k+2]; dataQ7[k+2] = val; sum += val * val; val = ((*fi++ + ditherQ7[k+3] + 64) & 0xFF80) - ditherQ7[k+3]; dataQ7[k+3] = val; sum += val * val; PSpec[k>>2] = sum >> 2; } /* compute correlation from power spectrum */ WebRtcIsac_FindCorrelation(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> (-lft_shft); } } /* find RC coefficients */ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15); /* quantize & code RC Coefficient */ WebRtcIsac_EncodeRc(RCQ15, streamdata); /* RC -> 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 += ( ARCoefQ12[j] * ((CorrQ7_norm[j-n] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3; } for (n = j+1; n <= AR_ORDER; n++) { nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[n-j] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3; } } if (lft_shft > 0) { nrg >>= lft_shft; } else { nrg <<= -lft_shft; } gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg); /* also shifts 31 bits to the left! */ /* quantize & code gain2_Q10 */ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) { return -1; } /* compute inverse AR power spectrum */ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1); for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { in_sqrt = invARSpec2_Q16[k]; i = 10; /* Negative values make no sense for a real sqrt-function. */ if (in_sqrt<0) in_sqrt=-in_sqrt; newRes = (in_sqrt / res + res) >> 1; do { res = newRes; newRes = (in_sqrt / res + res) >> 1; } while (newRes != res && i-- > 0); invARSpecQ8[k] = (WebRtc_Word16)newRes; } /* arithmetic coding of spectrum */ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, FRAMESAMPLES, !IS_SWB_12KHZ); if (err < 0) { return (err); } return 0; } /****************************************************************************** * WebRtcIsac_EncodeSpecUB16() * Quantize and encode real and imaginary part of the DFT coefficients. * This function is called when the codec is in 0-16 kHz bandwidth. * The real and imaginary part are computed by calling WebRtcIsac_Time2Spec(). * * * Input: * -*fr : pointer to a buffer where the real part of DFT * coefficients are stored. * -*fi : pointer to a buffer where the imaginary part * of DFT coefficients are stored. * * Output: * - streamdata : pointer to a stucture containg the encoded * data and theparameters needed for entropy * coding. * * Return value : < 0 if an error occures * 0 if succeeded. */ int WebRtcIsac_EncodeSpecUB16( const WebRtc_Word16* fr, const WebRtc_Word16* fi, Bitstr* streamdata) { WebRtc_Word16 ditherQ7[FRAMESAMPLES]; WebRtc_Word16 dataQ7[FRAMESAMPLES]; WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER]; 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, res; WebRtc_UWord32 sum; WebRtc_Word32 in_sqrt; WebRtc_Word32 newRes; WebRtc_Word16 err; int lft_shft; int k, n, j, i; /* create dither_float signal */ GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES); /* add dither and quantize, and compute power spectrum */ for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++) { val = ((fr[j] + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k]; dataQ7[k] = val; sum = val * val; val = ((fi[j] + ditherQ7[k+1] + 64) & 0xFF80) - ditherQ7[k+1]; dataQ7[k+1] = val; sum += val * val; val = ((fr[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k+2] + 64) & 0xFF80) - ditherQ7[k+2]; dataQ7[k+2] = val; sum += val * val; val = ((fi[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k+3] + 64) & 0xFF80) - ditherQ7[k+3]; dataQ7[k+3] = val; sum += val * val; PSpec[k>>2] = sum >> 2; } /* compute correlation from power spectrum */ WebRtcIsac_FindCorrelation(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> (-lft_shft); } } /* find RC coefficients */ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15); /* quantize & code RC Coef */ WebRtcIsac_EncodeRc(RCQ15, streamdata); /* RC -> 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 += ( ARCoefQ12[j] * ((CorrQ7_norm[j-n] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3; } for (n = j+1; n <= AR_ORDER; n++) { nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[n-j] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3; } } if (lft_shft > 0) { nrg >>= lft_shft; } else { nrg <<= -lft_shft; } gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg); /* also shifts 31 bits to the left! */ /* quantize & code gain2_Q10 */ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) { return -1; } /* compute inverse AR power spectrum */ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1); for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { in_sqrt = invARSpec2_Q16[k]; i = 10; /* Negative values make no sense for a real sqrt-function. */ if (in_sqrt<0) in_sqrt=-in_sqrt; newRes = (in_sqrt / res + res) >> 1; do { res = newRes; newRes = (in_sqrt / res + res) >> 1; } while (newRes != res && i-- > 0); invARSpecQ8[k] = (WebRtc_Word16)newRes; } /* arithmetic coding of spectrum */ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, FRAMESAMPLES, !IS_SWB_12KHZ); if (err < 0) { return (err); } return 0; } int WebRtcIsac_EncodeSpecUB12(const WebRtc_Word16 *fr, const WebRtc_Word16 *fi, Bitstr *streamdata) { WebRtc_Word16 ditherQ7[FRAMESAMPLES]; WebRtc_Word16 dataQ7[FRAMESAMPLES]; WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER]; WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER]; WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER]; 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, res; WebRtc_UWord32 sum; WebRtc_Word32 in_sqrt; WebRtc_Word32 newRes; WebRtc_Word16 err; int lft_shft; int k, n, j, i; /* create dither_float signal */ GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES); /* add dither and quantize, and compute power spectrum */ for (k = 0, j = 0; k < (FRAMESAMPLES_HALF); k += 4) { val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k]; dataQ7[k] = val; sum = (val) * (val); val = ((*fi++ + ditherQ7[k+1] + 64) & 0xFF80) - ditherQ7[k+1]; dataQ7[k+1] = val; sum += (val) * (val); if(j < FRAMESAMPLES_QUARTER) { PSpec[j] = sum >> 1; j++; } val = ((*fr++ + ditherQ7[k+2] + 64) & 0xFF80) - ditherQ7[k+2]; dataQ7[k+2] = val; sum = (val) * (val); val = ((*fi++ + ditherQ7[k+3] + 64) & 0xFF80) - ditherQ7[k+3]; dataQ7[k+3] = val; sum += (val) * (val); if(j < FRAMESAMPLES_QUARTER) { PSpec[j] = sum >> 1; j++; } } /* compute correlation from power spectrum */ WebRtcIsac_FindCorrelation(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> (-lft_shft); } } /* find RC coefficients */ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15); /* quantize & code RC Coef */ WebRtcIsac_EncodeRc(RCQ15, streamdata); /* RC -> 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 += ( ARCoefQ12[j] * ((CorrQ7_norm[j-n] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3; } for (n = j+1; n <= AR_ORDER; n++) { nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[n-j] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3; } } if (lft_shft > 0) { nrg >>= lft_shft; } else { nrg <<= -lft_shft; } gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg); /* also shifts 31 bits to the left! */ /* quantize & code gain2_Q10 */ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) { return -1; } /* compute inverse AR power spectrum */ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16); /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1); for (k = 0; k < FRAMESAMPLES_QUARTER; k++) { in_sqrt = invARSpec2_Q16[k]; i = 10; /* Negative values make no sense for a real sqrt-function. */ if (in_sqrt<0) in_sqrt=-in_sqrt; newRes = (in_sqrt / res + res) >> 1; do { res = newRes; newRes = (in_sqrt / res + res) >> 1; } while (newRes != res && i-- > 0); invARSpecQ8[k] = (WebRtc_Word16)newRes; } /* arithmetic coding of spectrum */ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (FRAMESAMPLES_HALF), IS_SWB_12KHZ); if (err < 0) { return (err); } return 0; } /* step-up */ void WebRtcIsac_Rc2Poly(double *RC, int N, double *a) { int m, k; double tmp[MAX_AR_MODEL_ORDER]; a[0] = 1.0; tmp[0] = 1.0; for (m=1; m<=N; m++) { /* copy */ for (k=1; k0; m--) { tmp_inv = 1.0 / (1.0 - RC[m]*RC[m]); for (k=1; k<=m; k++) tmp[k] = (a[k] - RC[m] * a[m-k+1]) * tmp_inv; for (k=1; k WebRtcIsac_kQKltMaxIndGain[k]) index_g[k] = WebRtcIsac_kQKltMaxIndGain[k]; index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[bmodel][k]+index_g[k]; pos = WebRtcIsac_kQKltOfLevelsGain[bmodel] + index_ovr_g[k]; /* determine number of bits */ sum = WebRtcIsac_kQKltCodeLenGain[pos]; Bits += sum; } for (k=0; k WebRtcIsac_kQKltMaxIndShape[k]) index_s[k] = WebRtcIsac_kQKltMaxIndShape[k]; index_ovr_s[k] = WebRtcIsac_kQKltOffsetShape[bmodel][k]+index_s[k]; pos = WebRtcIsac_kQKltOfLevelsShape[bmodel] + index_ovr_s[k]; sum = WebRtcIsac_kQKltCodeLenShape[pos]; Bits += sum; } /* Only one model remains in this version of the code, model = 0 */ *model=bmodel; *size=Bits; /* entropy coding of model number */ WebRtcIsac_EncHistMulti(streamdata, model, WebRtcIsac_kQKltModelCdfPtr, 1); /* entropy coding of quantization indices - shape only */ WebRtcIsac_EncHistMulti(streamdata, index_s, WebRtcIsac_kQKltCdfPtrShape[bmodel], KLT_ORDER_SHAPE); /* Save data for creation of multiple bit streams */ encData->LPCmodel[encData->startIdx] = 0; for (k=0; kLPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_s[k]; } /* find quantization levels for shape coefficients */ for (k=0; kLPCcoeffs_lo[(ORDERLO+1)*SUBFRAMES*encData->startIdx + k] = LPCCoef_lo[k]; } for (k=0; k<(ORDERHI+1)*SUBFRAMES; k++) { encData->LPCcoeffs_hi[(ORDERHI+1)*SUBFRAMES*encData->startIdx + k] = LPCCoef_hi[k]; } } WebRtc_Word16 WebRtcIsac_EncodeLpcUB( double* lpcVecs, Bitstr* streamdata, double* interpolLPCCoeff, WebRtc_Word16 bandwidth, ISACUBSaveEncDataStruct* encData) { double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME]; int idx[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME]; int interpolCntr; WebRtcIsac_Poly2LarUB(lpcVecs, bandwidth); WebRtcIsac_RemoveLarMean(lpcVecs, bandwidth); WebRtcIsac_DecorrelateIntraVec(lpcVecs, U, bandwidth); WebRtcIsac_DecorrelateInterVec(U, lpcVecs, bandwidth); WebRtcIsac_QuantizeUncorrLar(lpcVecs, idx, bandwidth); WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth); WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth); WebRtcIsac_AddLarMean(lpcVecs, bandwidth); switch(bandwidth) { case isac12kHz: { // Stor the indices to be used for multiple encoding. memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME * sizeof(int)); WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb12, UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME); for(interpolCntr = 0; interpolCntr < UB_INTERPOL_SEGMENTS; interpolCntr++) { WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff, WebRtcIsac_kLpcVecPerSegmentUb12 + 1); lpcVecs += UB_LPC_ORDER; interpolLPCCoeff += (WebRtcIsac_kLpcVecPerSegmentUb12 * (UB_LPC_ORDER + 1)); } break; } case isac16kHz: { // Stor the indices to be used for multiple encoding. memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME * sizeof(int)); WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb16, UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME); for(interpolCntr = 0; interpolCntr < UB16_INTERPOL_SEGMENTS; interpolCntr++) { WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff, WebRtcIsac_kLpcVecPerSegmentUb16 + 1); lpcVecs += UB_LPC_ORDER; interpolLPCCoeff += (WebRtcIsac_kLpcVecPerSegmentUb16 * (UB_LPC_ORDER + 1)); } break; } default: return -1; } return 0; } void WebRtcIsac_EncodeLpcGainLb(double *LPCCoef_lo, double *LPCCoef_hi, int model, Bitstr *streamdata, ISAC_SaveEncData_t* encData) { int j, k, n, pos, pos2, posg, offsg, offs2; int index_g[KLT_ORDER_GAIN]; int index_ovr_g[KLT_ORDER_GAIN]; double Bits; double tmpcoeffs_g[KLT_ORDER_GAIN]; double tmpcoeffs2_g[KLT_ORDER_GAIN]; double sum; /* log gains, mean removal and scaling */ posg = 0; for (k=0; k WebRtcIsac_kQKltMaxIndGain[k]) { index_g[k] = WebRtcIsac_kQKltMaxIndGain[k]; } index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[model][k]+index_g[k]; /* find quantization levels for coefficients */ tmpcoeffs_g[WebRtcIsac_kQKltSelIndGain[k]] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOfLevelsGain[model]+index_ovr_g[k]]; /* Save data for creation of multiple bit streams */ encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_g[k]; } /* entropy coding of quantization indices - gain */ WebRtcIsac_EncHistMulti(streamdata, index_g, WebRtcIsac_kQKltCdfPtrGain[model], KLT_ORDER_GAIN); /* find quantization levels for coefficients */ /* left transform */ offsg = 0; posg = 0; for (j=0; j WebRtcIsac_kQArBoundaryLevels[index[k]]) { while (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k] + 1]) index[k]++; } else { while (RCQ15[k] < WebRtcIsac_kQArBoundaryLevels[--index[k]]) ; } RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]); } /* entropy coding of quantization indices */ WebRtcIsac_EncHistMulti(streamdata, index, WebRtcIsac_kQArRcCdfPtr, AR_ORDER); } /* decode & dequantize squared Gain */ int WebRtcIsac_DecodeGain2(Bitstr *streamdata, WebRtc_Word32 *gainQ10) { int index, err; /* entropy decoding of quantization index */ err = WebRtcIsac_DecHistOneStepMulti(&index, streamdata, WebRtcIsac_kQGainCdf_ptr, WebRtcIsac_kQGainInitIndex, 1); if (err<0) // error check return err; /* find quantization level */ *gainQ10 = WebRtcIsac_kQGain2Levels[index]; return 0; } /* quantize & code squared Gain */ int WebRtcIsac_EncodeGain2(WebRtc_Word32 *gainQ10, Bitstr *streamdata) { int index; /* find quantization index */ index = WebRtcIsac_kQGainInitIndex[0]; if (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index]) { while (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index + 1]) index++; } else { while (*gainQ10 < WebRtcIsac_kQGain2BoundaryLevels[--index]) ; } /* dequantize */ *gainQ10 = WebRtcIsac_kQGain2Levels[index]; /* entropy coding of quantization index */ WebRtcIsac_EncHistMulti(streamdata, &index, WebRtcIsac_kQGainCdf_ptr, 1); return 0; } /* code and decode Pitch Gains and Lags functions */ /* decode & dequantize Pitch Gains */ int WebRtcIsac_DecodePitchGain(Bitstr *streamdata, WebRtc_Word16 *PitchGains_Q12) { int index_comb, err; const WebRtc_UWord16 *WebRtcIsac_kQPitchGainCdf_ptr[1]; /* entropy decoding of quantization indices */ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf; err = WebRtcIsac_DecHistBisectMulti(&index_comb, streamdata, WebRtcIsac_kQPitchGainCdf_ptr, WebRtcIsac_kQCdfTableSizeGain, 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] = WebRtcIsac_kQMeanGain1Q12[index_comb]; PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb]; PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb]; PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb]; return 0; } /* quantize & code Pitch Gains */ void WebRtcIsac_EncodePitchGain(WebRtc_Word16 *PitchGains_Q12, Bitstr *streamdata, ISAC_SaveEncData_t* encData) { int k,j; double C; double S[PITCH_SUBFRAMES]; int index[3]; int index_comb; const WebRtc_UWord16 *WebRtcIsac_kQPitchGainCdf_ptr[1]; double PitchGains[PITCH_SUBFRAMES] = {0,0,0,0}; /* take the asin */ for (k=0; k WebRtcIsac_kIndexUpperLimitGain[k]) index[k] = WebRtcIsac_kIndexUpperLimitGain[k]; index[k] -= WebRtcIsac_kIndexLowerLimitGain[k]; } /* calculate unique overall index */ index_comb = WebRtcIsac_kIndexMultsGain[0] * index[0] + WebRtcIsac_kIndexMultsGain[1] * index[1] + index[2]; /* unquantize back to pitch gains by table look-up */ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb]; PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb]; PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb]; PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb]; /* entropy coding of quantization pitch gains */ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf; WebRtcIsac_EncHistMulti(streamdata, &index_comb, WebRtcIsac_kQPitchGainCdf_ptr, 1); encData->pitchGain_index[encData->startIdx] = index_comb; } /* Pitch LAG */ /* decode & dequantize Pitch Lags */ int WebRtcIsac_DecodePitchLag(Bitstr *streamdata, WebRtc_Word16 *PitchGain_Q12, double *PitchLags) { int k, err; double StepSize; double C; int index[PITCH_SUBFRAMES]; double mean_gain; const double *mean_val2, *mean_val3, *mean_val4; const WebRtc_Word16 *lower_limit; const WebRtc_UWord16 *init_index; const WebRtc_UWord16 *cdf_size; const WebRtc_UWord16 **cdf; //(Y) double PitchGain[4]={0,0,0,0}; // /* compute mean pitch gain */ mean_gain = 0.0; for (k = 0; k < 4; k++) { //(Y) PitchGain[k] = ((float)PitchGain_Q12[k])/4096; //(Y) mean_gain += PitchGain[k]; } mean_gain /= 4.0; /* voicing classificiation */ if (mean_gain < 0.2) { StepSize = WebRtcIsac_kQPitchLagStepsizeLo; cdf = WebRtcIsac_kQPitchLagCdfPtrLo; cdf_size = WebRtcIsac_kQPitchLagCdfSizeLo; mean_val2 = WebRtcIsac_kQMeanLag2Lo; mean_val3 = WebRtcIsac_kQMeanLag3Lo; mean_val4 = WebRtcIsac_kQMeanLag4Lo; lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo; init_index = WebRtcIsac_kQInitIndexLagLo; } else if (mean_gain < 0.4) { StepSize = WebRtcIsac_kQPitchLagStepsizeMid; cdf = WebRtcIsac_kQPitchLagCdfPtrMid; cdf_size = WebRtcIsac_kQPitchLagCdfSizeMid; mean_val2 = WebRtcIsac_kQMeanLag2Mid; mean_val3 = WebRtcIsac_kQMeanLag3Mid; mean_val4 = WebRtcIsac_kQMeanLag4Mid; lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid; init_index = WebRtcIsac_kQInitIndexLagMid; } else { StepSize = WebRtcIsac_kQPitchLagStepsizeHi; cdf = WebRtcIsac_kQPitchLagCdfPtrHi; cdf_size = WebRtcIsac_kQPitchLagCdfSizeHi; mean_val2 = WebRtcIsac_kQMeanLag2Hi; mean_val3 = WebRtcIsac_kQMeanLag3Hi; mean_val4 = WebRtcIsac_kQMeanLag4Hi; lower_limit = WebRtcIsac_kQindexLowerLimitLagHi; init_index = WebRtcIsac_kQInitIndexLagHi; } /* entropy decoding of quantization indices */ err = WebRtcIsac_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1); if ((err<0) || (index[0]<0)) // error check return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG; err = WebRtcIsac_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 */ C = (index[0] + lower_limit[0]) * StepSize; for (k=0; kmeanGain[encData->startIdx] = mean_gain; /* voicing classification */ if (mean_gain < 0.2) { StepSize = WebRtcIsac_kQPitchLagStepsizeLo; cdf = WebRtcIsac_kQPitchLagCdfPtrLo; mean_val2 = WebRtcIsac_kQMeanLag2Lo; mean_val3 = WebRtcIsac_kQMeanLag3Lo; mean_val4 = WebRtcIsac_kQMeanLag4Lo; lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo; upper_limit = WebRtcIsac_kQIndexUpperLimitLagLo; } else if (mean_gain < 0.4) { StepSize = WebRtcIsac_kQPitchLagStepsizeMid; cdf = WebRtcIsac_kQPitchLagCdfPtrMid; mean_val2 = WebRtcIsac_kQMeanLag2Mid; mean_val3 = WebRtcIsac_kQMeanLag3Mid; mean_val4 = WebRtcIsac_kQMeanLag4Mid; lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid; upper_limit = WebRtcIsac_kQIndexUpperLimitLagMid; } else { StepSize = WebRtcIsac_kQPitchLagStepsizeHi; cdf = WebRtcIsac_kQPitchLagCdfPtrHi; mean_val2 = WebRtcIsac_kQMeanLag2Hi; mean_val3 = WebRtcIsac_kQMeanLag3Hi; mean_val4 = WebRtcIsac_kQMeanLag4Hi; lower_limit = WebRtcIsac_kQindexLowerLimitLagHi; upper_limit = WebRtcIsac_kQindexUpperLimitLagHi; } /* find quantization index */ for (k=0; k<4; k++) { /* transform */ C = 0.0; for (j=0; j upper_limit[k]) index[k] = upper_limit[k]; index[k] -= lower_limit[k]; /* Save data for creation of multiple bit streams */ encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k]; } /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */ C = (index[0] + lower_limit[0]) * StepSize; for (k=0; k WebRtcIsac_kQKltMaxIndGain[k]) { index_g[k] = WebRtcIsac_kQKltMaxIndGain[k]; } index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[model][k]+index_g[k]; /* find quantization levels for coefficients */ tmpcoeffs_g[WebRtcIsac_kQKltSelIndGain[k]] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOfLevelsGain[model]+index_ovr_g[k]]; } } /* decode & dequantize LPC Coef */ int WebRtcIsac_DecodeLpcCoefUB( Bitstr* streamdata, double* lpcVecs, double* percepFilterGains, WebRtc_Word16 bandwidth) { int index_s[KLT_ORDER_SHAPE]; double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME]; int err; /* entropy decoding of quantization indices */ switch(bandwidth) { case isac12kHz: { err = WebRtcIsac_DecHistOneStepMulti(index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb12, WebRtcIsac_kLpcShapeEntropySearchUb12, UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME); break; } case isac16kHz: { err = WebRtcIsac_DecHistOneStepMulti(index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb16, WebRtcIsac_kLpcShapeEntropySearchUb16, UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME); break; } default: return -1; } if (err<0) // error check { return err; } WebRtcIsac_DequantizeLpcParam(index_s, lpcVecs, bandwidth); WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth); WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth); WebRtcIsac_AddLarMean(lpcVecs, bandwidth); WebRtcIsac_DecodeLpcGainUb(percepFilterGains, streamdata); if(bandwidth == isac16kHz) { // decode another set of Gains WebRtcIsac_DecodeLpcGainUb(&percepFilterGains[SUBFRAMES], streamdata); } return 0; } WebRtc_Word16 WebRtcIsac_EncodeBandwidth( enum ISACBandwidth bandwidth, Bitstr* streamData) { int bandwidthMode; switch(bandwidth) { case isac12kHz: { bandwidthMode = 0; break; } case isac16kHz: { bandwidthMode = 1; break; } default: return -ISAC_DISALLOWED_ENCODER_BANDWIDTH; } WebRtcIsac_EncHistMulti(streamData, &bandwidthMode, WebRtcIsac_kOneBitEqualProbCdf_ptr, 1); return 0; } WebRtc_Word16 WebRtcIsac_DecodeBandwidth( Bitstr* streamData, enum ISACBandwidth* bandwidth) { int bandwidthMode; if(WebRtcIsac_DecHistOneStepMulti(&bandwidthMode, streamData, WebRtcIsac_kOneBitEqualProbCdf_ptr, WebRtcIsac_kOneBitEqualProbInitIndex, 1) < 0) { // error check return -ISAC_RANGE_ERROR_DECODE_BANDWITH; } switch(bandwidthMode) { case 0: { *bandwidth = isac12kHz; break; } case 1: { *bandwidth = isac16kHz; break; } default: return -ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER; } return 0; } WebRtc_Word16 WebRtcIsac_EncodeJitterInfo( WebRtc_Word32 jitterIndex, Bitstr* streamData) { // This is to avoid LINUX warning until we change 'int' to // 'Word32' int intVar; if((jitterIndex < 0) || (jitterIndex > 1)) { return -1; } intVar = (int)(jitterIndex); // Use the same CDF table as for bandwidth // both take two values with equal probability WebRtcIsac_EncHistMulti(streamData, &intVar, WebRtcIsac_kOneBitEqualProbCdf_ptr, 1); return 0; } WebRtc_Word16 WebRtcIsac_DecodeJitterInfo( Bitstr* streamData, WebRtc_Word32* jitterInfo) { int intVar; // Use the same CDF table as for bandwidth // both take two values with equal probability if(WebRtcIsac_DecHistOneStepMulti(&intVar, streamData, WebRtcIsac_kOneBitEqualProbCdf_ptr, WebRtcIsac_kOneBitEqualProbInitIndex, 1) < 0) { // error check return -ISAC_RANGE_ERROR_DECODE_BANDWITH; } *jitterInfo = (WebRtc_Word16)(intVar); return 0; }