// Update chart of frequency domain private void UpdateSpectra() { var fftSize = int.Parse(fftSizeTextBox.Text); var cepstrumSize = int.Parse(cepstrumSizeTextBox.Text); _hopSize = int.Parse(hopSizeTextBox.Text); if (fftSize != _fftSize) { _fftSize = fftSize; _fft = new Fft(fftSize); _cepstralTransform = new CepstralTransform(cepstrumSize, _fftSize); } if (cepstrumSize != _cepstrumSize) { _cepstrumSize = cepstrumSize; _cepstralTransform = new CepstralTransform(_cepstrumSize, _fftSize); } var pos = _hopSize * _specNo; var block = _signal[pos, pos + _fftSize]; block.ApplyWindow(WindowTypes.Hamming); var cepstrum = _cepstralTransform.Direct(block); var real = new float[_fftSize]; var imag = new float[_fftSize]; for (var i = 0; i < 32; i++) { real[i] = cepstrum[i]; } _fft.Direct(real, imag); var spectrum = _fft.PowerSpectrum(block, normalize: false).Samples; var avg = spectrum.Average(s => LevelScale.ToDecibel(s)); var spectrumEstimate = real.Take(_fftSize / 2 + 1) .Select(s => (float)LevelScale.FromDecibel(s * 40 / _fftSize - avg)) .ToArray(); spectrumPanel.Line = spectrum; spectrumPanel.Markline = spectrumEstimate; spectrumPanel.ToDecibel(); spectrumPanel.max_freq_value = spectrum.Length * _signal.SamplingRate / fftSize; }
public void TestComplexCepstrum() { var output = new float[8]; _ct.Direct(_input, output); Assert.That(output, Is.EqualTo(new[] { 5.34123949e+00, -6.07112628e-02, -3.81738790e-02, 1.43294733e-01, 6.28384672e-03, 1.79680255e-03, -5.12632421e-03, 7.09771400e-03 }).Within(1e-5)); }
private void UpdateSpectrumAndCepstrum() { var fftSize = int.Parse(fftSizeTextBox.Text); var cepstrumSize = int.Parse(cepstrumSizeTextBox.Text); _hopSize = int.Parse(hopSizeTextBox.Text); if (fftSize != _fftSize) { _fftSize = fftSize; _fft = new RealFft(fftSize); _cepstralTransform = new CepstralTransform(cepstrumSize, _fftSize); } if (cepstrumSize != _cepstrumSize) { _cepstrumSize = cepstrumSize; _cepstralTransform = new CepstralTransform(_cepstrumSize, _fftSize); } var pos = _hopSize * _specNo; var block = _signal[pos, pos + _fftSize]; //block.ApplyWindow(WindowTypes.Hamming); var cepstrum = _cepstralTransform.Direct(block); var pitch = Pitch.FromCepstrum(block); // ************************************************************************ // just visualize spectrum estimated from cepstral coefficients: // ************************************************************************ var real = new float[_fftSize]; var imag = new float[_fftSize]; for (var i = 0; i < 32; i++) { real[i] = cepstrum[i]; } _fft.Direct(real, real, imag); var spectrum = _fft.PowerSpectrum(block, normalize: false).Samples; var avg = spectrum.Average(s => LevelScale.ToDecibel(s)); var spectrumEstimate = real.Take(_fftSize / 2 + 1) .Select(s => (float)LevelScale.FromDecibel(s * 40 / _fftSize - avg)) .ToArray(); spectrumPanel.Line = spectrum; spectrumPanel.Markline = spectrumEstimate; spectrumPanel.ToDecibel(); cepstrumPanel.Line = cepstrum.Samples; cepstrumPanel.Mark = (int)(_signal.SamplingRate / pitch); }
public void TestInverseComplexCepstrum() { var ct = new CepstralTransform(8); var input = new[] { 1, 7, 2, 100, 59, 32, 11, 72f }; var output = new float[8]; var cepstrum = new float[8]; var d = ct.Direct(input, output); ct.Inverse(output, cepstrum, d); Assert.That(cepstrum, Is.EqualTo(input).Within(1e-4)); }
/// <summary> /// Pitch estimation from signal cepstrum /// </summary> /// <param name="signal"></param> /// <param name="low"></param> /// <param name="high"></param> /// <returns></returns> public static float FromCepstrum(DiscreteSignal signal, int startPos = 0, int endPos = -1, float low = 80, float high = 400, int cepstrumSize = 256, int fftSize = 512) { var samplingRate = signal.SamplingRate; if (endPos == -1) { endPos = signal.Length; } if (startPos != 0 || endPos != signal.Length) { signal = signal[startPos, endPos]; } var pitch1 = (int)(1.0 * samplingRate / high); // 2,5 ms = 400Hz var pitch2 = Math.Min(cepstrumSize - 1, (int)(1.0 * samplingRate / low)); // 12,5 ms = 80Hz var cepstralTransform = new CepstralTransform(cepstrumSize, fftSize); var cepstrum = cepstralTransform.Direct(signal); var max = cepstrum[pitch1]; var peakIndex = pitch1; for (var k = pitch1 + 1; k <= pitch2; k++) { if (cepstrum[k] > max) { max = cepstrum[k]; peakIndex = k; } } return((float)samplingRate / peakIndex); }