/// <summary> /// Method for computing LPCC features. /// It essentially duplicates LPC extractor code /// (for efficient memory usage it doesn't just delegate its work to LpcExtractor) /// and then post-processes LPC vectors to obtain LPCC coefficients. /// </summary> /// <param name="block">Samples for analysis</param> /// <param name="features">LPCC vector</param> public override void ProcessFrame(float[] block, float[] features) { block.FastCopyTo(_reversed, FrameSize); // 1) autocorrelation _convolver.CrossCorrelate(block, _reversed, _cc); // 2) Levinson-Durbin for (int k = 0; k < _lpc.Length; _lpc[k] = 0, k++) { ; } var err = Lpc.LevinsonDurbin(_cc, _lpc, _order, FrameSize - 1); // 3) compute LPCC coefficients from LPC Lpc.ToCepstrum(_lpc, err, features); // 4) (optional) liftering if (_lifterCoeffs != null) { features.ApplyWindow(_lifterCoeffs); } }
/// <summary> /// Computes LPCC vector in one frame. /// </summary> /// <param name="block">Block of data</param> /// <param name="features">Features (one LPCC feature vector) computed in the block</param> public override void ProcessFrame(float[] block, float[] features) { // The code here essentially duplicates LPC extractor code // (for efficient memory usage it doesn't just delegate its work to LpcExtractor) // and then post-processes LPC vectors to obtain LPCC coefficients. block.FastCopyTo(_reversed, FrameSize); // 1) autocorrelation _convolver.CrossCorrelate(block, _reversed, _cc); // 2) Levinson-Durbin for (int k = 0; k < _lpc.Length; _lpc[k] = 0, k++) { ; } var err = Lpc.LevinsonDurbin(_cc, _lpc, _order, FrameSize - 1); // 3) compute LPCC coefficients from LPC Lpc.ToCepstrum(_lpc, err, features); // 4) (optional) liftering if (_lifterCoeffs != null) { features.ApplyWindow(_lifterCoeffs); } }
/// <summary> /// Standard method for computing LPC vector. /// /// Note: /// The first LP coefficient is always equal to 1.0. /// This method replaces it with the value of prediction error. /// /// </summary> /// <param name="block">Samples for analysis</param> /// <param name="features">LPC vector</param> public override void ProcessFrame(float[] block, float[] features) { block.FastCopyTo(_reversed, FrameSize); // 1) autocorrelation _convolver.CrossCorrelate(block, _reversed, _cc); // 2) levinson-durbin var err = Lpc.LevinsonDurbin(_cc, features, _order, FrameSize - 1); features[0] = err; }
public void TestLpcToLsf() { //float[] lpc = { 1, 0.6149f, 0.9899f, 0, 0.0031f, -0.008f, 0.0154f }; //float[] lsf = new float[lpc.Length]; //Lpc.ToLsf(lpc, lsf); //Assert.That(lsf, Is.EqualTo(new [] { 0.62694603f, 1.25538484f, 1.82578472f, 1.87689099f, 1.95275509f, 2.51259995f, 3.1415927f }).Within(1e-5)); float[] lpc = { 1, 0.6149f, 0.2899f, 0.0031f, -0.0082f, -0.123f }; float[] lsf = new float[lpc.Length]; Lpc.ToLsf(lpc, lsf); Assert.That(lsf, Is.EqualTo(new[] { 0.6471242f, 1.29403331f, 1.74836394f, 2.26815244f, 2.62021719f, 3.1415927f }).Within(1e-5)); }
public void TestLsfToLpc() { //float[] lsf = { 0.62694603f, 1.25538484f, 1.82578472f, 1.87689099f, 1.95275509f, 2.51259995f, 3.1415927f }; //float[] lpc = new float[lsf.Length]; //Lpc.FromLsf(lsf, lpc); //Assert.That(lpc, Is.EqualTo(new[] { 1, 0.6149f, 0.9899f, 0, 0.0031f, -0.008f, 0.0154f }).Within(1e-5)); float[] lsf = { 0.783008181f, 1.294033314f, 1.56781325f, 2.26815244f, 2.849793301f, 3.1415927f }; float[] lpc = new float[lsf.Length]; Lpc.FromLsf(lsf, lpc); Assert.That(lpc, Is.EqualTo(new[] { 1, 0.6149f, 0.2899f, 0.5f, -0.0082f, -0.123f }).Within(1e-5)); }
unsafe void Restore_samples_lpc(FlacFrame frame, int ch) { FlacSubframeInfo sub = frame.subframes[ch]; ulong csum = 0; fixed(int *coefs = sub.best.coefs) { for (int i = sub.best.order; i > 0; i--) { csum += (ulong)Math.Abs(coefs[i - 1]); } if ((csum << sub.obits) >= 1UL << 32) { Lpc.Decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); } else { Lpc.Decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); } } }
/// <summary> /// Method for computing LPCC features. /// It essentially duplicates LPC extractor code /// (for efficient memory usage it doesn't just delegate its work to LpcExtractor) /// and then post-processes LPC vectors to obtain LPCC coefficients. /// </summary> /// <param name="block">Samples for analysis</param> /// <returns>LPCC vector</returns> public override float[] ProcessFrame(float[] block) { // 1) apply window (usually signal isn't windowed for LPC, so we check first) if (_window != WindowTypes.Rectangular) { block.ApplyWindow(_windowSamples); } block.FastCopyTo(_reversed, FrameSize); // 2) autocorrelation _convolver.CrossCorrelate(block, _reversed, _cc); // 3) Levinson-Durbin for (int k = 0; k < _lpc.Length; _lpc[k] = 0, k++) { ; } var err = Lpc.LevinsonDurbin(_cc, _lpc, _order, FrameSize - 1); // 4) compute LPCC coefficients from LPC var lpcc = new float[FeatureCount]; Lpc.ToCepstrum(_lpc, err, lpcc); // 5) (optional) liftering if (_lifterCoeffs != null) { lpcc.ApplyWindow(_lifterCoeffs); } return(lpcc); }
/// <summary> /// Standard method for computing LPC vector. /// /// Note: /// The first LP coefficient is always equal to 1.0. /// This method replaces it with the value of prediction error. /// /// </summary> /// <param name="block">Samples for analysis</param> /// <returns>LPC vector</returns> public override float[] ProcessFrame(float[] block) { // 1) apply window (usually signal isn't windowed for LPC, so we check first) if (_window != WindowTypes.Rectangular) { block.ApplyWindow(_windowSamples); } block.FastCopyTo(_reversed, FrameSize); // 2) autocorrelation _convolver.CrossCorrelate(block, _reversed, _cc); // 3) levinson-durbin var lpc = new float[_order + 1]; var err = Lpc.LevinsonDurbin(_cc, lpc, _order, FrameSize - 1); lpc[0] = err; return(lpc); }
/// <summary> /// <para>Computes PLP-RASTA feature vector in one frame.</para> /// <para> /// General algorithm: /// <list type="number"> /// <item>Apply window</item> /// <item>Obtain power spectrum</item> /// <item>Apply filterbank of bark bands (or mel bands)</item> /// <item>[Optional] filter each component of the processed spectrum with a RASTA filter</item> /// <item>Apply equal loudness curve</item> /// <item>Apply nonlinearity (take cubic root)</item> /// <item>Do LPC</item> /// <item>Convert LPC to cepstrum</item> /// <item>[Optional] lifter cepstrum</item> /// </list> /// </para> /// </summary> /// <param name="block">Block of data</param> /// <param name="features">Features (one PLP feature vector) computed in the block</param> public override void ProcessFrame(float[] block, float[] features) { // 0) base extractor applies window // 1) calculate power spectrum (without normalization) _fft.PowerSpectrum(block, _spectrum, false); // 2) apply filterbank on the result (bark frequencies by default) FilterBanks.Apply(FilterBank, _spectrum, _bandSpectrum); // 3) RASTA filtering in log-domain [optional] if (_rasta > 0) { for (var k = 0; k < _bandSpectrum.Length; k++) { var log = (float)Math.Log(_bandSpectrum[k] + float.Epsilon); log = _rastaFilters[k].Process(log); _bandSpectrum[k] = (float)Math.Exp(log); } } // 4) and 5) apply equal loudness curve and take cubic root for (var k = 0; k < _bandSpectrum.Length; k++) { _bandSpectrum[k] = (float)Math.Pow(Math.Max(_bandSpectrum[k], 1.0) * _equalLoudnessCurve[k], 0.33); } // 6) LPC from power spectrum: var n = _idftTable[0].Length; // get autocorrelation samples from post-processed power spectrum (via IDFT): for (var k = 0; k < _idftTable.Length; k++) { var acc = _idftTable[k][0] * _bandSpectrum[0] + _idftTable[k][n - 1] * _bandSpectrum[n - 3]; // add values at two duplicated edges right away for (var j = 1; j < n - 1; j++) { acc += _idftTable[k][j] * _bandSpectrum[j - 1]; } _cc[k] = acc / (2 * (n - 1)); } // LPC: for (var k = 0; k < _lpc.Length; _lpc[k] = 0, k++) { ; } var err = Lpc.LevinsonDurbin(_cc, _lpc, _lpcOrder); // 7) compute LPCC coefficients from LPC Lpc.ToCepstrum(_lpc, err, features); // 8) (optional) liftering if (_lifterCoeffs != null) { features.ApplyWindow(_lifterCoeffs); } // 9) (optional) replace first coeff with log(energy) if (_includeEnergy) { features[0] = (float)Math.Log(Math.Max(block.Sum(x => x * x), _logEnergyFloor)); } }
/** * Encoder routine ( speech data should be in new_speech ). * * @param ana output: analysis parameters */ public void coder_ld8k( int[] ana ) { /* LPC coefficients */ var r = new float[MP1]; /* Autocorrelations low and hi */ var A_t = new float[MP1 * 2]; /* A(z) unquantized for the 2 subframes */ var Aq_t = new float[MP1 * 2]; /* A(z) quantized for the 2 subframes */ var Ap1 = new float[MP1]; /* A(z) with spectral expansion */ var Ap2 = new float[MP1]; /* A(z) with spectral expansion */ float[] A, Aq; /* Pointer on A_t and Aq_t */ int A_offset, Aq_offset; /* LSP coefficients */ float[] lsp_new = new float[M], lsp_new_q = new float[M]; /* LSPs at 2th subframe */ var lsf_int = new float[M]; /* Interpolated LSF 1st subframe. */ var lsf_new = new float[M]; /* Variable added for adaptive gamma1 and gamma2 of the PWF */ var rc = new float[M]; /* Reflection coefficients */ var gamma1 = new float[2]; /* Gamma1 for 1st and 2nd subframes */ var gamma2 = new float[2]; /* Gamma2 for 1st and 2nd subframes */ /* Other vectors */ var synth = new float[L_FRAME]; /* Buffer for synthesis speech */ var h1 = new float[L_SUBFR]; /* Impulse response h1[] */ var xn = new float[L_SUBFR]; /* Target vector for pitch search */ var xn2 = new float[L_SUBFR]; /* Target vector for codebook search */ var code = new float[L_SUBFR]; /* Fixed codebook excitation */ var y1 = new float[L_SUBFR]; /* Filtered adaptive excitation */ var y2 = new float[L_SUBFR]; /* Filtered fixed codebook excitation */ var g_coeff = new float[5]; /* Correlations between xn, y1, & y2: * <y1,y1>, <xn,y1>, <y2,y2>, <xn,y2>,<y1,y2>*/ /* Scalars */ int i, j, i_gamma, i_subfr; var iRef = new IntReference(); int T_op, t0; IntReference t0_min = new IntReference(), t0_max = new IntReference(), t0_frac = new IntReference(); int index, taming; float gain_pit, gain_code = 0.0f; FloatReference _gain_pit = new FloatReference(), _gain_code = new FloatReference(); var ana_offset = 0; /*------------------------------------------------------------------------* * - Perform LPC analysis: * * * autocorrelation + lag windowing * * * Levinson-durbin algorithm to find a[] * * * convert a[] to lsp[] * * * quantize and code the LSPs * * * find the interpolated LSPs and convert to a[] for the 2 * * subframes (both quantized and unquantized) * *------------------------------------------------------------------------*/ /* LP analysis */ Lpc.autocorr(p_window, p_window_offset, M, r); /* Autocorrelations */ Lpc.lag_window(M, r); /* Lag windowing */ Lpc.levinson(r, A_t, MP1, rc); /* Levinson Durbin */ Lpc.az_lsp(A_t, MP1, lsp_new, lsp_old); /* From A(z) to lsp */ /* LSP quantization */ quaLsp.qua_lsp(lsp_new, lsp_new_q, ana); ana_offset += 2; /* Advance analysis parameters pointer */ /*--------------------------------------------------------------------* * Find interpolated LPC parameters in all subframes (both quantized * * and unquantized). * * The interpolated parameters are in array A_t[] of size (M+1)*4 * * and the quantized interpolated parameters are in array Aq_t[] * *--------------------------------------------------------------------*/ Lpcfunc.int_lpc(lsp_old, lsp_new, lsf_int, lsf_new, A_t); Lpcfunc.int_qlpc(lsp_old_q, lsp_new_q, Aq_t); /* update the LSPs for the next frame */ for (i = 0; i < M; i++) { lsp_old[i] = lsp_new[i]; lsp_old_q[i] = lsp_new_q[i]; } /*----------------------------------------------------------------------* * - Find the weighting factors * *----------------------------------------------------------------------*/ pwf.perc_var(gamma1, gamma2, lsf_int, lsf_new, rc); /*----------------------------------------------------------------------* * - Find the weighted input speech w_sp[] for the whole speech frame * * - Find the open-loop pitch delay for the whole speech frame * * - Set the range for searching closed-loop pitch in 1st subframe * *----------------------------------------------------------------------*/ Lpcfunc.weight_az(A_t, 0, gamma1[0], M, Ap1); Lpcfunc.weight_az(A_t, 0, gamma2[0], M, Ap2); Filter.residu(Ap1, 0, speech, speech_offset, wsp, wsp_offset, L_SUBFR); Filter.syn_filt(Ap2, 0, wsp, wsp_offset, wsp, wsp_offset, L_SUBFR, mem_w, 0, 1); Lpcfunc.weight_az(A_t, MP1, gamma1[1], M, Ap1); Lpcfunc.weight_az(A_t, MP1, gamma2[1], M, Ap2); Filter.residu(Ap1, 0, speech, speech_offset + L_SUBFR, wsp, wsp_offset + L_SUBFR, L_SUBFR); Filter.syn_filt(Ap2, 0, wsp, wsp_offset + L_SUBFR, wsp, wsp_offset + L_SUBFR, L_SUBFR, mem_w, 0, 1); /* Find open loop pitch lag for whole speech frame */ T_op = Pitch.pitch_ol(wsp, wsp_offset, PIT_MIN, PIT_MAX, L_FRAME); /* range for closed loop pitch search in 1st subframe */ t0_min.value = T_op - 3; if (t0_min.value < PIT_MIN) { t0_min.value = PIT_MIN; } t0_max.value = t0_min.value + 6; if (t0_max.value > PIT_MAX) { t0_max.value = PIT_MAX; t0_min.value = t0_max.value - 6; } /*------------------------------------------------------------------------* * Loop for every subframe in the analysis frame * *------------------------------------------------------------------------* * To find the pitch and innovation parameters. The subframe size is * * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. * * - find the weighted LPC coefficients * * - find the LPC residual signal * * - compute the target signal for pitch search * * - compute impulse response of weighted synthesis filter (h1[]) * * - find the closed-loop pitch parameters * * - encode the pitch delay * * - update the impulse response h1[] by including fixed-gain pitch * * - find target vector for codebook search * * - codebook search * * - encode codebook address * * - VQ of pitch and codebook gains * * - find synthesis speech * * - update states of weighting filter * *------------------------------------------------------------------------*/ A = A_t; /* pointer to interpolated LPC parameters */ A_offset = 0; Aq = Aq_t; /* pointer to interpolated quantized LPC parameters */ Aq_offset = 0; i_gamma = 0; for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { /*---------------------------------------------------------------* * Find the weighted LPC coefficients for the weighting filter. * *---------------------------------------------------------------*/ Lpcfunc.weight_az(A, A_offset, gamma1[i_gamma], M, Ap1); Lpcfunc.weight_az(A, A_offset, gamma2[i_gamma], M, Ap2); i_gamma++; /*---------------------------------------------------------------* * Compute impulse response, h1[], of weighted synthesis filter * *---------------------------------------------------------------*/ for (i = 0; i <= M; i++) { ai_zero[i] = Ap1[i]; } Filter.syn_filt(Aq, Aq_offset, ai_zero, 0, h1, 0, L_SUBFR, zero, zero_offset, 0); Filter.syn_filt(Ap2, 0, h1, 0, h1, 0, L_SUBFR, zero, zero_offset, 0); /*------------------------------------------------------------------------* * * * Find the target vector for pitch search: * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * |------| res[n] * * speech[n]---| A(z) |-------- * * |------| | |--------| error[n] |------| * * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target * * exc |--------| |------| * * * * Instead of subtracting the zero-input response of filters from * * the weighted input speech, the above configuration is used to * * compute the target vector. This configuration gives better performance * * with fixed-point implementation. The memory of 1/A(z) is updated by * * filtering (res[n]-exc[n]) through 1/A(z), or simply by subtracting * * the synthesis speech from the input speech: * * error[n] = speech[n] - syn[n]. * * The memory of W(z) is updated by filtering error[n] through W(z), * * or more simply by subtracting the filtered adaptive and fixed * * codebook excitations from the target: * * target[n] - gain_pit*y1[n] - gain_code*y2[n] * * as these signals are already available. * * * *------------------------------------------------------------------------*/ Filter.residu( Aq, Aq_offset, speech, speech_offset + i_subfr, exc, exc_offset + i_subfr, L_SUBFR); /* LPC residual */ Filter.syn_filt(Aq, Aq_offset, exc, exc_offset + i_subfr, error, error_offset, L_SUBFR, mem_err, 0, 0); Filter.residu(Ap1, 0, error, error_offset, xn, 0, L_SUBFR); Filter.syn_filt(Ap2, 0, xn, 0, xn, 0, L_SUBFR, mem_w0, 0, 0); /* target signal xn[]*/ /*----------------------------------------------------------------------* * Closed-loop fractional pitch search * *----------------------------------------------------------------------*/ t0 = Pitch.pitch_fr3( exc, exc_offset + i_subfr, xn, h1, L_SUBFR, t0_min.value, t0_max.value, i_subfr, t0_frac); index = Pitch.enc_lag3(t0, t0_frac.value, t0_min, t0_max, PIT_MIN, PIT_MAX, i_subfr); ana[ana_offset] = index; ana_offset++; if (i_subfr == 0) { ana[ana_offset] = PParity.parity_pitch(index); ana_offset++; } /*-----------------------------------------------------------------* * - find unity gain pitch excitation (adaptive codebook entry) * * with fractional interpolation. * * - find filtered pitch exc. y1[]=exc[] convolve with h1[]) * * - compute pitch gain and limit between 0 and 1.2 * * - update target vector for codebook search * * - find LTP residual. * *-----------------------------------------------------------------*/ PredLt3.pred_lt_3(exc, exc_offset + i_subfr, t0, t0_frac.value, L_SUBFR); Filter.convolve(exc, exc_offset + i_subfr, h1, y1, L_SUBFR); gain_pit = Pitch.g_pitch(xn, y1, g_coeff, L_SUBFR); /* clip pitch gain if taming is necessary */ taming = this.taming.test_err(t0, t0_frac.value); if (taming == 1) { if (gain_pit > GPCLIP) { gain_pit = GPCLIP; } } for (i = 0; i < L_SUBFR; i++) { xn2[i] = xn[i] - y1[i] * gain_pit; } /*-----------------------------------------------------* * - Innovative codebook search. * *-----------------------------------------------------*/ iRef.value = i; index = acelpCo.ACELP_codebook(xn2, h1, t0, sharp, i_subfr, code, y2, iRef); i = iRef.value; ana[ana_offset] = index; /* Positions index */ ana_offset++; ana[ana_offset] = i; /* Signs index */ ana_offset++; /*-----------------------------------------------------* * - Quantization of gains. * *-----------------------------------------------------*/ CorFunc.corr_xy2(xn, y1, y2, g_coeff); _gain_pit.value = gain_pit; _gain_code.value = gain_code; ana[ana_offset] = quaGain.qua_gain(code, g_coeff, L_SUBFR, _gain_pit, _gain_code, taming); gain_pit = _gain_pit.value; gain_code = _gain_code.value; ana_offset++; /*------------------------------------------------------------* * - Update pitch sharpening "sharp" with quantized gain_pit * *------------------------------------------------------------*/ sharp = gain_pit; if (sharp > SHARPMAX) { sharp = SHARPMAX; } if (sharp < SHARPMIN) { sharp = SHARPMIN; } /*------------------------------------------------------* * - Find the total excitation * * - find synthesis speech corresponding to exc[] * * - update filters' memories for finding the target * * vector in the next subframe * * (update error[-m..-1] and mem_w0[]) * * update error function for taming process * *------------------------------------------------------*/ for (i = 0; i < L_SUBFR; i++) { exc[exc_offset + i + i_subfr] = gain_pit * exc[exc_offset + i + i_subfr] + gain_code * code[i]; } this.taming.update_exc_err(gain_pit, t0); Filter.syn_filt(Aq, Aq_offset, exc, exc_offset + i_subfr, synth, i_subfr, L_SUBFR, mem_syn, 0, 1); for (i = L_SUBFR - M, j = 0; i < L_SUBFR; i++, j++) { mem_err[j] = speech[speech_offset + i_subfr + i] - synth[i_subfr + i]; mem_w0[j] = xn[i] - gain_pit * y1[i] - gain_code * y2[i]; } A_offset += MP1; /* interpolated LPC parameters for next subframe */ Aq_offset += MP1; } /*--------------------------------------------------* * Update signal for next frame. * * -> shift to the left by L_FRAME: * * speech[], wsp[] and exc[] * *--------------------------------------------------*/ Util.copy(old_speech, L_FRAME, old_speech, L_TOTAL - L_FRAME); Util.copy(old_wsp, L_FRAME, old_wsp, PIT_MAX); Util.copy(old_exc, L_FRAME, old_exc, PIT_MAX + L_INTERPOL); }
/// <summary> /// Standard method for computing PLP features. /// In each frame do: /// /// 1) Apply window /// 2) Obtain power spectrum /// 3) Apply filterbank of bark bands (or mel bands) /// 4) [Optional] filter each component of the processed spectrum with a RASTA filter /// 5) Apply equal loudness curve /// 6) Take cubic root /// 7) Do LPC /// 8) Convert LPC to cepstrum /// 9) [Optional] lifter cepstrum /// /// </summary> /// <param name="block">Samples for analysis</param> /// <returns>PLP vector</returns> public override float[] ProcessFrame(float[] block) { // fill zeros to fftSize if frameSize < fftSize (blockSize) for (var k = FrameSize; k < block.Length; block[k++] = 0) { ; } // 1) apply window block.ApplyWindow(_windowSamples); // 2) calculate power spectrum (without normalization) _fft.PowerSpectrum(block, _spectrum, false); // 3) apply filterbank on the result (bark frequencies by default) FilterBanks.Apply(FilterBank, _spectrum, _bandSpectrum); // 4) RASTA filtering in log-domain [optional] if (_rasta > 0) { for (var k = 0; k < _bandSpectrum.Length; k++) { var log = (float)Math.Log(_bandSpectrum[k] + float.Epsilon); log = _rastaFilters[k].Process(log); _bandSpectrum[k] = (float)Math.Exp(log); } } // 5) and 6) apply equal loudness curve and take cubic root for (var k = 0; k < _bandSpectrum.Length; k++) { _bandSpectrum[k] = (float)Math.Pow(Math.Max(_bandSpectrum[k], 1.0) * _equalLoudnessCurve[k], 0.33); } // 7) LPC from power spectrum: var n = _idftTable[0].Length; // get autocorrelation samples from post-processed power spectrum (via IDFT): for (var k = 0; k < _idftTable.Length; k++) { var acc = _idftTable[k][0] * _bandSpectrum[0] + _idftTable[k][n - 1] * _bandSpectrum[n - 3]; // add values at two duplicated edges right away for (var j = 1; j < n - 1; j++) { acc += _idftTable[k][j] * _bandSpectrum[j - 1]; } _cc[k] = acc / (2 * (n - 1)); } // LPC: for (var k = 0; k < _lpc.Length; _lpc[k] = 0, k++) { ; } var err = Lpc.LevinsonDurbin(_cc, _lpc, _lpcOrder); // 8) compute LPCC coefficients from LPC var lpcc = new float[FeatureCount]; Lpc.ToCepstrum(_lpc, err, lpcc); // 9) (optional) liftering if (_lifterCoeffs != null) { lpcc.ApplyWindow(_lifterCoeffs); } return(lpcc); }