void WebRtcVad_Allpass(WebRtc_Word16 *in_vector, WebRtc_Word16 *out_vector, WebRtc_Word16 filter_coefficients, int vector_length, WebRtc_Word16 *filter_state) { // The filter can only cause overflow (in the w16 output variable) // if more than 4 consecutive input numbers are of maximum value and // has the the same sign as the impulse responses first taps. // First 6 taps of the impulse response: 0.6399 0.5905 -0.3779 // 0.2418 -0.1547 0.0990 int n; WebRtc_Word16 tmp16; WebRtc_Word32 tmp32, in32, state32; state32 = WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)(*filter_state)), 16); // Q31 for (n = 0; n < vector_length; n++) { tmp32 = state32 + WEBRTC_SPL_MUL_16_16(filter_coefficients, (*in_vector)); tmp16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 16); *out_vector++ = tmp16; in32 = WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)(*in_vector)), 14); state32 = in32 - WEBRTC_SPL_MUL_16_16(filter_coefficients, tmp16); state32 = WEBRTC_SPL_LSHIFT_W32(state32, 1); in_vector += 2; } *filter_state = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(state32, 16); }
/* The conversion is implemented by the step-down algorithm */ void WebRtcSpl_AToK_JSK( WebRtc_Word16 *a16, /* Q11 */ WebRtc_Word16 useOrder, WebRtc_Word16 *k16 /* Q15 */ ) { int m, k; WebRtc_Word32 tmp32[MAX_AR_MODEL_ORDER]; WebRtc_Word32 tmp32b; WebRtc_Word32 tmp_inv_denum32; WebRtc_Word16 tmp_inv_denum16; k16[useOrder-1]= WEBRTC_SPL_LSHIFT_W16(a16[useOrder], 4); //Q11<<4 => Q15 for (m=useOrder-1; m>0; m--) { tmp_inv_denum32 = ((WebRtc_Word32) 1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]); // (1 - k^2) in Q30 tmp_inv_denum16 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp_inv_denum32, 15); // (1 - k^2) in Q15 for (k=1; k<=m; k++) { tmp32b = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)a16[k], 16) - WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(k16[m], a16[m-k+1]), 1); tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12 } for (k=1; k<m; k++) { a16[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32[k], 1); //Q12>>1 => Q11 } tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092); k16[m-1] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmp32[m], 3); //Q12<<3 => Q15 } return; }
static __inline int32_t Log2Q8( uint32_t x ) { int32_t zeros, lg2; int16_t frac; zeros=WebRtcSpl_NormU32(x); frac=(int16_t)WEBRTC_SPL_RSHIFT_W32(((uint32_t)(WEBRTC_SPL_LSHIFT_W32(x, zeros))&0x7FFFFFFF), 23); /* log2(magn(i)) */ lg2= (WEBRTC_SPL_LSHIFT_W32((31-zeros), 8)+frac); return lg2; }
void WebRtcIlbcfix_CbMemEnergy(int16_t range, int16_t * CB, /* (i) The CB memory (1:st section) */ int16_t * filteredCB, /* (i) The filtered CB memory (2:nd section) */ int16_t lMem, /* (i) Length of the CB memory */ int16_t lTarget, /* (i) Length of the target vector */ int16_t * energyW16, /* (o) Energy in the CB vectors */ int16_t * energyShifts, /* (o) Shift value of the energy */ int16_t scale, /* (i) The scaling of all energy values */ int16_t base_size /* (i) Index to where the energy values should be stored */ ) { int16_t *ppi, *ppo, *pp; int32_t energy, tmp32; /* Compute the energy and store it in a vector. Also the * corresponding shift values are stored. The energy values * are reused in all three stages. */ /* Calculate the energy in the first block of 'lTarget' sampels. */ ppi = CB + lMem - lTarget - 1; ppo = CB + lMem - 1; pp = CB + lMem - lTarget; energy = WebRtcSpl_DotProductWithScale(pp, pp, lTarget, scale); /* Normalize the energy and store the number of shifts */ energyShifts[0] = (int16_t) WebRtcSpl_NormW32(energy); tmp32 = WEBRTC_SPL_LSHIFT_W32(energy, energyShifts[0]); energyW16[0] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32, 16); /* Compute the energy of the rest of the cb memory * by step wise adding and subtracting the next * sample and the last sample respectively. */ WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, 0); /* Next, precompute the energy values for the filtered cb section */ pp = filteredCB + lMem - lTarget; energy = WebRtcSpl_DotProductWithScale(pp, pp, lTarget, scale); /* Normalize the energy and store the number of shifts */ energyShifts[base_size] = (int16_t) WebRtcSpl_NormW32(energy); tmp32 = WEBRTC_SPL_LSHIFT_W32(energy, energyShifts[base_size]); energyW16[base_size] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32, 16); ppi = filteredCB + lMem - 1 - lTarget; ppo = filteredCB + lMem - 1; WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, base_size); }
void WebRtcSpl_LpcToReflCoef(int16_t* a16, int use_order, int16_t* k16) { int m, k; int32_t tmp32[SPL_LPC_TO_REFL_COEF_MAX_AR_MODEL_ORDER]; int32_t tmp_inv_denom32; int16_t tmp_inv_denom16; k16[use_order - 1] = a16[use_order] << 3; // Q12<<3 => Q15 for (m = use_order - 1; m > 0; m--) { // (1 - k^2) in Q30 tmp_inv_denom32 = 1073741823 - k16[m] * k16[m]; // (1 - k^2) in Q15 tmp_inv_denom16 = (int16_t)(tmp_inv_denom32 >> 15); for (k = 1; k <= m; k++) { // tmp[k] = (a[k] - RC[m] * a[m-k+1]) / (1.0 - RC[m]*RC[m]); // [Q12<<16 - (Q15*Q12)<<1] = [Q28 - Q28] = Q28 tmp32[k] = (a16[k] << 16) - (k16[m] * a16[m - k + 1] << 1); tmp32[k] = WebRtcSpl_DivW32W16(tmp32[k], tmp_inv_denom16); //Q28/Q15 = Q13 } for (k = 1; k < m; k++) { a16[k] = (int16_t)(tmp32[k] >> 1); // Q13>>1 => Q12 } tmp32[m] = WEBRTC_SPL_SAT(8191, tmp32[m], -8191); k16[m - 1] = (int16_t)WEBRTC_SPL_LSHIFT_W32(tmp32[m], 2); //Q13<<2 => Q15 } return; }
static __inline int32_t CalcLrIntQ(int32_t fixVal, int16_t qDomain) { int32_t intgr; int32_t roundVal; roundVal = WEBRTC_SPL_LSHIFT_W32((int32_t)1, qDomain - 1); intgr = WEBRTC_SPL_RSHIFT_W32(fixVal + roundVal, qDomain); return intgr; }
WebRtc_UWord32 WebRtcNetEQ_ScaleTimestampExternalToInternal(const MCUInst_t *MCU_inst, WebRtc_UWord32 externalTS) { WebRtc_Word32 timestampDiff; WebRtc_UWord32 internalTS; /* difference between this and last incoming timestamp */ timestampDiff = externalTS - MCU_inst->externalTS; switch (MCU_inst->scalingFactor) { case kTSscalingTwo: { /* multiply with 2 */ timestampDiff = WEBRTC_SPL_LSHIFT_W32(timestampDiff, 1); break; } case kTSscalingTwoThirds: { /* multiply with 2/3 */ timestampDiff = WEBRTC_SPL_LSHIFT_W32(timestampDiff, 1); timestampDiff = WebRtcSpl_DivW32W16(timestampDiff, 3); break; } case kTSscalingFourThirds: { /* multiply with 4/3 */ timestampDiff = WEBRTC_SPL_LSHIFT_W32(timestampDiff, 2); timestampDiff = WebRtcSpl_DivW32W16(timestampDiff, 3); break; } default: { /* no scaling */ } } /* add the scaled difference to last scaled timestamp and save ... */ internalTS = MCU_inst->internalTS + timestampDiff; return internalTS; }
void WebRtcSpl_SynthesisQMF(const int16_t* low_band, const int16_t* high_band, size_t band_length, int16_t* out_data, int32_t* filter_state1, int32_t* filter_state2) { int32_t tmp; int32_t half_in1[kMaxBandFrameLength]; int32_t half_in2[kMaxBandFrameLength]; int32_t filter1[kMaxBandFrameLength]; int32_t filter2[kMaxBandFrameLength]; size_t i; int16_t k; assert(band_length <= kMaxBandFrameLength); // Obtain the sum and difference channels out of upper and lower-band channels. // Also shift to Q10 domain. for (i = 0; i < band_length; i++) { tmp = (int32_t)low_band[i] + (int32_t)high_band[i]; half_in1[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10); tmp = (int32_t)low_band[i] - (int32_t)high_band[i]; half_in2[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10); } // all-pass filter the sum and difference channels WebRtcSpl_AllPassQMF(half_in1, band_length, filter1, WebRtcSpl_kAllPassFilter2, filter_state1); WebRtcSpl_AllPassQMF(half_in2, band_length, filter2, WebRtcSpl_kAllPassFilter1, filter_state2); // The filtered signals are even and odd samples of the output. Combine // them. The signals are Q10 should shift them back to Q0 and take care of // saturation. for (i = 0, k = 0; i < band_length; i++) { tmp = (filter2[i] + 512) >> 10; out_data[k++] = WebRtcSpl_SatW32ToW16(tmp); tmp = (filter1[i] + 512) >> 10; out_data[k++] = WebRtcSpl_SatW32ToW16(tmp); } }
void WebRtcSpl_AnalysisQMF(const int16_t* in_data, size_t in_data_length, int16_t* low_band, int16_t* high_band, int32_t* filter_state1, int32_t* filter_state2) { size_t i; int16_t k; int32_t tmp; int32_t half_in1[kMaxBandFrameLength]; int32_t half_in2[kMaxBandFrameLength]; int32_t filter1[kMaxBandFrameLength]; int32_t filter2[kMaxBandFrameLength]; const size_t band_length = in_data_length / 2; assert(in_data_length % 2 == 0); assert(band_length <= kMaxBandFrameLength); // Split even and odd samples. Also shift them to Q10. for (i = 0, k = 0; i < band_length; i++, k += 2) { half_in2[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)in_data[k], 10); half_in1[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)in_data[k + 1], 10); } // All pass filter even and odd samples, independently. WebRtcSpl_AllPassQMF(half_in1, band_length, filter1, WebRtcSpl_kAllPassFilter1, filter_state1); WebRtcSpl_AllPassQMF(half_in2, band_length, filter2, WebRtcSpl_kAllPassFilter2, filter_state2); // Take the sum and difference of filtered version of odd and even // branches to get upper & lower band. for (i = 0; i < band_length; i++) { tmp = (filter1[i] + filter2[i] + 1024) >> 11; low_band[i] = WebRtcSpl_SatW32ToW16(tmp); tmp = (filter1[i] - filter2[i] + 1024) >> 11; high_band[i] = WebRtcSpl_SatW32ToW16(tmp); } }
static __inline WebRtc_Word32 log2_Q8_LPC( WebRtc_UWord32 x ) { WebRtc_Word32 zeros, lg2; WebRtc_Word16 frac; zeros=WebRtcSpl_NormU32(x); frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23); /* log2(x) */ lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac); return lg2; }
static void AllpassFilterForDec32(WebRtc_Word16 *InOut16, //Q0 const WebRtc_Word32 *APSectionFactors, //Q15 WebRtc_Word16 lengthInOut, WebRtc_Word32 *FilterState) //Q16 { int n, j; WebRtc_Word32 a, b; for (j=0; j<ALLPASSSECTIONS; j++) { for (n=0;n<lengthInOut;n+=2){ a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15 a = WEBRTC_SPL_LSHIFT_W32(a, 1); // Q15 -> Q16 b = WEBRTC_SPL_ADD_SAT_W32(a, FilterState[j]); //Q16+Q16=Q16 a = WEBRTC_SPL_MUL_16_32_RSFT16( (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16), -APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15 FilterState[j] = WEBRTC_SPL_ADD_SAT_W32( WEBRTC_SPL_LSHIFT_W32(a,1), WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)InOut16[n], 16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16 InOut16[n] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0 } } }
void WebRtcIlbcfix_CbMemEnergyAugmentation( int16_t *interpSamples, /* (i) The interpolated samples */ int16_t *CBmem, /* (i) The CB memory */ int16_t scale, /* (i) The scaling of all energy values */ int16_t base_size, /* (i) Index to where the energy values should be stored */ int16_t *energyW16, /* (o) Energy in the CB vectors */ int16_t *energyShifts /* (o) Shift value of the energy */ ){ int32_t energy, tmp32; int16_t *ppe, *pp, *interpSamplesPtr; int16_t *CBmemPtr, lagcount; int16_t *enPtr=&energyW16[base_size-20]; int16_t *enShPtr=&energyShifts[base_size-20]; int32_t nrjRecursive; CBmemPtr = CBmem+147; interpSamplesPtr = interpSamples; /* Compute the energy for the first (low-5) noninterpolated samples */ nrjRecursive = WebRtcSpl_DotProductWithScale( CBmemPtr-19, CBmemPtr-19, 15, scale); ppe = CBmemPtr - 20; for (lagcount=20; lagcount<=39; lagcount++) { /* Update the energy recursively to save complexity */ nrjRecursive = nrjRecursive + WEBRTC_SPL_MUL_16_16_RSFT(*ppe, *ppe, scale); ppe--; energy = nrjRecursive; /* interpolation */ energy += WebRtcSpl_DotProductWithScale(interpSamplesPtr, interpSamplesPtr, 4, scale); interpSamplesPtr += 4; /* Compute energy for the remaining samples */ pp = CBmemPtr - lagcount; energy += WebRtcSpl_DotProductWithScale(pp, pp, SUBL-lagcount, scale); /* Normalize the energy and store the number of shifts */ (*enShPtr) = (int16_t)WebRtcSpl_NormW32(energy); tmp32 = WEBRTC_SPL_LSHIFT_W32(energy, (*enShPtr)); (*enPtr) = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32, 16); enShPtr++; enPtr++; } }
/* Compute the energy of the rest of the cb memory * by step wise adding and subtracting the next * sample and the last sample respectively */ void WebRtcIlbcfix_CbMemEnergyCalc( WebRtc_Word32 energy, /* (i) input start energy */ WebRtc_Word16 range, /* (i) number of iterations */ WebRtc_Word16 *ppi, /* (i) input pointer 1 */ WebRtc_Word16 *ppo, /* (i) input pointer 2 */ WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */ WebRtc_Word16 *energyShifts, /* (o) Shift value of the energy */ WebRtc_Word16 scale, /* (i) The scaling of all energy values */ WebRtc_Word16 base_size /* (i) Index to where the energy values should be stored */ ) { WebRtc_Word16 j,shft; WebRtc_Word32 tmp; WebRtc_Word16 *eSh_ptr; WebRtc_Word16 *eW16_ptr; eSh_ptr = &energyShifts[1+base_size]; eW16_ptr = &energyW16[1+base_size]; for(j=0;j<range-1;j++) { /* Calculate next energy by a +/- operation on the edge samples */ tmp = WEBRTC_SPL_MUL_16_16(*ppi, *ppi); tmp -= WEBRTC_SPL_MUL_16_16(*ppo, *ppo); energy += WEBRTC_SPL_RSHIFT_W32(tmp, scale); energy = WEBRTC_SPL_MAX(energy, 0); ppi--; ppo--; /* Normalize the energy into a WebRtc_Word16 and store the number of shifts */ shft = (WebRtc_Word16)WebRtcSpl_NormW32(energy); *eSh_ptr++ = shft; tmp = WEBRTC_SPL_LSHIFT_W32(energy, shft); *eW16_ptr++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp, 16); } }
/* Compute the energy of the rest of the cb memory * by step wise adding and subtracting the next * sample and the last sample respectively */ void WebRtcIlbcfix_CbMemEnergyCalc( int32_t energy, /* (i) input start energy */ int16_t range, /* (i) number of iterations */ int16_t *ppi, /* (i) input pointer 1 */ int16_t *ppo, /* (i) input pointer 2 */ int16_t *energyW16, /* (o) Energy in the CB vectors */ int16_t *energyShifts, /* (o) Shift value of the energy */ int16_t scale, /* (i) The scaling of all energy values */ int16_t base_size /* (i) Index to where the energy values should be stored */ ) { int16_t j,shft; int32_t tmp; int16_t *eSh_ptr; int16_t *eW16_ptr; eSh_ptr = &energyShifts[1+base_size]; eW16_ptr = &energyW16[1+base_size]; for(j=0;j<range-1;j++) { /* Calculate next energy by a +/- operation on the edge samples */ tmp = (*ppi) * (*ppi) - (*ppo) * (*ppo); energy += tmp >> scale; energy = WEBRTC_SPL_MAX(energy, 0); ppi--; ppo--; /* Normalize the energy into a int16_t and store the number of shifts */ shft = (int16_t)WebRtcSpl_NormW32(energy); *eSh_ptr++ = shft; tmp = WEBRTC_SPL_LSHIFT_W32(energy, shft); *eW16_ptr++ = (int16_t)(tmp >> 16); } }
void WebRtcIsacfix_DecimateAllpass32(const WebRtc_Word16 *in, WebRtc_Word32 *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */ WebRtc_Word16 N, /* number of input samples */ WebRtc_Word16 *out) /* array of size N/2 */ { int n; WebRtc_Word16 data_vec[PITCH_FRAME_LEN]; /* copy input */ memcpy(data_vec+1, in, WEBRTC_SPL_MUL_16_16(sizeof(WebRtc_Word16), (N-1))); data_vec[0] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)],16); //the z^(-1) state state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)] = WEBRTC_SPL_LSHIFT_W32((WebRtc_UWord32)in[N-1],16); AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in); AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS); for (n=0;n<N/2;n++) { out[n]=WEBRTC_SPL_ADD_SAT_W16(data_vec[WEBRTC_SPL_MUL_16_16(2, n)], data_vec[WEBRTC_SPL_MUL_16_16(2, n)+1]); } }
void WebRtcIsacfix_PitchFilter(int16_t* indatQQ, // Q10 if type is 1 or 4, // Q0 if type is 2. int16_t* outdatQQ, PitchFiltstr* pfp, int16_t* lagsQ7, int16_t* gainsQ12, int16_t type) { int k, ind, cnt; int16_t sign = 1; int16_t inystateQQ[PITCH_DAMPORDER]; int16_t ubufQQ[PITCH_INTBUFFSIZE + QLOOKAHEAD]; const int16_t Gain = 21299; // 1.3 in Q14 int16_t oldLagQ7; int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12; int indW32 = 0, frcQQ = 0; int32_t tmpW32; const int16_t* fracoeffQQ = NULL; // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM(). COMPILE_ASSERT(PITCH_FRACORDER == 9); COMPILE_ASSERT(PITCH_DAMPORDER == 5); // Set up buffer and states. memcpy(ubufQQ, pfp->ubufQQ, sizeof(pfp->ubufQQ)); memcpy(inystateQQ, pfp->ystateQQ, sizeof(inystateQQ)); // Get old lag and gain value from memory. oldLagQ7 = pfp->oldlagQ7; oldGainQ12 = pfp->oldgainQ12; if (type == 4) { sign = -1; // Make output more periodic. for (k = 0; k < PITCH_SUBFRAMES; k++) { gainsQ12[k] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( gainsQ12[k], Gain, 14); } } // No interpolation if pitch lag step is big. if ((WEBRTC_SPL_MUL_16_16_RSFT(lagsQ7[0], 3, 1) < oldLagQ7) || (lagsQ7[0] > WEBRTC_SPL_MUL_16_16_RSFT(oldLagQ7, 3, 1))) { oldLagQ7 = lagsQ7[0]; oldGainQ12 = gainsQ12[0]; } ind = 0; for (k = 0; k < PITCH_SUBFRAMES; k++) { // Calculate interpolation steps. lagdeltaQ7 = lagsQ7[k] - oldLagQ7; lagdeltaQ7 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( lagdeltaQ7, kDivFactor, 15); curLagQ7 = oldLagQ7; gaindeltaQ12 = gainsQ12[k] - oldGainQ12; gaindeltaQ12 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( gaindeltaQ12, kDivFactor, 15); curGainQ12 = oldGainQ12; oldLagQ7 = lagsQ7[k]; oldGainQ12 = gainsQ12[k]; // Each frame has 4 60-sample pitch subframes, and each subframe has 5 // 12-sample segments. Each segment need to be processed with // newly-updated parameters, so we break the pitch filtering into // two for-loops (5 x 12) below. It's also why kDivFactor = 0.2 (in Q15). for (cnt = 0; cnt < kSegments; cnt++) { // Update parameters for each segment. curGainQ12 += gaindeltaQ12; curLagQ7 += lagdeltaQ7; indW32 = CalcLrIntQ(curLagQ7, 7); tmpW32 = WEBRTC_SPL_LSHIFT_W32(indW32, 7); tmpW32 -= curLagQ7; frcQQ = WEBRTC_SPL_RSHIFT_W32(tmpW32, 4); frcQQ += 4; if (frcQQ == PITCH_FRACS) { frcQQ = 0; } fracoeffQQ = kIntrpCoef[frcQQ]; // Pitch filtering. WebRtcIsacfix_PitchFilterCore(PITCH_SUBFRAME_LEN / kSegments, curGainQ12, indW32, sign, inystateQQ, ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind); } } // Export buffer and states. memcpy(pfp->ubufQQ, ubufQQ + PITCH_FRAME_LEN, sizeof(pfp->ubufQQ)); memcpy(pfp->ystateQQ, inystateQQ, sizeof(pfp->ystateQQ)); pfp->oldlagQ7 = oldLagQ7; pfp->oldgainQ12 = oldGainQ12; if (type == 2) { // Filter look-ahead segment. WebRtcIsacfix_PitchFilterCore(QLOOKAHEAD, curGainQ12, indW32, 1, inystateQQ, ubufQQ, fracoeffQQ, indatQQ, outdatQQ, &ind); } }
void WebRtcIsacfix_Time2SpecC(int16_t *inre1Q9, int16_t *inre2Q9, int16_t *outreQ7, int16_t *outimQ7) { int k; int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2]; int16_t tmp1rQ14, tmp1iQ14; int32_t xrQ16, xiQ16, yrQ16, yiQ16; int32_t v1Q16, v2Q16; int16_t factQ19, sh; /* Multiply with complex exponentials and combine into one complex vector */ factQ19 = 16921; // 0.5/sqrt(240) in Q19 is round(.5/sqrt(240)*(2^19)) = 16921 for (k = 0; k < FRAMESAMPLES/2; k++) { tmp1rQ14 = WebRtcIsacfix_kCosTab1[k]; tmp1iQ14 = WebRtcIsacfix_kSinTab1[k]; xrQ16 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(tmp1rQ14, inre1Q9[k]) + WEBRTC_SPL_MUL_16_16(tmp1iQ14, inre2Q9[k]), 7); xiQ16 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(tmp1rQ14, inre2Q9[k]) - WEBRTC_SPL_MUL_16_16(tmp1iQ14, inre1Q9[k]), 7); tmpreQ16[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xrQ16)+4, 3); // (Q16*Q19>>16)>>3 = Q16 tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xiQ16)+4, 3); // (Q16*Q19>>16)>>3 = Q16 } xrQ16 = WebRtcSpl_MaxAbsValueW32(tmpreQ16, FRAMESAMPLES/2); yrQ16 = WebRtcSpl_MaxAbsValueW32(tmpimQ16, FRAMESAMPLES/2); if (yrQ16>xrQ16) { xrQ16 = yrQ16; } sh = WebRtcSpl_NormW32(xrQ16); sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh) //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh) //"Fastest" vectors if (sh>=0) { for (k=0; k<FRAMESAMPLES/2; k++) { inre1Q9[k] = (int16_t) WEBRTC_SPL_LSHIFT_W32(tmpreQ16[k], sh); //Q(16+sh) inre2Q9[k] = (int16_t) WEBRTC_SPL_LSHIFT_W32(tmpimQ16[k], sh); //Q(16+sh) } } else { int32_t round = WEBRTC_SPL_LSHIFT_W32((int32_t)1, -sh-1); for (k=0; k<FRAMESAMPLES/2; k++) { inre1Q9[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmpreQ16[k]+round, -sh); //Q(16+sh) inre2Q9[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmpimQ16[k]+round, -sh); //Q(16+sh) } } /* Get DFT */ WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call //"Fastest" vectors if (sh>=0) { for (k=0; k<FRAMESAMPLES/2; k++) { tmpreQ16[k] = WEBRTC_SPL_RSHIFT_W32((int32_t)inre1Q9[k], sh); //Q(16+sh) -> Q16 tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32((int32_t)inre2Q9[k], sh); //Q(16+sh) -> Q16 } } else { for (k=0; k<FRAMESAMPLES/2; k++) { tmpreQ16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)inre1Q9[k], -sh); //Q(16+sh) -> Q16 tmpimQ16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)inre2Q9[k], -sh); //Q(16+sh) -> Q16 } } /* Use symmetry to separate into two complex vectors and center frames in time around zero */ for (k = 0; k < FRAMESAMPLES/4; k++) { xrQ16 = tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k]; yiQ16 = -tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k]; xiQ16 = tmpimQ16[k] - tmpimQ16[FRAMESAMPLES/2 - 1 - k]; yrQ16 = tmpimQ16[k] + tmpimQ16[FRAMESAMPLES/2 - 1 - k]; tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k]; tmp1iQ14 = WebRtcIsacfix_kSinTab2[k]; v1Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xiQ16); v2Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xiQ16); outreQ7[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(v1Q16, 9); outimQ7[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(v2Q16, 9); v1Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yiQ16); v2Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yiQ16); outreQ7[FRAMESAMPLES/2 - 1 - k] = (int16_t)WEBRTC_SPL_RSHIFT_W32(v1Q16, 9); //CalcLrIntQ(v1Q16, 9); outimQ7[FRAMESAMPLES/2 - 1 - k] = (int16_t)WEBRTC_SPL_RSHIFT_W32(v2Q16, 9); //CalcLrIntQ(v2Q16, 9); } }
void WebRtcIsacfix_Spec2TimeC(int16_t *inreQ7, int16_t *inimQ7, int32_t *outre1Q16, int32_t *outre2Q16) { int k; int16_t tmp1rQ14, tmp1iQ14; int32_t xrQ16, xiQ16, yrQ16, yiQ16; int32_t tmpInRe, tmpInIm, tmpInRe2, tmpInIm2; int16_t factQ11; int16_t sh; for (k = 0; k < FRAMESAMPLES/4; k++) { /* Move zero in time to beginning of frames */ tmp1rQ14 = -WebRtcIsacfix_kSinTab2[FRAMESAMPLES/4 - 1 - k]; tmp1iQ14 = WebRtcIsacfix_kSinTab2[k]; tmpInRe = WEBRTC_SPL_LSHIFT_W32((int32_t) inreQ7[k], 9); // Q7 -> Q16 tmpInIm = WEBRTC_SPL_LSHIFT_W32((int32_t) inimQ7[k], 9); // Q7 -> Q16 tmpInRe2 = WEBRTC_SPL_LSHIFT_W32((int32_t) inreQ7[FRAMESAMPLES/2 - 1 - k], 9); // Q7 -> Q16 tmpInIm2 = WEBRTC_SPL_LSHIFT_W32((int32_t) inimQ7[FRAMESAMPLES/2 - 1 - k], 9); // Q7 -> Q16 xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm); xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe); yrQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm2) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe2); yiQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe2) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm2); /* Combine into one vector, z = x + j * y */ outre1Q16[k] = xrQ16 - yiQ16; outre1Q16[FRAMESAMPLES/2 - 1 - k] = xrQ16 + yiQ16; outre2Q16[k] = xiQ16 + yrQ16; outre2Q16[FRAMESAMPLES/2 - 1 - k] = -xiQ16 + yrQ16; } /* Get IDFT */ tmpInRe = WebRtcSpl_MaxAbsValueW32(outre1Q16, 240); tmpInIm = WebRtcSpl_MaxAbsValueW32(outre2Q16, 240); if (tmpInIm>tmpInRe) { tmpInRe = tmpInIm; } sh = WebRtcSpl_NormW32(tmpInRe); sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh) //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh) //"Fastest" vectors if (sh>=0) { for (k=0; k<240; k++) { inreQ7[k] = (int16_t) WEBRTC_SPL_LSHIFT_W32(outre1Q16[k], sh); //Q(16+sh) inimQ7[k] = (int16_t) WEBRTC_SPL_LSHIFT_W32(outre2Q16[k], sh); //Q(16+sh) } } else { int32_t round = WEBRTC_SPL_LSHIFT_W32((int32_t)1, -sh-1); for (k=0; k<240; k++) { inreQ7[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(outre1Q16[k]+round, -sh); //Q(16+sh) inimQ7[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(outre2Q16[k]+round, -sh); //Q(16+sh) } } WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call //"Fastest" vectors if (sh>=0) { for (k=0; k<240; k++) { outre1Q16[k] = WEBRTC_SPL_RSHIFT_W32((int32_t)inreQ7[k], sh); //Q(16+sh) -> Q16 outre2Q16[k] = WEBRTC_SPL_RSHIFT_W32((int32_t)inimQ7[k], sh); //Q(16+sh) -> Q16 } } else { for (k=0; k<240; k++) { outre1Q16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)inreQ7[k], -sh); //Q(16+sh) -> Q16 outre2Q16[k] = WEBRTC_SPL_LSHIFT_W32((int32_t)inimQ7[k], -sh); //Q(16+sh) -> Q16 } } /* Divide through by the normalizing constant: */ /* scale all values with 1/240, i.e. with 273 in Q16 */ /* 273/65536 ~= 0.0041656 */ /* 1/240 ~= 0.0041666 */ for (k=0; k<240; k++) { outre1Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre1Q16[k]); outre2Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k]); } /* Demodulate and separate */ factQ11 = 31727; // sqrt(240) in Q11 is round(15.49193338482967*2048) = 31727 for (k = 0; k < FRAMESAMPLES/2; k++) { tmp1rQ14 = WebRtcIsacfix_kCosTab1[k]; tmp1iQ14 = WebRtcIsacfix_kSinTab1[k]; xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre1Q16[k]) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre2Q16[k]); xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre2Q16[k]) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre1Q16[k]); xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16); xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16); outre2Q16[k] = xiQ16; outre1Q16[k] = xrQ16; } }
static void PCorr2Q32(const int16_t *in, int32_t *logcorQ8) { int16_t scaling,n,k; int32_t ysum32,csum32, lys, lcs; int32_t oneQ8; const int16_t *x, *inptr; oneQ8 = WEBRTC_SPL_LSHIFT_W32((int32_t)1, 8); // 1.00 in Q8 x = in + PITCH_MAX_LAG/2 + 2; scaling = WebRtcSpl_GetScalingSquare ((int16_t *) in, PITCH_CORR_LEN2, PITCH_CORR_LEN2); ysum32 = 1; csum32 = 0; x = in + PITCH_MAX_LAG/2 + 2; for (n = 0; n < PITCH_CORR_LEN2; n++) { ysum32 += WEBRTC_SPL_MUL_16_16_RSFT( (int16_t) in[n],(int16_t) in[n], scaling); // Q0 csum32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t) x[n],(int16_t) in[n], scaling); // Q0 } logcorQ8 += PITCH_LAG_SPAN2 - 1; lys=Log2Q8((uint32_t) ysum32); // Q8 lys=WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum); if (csum32>0) { lcs=Log2Q8((uint32_t) csum32); // 2log(csum) in Q8 if (lcs>(lys + oneQ8) ){ // csum/sqrt(ysum) > 2 in Q8 *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum)) } else { *logcorQ8 = oneQ8; // 1.00 } } else { *logcorQ8 = 0; } for (k = 1; k < PITCH_LAG_SPAN2; k++) { inptr = &in[k]; ysum32 -= WEBRTC_SPL_MUL_16_16_RSFT( (int16_t) in[k-1],(int16_t) in[k-1], scaling); ysum32 += WEBRTC_SPL_MUL_16_16_RSFT( (int16_t) in[PITCH_CORR_LEN2 + k - 1],(int16_t) in[PITCH_CORR_LEN2 + k - 1], scaling); #ifdef WEBRTC_ARCH_ARM_NEON { int32_t vbuff[4]; int32x4_t int_32x4_sum = vmovq_n_s32(0); // Can't shift a Neon register to right with a non-constant shift value. int32x4_t int_32x4_scale = vdupq_n_s32(-scaling); // Assert a codition used in loop unrolling at compile-time. COMPILE_ASSERT(PITCH_CORR_LEN2 %4 == 0); for (n = 0; n < PITCH_CORR_LEN2; n += 4) { int16x4_t int_16x4_x = vld1_s16(&x[n]); int16x4_t int_16x4_in = vld1_s16(&inptr[n]); int32x4_t int_32x4 = vmull_s16(int_16x4_x, int_16x4_in); int_32x4 = vshlq_s32(int_32x4, int_32x4_scale); int_32x4_sum = vaddq_s32(int_32x4_sum, int_32x4); } // Use vector store to avoid long stall from data trasferring // from vector to general register. vst1q_s32(vbuff, int_32x4_sum); csum32 = vbuff[0] + vbuff[1]; csum32 += vbuff[2]; csum32 += vbuff[3]; } #else csum32 = 0; if(scaling == 0) { for (n = 0; n < PITCH_CORR_LEN2; n++) { csum32 += x[n] * inptr[n]; } } else { for (n = 0; n < PITCH_CORR_LEN2; n++) { csum32 += (x[n] * inptr[n]) >> scaling; } } #endif logcorQ8--; lys=Log2Q8((uint32_t)ysum32); // Q8 lys=WEBRTC_SPL_RSHIFT_W32(lys, 1); //sqrt(ysum); if (csum32>0) { lcs=Log2Q8((uint32_t) csum32); // 2log(csum) in Q8 if (lcs>(lys + oneQ8) ){ // csum/sqrt(ysum) > 2 *logcorQ8 = lcs - lys; // log2(csum/sqrt(ysum)) } else { *logcorQ8 = oneQ8; // 1.00 } } else { *logcorQ8 = 0; } } }
int WebRtcNetEQ_RTCPGetStats(WebRtcNetEQ_RTCP_t *RTCP_inst, uint16_t *puw16_fraction_lost, uint32_t *puw32_cum_lost, uint32_t *puw32_ext_max, uint32_t *puw32_jitter, int16_t doNotReset) { uint32_t uw32_exp_nr, uw32_exp_interval, uw32_rec_interval; int32_t w32_lost; /* Extended highest sequence number received */ *puw32_ext_max = (uint32_t) WEBRTC_SPL_LSHIFT_W32((uint32_t)RTCP_inst->cycles, 16) + RTCP_inst->max_seq; /* * Calculate expected number of packets and compare it to the number of packets that * were actually received => the cumulative number of packets lost can be extracted. */ uw32_exp_nr = *puw32_ext_max - RTCP_inst->base_seq + 1; if (RTCP_inst->received == 0) { /* no packets received, assume none lost */ *puw32_cum_lost = 0; } else if (uw32_exp_nr > RTCP_inst->received) { *puw32_cum_lost = uw32_exp_nr - RTCP_inst->received; if (*puw32_cum_lost > (uint32_t) 0xFFFFFF) { *puw32_cum_lost = 0xFFFFFF; } } else { *puw32_cum_lost = 0; } /* Fraction lost (Since last report) */ uw32_exp_interval = uw32_exp_nr - RTCP_inst->exp_prior; if (!doNotReset) { RTCP_inst->exp_prior = uw32_exp_nr; } uw32_rec_interval = RTCP_inst->received - RTCP_inst->rec_prior; if (!doNotReset) { RTCP_inst->rec_prior = RTCP_inst->received; } w32_lost = (int32_t) (uw32_exp_interval - uw32_rec_interval); if (uw32_exp_interval == 0 || w32_lost <= 0 || RTCP_inst->received == 0) { *puw16_fraction_lost = 0; } else { *puw16_fraction_lost = (uint16_t) (WEBRTC_SPL_LSHIFT_W32(w32_lost, 8) / uw32_exp_interval); } if (*puw16_fraction_lost > 0xFF) { *puw16_fraction_lost = 0xFF; } /* Inter-arrival jitter */ *puw32_jitter = (RTCP_inst->jitter) >> 4; /* scaling from Q4 */ return 0; }
void WebRtcIsacfix_InitialPitch(const int16_t *in, /* Q0 */ PitchAnalysisStruct *State, int16_t *lagsQ7 /* Q7 */ ) { int16_t buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2]; int32_t *crrvecQ8_1,*crrvecQ8_2; int32_t cv1q[PITCH_LAG_SPAN2+2],cv2q[PITCH_LAG_SPAN2+2], peakvq[PITCH_LAG_SPAN2+2]; int k; int16_t peaks_indq; int16_t peakiq[PITCH_LAG_SPAN2]; int32_t corr; int32_t corr32, corr_max32, corr_max_o32; int16_t npkq; int16_t best4q[4]={0,0,0,0}; int32_t xq[3],yq[1],fyq[1]; int32_t *fxq; int32_t best_lag1q, best_lag2q; int32_t tmp32a,tmp32b,lag32,ratq; int16_t start; int16_t oldgQ12, tmp16a, tmp16b, gain_bias16,tmp16c, tmp16d, bias16; int32_t tmp32c,tmp32d, tmp32e; int16_t old_lagQ; int32_t old_lagQ8; int32_t lagsQ8[4]; old_lagQ = State->PFstr_wght.oldlagQ7; // Q7 old_lagQ8= WEBRTC_SPL_LSHIFT_W32((int32_t)old_lagQ,1); //Q8 oldgQ12= State->PFstr_wght.oldgainQ12; crrvecQ8_1=&cv1q[1]; crrvecQ8_2=&cv2q[1]; /* copy old values from state buffer */ memcpy(buf_dec16, State->dec_buffer16, WEBRTC_SPL_MUL_16_16(sizeof(int16_t), (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2))); /* decimation; put result after the old values */ WebRtcIsacfix_DecimateAllpass32(in, State->decimator_state32, PITCH_FRAME_LEN, &buf_dec16[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]); /* low-pass filtering */ start= PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; WebRtcSpl_FilterARFastQ12(&buf_dec16[start],&buf_dec16[start],(int16_t*)kACoefQ12,3, PITCH_FRAME_LEN/2); /* copy end part back into state buffer */ for (k = 0; k < (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2); k++) State->dec_buffer16[k] = buf_dec16[k+PITCH_FRAME_LEN/2]; /* compute correlation for first and second half of the frame */ PCorr2Q32(buf_dec16, crrvecQ8_1); PCorr2Q32(buf_dec16 + PITCH_CORR_STEP2, crrvecQ8_2); /* bias towards pitch lag of previous frame */ tmp32a = Log2Q8((uint32_t) old_lagQ8) - 2304; // log2(0.5*oldlag) in Q8 tmp32b = WEBRTC_SPL_MUL_16_16_RSFT(oldgQ12,oldgQ12, 10); //Q12 & * 4.0; gain_bias16 = (int16_t) tmp32b; //Q12 if (gain_bias16 > 3276) gain_bias16 = 3276; // 0.8 in Q12 for (k = 0; k < PITCH_LAG_SPAN2; k++) { if (crrvecQ8_1[k]>0) { tmp32b = Log2Q8((uint32_t) (k + (PITCH_MIN_LAG/2-2))); tmp16a = (int16_t) (tmp32b - tmp32a); // Q8 & fabs(ratio)<4 tmp32c = WEBRTC_SPL_MUL_16_16_RSFT(tmp16a,tmp16a, 6); //Q10 tmp16b = (int16_t) tmp32c; // Q10 & <8 tmp32d = WEBRTC_SPL_MUL_16_16_RSFT(tmp16b, 177 , 8); // mult with ln2 in Q8 tmp16c = (int16_t) tmp32d; // Q10 & <4 tmp16d = Exp2Q10((int16_t) -tmp16c); //Q10 tmp32c = WEBRTC_SPL_MUL_16_16_RSFT(gain_bias16,tmp16d,13); // Q10 & * 0.5 bias16 = (int16_t) (1024 + tmp32c); // Q10 tmp32b = Log2Q8((uint32_t) bias16) - 2560; // Q10 in -> Q8 out with 10*2^8 offset crrvecQ8_1[k] += tmp32b ; // -10*2^8 offset } } /* taper correlation functions */ for (k = 0; k < 3; k++) { crrvecQ8_1[k] += kLogLagWinQ8[k]; crrvecQ8_2[k] += kLogLagWinQ8[k]; crrvecQ8_1[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k]; crrvecQ8_2[PITCH_LAG_SPAN2-1-k] += kLogLagWinQ8[k]; } /* Make zeropadded corr vectors */ cv1q[0]=0; cv2q[0]=0; cv1q[PITCH_LAG_SPAN2+1]=0; cv2q[PITCH_LAG_SPAN2+1]=0; corr_max32 = 0; for (k = 1; k <= PITCH_LAG_SPAN2; k++) { corr32=crrvecQ8_1[k-1]; if (corr32 > corr_max32) corr_max32 = corr32; corr32=crrvecQ8_2[k-1]; corr32 += -4; // Compensate for later (log2(0.99)) if (corr32 > corr_max32) corr_max32 = corr32; } /* threshold value to qualify as a peak */ // corr_max32 += -726; // log(0.14)/log(2.0) in Q8 corr_max32 += -1000; // log(0.14)/log(2.0) in Q8 corr_max_o32 = corr_max32; /* find peaks in corr1 */ peaks_indq = 0; for (k = 1; k <= PITCH_LAG_SPAN2; k++) { corr32=cv1q[k]; if (corr32>corr_max32) { // Disregard small peaks if ((corr32>=cv1q[k-1]) && (corr32>cv1q[k+1])) { // Peak? peakvq[peaks_indq] = corr32; peakiq[peaks_indq++] = k; } } } /* find highest interpolated peak */ corr_max32=0; best_lag1q =0; if (peaks_indq > 0) { FindFour32(peakvq, (int16_t) peaks_indq, best4q); npkq = WEBRTC_SPL_MIN(peaks_indq, 4); for (k=0;k<npkq;k++) { lag32 = peakiq[best4q[k]]; fxq = &cv1q[peakiq[best4q[k]]-1]; xq[0]= lag32; xq[0] = WEBRTC_SPL_LSHIFT_W32(xq[0], 8); Intrp1DQ8(xq, fxq, yq, fyq); tmp32a= Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8 /* Bias towards short lags */ /* log(pow(0.8, log(2.0 * *y )))/log(2.0) */ tmp32b= WEBRTC_SPL_MUL_16_16_RSFT((int16_t) tmp32a, -42, 8); tmp32c= tmp32b + 256; *fyq += tmp32c; if (*fyq > corr_max32) { corr_max32 = *fyq; best_lag1q = *yq; } } tmp32a = best_lag1q - OFFSET_Q8; tmp32b = WEBRTC_SPL_LSHIFT_W32(tmp32a, 1); lagsQ8[0] = tmp32b + PITCH_MIN_LAG_Q8; lagsQ8[1] = lagsQ8[0]; } else { lagsQ8[0] = old_lagQ8; lagsQ8[1] = lagsQ8[0]; } /* Bias towards constant pitch */ tmp32a = lagsQ8[0] - PITCH_MIN_LAG_Q8; ratq = WEBRTC_SPL_RSHIFT_W32(tmp32a, 1) + OFFSET_Q8; for (k = 1; k <= PITCH_LAG_SPAN2; k++) { tmp32a = WEBRTC_SPL_LSHIFT_W32(k, 7); // 0.5*k Q8 tmp32b = (int32_t) (WEBRTC_SPL_LSHIFT_W32(tmp32a, 1)) - ratq; // Q8 tmp32c = WEBRTC_SPL_MUL_16_16_RSFT((int16_t) tmp32b, (int16_t) tmp32b, 8); // Q8 tmp32b = (int32_t) tmp32c + (int32_t) WEBRTC_SPL_RSHIFT_W32(ratq, 1); // (k-r)^2 + 0.5 * r Q8 tmp32c = Log2Q8((uint32_t) tmp32a) - 2048; // offset 8*2^8 , log2(0.5*k) Q8 tmp32d = Log2Q8((uint32_t) tmp32b) - 2048; // offset 8*2^8 , log2(0.5*k) Q8 tmp32e = tmp32c -tmp32d; cv2q[k] += WEBRTC_SPL_RSHIFT_W32(tmp32e, 1); } /* find peaks in corr2 */ corr_max32 = corr_max_o32; peaks_indq = 0; for (k = 1; k <= PITCH_LAG_SPAN2; k++) { corr=cv2q[k]; if (corr>corr_max32) { // Disregard small peaks if ((corr>=cv2q[k-1]) && (corr>cv2q[k+1])) { // Peak? peakvq[peaks_indq] = corr; peakiq[peaks_indq++] = k; } } } /* find highest interpolated peak */ corr_max32 = 0; best_lag2q =0; if (peaks_indq > 0) { FindFour32(peakvq, (int16_t) peaks_indq, best4q); npkq = WEBRTC_SPL_MIN(peaks_indq, 4); for (k=0;k<npkq;k++) { lag32 = peakiq[best4q[k]]; fxq = &cv2q[peakiq[best4q[k]]-1]; xq[0]= lag32; xq[0] = WEBRTC_SPL_LSHIFT_W32(xq[0], 8); Intrp1DQ8(xq, fxq, yq, fyq); /* Bias towards short lags */ /* log(pow(0.8, log(2.0f * *y )))/log(2.0f) */ tmp32a= Log2Q8((uint32_t) *yq) - 2048; // offset 8*2^8 tmp32b= WEBRTC_SPL_MUL_16_16_RSFT((int16_t) tmp32a, -82, 8); tmp32c= tmp32b + 256; *fyq += tmp32c; if (*fyq > corr_max32) { corr_max32 = *fyq; best_lag2q = *yq; } } tmp32a = best_lag2q - OFFSET_Q8; tmp32b = WEBRTC_SPL_LSHIFT_W32(tmp32a, 1); lagsQ8[2] = tmp32b + PITCH_MIN_LAG_Q8; lagsQ8[3] = lagsQ8[2]; } else { lagsQ8[2] = lagsQ8[0]; lagsQ8[3] = lagsQ8[0]; } lagsQ7[0]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[0], 1); lagsQ7[1]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[1], 1); lagsQ7[2]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[2], 1); lagsQ7[3]=(int16_t) WEBRTC_SPL_RSHIFT_W32(lagsQ8[3], 1); }
// Update the noise estimation information. static void UpdateNoiseEstimateNeon(NsxInst_t* inst, int offset) { // int i = 0; const int16_t kExp2Const = 11819; // Q13 int16_t* ptr_noiseEstLogQuantile = NULL; int16_t* ptr_noiseEstQuantile = NULL; int16x4_t kExp2Const16x4 = vdup_n_s16(kExp2Const); int32x4_t twentyOne32x4 = vdupq_n_s32(21); int32x4_t constA32x4 = vdupq_n_s32(0x1fffff); int32x4_t constB32x4 = vdupq_n_s32(0x200000); int16_t tmp16 = WebRtcSpl_MaxValueW16(inst->noiseEstLogQuantile + offset, inst->magnLen); // Guarantee a Q-domain as high as possible and still fit in int16 inst->qNoise = 14 - (int) WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2Const, tmp16, 21); int32x4_t qNoise32x4 = vdupq_n_s32(inst->qNoise); for (ptr_noiseEstLogQuantile = &inst->noiseEstLogQuantile[offset], ptr_noiseEstQuantile = &inst->noiseEstQuantile[0]; ptr_noiseEstQuantile < &inst->noiseEstQuantile[inst->magnLen - 3]; ptr_noiseEstQuantile += 4, ptr_noiseEstLogQuantile += 4) { // tmp32no2 = WEBRTC_SPL_MUL_16_16(kExp2Const, // inst->noiseEstLogQuantile[offset + i]); int16x4_t v16x4 = vld1_s16(ptr_noiseEstLogQuantile); int32x4_t v32x4B = vmull_s16(v16x4, kExp2Const16x4); // tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac int32x4_t v32x4A = vandq_s32(v32x4B, constA32x4); v32x4A = vorrq_s32(v32x4A, constB32x4); // tmp16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32no2, 21); v32x4B = vshrq_n_s32(v32x4B, 21); // tmp16 -= 21;// shift 21 to get result in Q0 v32x4B = vsubq_s32(v32x4B, twentyOne32x4); // tmp16 += (int16_t) inst->qNoise; // shift to get result in Q(qNoise) v32x4B = vaddq_s32(v32x4B, qNoise32x4); // if (tmp16 < 0) { // tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no1, -tmp16); // } else { // tmp32no1 = WEBRTC_SPL_LSHIFT_W32(tmp32no1, tmp16); // } v32x4B = vshlq_s32(v32x4A, v32x4B); // tmp16 = WebRtcSpl_SatW32ToW16(tmp32no1); v16x4 = vqmovn_s32(v32x4B); //inst->noiseEstQuantile[i] = tmp16; vst1_s16(ptr_noiseEstQuantile, v16x4); } // Last iteration: // inst->quantile[i]=exp(inst->lquantile[offset+i]); // in Q21 int32_t tmp32no2 = WEBRTC_SPL_MUL_16_16(kExp2Const, *ptr_noiseEstLogQuantile); int32_t tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac tmp16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32no2, 21); tmp16 -= 21;// shift 21 to get result in Q0 tmp16 += (int16_t) inst->qNoise; //shift to get result in Q(qNoise) if (tmp16 < 0) { tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no1, -tmp16); } else { tmp32no1 = WEBRTC_SPL_LSHIFT_W32(tmp32no1, tmp16); } *ptr_noiseEstQuantile = WebRtcSpl_SatW32ToW16(tmp32no1); }
/**************************************************************************** * WebRtcIsacfix_EncTerminate(...) * * Final call to the arithmetic coder for an encoder call. This function * terminates and return byte stream. * * Input: * - streamData : in-/output struct containing bitstream * * Return value : number of bytes in the stream */ WebRtc_Word16 WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData) { WebRtc_UWord16 *streamPtr; WebRtc_UWord16 negCarry; /* point to the right place in the stream buffer */ streamPtr = streamData->stream + streamData->stream_index; /* find minimum length (determined by current interval width) */ if ( streamData->W_upper > 0x01FFFFFF ) { streamData->streamval += 0x01000000; /* if result is less than the added value we must take care of the carry */ if (streamData->streamval < 0x01000000) { /* propagate carry */ if (streamData->full == 0) { /* Add value to current value */ negCarry = *streamPtr; negCarry += 0x0100; *streamPtr = negCarry; /* if value is too big, propagate carry to next byte, and so on */ while (!(negCarry)) { negCarry = *--streamPtr; negCarry++; *streamPtr = negCarry; } } else { /* propagate carry by adding one to the previous byte in the * stream if that byte is 0xFFFF we need to propagate the carry * furhter back in the stream */ while ( !(++(*--streamPtr)) ); } /* put pointer back to the old value */ streamPtr = streamData->stream + streamData->stream_index; } /* write remaining data to bitstream, if "full == 0" first byte has data */ if (streamData->full == 0) { *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24); streamData->full = 1; } else { *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_W32( WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8); streamData->full = 0; } } else { streamData->streamval += 0x00010000; /* if result is less than the added value we must take care of the carry */ if (streamData->streamval < 0x00010000) { /* propagate carry */ if (streamData->full == 0) { /* Add value to current value */ negCarry = *streamPtr; negCarry += 0x0100; *streamPtr = negCarry; /* if value to big, propagate carry to next byte, and so on */ while (!(negCarry)) { negCarry = *--streamPtr; negCarry++; *streamPtr = negCarry; } } else { /* Add carry to previous byte */ while ( !(++(*--streamPtr)) ); } /* put pointer back to the old value */ streamPtr = streamData->stream + streamData->stream_index; } /* write remaining data (2 bytes) to bitstream */ if (streamData->full) { *streamPtr++ = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 16); } else { *streamPtr++ |= (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24); *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 8) & 0xFF00; } } /* calculate stream length in bytes */ return (((streamPtr - streamData->stream)<<1) + !(streamData->full)); }
int WebRtcNetEQ_UpdateIatStatistics(AutomodeInst_t *inst, int maxBufLen, uint16_t seqNumber, uint32_t timeStamp, int32_t fsHz, int mdCodec, int streamingMode) { uint32_t timeIat; /* inter-arrival time */ int i; int32_t tempsum = 0; /* temp summation */ int32_t tempvar; /* temporary variable */ int retval = 0; /* return value */ int16_t packetLenSamp; /* packet speech length in samples */ /****************/ /* Sanity check */ /****************/ if (maxBufLen <= 1 || fsHz <= 0) { /* maxBufLen must be at least 2 and fsHz must both be strictly positive */ return -1; } /****************************/ /* Update packet statistics */ /****************************/ /* Try calculating packet length from current and previous timestamps */ if (!WebRtcNetEQ_IsNewerTimestamp(timeStamp, inst->lastTimeStamp) || !WebRtcNetEQ_IsNewerSequenceNumber(seqNumber, inst->lastSeqNo)) { /* Wrong timestamp or sequence order; revert to backup plan */ packetLenSamp = inst->packetSpeechLenSamp; /* use stored value */ } else { /* calculate timestamps per packet */ packetLenSamp = (int16_t) WebRtcSpl_DivU32U16(timeStamp - inst->lastTimeStamp, seqNumber - inst->lastSeqNo); } /* Check that the packet size is positive; if not, the statistics cannot be updated. */ if (inst->firstPacketReceived && packetLenSamp > 0) { /* packet size ok */ /* calculate inter-arrival time in integer packets (rounding down) */ timeIat = WebRtcSpl_DivW32W16(inst->packetIatCountSamp, packetLenSamp); /* Special operations for streaming mode */ if (streamingMode != 0) { /* * Calculate IAT in Q8, including fractions of a packet (i.e., more accurate * than timeIat). */ int16_t timeIatQ8 = (int16_t) WebRtcSpl_DivW32W16( WEBRTC_SPL_LSHIFT_W32(inst->packetIatCountSamp, 8), packetLenSamp); /* * Calculate cumulative sum iat with sequence number compensation (ideal arrival * times makes this sum zero). */ inst->cSumIatQ8 += (timeIatQ8 - WEBRTC_SPL_LSHIFT_W32(seqNumber - inst->lastSeqNo, 8)); /* subtract drift term */ inst->cSumIatQ8 -= CSUM_IAT_DRIFT; /* ensure not negative */ inst->cSumIatQ8 = WEBRTC_SPL_MAX(inst->cSumIatQ8, 0); /* remember max */ if (inst->cSumIatQ8 > inst->maxCSumIatQ8) { inst->maxCSumIatQ8 = inst->cSumIatQ8; inst->maxCSumUpdateTimer = 0; } /* too long since the last maximum was observed; decrease max value */ if (inst->maxCSumUpdateTimer > (uint32_t) WEBRTC_SPL_MUL_32_16(fsHz, MAX_STREAMING_PEAK_PERIOD)) { inst->maxCSumIatQ8 -= 4; /* remove 1000*4/256 = 15.6 ms/s */ } } /* end of streaming mode */ /* check for discontinuous packet sequence and re-ordering */ if (WebRtcNetEQ_IsNewerSequenceNumber(seqNumber, inst->lastSeqNo + 1)) { /* Compensate for gap in the sequence numbers. * Reduce IAT with expected extra time due to lost packets, but ensure that * the IAT is not negative. */ timeIat -= WEBRTC_SPL_MIN(timeIat, (uint16_t) (seqNumber - (uint16_t) (inst->lastSeqNo + 1))); } else if (!WebRtcNetEQ_IsNewerSequenceNumber(seqNumber, inst->lastSeqNo)) { /* compensate for re-ordering */ timeIat += (uint16_t) (inst->lastSeqNo + 1 - seqNumber); } /* saturate IAT at maximum value */ timeIat = WEBRTC_SPL_MIN( timeIat, MAX_IAT ); /* update iatProb = forgetting_factor * iatProb for all elements */ for (i = 0; i <= MAX_IAT; i++) { int32_t tempHi, tempLo; /* Temporary variables */ /* * Multiply iatProbFact (Q15) with iatProb (Q30) and right-shift 15 steps * to come back to Q30. The operation is done in two steps: */ /* * 1) Multiply the high 16 bits (15 bits + sign) of iatProb. Shift iatProb * 16 steps right to get the high 16 bits in a int16_t prior to * multiplication, and left-shift with 1 afterwards to come back to * Q30 = (Q15 * (Q30>>16)) << 1. */ tempHi = WEBRTC_SPL_MUL_16_16(inst->iatProbFact, (int16_t) WEBRTC_SPL_RSHIFT_W32(inst->iatProb[i], 16)); tempHi = WEBRTC_SPL_LSHIFT_W32(tempHi, 1); /* left-shift 1 step */ /* * 2) Isolate and multiply the low 16 bits of iatProb. Right-shift 15 steps * afterwards to come back to Q30 = (Q15 * Q30) >> 15. */ tempLo = inst->iatProb[i] & 0x0000FFFF; /* sift out the 16 low bits */ tempLo = WEBRTC_SPL_MUL_16_U16(inst->iatProbFact, (uint16_t) tempLo); tempLo = WEBRTC_SPL_RSHIFT_W32(tempLo, 15); /* Finally, add the high and low parts */ inst->iatProb[i] = tempHi + tempLo; /* Sum all vector elements while we are at it... */ tempsum += inst->iatProb[i]; } /* * Increase the probability for the currently observed inter-arrival time * with 1 - iatProbFact. The factor is in Q15, iatProb in Q30; * hence, left-shift 15 steps to obtain result in Q30. */ inst->iatProb[timeIat] += (32768 - inst->iatProbFact) << 15; tempsum += (32768 - inst->iatProbFact) << 15; /* add to vector sum */ /* * Update iatProbFact (changes only during the first seconds after reset) * The factor converges to IAT_PROB_FACT. */ inst->iatProbFact += (IAT_PROB_FACT - inst->iatProbFact + 3) >> 2; /* iatProb should sum up to 1 (in Q30). */ tempsum -= 1 << 30; /* should be zero */ /* Check if it does, correct if it doesn't. */ if (tempsum > 0) { /* tempsum too large => decrease a few values in the beginning */ i = 0; while (i <= MAX_IAT && tempsum > 0) { /* Remove iatProb[i] / 16 from iatProb, but not more than tempsum */ tempvar = WEBRTC_SPL_MIN(tempsum, inst->iatProb[i] >> 4); inst->iatProb[i++] -= tempvar; tempsum -= tempvar; } }
/* filter the signal using normalized lattice filter */ void WebRtcIsacfix_NormLatticeFilterAr(int16_t orderCoef, int16_t *stateGQ0, int32_t *lat_inQ25, int16_t *filt_coefQ15, int32_t *gain_lo_hiQ17, int16_t lo_hi, int16_t *lat_outQ0) { int ii,n,k,i,u; int16_t sthQ15[MAX_AR_MODEL_ORDER]; int16_t cthQ15[MAX_AR_MODEL_ORDER]; int32_t tmp32; int16_t tmpAR; int16_t ARfQ0vec[HALF_SUBFRAMELEN]; int16_t ARgQ0vec[MAX_AR_MODEL_ORDER+1]; int32_t inv_gain32; int16_t inv_gain16; int16_t den16; int16_t sh; int16_t temp2,temp3; int16_t ord_1 = orderCoef+1; for (u=0;u<SUBFRAMES;u++) { int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN); //set the denominator and numerator of the Direct Form temp2 = (int16_t)WEBRTC_SPL_MUL_16_16(u, orderCoef); temp3 = (int16_t)WEBRTC_SPL_MUL_16_16(2, u) + lo_hi; for (ii=0; ii<orderCoef; ii++) { sthQ15[ii] = filt_coefQ15[temp2+ii]; } WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15); /* Simulation of the 25 files shows that maximum value in the vector gain_lo_hiQ17[] is 441344, which means that it is log2((2^31)/441344) = 12.2 shifting bits from saturation. Therefore, it should be safe to use Q27 instead of Q17. */ tmp32 = WEBRTC_SPL_LSHIFT_W32(gain_lo_hiQ17[temp3], 10); // Q27 for (k=0;k<orderCoef;k++) { tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], tmp32); // Q15*Q27>>15 = Q27 } sh = WebRtcSpl_NormW32(tmp32); // tmp32 is the gain den16 = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh-16); //Q(27+sh-16) = Q(sh+11) (all 16 bits are value bits) inv_gain32 = WebRtcSpl_DivW32W16((int32_t)2147483647, den16); // 1/gain in Q31/Q(sh+11) = Q(20-sh) //initial conditions inv_gain16 = (int16_t)(inv_gain32 >> 2); // 1/gain in Q(20-sh-2) = Q(18-sh) for (i=0;i<HALF_SUBFRAMELEN;i++) { tmp32 = WEBRTC_SPL_LSHIFT_W32(lat_inQ25[i + temp1], 1); //Q25->Q26 tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(inv_gain16, tmp32); //lat_in[]*inv_gain in (Q(18-sh)*Q26)>>16 = Q(28-sh) tmp32 = WEBRTC_SPL_SHIFT_W32(tmp32, -(28-sh)); // lat_in[]*inv_gain in Q0 ARfQ0vec[i] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0 } for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders { tmp32 = (cthQ15[i] * ARfQ0vec[0] - sthQ15[i] * stateGQ0[i] + 16384) >> 15; tmpAR = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0 tmp32 = (sthQ15[i] * ARfQ0vec[0] + cthQ15[i] * stateGQ0[i] + 16384) >> 15; ARgQ0vec[i+1] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0 ARfQ0vec[0] = tmpAR; } ARgQ0vec[0] = ARfQ0vec[0]; // Filter ARgQ0vec[] and ARfQ0vec[] through coefficients cthQ15[] and sthQ15[]. WebRtcIsacfix_FilterArLoop(ARgQ0vec, ARfQ0vec, cthQ15, sthQ15, orderCoef); for(n=0;n<HALF_SUBFRAMELEN;n++) { lat_outQ0[n + temp1] = ARfQ0vec[n]; } /* cannot use memcpy in the following */ for (i=0;i<ord_1;i++) { stateGQ0[i] = ARgQ0vec[i]; } } return; }
WebRtc_Word16 WebRtcSpl_LevinsonW32_JSK( WebRtc_Word32 *R, /* (i) Autocorrelation of length >= order+1 */ WebRtc_Word16 *A, /* (o) A[0..order] LPC coefficients (Q11) */ WebRtc_Word16 *K, /* (o) K[0...order-1] Reflection coefficients (Q15) */ WebRtc_Word16 order /* (i) filter order */ ) { WebRtc_Word16 i, j; WebRtc_Word16 R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1]; /* Aurocorr coefficients in high precision */ WebRtc_Word16 A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1]; /* LPC coefficients in high precicion */ WebRtc_Word16 A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1]; /* LPC coefficients for next iteration */ WebRtc_Word16 K_hi, K_low; /* reflection coefficient in high precision */ WebRtc_Word16 Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision and with scale factor */ WebRtc_Word16 tmp_hi, tmp_low; WebRtc_Word32 temp1W32, temp2W32, temp3W32; WebRtc_Word16 norm; /* Normalize the autocorrelation R[0]...R[order+1] */ norm = WebRtcSpl_NormW32(R[0]); for (i=order;i>=0;i--) { temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm); /* Put R in hi and low format */ R_hi[i] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); R_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)), 1); } /* K = A[1] = -R[1] / R[0] */ temp2W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[1],16) + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[1],1); /* R[1] in Q31 */ temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); /* abs R[1] */ temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */ /* Put back the sign on R[1] */ if (temp2W32 > 0) { temp1W32 = -temp1W32; } /* Put K in hi and low format */ K_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1); /* Store first reflection coefficient */ K[0] = K_hi; temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4); /* A[1] in Q27 */ /* Put A[1] in hi and low format */ A_hi[1] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); A_low[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[1], 16)), 1); /* Alpha = R[0] * (1-K^2) */ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) + WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1); /* temp1W32 = k^2 in Q31 */ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; /* temp1W32 = (1 - K[0]*K[0]) in Q31 */ /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */ tmp_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1); /* Calculate Alpha in Q31 */ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low), 15) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi), 15) ), 1); /* Normalize Alpha and put it in hi and low format */ Alpha_exp = WebRtcSpl_NormW32(temp1W32); temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp); Alpha_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1); /* Perform the iterative calculations in the Levinson Durbin algorithm */ for (i=2; i<=order; i++) { /* ---- \ temp1W32 = R[i] + > R[j]*A[i-j] / ---- j=1..i-1 */ temp1W32 = 0; for(j=1; j<i; j++) { /* temp1W32 is in Q31 */ temp1W32 += (WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]), 1) + WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]), 15) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]), 15) ), 1)); } temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4); temp1W32 += (WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16) + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[i], 1)); /* K = -temp1W32 / Alpha */ temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* abs(temp1W32) */ temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */ /* Put the sign of temp1W32 back again */ if (temp1W32 > 0) { temp3W32 = -temp3W32; } /* Use the Alpha shifts from earlier to denormalize */ norm = WebRtcSpl_NormW32(temp3W32); if ((Alpha_exp <= norm)||(temp3W32==0)) { temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp); } else { if (temp3W32 > 0) { temp3W32 = (WebRtc_Word32)0x7fffffffL; } else { temp3W32 = (WebRtc_Word32)0x80000000L; } } /* Put K on hi and low format */ K_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16); K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1); /* Store Reflection coefficient in Q15 */ K[i-1] = K_hi; /* Test for unstable filter. If unstable return 0 and let the user decide what to do in that case */ if ((WebRtc_Word32)WEBRTC_SPL_ABS_W16(K_hi) > (WebRtc_Word32)32740) { return(-i); /* Unstable filter */ } /* Compute updated LPC coefficient: Anew[i] Anew[j]= A[j] + K*A[i-j] for j=1..i-1 Anew[i]= K */ for(j=1; j<i; j++) { temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[j],16) + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[j],1); /* temp1W32 = A[j] in Q27 */ temp1W32 += WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j]) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]), 15) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]), 15) ), 1); /* temp1W32 += K*A[i-j] in Q27 */ /* Put Anew in hi and low format */ A_upd_hi[j] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); A_upd_low[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[j], 16)), 1); } temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4); /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */ /* Store Anew in hi and low format */ A_upd_hi[i] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16); A_upd_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[i], 16)), 1); /* Alpha = Alpha * (1-K^2) */ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) + WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1); /* K*K in Q31 */ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; /* 1 - K*K in Q31 */ /* Convert 1- K^2 in hi and low format */ tmp_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1); /* Calculate Alpha = Alpha * (1-K^2) in Q31 */ temp1W32 = WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low), 15) + WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi), 15)), 1); /* Normalize Alpha and store it on hi and low format */ norm = WebRtcSpl_NormW32(temp1W32); temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm); Alpha_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1); /* Update the total nomalization of Alpha */ Alpha_exp = Alpha_exp + norm; /* Update A[] */ for(j=1; j<=i; j++) { A_hi[j] =A_upd_hi[j]; A_low[j] =A_upd_low[j]; } } /* Set A[0] to 1.0 and store the A[i] i=1...order in Q12 (Convert from Q27 and use rounding) */ A[0] = 2048; for(i=1; i<=order; i++) { /* temp1W32 in Q27 */ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[i], 16) + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[i], 1); /* Round and store upper word */ A[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32+(WebRtc_Word32)32768, 16); } return(1); /* Stable filters */ }
/* MA filter */ void WebRtcIsacfix_NormLatticeFilterMa(int16_t orderCoef, int32_t *stateGQ15, int16_t *lat_inQ0, int16_t *filt_coefQ15, int32_t *gain_lo_hiQ17, int16_t lo_hi, int16_t *lat_outQ9) { int16_t sthQ15[MAX_AR_MODEL_ORDER]; int16_t cthQ15[MAX_AR_MODEL_ORDER]; int u, i, k, n; int16_t temp2,temp3; int16_t ord_1 = orderCoef+1; int32_t inv_cthQ16[MAX_AR_MODEL_ORDER]; int32_t gain32, fQtmp; int16_t gain16; int16_t gain_sh; int32_t tmp32, tmp32b; int32_t fQ15vec[HALF_SUBFRAMELEN]; int32_t gQ15[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN]; int16_t sh; int16_t t16a; int16_t t16b; for (u=0;u<SUBFRAMES;u++) { int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN); /* set the Direct Form coefficients */ temp2 = (int16_t)WEBRTC_SPL_MUL_16_16(u, orderCoef); temp3 = (int16_t)WEBRTC_SPL_MUL_16_16(2, u)+lo_hi; /* compute lattice filter coefficients */ memcpy(sthQ15, &filt_coefQ15[temp2], orderCoef * sizeof(int16_t)); WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15); /* compute the gain */ gain32 = gain_lo_hiQ17[temp3]; gain_sh = WebRtcSpl_NormW32(gain32); gain32 = WEBRTC_SPL_LSHIFT_W32(gain32, gain_sh); //Q(17+gain_sh) for (k=0;k<orderCoef;k++) { gain32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], gain32); //Q15*Q(17+gain_sh)>>15 = Q(17+gain_sh) inv_cthQ16[k] = WebRtcSpl_DivW32W16((int32_t)2147483647, cthQ15[k]); // 1/cth[k] in Q31/Q15 = Q16 } gain16 = (int16_t)(gain32 >> 16); // Q(1+gain_sh). /* normalized lattice filter */ /*****************************/ /* initial conditions */ for (i=0;i<HALF_SUBFRAMELEN;i++) { fQ15vec[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)lat_inQ0[i + temp1], 15); //Q15 gQ15[0][i] = WEBRTC_SPL_LSHIFT_W32((int32_t)lat_inQ0[i + temp1], 15); //Q15 } fQtmp = fQ15vec[0]; /* get the state of f&g for the first input, for all orders */ for (i=1;i<ord_1;i++) { // Calculate f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]); tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], stateGQ15[i-1]);//Q15*Q15>>15 = Q15 tmp32b= fQtmp + tmp32; //Q15+Q15=Q15 tmp32 = inv_cthQ16[i-1]; //Q16 t16a = (int16_t)(tmp32 >> 16); t16b = (int16_t) (tmp32-WEBRTC_SPL_LSHIFT_W32(((int32_t)t16a), 16)); if (t16b<0) t16a++; tmp32 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b); fQtmp = tmp32; // Q15 // Calculate g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0]; tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[i-1], stateGQ15[i-1]); //Q15*Q15>>15 = Q15 tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], fQtmp); //Q15*Q15>>15 = Q15 tmp32 = tmp32 + tmp32b;//Q15+Q15 = Q15 gQ15[i][0] = tmp32; // Q15 } /* filtering */ /* save the states */ for(k=0;k<orderCoef;k++) { // for 0 <= n < HALF_SUBFRAMELEN - 1: // f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]); // g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1]; WebRtcIsacfix_FilterMaLoopFix(sthQ15[k], cthQ15[k], inv_cthQ16[k], &gQ15[k][0], &gQ15[k+1][1], &fQ15vec[1]); } fQ15vec[0] = fQtmp; for(n=0;n<HALF_SUBFRAMELEN;n++) { //gain32 >>= gain_sh; // Q(17+gain_sh) -> Q17 tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(gain16, fQ15vec[n]); //Q(1+gain_sh)*Q15>>16 = Q(gain_sh) sh = 9-gain_sh; //number of needed shifts to reach Q9 t16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh); lat_outQ9[n + temp1] = t16a; } /* save the states */ for (i=0;i<ord_1;i++) { stateGQ15[i] = gQ15[i][HALF_SUBFRAMELEN-1]; } //process next frame } return; }
// Compute speech/noise probability // speech/noise probability is returned in: probSpeechFinal //snrLocPrior is the prior SNR for each frequency (in Q11) //snrLocPost is the post SNR for each frequency (in Q11) void WebRtcNsx_SpeechNoiseProb(NsxInst_t* inst, uint16_t* nonSpeechProbFinal, uint32_t* priorLocSnr, uint32_t* postLocSnr) { uint32_t zeros, num, den, tmpU32no1, tmpU32no2, tmpU32no3; int32_t invLrtFX, indPriorFX, tmp32, tmp32no1, tmp32no2, besselTmpFX32; int32_t frac32, logTmp; int32_t logLrtTimeAvgKsumFX; int16_t indPriorFX16; int16_t tmp16, tmp16no1, tmp16no2, tmpIndFX, tableIndex, frac, intPart; int i, normTmp, normTmp2, nShifts; // compute feature based on average LR factor // this is the average over all frequencies of the smooth log LRT logLrtTimeAvgKsumFX = 0; for (i = 0; i < inst->magnLen; i++) { besselTmpFX32 = (int32_t)postLocSnr[i]; // Q11 normTmp = WebRtcSpl_NormU32(postLocSnr[i]); num = WEBRTC_SPL_LSHIFT_U32(postLocSnr[i], normTmp); // Q(11+normTmp) if (normTmp > 10) { den = WEBRTC_SPL_LSHIFT_U32(priorLocSnr[i], normTmp - 11); // Q(normTmp) } else { den = WEBRTC_SPL_RSHIFT_U32(priorLocSnr[i], 11 - normTmp); // Q(normTmp) } if (den > 0) { besselTmpFX32 -= WEBRTC_SPL_UDIV(num, den); // Q11 } else { besselTmpFX32 -= num; // Q11 } // inst->logLrtTimeAvg[i] += LRT_TAVG * (besselTmp - log(snrLocPrior) // - inst->logLrtTimeAvg[i]); // Here, LRT_TAVG = 0.5 zeros = WebRtcSpl_NormU32(priorLocSnr[i]); frac32 = (int32_t)(((priorLocSnr[i] << zeros) & 0x7FFFFFFF) >> 19); tmp32 = WEBRTC_SPL_MUL(frac32, frac32); tmp32 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(tmp32, -43), 19); tmp32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)frac32, 5412, 12); frac32 = tmp32 + 37; // tmp32 = log2(priorLocSnr[i]) tmp32 = (int32_t)(((31 - zeros) << 12) + frac32) - (11 << 12); // Q12 logTmp = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_32_16(tmp32, 178), 8); // log2(priorLocSnr[i])*log(2) tmp32no1 = WEBRTC_SPL_RSHIFT_W32(logTmp + inst->logLrtTimeAvgW32[i], 1); // Q12 inst->logLrtTimeAvgW32[i] += (besselTmpFX32 - tmp32no1); // Q12 logLrtTimeAvgKsumFX += inst->logLrtTimeAvgW32[i]; // Q12 } inst->featureLogLrt = WEBRTC_SPL_RSHIFT_W32(logLrtTimeAvgKsumFX * 5, inst->stages + 10); // 5 = BIN_SIZE_LRT / 2 // done with computation of LR factor // //compute the indicator functions // // average LRT feature // FLOAT code // indicator0 = 0.5 * (tanh(widthPrior * // (logLrtTimeAvgKsum - threshPrior0)) + 1.0); tmpIndFX = 16384; // Q14(1.0) tmp32no1 = logLrtTimeAvgKsumFX - inst->thresholdLogLrt; // Q12 nShifts = 7 - inst->stages; // WIDTH_PR_MAP_SHIFT - inst->stages + 5; //use larger width in tanh map for pause regions if (tmp32no1 < 0) { tmpIndFX = 0; tmp32no1 = -tmp32no1; //widthPrior = widthPrior * 2.0; nShifts++; } tmp32no1 = WEBRTC_SPL_SHIFT_W32(tmp32no1, nShifts); // Q14 // compute indicator function: sigmoid map tableIndex = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 14); if ((tableIndex < 16) && (tableIndex >= 0)) { tmp16no2 = kIndicatorTable[tableIndex]; tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex]; frac = (int16_t)(tmp32no1 & 0x00003fff); // Q14 tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, frac, 14); if (tmpIndFX == 0) { tmpIndFX = 8192 - tmp16no2; // Q14 } else { tmpIndFX = 8192 + tmp16no2; // Q14 } } indPriorFX = WEBRTC_SPL_MUL_16_16(inst->weightLogLrt, tmpIndFX); // 6*Q14 //spectral flatness feature if (inst->weightSpecFlat) { tmpU32no1 = WEBRTC_SPL_UMUL(inst->featureSpecFlat, 400); // Q10 tmpIndFX = 16384; // Q14(1.0) //use larger width in tanh map for pause regions tmpU32no2 = inst->thresholdSpecFlat - tmpU32no1; //Q10 nShifts = 4; if (inst->thresholdSpecFlat < tmpU32no1) { tmpIndFX = 0; tmpU32no2 = tmpU32no1 - inst->thresholdSpecFlat; //widthPrior = widthPrior * 2.0; nShifts++; } tmp32no1 = (int32_t)WebRtcSpl_DivU32U16(WEBRTC_SPL_LSHIFT_U32(tmpU32no2, nShifts), 25); //Q14 tmpU32no1 = WebRtcSpl_DivU32U16(WEBRTC_SPL_LSHIFT_U32(tmpU32no2, nShifts), 25); //Q14 // compute indicator function: sigmoid map // FLOAT code // indicator1 = 0.5 * (tanh(sgnMap * widthPrior * // (threshPrior1 - tmpFloat1)) + 1.0); tableIndex = (int16_t)WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 14); if (tableIndex < 16) { tmp16no2 = kIndicatorTable[tableIndex]; tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex]; frac = (int16_t)(tmpU32no1 & 0x00003fff); // Q14 tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, frac, 14); if (tmpIndFX) { tmpIndFX = 8192 + tmp16no2; // Q14 } else { tmpIndFX = 8192 - tmp16no2; // Q14 } } indPriorFX += WEBRTC_SPL_MUL_16_16(inst->weightSpecFlat, tmpIndFX); // 6*Q14 } //for template spectral-difference if (inst->weightSpecDiff) { tmpU32no1 = 0; if (inst->featureSpecDiff) { normTmp = WEBRTC_SPL_MIN(20 - inst->stages, WebRtcSpl_NormU32(inst->featureSpecDiff)); tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(inst->featureSpecDiff, normTmp); // Q(normTmp-2*stages) tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->timeAvgMagnEnergy, 20 - inst->stages - normTmp); if (tmpU32no2 > 0) { // Q(20 - inst->stages) tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); } else { tmpU32no1 = (uint32_t)(0x7fffffff); } } tmpU32no3 = WEBRTC_SPL_UDIV(WEBRTC_SPL_LSHIFT_U32(inst->thresholdSpecDiff, 17), 25); tmpU32no2 = tmpU32no1 - tmpU32no3; nShifts = 1; tmpIndFX = 16384; // Q14(1.0) //use larger width in tanh map for pause regions if (tmpU32no2 & 0x80000000) { tmpIndFX = 0; tmpU32no2 = tmpU32no3 - tmpU32no1; //widthPrior = widthPrior * 2.0; nShifts--; } tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, nShifts); // compute indicator function: sigmoid map /* FLOAT code indicator2 = 0.5 * (tanh(widthPrior * (tmpFloat1 - threshPrior2)) + 1.0); */ tableIndex = (int16_t)WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 14); if (tableIndex < 16) { tmp16no2 = kIndicatorTable[tableIndex]; tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex]; frac = (int16_t)(tmpU32no1 & 0x00003fff); // Q14 tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( tmp16no1, frac, 14); if (tmpIndFX) { tmpIndFX = 8192 + tmp16no2; } else { tmpIndFX = 8192 - tmp16no2; } } indPriorFX += WEBRTC_SPL_MUL_16_16(inst->weightSpecDiff, tmpIndFX); // 6*Q14 } //combine the indicator function with the feature weights // FLOAT code // indPrior = 1 - (weightIndPrior0 * indicator0 + weightIndPrior1 * // indicator1 + weightIndPrior2 * indicator2); indPriorFX16 = WebRtcSpl_DivW32W16ResW16(98307 - indPriorFX, 6); // Q14 // done with computing indicator function //compute the prior probability // FLOAT code // inst->priorNonSpeechProb += PRIOR_UPDATE * // (indPriorNonSpeech - inst->priorNonSpeechProb); tmp16 = indPriorFX16 - inst->priorNonSpeechProb; // Q14 inst->priorNonSpeechProb += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( PRIOR_UPDATE_Q14, tmp16, 14); // Q14 //final speech probability: combine prior model with LR factor: memset(nonSpeechProbFinal, 0, sizeof(uint16_t) * inst->magnLen); if (inst->priorNonSpeechProb > 0) { for (i = 0; i < inst->magnLen; i++) { // FLOAT code // invLrt = exp(inst->logLrtTimeAvg[i]); // invLrt = inst->priorSpeechProb * invLrt; // nonSpeechProbFinal[i] = (1.0 - inst->priorSpeechProb) / // (1.0 - inst->priorSpeechProb + invLrt); // invLrt = (1.0 - inst->priorNonSpeechProb) * invLrt; // nonSpeechProbFinal[i] = inst->priorNonSpeechProb / // (inst->priorNonSpeechProb + invLrt); if (inst->logLrtTimeAvgW32[i] < 65300) { tmp32no1 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL( inst->logLrtTimeAvgW32[i], 23637), 14); // Q12 intPart = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 12); if (intPart < -8) { intPart = -8; } frac = (int16_t)(tmp32no1 & 0x00000fff); // Q12 // Quadratic approximation of 2^frac tmp32no2 = WEBRTC_SPL_RSHIFT_W32(frac * frac * 44, 19); // Q12 tmp32no2 += WEBRTC_SPL_MUL_16_16_RSFT(frac, 84, 7); // Q12 invLrtFX = WEBRTC_SPL_LSHIFT_W32(1, 8 + intPart) + WEBRTC_SPL_SHIFT_W32(tmp32no2, intPart - 4); // Q8 normTmp = WebRtcSpl_NormW32(invLrtFX); normTmp2 = WebRtcSpl_NormW16((16384 - inst->priorNonSpeechProb)); if (normTmp + normTmp2 >= 7) { if (normTmp + normTmp2 < 15) { invLrtFX = WEBRTC_SPL_RSHIFT_W32(invLrtFX, 15 - normTmp2 - normTmp); // Q(normTmp+normTmp2-7) tmp32no1 = WEBRTC_SPL_MUL_32_16(invLrtFX, (16384 - inst->priorNonSpeechProb)); // Q(normTmp+normTmp2+7) invLrtFX = WEBRTC_SPL_SHIFT_W32(tmp32no1, 7 - normTmp - normTmp2); // Q14 } else { tmp32no1 = WEBRTC_SPL_MUL_32_16(invLrtFX, (16384 - inst->priorNonSpeechProb)); // Q22 invLrtFX = WEBRTC_SPL_RSHIFT_W32(tmp32no1, 8); // Q14 } tmp32no1 = WEBRTC_SPL_LSHIFT_W32((int32_t)inst->priorNonSpeechProb, 8); // Q22 nonSpeechProbFinal[i] = (uint16_t)WEBRTC_SPL_DIV(tmp32no1, (int32_t)inst->priorNonSpeechProb + invLrtFX); // Q8 } } } } }
int16_t WebRtcIsacfix_DecodeImpl(int16_t *signal_out16, ISACFIX_DecInst_t *ISACdec_obj, int16_t *current_framesamples) { int k; int err; int16_t BWno; int16_t len = 0; int16_t model; int16_t Vector_Word16_1[FRAMESAMPLES/2]; int16_t Vector_Word16_2[FRAMESAMPLES/2]; int32_t Vector_Word32_1[FRAMESAMPLES/2]; int32_t Vector_Word32_2[FRAMESAMPLES/2]; int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs int32_t gain_lo_hiQ17[2*SUBFRAMES]; int16_t PitchLags_Q7[PITCH_SUBFRAMES]; int16_t PitchGains_Q12[PITCH_SUBFRAMES]; int16_t AvgPitchGain_Q12; int16_t tmp_1, tmp_2; int32_t tmp32a, tmp32b; int16_t gainQ13; int16_t frame_nb; /* counter */ int16_t frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */ int16_t processed_samples; /* PLC */ int16_t overlapWin[ 240 ]; (ISACdec_obj->bitstr_obj).W_upper = 0xFFFFFFFF; (ISACdec_obj->bitstr_obj).streamval = 0; (ISACdec_obj->bitstr_obj).stream_index = 0; (ISACdec_obj->bitstr_obj).full = 1; /* decode framelength and BW estimation - not used, only for stream pointer*/ err = WebRtcIsacfix_DecodeFrameLen(&ISACdec_obj->bitstr_obj, current_framesamples); if (err<0) // error check return err; frame_mode = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, MAX_FRAMESAMPLES); /* 0, or 1 */ processed_samples = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, frame_mode+1); /* either 320 (20ms) or 480 (30, 60 ms) */ err = WebRtcIsacfix_DecodeSendBandwidth(&ISACdec_obj->bitstr_obj, &BWno); if (err<0) // error check return err; /* one loop if it's one frame (20 or 30ms), 2 loops if 2 frames bundled together (60ms) */ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) { /* decode & dequantize pitch parameters */ err = WebRtcIsacfix_DecodePitchGain(&(ISACdec_obj->bitstr_obj), PitchGains_Q12); if (err<0) // error check return err; err = WebRtcIsacfix_DecodePitchLag(&ISACdec_obj->bitstr_obj, PitchGains_Q12, PitchLags_Q7); if (err<0) // error check return err; AvgPitchGain_Q12 = (int16_t)(((int32_t)PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3])>>2); /* decode & dequantize FiltCoef */ err = WebRtcIsacfix_DecodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15, &ISACdec_obj->bitstr_obj, &model); if (err<0) // error check return err; /* decode & dequantize spectrum */ len = WebRtcIsacfix_DecodeSpec(&ISACdec_obj->bitstr_obj, Vector_Word16_1, Vector_Word16_2, AvgPitchGain_Q12); if (len < 0) // error check return len; // Why does this need Q16 in and out? /JS WebRtcIsacfix_Spec2Time(Vector_Word16_1, Vector_Word16_2, Vector_Word32_1, Vector_Word32_2); for (k=0; k<FRAMESAMPLES/2; k++) { Vector_Word16_1[k] = (int16_t)WEBRTC_SPL_RSHIFT_W32(Vector_Word32_1[k]+64, 7); //Q16 -> Q9 } /* ---- If this is recovery frame ---- */ if( (ISACdec_obj->plcstr_obj).used == PLC_WAS_USED ) { (ISACdec_obj->plcstr_obj).used = PLC_NOT_USED; if( (ISACdec_obj->plcstr_obj).B < 1000 ) { (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 4000; } ISACdec_obj->plcstr_obj.decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */ ISACdec_obj->plcstr_obj.decayCoeffNoise = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */ ISACdec_obj->plcstr_obj.pitchCycles = 0; PitchGains_Q12[0] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(PitchGains_Q12[0], 700, 10 ); /* ---- Add-overlap ---- */ WebRtcSpl_GetHanningWindow( overlapWin, RECOVERY_OVERLAP ); for( k = 0; k < RECOVERY_OVERLAP; k++ ) Vector_Word16_1[k] = WebRtcSpl_AddSatW16( (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( (ISACdec_obj->plcstr_obj).overlapLP[k], overlapWin[RECOVERY_OVERLAP - k - 1], 14), (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( Vector_Word16_1[k], overlapWin[k], 14) ); } /* --- Store side info --- */ if( frame_nb == frame_mode ) { /* --- LPC info */ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).lofilt_coefQ15, &lofilt_coefQ15[(SUBFRAMES-1)*ORDERLO], ORDERLO ); WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).hifilt_coefQ15, &hifilt_coefQ15[(SUBFRAMES-1)*ORDERHI], ORDERHI ); (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0] = gain_lo_hiQ17[(SUBFRAMES-1) * 2]; (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1] = gain_lo_hiQ17[(SUBFRAMES-1) * 2 + 1]; /* --- LTP info */ (ISACdec_obj->plcstr_obj).AvgPitchGain_Q12 = PitchGains_Q12[3]; (ISACdec_obj->plcstr_obj).lastPitchGain_Q12 = PitchGains_Q12[3]; (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = PitchLags_Q7[3]; if( PitchLags_Q7[3] < 3000 ) (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 += PitchLags_Q7[3]; WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvIn, Vector_Word16_1, FRAMESAMPLES/2 ); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* inverse pitch filter */ WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2, &ISACdec_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 4); if( frame_nb == frame_mode ) { WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvOut, &(Vector_Word16_2[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10)]), PITCH_MAX_LAG ); } /* reduce gain to compensate for pitch enhancer */ /* gain = 1.0f - 0.45f * AvgPitchGain; */ tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(AvgPitchGain_Q12, 29, 0); // Q18 tmp32b = 262144 - tmp32a; // Q18 gainQ13 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q13 for (k = 0; k < FRAMESAMPLES/2; k++) { Vector_Word32_1[k] = (int32_t) WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(Vector_Word16_2[k], gainQ13), 3); // Q25 } /* perceptual post-filtering (using normalized lattice filter) */ WebRtcIsacfix_NormLatticeFilterAr(ORDERLO, (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0, Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1); /* --- Store Highpass Residual --- */ for (k = 0; k < FRAMESAMPLES/2; k++) Vector_Word32_1[k] = WEBRTC_SPL_LSHIFT_W32(Vector_Word32_2[k], 9); // Q16 -> Q25 for( k = 0; k < PITCH_MAX_LAG + 10; k++ ) (ISACdec_obj->plcstr_obj).prevHP[k] = Vector_Word32_1[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10) + k]; WebRtcIsacfix_NormLatticeFilterAr(ORDERHI, (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0, Vector_Word32_1, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2); /* recombine the 2 bands */ /* Form the polyphase signals, and compensate for DC offset */ for (k=0;k<FRAMESAMPLES/2;k++) { tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/ tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k])); /* Construct a new lower channel signal*/ Vector_Word16_1[k] = tmp_1; Vector_Word16_2[k] = tmp_2; } WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1, Vector_Word16_2, signal_out16 + frame_nb * processed_samples, &ISACdec_obj->postfiltbankstr_obj); } return len; }
void WebRtcIlbcfix_CbSearchCore( int32_t *cDot, /* (i) Cross Correlation */ int16_t range, /* (i) Search range */ int16_t stage, /* (i) Stage of this search */ int16_t *inverseEnergy, /* (i) Inversed energy */ int16_t *inverseEnergyShift, /* (i) Shifts of inversed energy with the offset 2*16-29 */ int32_t *Crit, /* (o) The criteria */ int16_t *bestIndex, /* (o) Index that corresponds to maximum criteria (in this vector) */ int32_t *bestCrit, /* (o) Value of critera for the chosen index */ int16_t *bestCritSh) /* (o) The domain of the chosen criteria */ { int32_t maxW32, tmp32; int16_t max, sh, tmp16; int i; int32_t *cDotPtr; int16_t cDotSqW16; int16_t *inverseEnergyPtr; int32_t *critPtr; int16_t *inverseEnergyShiftPtr; /* Don't allow negative values for stage 0 */ if (stage==0) { cDotPtr=cDot; for (i=0;i<range;i++) { *cDotPtr=WEBRTC_SPL_MAX(0, (*cDotPtr)); cDotPtr++; } } /* Normalize cDot to int16_t, calculate the square of cDot and store the upper int16_t */ maxW32 = WebRtcSpl_MaxAbsValueW32(cDot, range); sh = (int16_t)WebRtcSpl_NormW32(maxW32); cDotPtr = cDot; inverseEnergyPtr = inverseEnergy; critPtr = Crit; inverseEnergyShiftPtr=inverseEnergyShift; max=WEBRTC_SPL_WORD16_MIN; for (i=0;i<range;i++) { /* Calculate cDot*cDot and put the result in a int16_t */ tmp32 = WEBRTC_SPL_LSHIFT_W32(*cDotPtr,sh); tmp16 = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32,16); cDotSqW16 = (int16_t)(((int32_t)(tmp16)*(tmp16))>>16); /* Calculate the criteria (cDot*cDot/energy) */ *critPtr=WEBRTC_SPL_MUL_16_16(cDotSqW16, (*inverseEnergyPtr)); /* Extract the maximum shift value under the constraint that the criteria is not zero */ if ((*critPtr)!=0) { max = WEBRTC_SPL_MAX((*inverseEnergyShiftPtr), max); } inverseEnergyPtr++; inverseEnergyShiftPtr++; critPtr++; cDotPtr++; } /* If no max shifts still at initialization value, set shift to zero */ if (max==WEBRTC_SPL_WORD16_MIN) { max = 0; } /* Modify the criterias, so that all of them use the same Q domain */ critPtr=Crit; inverseEnergyShiftPtr=inverseEnergyShift; for (i=0;i<range;i++) { /* Guarantee that the shift value is less than 16 in order to simplify for DSP's (and guard against >31) */ tmp16 = WEBRTC_SPL_MIN(16, max-(*inverseEnergyShiftPtr)); (*critPtr)=WEBRTC_SPL_SHIFT_W32((*critPtr),-tmp16); critPtr++; inverseEnergyShiftPtr++; } /* Find the index of the best value */ *bestIndex = WebRtcSpl_MaxIndexW32(Crit, range); *bestCrit = Crit[*bestIndex]; /* Calculate total shifts of this criteria */ *bestCritSh = 32 - 2*sh + max; return; }