/// <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> /// 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> /// 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> /// <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)); } }
/// <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); }