private void openToolStripMenuItem_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); if (ofd.ShowDialog() != DialogResult.OK) { return; } _waveFileName = ofd.FileName; using (var stream = new FileStream(_waveFileName, FileMode.Open)) { var waveFile = new WaveFile(stream); _bitDepth = waveFile.WaveFmt.BitsPerSample; _signal = waveFile[Channels.Average]; } _stft = new Stft(1024, 256); var processed = _stft.Inverse(_stft.Direct(_signal)); _processedSignal = new DiscreteSignal(_signal.SamplingRate, processed); signalPanel.Gain = 120; signalPanel.Signal = _signal; processedSignalPanel.Gain = 120; processedSignalPanel.Signal = _processedSignal; _spectrogram = _stft.Spectrogram(_signal); spectrogramPanel.Spectrogram = _spectrogram; }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); if (ofd.ShowDialog() != DialogResult.OK) { return; } using (var stream = new FileStream(ofd.FileName, FileMode.Open)) { var waveFile = new WaveFile(stream); _signal = waveFile[Channels.Left]; } _stft = new Stft(_frameSize, _hopSize); var frameDuration = (double)_frameSize / _signal.SamplingRate; var hopDuration = (double)_hopSize / _signal.SamplingRate; var freqs = new[] { 300f, 600, 1000, 2000, 4000, 7000 }; var pitchExtractor = new PitchExtractor(_signal.SamplingRate, frameDuration, hopDuration, high: 900 /*Hz*/); var pitchTrack = pitchExtractor.ParallelComputeFrom(_signal) .Select(p => p.Features[0]) .ToArray(); var tdExtractor = new TimeDomainFeaturesExtractor(_signal.SamplingRate, "all", frameDuration, hopDuration); var spectralExtractor = new SpectralFeaturesExtractor(_signal.SamplingRate, "sc+sn", frameDuration, hopDuration, frequencies: freqs); var mpeg7Extractor = new Mpeg7SpectralFeaturesExtractor(_signal.SamplingRate, "all", frameDuration, hopDuration); mpeg7Extractor.IncludeHarmonicFeatures("all"); mpeg7Extractor.SetPitchTrack(pitchTrack); tdExtractor.AddFeature("pitch_zcr", (signal, start, end) => { return(Pitch.FromZeroCrossingsSchmitt(signal, start, end)); }); //spectralExtractor.AddFeature("pitch_hss", (spectrum, fs) => { return Pitch.FromHss(spectrum, _signal.SamplingRate); } ); var tdVectors = tdExtractor.ParallelComputeFrom(_signal); var spectralVectors = spectralExtractor.ParallelComputeFrom(_signal); var mpeg7Vectors = mpeg7Extractor.ParallelComputeFrom(_signal); _vectors = FeaturePostProcessing.Join(tdVectors, spectralVectors, mpeg7Vectors); //FeaturePostProcessing.NormalizeMean(_vectors); //FeaturePostProcessing.AddDeltas(_vectors); var descriptions = tdExtractor.FeatureDescriptions .Concat(spectralExtractor.FeatureDescriptions) .Concat(mpeg7Extractor.FeatureDescriptions); FillFeaturesList(_vectors, descriptions); spectrogramPlot.ColorMapName = "afmhot"; spectrogramPlot.MarklineThickness = 2; spectrogramPlot.Spectrogram = _stft.Spectrogram(_signal); }
/// <summary> /// Constructs <see cref="HarmonicPercussiveSeparator"/>. /// </summary> /// <param name="fftSize">FFT size</param> /// <param name="hopSize">Hop length (number of samples)</param> /// <param name="harmonicWinSize">Size of median filter along time axis</param> /// <param name="percussiveWinSize">Size of median filter along frequency axis</param> /// <param name="masking">Masking mode</param> public HarmonicPercussiveSeparator(int fftSize = 2048, int hopSize = 512, int harmonicWinSize = 17, int percussiveWinSize = 17, HpsMasking masking = HpsMasking.WienerOrder2) { _stft = new Stft(fftSize, hopSize); _medianHarmonic = new MedianFilter(harmonicWinSize); _medianPercussive = new MedianFilter(percussiveWinSize); switch (masking) { case HpsMasking.Binary: _mask = BinaryMask; break; case HpsMasking.WienerOrder1: _mask = WienerMask1; break; default: _mask = WienerMask2; break; } }
private void Evaluate() { var fftSize = int.Parse(fftSizeTextBox.Text); var hopSize = int.Parse(hopSizeTextBox.Text); var harmWinSize = int.Parse(harmonicWindowTextBox.Text); var percWinSize = int.Parse(percussiveWindowTextBox.Text); var masking = HpsMasking.Binary; if (maskingComboBox.SelectedIndex == 1) { masking = HpsMasking.WienerOrder1; } else if (maskingComboBox.SelectedIndex == 2) { masking = HpsMasking.WienerOrder2; } var hpss = new HarmonicPercussiveSeparator(fftSize, hopSize, harmWinSize, percWinSize, masking) .EvaluateSignals(_signal); //.EvaluateSpectrograms(_signal); var stft = new Stft(512, 256); _harmonicSignal = hpss.Item1; // new DiscreteSignal(_signal.SamplingRate, stft.ReconstructMagnitudePhase(hpss.Item1)); _percussiveSignal = hpss.Item2; // new DiscreteSignal(_signal.SamplingRate, stft.ReconstructMagnitudePhase(hpss.Item2)); spectrogramPlot1.Spectrogram = stft.Spectrogram(_signal); spectrogramPlot2.Spectrogram = stft.Spectrogram(_harmonicSignal); spectrogramPlot3.Spectrogram = stft.Spectrogram(_percussiveSignal); }
/// <summary> /// Constructor /// </summary> /// <param name="spectrogram"></param> /// <param name="stft"></param> /// <param name="power"></param> public GriffinLimReconstructor(List <float[]> spectrogram, Stft stft, int power = 2) { _stft = stft; _magnitudes = spectrogram; if (power == 2) { for (var i = 0; i < _magnitudes.Count; i++) { for (var j = 0; j < _magnitudes[i].Length; j++) { _magnitudes[i][j] = (float)Math.Sqrt(_magnitudes[i][j]); } } } for (var i = 0; i < _magnitudes.Count; i++) { for (var j = 0; j < _magnitudes[i].Length; j++) { _magnitudes[i][j] *= 20; // how to calculate this compensation? } } }
/// <summary> /// Computes periodogram using Welch's method. /// If <paramref name="samplingRate"/>=0 then power spectrum is evaluated, otherwise power spectral density is evaluated. /// </summary> /// <param name="signal">Signal</param> /// <param name="windowSize">Window size (number of samples)</param> /// <param name="hopSize">Hop size (number of samples)</param> /// <param name="window">Windowing function</param> /// <param name="fftSize">FFT size</param> /// <param name="samplingRate">If sampling rate=0 then power spectrum is evaluated, otherwise power spectral density is evaluated</param> public static float[] Welch(DiscreteSignal signal, int windowSize = 1024, int hopSize = 256, WindowType window = WindowType.Hann, int fftSize = 0, int samplingRate = 0) { var stft = new Stft(windowSize, hopSize, window, fftSize); var periodogram = stft.AveragePeriodogram(signal.Samples); // scaling is compliant with sciPy function welch(): float scale; if (samplingRate > 0) // a.k.a. 'density' { var ws = Window.OfType(window, windowSize).Select(w => w * w).Sum(); scale = 2 / (ws * samplingRate); } else // a.k.a. 'spectrum' { var ws = Window.OfType(window, windowSize).Sum(); scale = 2 / (ws * ws); } for (var j = 0; j < periodogram.Length; j++) { periodogram[j] *= scale; } return(periodogram); }
private List <Beat> MicroAlignBeats(IList <float> signal, List <Beat> strengthFilteredBeats, int stepSizeOfOriginalSearch) { //original found beats are detected with a window size of 1024, resulting in a precision of 1024/44100=23ms //this is sometimes big enough to feel being 'off-beat' //perform a more precise search with smaller window to find the best place to put the beat //128/44100=3ms var alignedBeats = new List <Beat>(); var stftWindowSize = 1024; //not sure about this number var stepSize = 128; var stft = new Stft(windowSize: stftWindowSize, hopSize: stepSize, window: WindowTypes.Hamming); var spectrogram = stft.Spectrogram(signal.ToArray()); var windowPositions = SequenceGeneration .Linspace(stftWindowSize / 2.0, signal.Count - stftWindowSize / 2.0, spectrogram.Count) .ToList(); foreach (var beat in strengthFilteredBeats) { var alignedBeat = new Beat(); alignedBeat.Strength = beat.Strength; var searchSampleIndexStart = Math.Max(0, beat.SampleIndex - (stepSizeOfOriginalSearch / 2)); var searchSampleIndexEnd = Math.Min(signal.Count, beat.SampleIndex + (stepSizeOfOriginalSearch / 2)); var searchIndexStart = windowPositions.FindIndex(x => x >= searchSampleIndexStart); var searchIndexEnd = windowPositions.FindLastIndex(x => x < searchSampleIndexEnd); var bestMatchingIndex = searchIndexStart; var strengthOfBestMatch = 0.0; for (int timeIndex = searchIndexStart + 1; timeIndex <= searchIndexEnd; ++timeIndex) { var strengthOfTimeIndex = 0.0; for (int frequency = 0; frequency < spectrogram[0].Length; ++frequency) { var diff = spectrogram[timeIndex][frequency] - spectrogram[timeIndex - 1][frequency]; if (diff > 0) { strengthOfTimeIndex += diff; } } if (strengthOfTimeIndex > strengthOfBestMatch) { bestMatchingIndex = timeIndex; strengthOfBestMatch = strengthOfTimeIndex; } } alignedBeat.SampleIndex = (int)windowPositions[bestMatchingIndex]; alignedBeats.Add(alignedBeat); } return(alignedBeats); }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); if (ofd.ShowDialog() != DialogResult.OK) { return; } using (var stream = new FileStream(ofd.FileName, FileMode.Open)) { var waveFile = new WaveFile(stream); _signal = waveFile[Channels.Left]; } _fftSize = int.Parse(fftSizeTextBox.Text); _cepstrumSize = int.Parse(cepstrumSizeTextBox.Text); _hopSize = int.Parse(hopSizeTextBox.Text); _fft = new RealFft(_fftSize); _cepstralTransform = new CepstralTransform(_cepstrumSize, _fftSize); var options = new PitchOptions { SamplingRate = _signal.SamplingRate, FrameDuration = (double)_fftSize / _signal.SamplingRate, HopDuration = (double)_hopSize / _signal.SamplingRate }; var pitchExtractor = new PitchExtractor(options); _pitches = pitchExtractor.ParallelComputeFrom(_signal); _specNo = 0; specNoComboBox.DataSource = Enumerable.Range(1, _pitches.Count).ToArray(); // obtain spectrogram _stft = new Stft(_fftSize, _hopSize, WindowTypes.Rectangular); var spectrogram = _stft.Spectrogram(_signal); spectrogramPanel.ColorMapName = "viridis"; spectrogramPanel.MarklineThickness = 6; spectrogramPanel.Spectrogram = spectrogram.Select(s => s.Take(224).ToArray()).ToList(); spectrogramPanel.Markline = _pitches.Select(p => p[0] * _fftSize / _signal.SamplingRate).ToArray(); }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); if (ofd.ShowDialog() != DialogResult.OK) { return; } using (var stream = new FileStream(ofd.FileName, FileMode.Open)) { var waveFile = new WaveFile(stream); _signal = waveFile[Channels.Left]; } _fftSize = int.Parse(fftSizeTextBox.Text); _cepstrumSize = int.Parse(cepstrumSizeTextBox.Text); _hopSize = int.Parse(hopSizeTextBox.Text); _fft = new Fft(_fftSize); _cepstralTransform = new CepstralTransform(_cepstrumSize, _fftSize); var pitchTracker = new Pitch((float)_fftSize / _signal.SamplingRate, (float)_hopSize / _signal.SamplingRate); _pitchTrack = pitchTracker.Track(_signal); UpdateSpectra(); UpdateAutoCorrelation(); // obtain spectrogram _stft = new Stft(_fftSize, _hopSize, WindowTypes.Rectangular); var spectrogram = _stft.Spectrogram(_signal); spectrogramPanel.ColorMapName = "viridis"; spectrogramPanel.Spectrogram = spectrogram.Select(s => s.Take(224).ToArray()).ToList(); spectrogramPanel.Markline = _pitchTrack.Select(p => p * _fftSize / _signal.SamplingRate).ToArray(); specNoComboBox.DataSource = Enumerable.Range(1, _pitchTrack.Count).ToArray(); _specNo = 0; }
/// <summary> /// Takes an audio signal, detects the beats and returns a list of all times (in seconds) where a beat is located /// </summary> /// <param name="signal">Expected to be normalized to -1 to 1</param> /// <param name="sampleRate">Sample rate of signal</param> /// <returns>Sample indices of beats</returns> public BeatDetectorResult DetectBeats(IList <float> signal, int sampleRate) { var stftWindowSize = 4096; var stepSize = 1024; var lowerLimit = 0.1 * sampleRate; var upperLimit = 1.0 * sampleRate; var stft = new Stft(windowSize: stftWindowSize, hopSize: stepSize, window: WindowTypes.Hamming); var spectrogram = stft.Spectrogram(signal.ToArray()); var windowPositions = SequenceGeneration .Linspace(stftWindowSize / 2.0, signal.Count - stftWindowSize / 2.0, spectrogram.Count) .ToList(); var fftMagnitudeIncreaseSeries = ComputeFftMagnitudeIncreaseSeries(spectrogram, windowPositions); var candidateBeats = FindCandidateBeats(fftMagnitudeIncreaseSeries, sampleRate, stepSize, out var songIntensity); var filteredBeats = FilterBeats(candidateBeats, lowerLimit); var beatsPerMinute = DetermineBeatsPerMinute(filteredBeats, sampleRate, upperLimit); var regularBeats = GenerateRegularBeats(filteredBeats, beatsPerMinute, sampleRate, signal.Count); var beatsPerBar = 4; return(new BeatDetectorResult(beatsPerMinute, beatsPerBar, filteredBeats, regularBeats, songIntensity)); }
/// <summary> /// Takes an audio signal, detects the beats and returns a list of all times (in seconds) where a beat is located /// </summary> /// <param name="signal">Expected to be normalized to -1 to 1</param> /// <param name="sampleRate">Sample rate of signal</param> /// <returns>Sample indices of beats</returns> public BeatDetectorResult DetectBeats(IList <float> signal, int sampleRate) { var stftWindowSize = 4096; var stepSize = 1024; var stft = new Stft(windowSize: stftWindowSize, hopSize: stepSize, window: WindowTypes.Hamming); var spectrogram = stft.Spectrogram(signal.ToArray()); var windowPositions = SequenceGeneration .Linspace(stftWindowSize / 2.0, signal.Count - stftWindowSize / 2.0, spectrogram.Count) .ToList(); var focusedFrequency = DetermineFocusedFrequency(sampleRate, spectrogram, windowPositions); var beatCandidates = GetBeatCandidates(spectrogram, focusedFrequency, windowPositions); var strengthFilteredBeats = MergeBeatsByStrength(sampleRate, beatCandidates); var alignedBeats = MicroAlignBeats(signal, strengthFilteredBeats, stepSize); var songIntensity = GetSongIntensity(spectrogram, windowPositions, sampleRate, stepSize); var bpm = 60 * strengthFilteredBeats.Count() / (signal.Count / (double)sampleRate); return(new BeatDetectorResult(bpm, alignedBeats, songIntensity)); }
// Open file private void openToolStripMenuItem_Click(object sender, EventArgs e) { spectrumPanel.refresh(); signalPanel.refresh(); signalPanel.Stride = 64; var ofd = new OpenFileDialog(); if (ofd.ShowDialog() != DialogResult.OK) { return; } txtFilePath.Text = ofd.FileName; _waveFileName = ofd.FileName; try { using (var stream = new FileStream(_waveFileName, FileMode.Open)) { IAudioContainer waveFile = new WaveFile(stream); _signal = waveFile[Channels.Left]; _signal_storage = _signal; } } catch (IOException ex) { Console.WriteLine("Error reading from {0}. Message = {1}", _waveFileName, ex.Message); } // Get duration WaveFileReader wf = new WaveFileReader(_waveFileName); var totalTime = wf.TotalTime; txtTotalTime.Text = totalTime.TotalMilliseconds.ToString() + " ms"; signalPanel.max_time_value = (float)totalTime.TotalMilliseconds; var max_value = _signal[0]; var count = 0; for (int i = 1; i < _signal.Length; i++) { if (max_value < _signal[i]) { max_value = _signal[i]; } if (_signal[i] > 0.2) { count++; } } txtMaxValue.Text = max_value.ToString(); signalPanel.Signal = _signal; _fftSize = int.Parse(fftSizeTextBox.Text); _cepstrumSize = int.Parse(cepstrumSizeTextBox.Text); _hopSize = int.Parse(hopSizeTextBox.Text); _fft = new Fft(_fftSize); _cepstralTransform = new CepstralTransform(_cepstrumSize, _fftSize); var pitchTracker = new Pitch((float)_fftSize / _signal.SamplingRate, (float)_hopSize / _signal.SamplingRate); _pitchTrack = pitchTracker.Track(_signal); // Show chart in frequency domain UpdateAutoCorrelation(); UpdateSpectra(); // obtain spectrogram _stft = new Stft(_fftSize, _hopSize, WindowTypes.Rectangular); var spectrogram = _stft.Spectrogram(_signal); specNoComboBox.DataSource = Enumerable.Range(1, _pitchTrack.Count).ToArray(); _specNo = 0; spectrumPanelAfterFilter.refresh(); signalPanelAfterFilter.refresh(); lblNote.Visible = false; savePWMDataToolStripMenuItem.Enabled = true; }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); if (ofd.ShowDialog() != DialogResult.OK) { return; } _waveFileName = ofd.FileName; using (var stream = new FileStream(_waveFileName, FileMode.Open)) { var waveFile = new WaveFile(stream); _bitDepth = waveFile.WaveFmt.BitsPerSample; _signal = waveFile[Channels.Average]; } _stft = new Stft(512, 64, _windowType); _spectrogram = _stft.Spectrogram(_signal); //var processed = _stft.Inverse(_stft.Direct(_signal)); //_processedSignal = new DiscreteSignal(_signal.SamplingRate, processed); // 1) check also this: var mp = _stft.MagnitudePhaseSpectrogram(_signal); var processed = _stft.ReconstructMagnitudePhase(mp); _processedSignal = new DiscreteSignal(_signal.SamplingRate, processed); // 2) or check this: //var processed = new GriffinLimReconstructor(_spectrogram, _stft).Reconstruct(); //_processedSignal = new DiscreteSignal(_signal.SamplingRate, processed); signalPanel.Gain = 120; signalPanel.Signal = _signal; processedSignalPanel.Gain = 120; processedSignalPanel.Signal = _processedSignal; spectrogramPanel.Spectrogram = _spectrogram; //// StftC - has complex FFT //// RealFFT-based Stft is 30% faster! //var sr = new Stft(2048, 256); //var sc = new StftC(2048, 256); //var sw = new Stopwatch(); //sw.Start(); //for (var i = 0; i < 10; i++) //{ // var processed1 = sr.Inverse(sr.Direct(_signal)); // _processedSignal = new DiscreteSignal(_signal.SamplingRate, processed1); //} //sw.Stop(); //var t1 = sw.Elapsed; //sw.Reset(); //sw.Start(); //for (var i = 0; i < 10; i++) //{ // var processed1 = sc.Inverse(sc.Direct(_signal)); // _processedSignal = new DiscreteSignal(_signal.SamplingRate, processed1); //} //sw.Stop(); //var t2 = sw.Elapsed; //MessageBox.Show(t1 + " " + t2); }