Пример #1
1
        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;
        }
Пример #2
1
        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;
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        /// <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?
                }
            }
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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();
        }
Пример #9
0
        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;
        }
Пример #10
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));
        }
Пример #11
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 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));
        }
Пример #12
0
        // 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;
        }
Пример #13
0
        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);
        }