/// <summary> /// Compute the sequence of feature vectors from some fragment of a signal /// </summary> /// <param name="signal">Signal</param> /// <param name="startSample">The number (position) of the first sample for processing</param> /// <param name="endSample">The number (position) of last sample for processing</param> /// <returns>Sequence of feature vectors</returns> public override List <FeatureVector> ComputeFrom(DiscreteSignal signal, int startSample, int endSample) { var frameSize = (int)(signal.SamplingRate * FrameSize); var hopSize = (int)(signal.SamplingRate * HopSize); var fftSize = _fftSize >= frameSize ? _fftSize : MathUtils.NextPowerOfTwo(frameSize); var resolution = (float)signal.SamplingRate / fftSize; var frequencies = Enumerable.Range(0, fftSize + 1) .Select(f => f * resolution) .ToArray(); var featureVectors = new List <FeatureVector>(); var featureCount = FeatureCount; var fft = new Fft(fftSize); // reserve memory for reusable blocks var spectrum = new float[fftSize / 2 + 1]; // buffer for magnitude spectrum var block = new float[fftSize]; // buffer for currently processed block var zeroblock = new float[fftSize]; // just a buffer of zeros for quick memset var i = startSample; while (i + frameSize < endSample) { // prepare all blocks in memory for the current step: zeroblock.FastCopyTo(block, fftSize); signal.Samples.FastCopyTo(block, frameSize, i); fft.MagnitudeSpectrum(block, spectrum); var featureVector = new float[featureCount]; for (var j = 0; j < featureCount; j++) { featureVector[j] = _extractors[j](spectrum, frequencies); } featureVectors.Add(new FeatureVector { Features = featureVector, TimePosition = (double)i / signal.SamplingRate }); i += hopSize; } return(featureVectors); }
/// <summary> /// Compute the sequence of feature vectors from some fragment of a signal /// </summary> /// <param name="samples">Signal</param> /// <param name="startSample">The number (position) of the first sample for processing</param> /// <param name="endSample">The number (position) of last sample for processing</param> /// <returns>Sequence of feature vectors</returns> public override List <FeatureVector> ComputeFrom(float[] samples, int startSample, int endSample) { Guard.AgainstInvalidRange(startSample, endSample, "starting pos", "ending pos"); var nullExtractorPos = _extractors.IndexOf(null); if (nullExtractorPos >= 0) { throw new ArgumentException($"Unknown feature: {FeatureDescriptions[nullExtractorPos]}"); } var featureVectors = new List <FeatureVector>(); var pitchPos = 0; var i = startSample; while (i + FrameSize < endSample) { // prepare all blocks in memory for the current step: _zeroblock.FastCopyTo(_block, _fftSize); samples.FastCopyTo(_block, FrameSize, i); // apply window if necessary if (_window != WindowTypes.Rectangular) { _block.ApplyWindow(_windowSamples); } // compute and prepare spectrum _fft.MagnitudeSpectrum(_block, _spectrum); // apply filterbank (ignoring 0th coefficient) for (var k = 0; k < _filterbank.Length; k++) { _mappedSpectrum[k + 1] = 0.0f; for (var j = 0; j < _spectrum.Length; j++) { _mappedSpectrum[k + 1] += _filterbank[k][j] * _spectrum[j]; } } // extract spectral features var featureVector = new float[FeatureCount]; for (var j = 0; j < _extractors.Count; j++) { featureVector[j] = _extractors[j](_mappedSpectrum, _frequencies); } // ...and maybe harmonic features if (_harmonicExtractors != null) { var pitch = _pitchTrack == null?_pitchEstimator(_spectrum) : _pitchTrack[pitchPos++]; _peaksDetector(_spectrum, _peaks, _peakFrequencies, SamplingRate, pitch); var offset = _extractors.Count; for (var j = 0; j < _harmonicExtractors.Count; j++) { featureVector[j + offset] = _harmonicExtractors[j](_spectrum, _peaks, _peakFrequencies); } } // finally create new feature vector featureVectors.Add(new FeatureVector { Features = featureVector, TimePosition = (double)i / SamplingRate }); i += HopSize; } return(featureVectors); }
/// <summary> /// Compute the sequence of feature vectors from some fragment of a signal /// </summary> /// <param name="samples">Signal</param> /// <param name="startSample">The number (position) of the first sample for processing</param> /// <param name="endSample">The number (position) of last sample for processing</param> /// <returns>Sequence of feature vectors</returns> public override List <FeatureVector> ComputeFrom(float[] samples, int startSample, int endSample) { Guard.AgainstInvalidRange(startSample, endSample, "starting pos", "ending pos"); var nullExtractorPos = _extractors.IndexOf(null); if (nullExtractorPos >= 0) { throw new ArgumentException($"Unknown feature: {FeatureDescriptions[nullExtractorPos]}"); } var featureVectors = new List <FeatureVector>(); var i = startSample; while (i + FrameSize < endSample) { // prepare all blocks in memory for the current step: _zeroblock.FastCopyTo(_block, _fftSize); samples.FastCopyTo(_block, FrameSize, i); // apply window if necessary if (_window != WindowTypes.Rectangular) { _block.ApplyWindow(_windowSamples); } // compute and prepare spectrum _fft.MagnitudeSpectrum(_block, _spectrum); var featureVector = new float[FeatureCount]; if (_spectrum.Length == _frequencies.Length) { _mappedSpectrum = _spectrum; } else { for (var j = 0; j < _mappedSpectrum.Length; j++) { _mappedSpectrum[j] = _spectrum[_frequencyPositions[j]]; } } // extract spectral features for (var j = 0; j < _extractors.Count; j++) { featureVector[j] = _extractors[j](_mappedSpectrum, _frequencies); } // finally create new feature vector featureVectors.Add(new FeatureVector { Features = featureVector, TimePosition = (double)i / SamplingRate }); i += HopSize; } return(featureVectors); }