/// <summary> /// <para>Computes S(implified)PNCC vector in one frame according to [Kim and Stern, 2016].</para> /// <para> /// General algorithm: /// <list type="number"> /// <item>Apply window</item> /// <item>Obtain power spectrum</item> /// <item>Apply gammatone filters (squared)</item> /// <item>Mean power normalization</item> /// <item>Apply nonlinearity</item> /// <item>Do DCT-II (normalized)</item> /// </list> /// </para> /// </summary> /// <param name="block">Block of data</param> /// <param name="features">Features (one SPNCC feature vector) computed in the block</param> public override void ProcessFrame(float[] block, float[] features) { const float meanPower = 1e10f; // 0) base extractor applies window // 1) calculate power spectrum _fft.PowerSpectrum(block, _spectrum, false); // 2) apply gammatone filterbank FilterBanks.Apply(FilterBank, _spectrum, _filteredSpectrum); // 3) mean power normalization: var sumPower = 0.0f; for (var j = 0; j < _filteredSpectrum.Length; j++) { sumPower += _filteredSpectrum[j]; } _mean = LambdaMu * _mean + (1 - LambdaMu) * sumPower; for (var j = 0; j < _filteredSpectrum.Length; j++) { _filteredSpectrum[j] *= meanPower / _mean; } // 4) nonlinearity (pow ^ d or Log10) if (_power != 0) { for (var j = 0; j < _filteredSpectrum.Length; j++) { _filteredSpectrum[j] = (float)Math.Pow(_filteredSpectrum[j], 1.0 / _power); } } else { for (var j = 0; j < _filteredSpectrum.Length; j++) { _filteredSpectrum[j] = (float)Math.Log10(_filteredSpectrum[j] + float.Epsilon); } } // 5) dct-II (normalized) _dct.DirectNorm(_filteredSpectrum, features); // 6) (optional) replace first coeff with log(energy) if (_includeEnergy) { features[0] = (float)Math.Log(Math.Max(block.Sum(x => x * x), _logEnergyFloor)); } }
public void TestDct2Norm() { float[] res = new float[6]; float[] resDct2 = { 0.91923882f, -0.11214018f, 0.35370055f, -0.30289775f, 0.49497475f, 0.18332565f }; var dct2 = new Dct2(8); dct2.DirectNorm(_test, res); Assert.That(res, Is.EqualTo(resDct2).Within(1e-5)); }
/// <summary> /// S(implified)PNCC algorithm according to [Kim & Stern, 2016]. /// In each frame do: /// /// 1) Apply window (if rectangular window was specified then just do nothing) /// 2) Obtain power spectrum /// 3) Apply gammatone filters (squared) /// 4) Mean power normalization /// 5) Apply nonlinearity /// 6) Do dct-II (normalized) /// /// </summary> /// <param name="samples">Samples for analysis</param> /// <returns>List of pncc vectors</returns> public override float[] ProcessFrame(float[] block) { const float meanPower = 1e10f; // fill zeros to fftSize if frameSize < fftSize for (var k = FrameSize; k < block.Length; block[k++] = 0) { ; } // 1) apply window block.ApplyWindow(_windowSamples); // 2) calculate power spectrum _fft.PowerSpectrum(block, _spectrum, false); // 3) apply gammatone filterbank FilterBanks.Apply(FilterBank, _spectrum, _filteredSpectrum); // 4) mean power normalization: var sumPower = 0.0f; for (var j = 0; j < _filteredSpectrum.Length; j++) { sumPower += _filteredSpectrum[j]; } _mean = LambdaMu * _mean + (1 - LambdaMu) * sumPower; for (var j = 0; j < _filteredSpectrum.Length; j++) { _filteredSpectrum[j] *= meanPower / _mean; } // 5) nonlinearity (pow ^ d or Log10) if (_power != 0) { for (var j = 0; j < _filteredSpectrum.Length; j++) { _filteredSpectrum[j] = (float)Math.Pow(_filteredSpectrum[j], 1.0 / _power); } } else { for (var j = 0; j < _filteredSpectrum.Length; j++) { _filteredSpectrum[j] = (float)Math.Log10(_filteredSpectrum[j] + float.Epsilon); } } // 6) dct-II (normalized) var spnccs = new float[FeatureCount]; _dct.DirectNorm(_filteredSpectrum, spnccs); return(spnccs); }