public void TestAdaptiveSpectrogram() { // test variables var audioSystem = BassProxy.Instance; // 0. Get Audio Data float[] audioSamples = BassProxy.ReadMonoFromFile(WAVE_INPUT_FILEPATH, SAMPLING_RATE); var aspec = new AdaptiveSpectrogram(SAMPLING_RATE); int blockSize = aspec.GetPreferredBlockSize(); // 2048 int stepSize = aspec.GetPreferredStepSize(); // 1024 = 50% overlap // print out a normal spectrogram for comparison double[][] spec1 = FFTUtils.CreateSpectrogramLomont(audioSamples, blockSize, stepSize); var spec1M = new Matrix(spec1).Transpose(); spec1M.DrawMatrixImage("spec1_normal.png", -1, -1, true, true); // split the signal into chunks to feed the AdaptiveSpectrogram var chunks = MathUtils.Split(audioSamples, stepSize, false); int chunkLength = chunks.Count(); Console.WriteLine("Chunk count: {0}", chunkLength); int count = 1; IEnumerable <double[]> spec = new double[0][]; float[] lastChunk = null; foreach (var chunk in chunks) { Console.Write("Processing chunk: {0} \r", count); if (lastChunk != null) { // add two chunks together, because adaptive spectrogram expects 50% overlap var z = new float[lastChunk.Length + chunk.Count()]; lastChunk.CopyTo(z, 0); chunk.ToArray().CopyTo(z, chunk.Count()); // process two last chunks as one (e.g. 50% overlap) var chunkData = aspec.Process(z); // store in spectrogram spec = spec.Concat(chunkData); //var chunkM = new Matrix(chunkData); //chunkM.WriteCSV("chunkData_" + count + ".csv"); } lastChunk = chunk.ToArray(); count++; } var specM = new Matrix(spec.ToArray()).Transpose(); //specM.WriteCSV("spec_all.csv"); specM.DrawMatrixImage("spec_adaptive.png", -1, -1, true, true); }
public void TestMelFrequencyFiltering() { var audio = BassProxy.Instance; //const string fileName = @"Tests\Passacaglia, Handel-Saw-86bmp.wav"; const string fileName = @"Tests\Passacaglia, Handel-Sine-86bmp.wav"; const int sampleRate = 44100; const int fftWindowsSize = 2048; const int fftOverlap = 1024; const bool colorize = true; const int melFilters = 120; var monoSignal = BassProxy.ReadMonoFromFile(fileName, sampleRate); double[][] specNormal = FFTUtils.CreateSpectrogramLomont(monoSignal, fftWindowsSize, fftOverlap); var specNormalMat = new Matrix(specNormal).Transpose(); specNormalMat.DrawMatrixImage("spec_normal.png", -1, -1, colorize, true); // Mel Scale Filterbank // Mel-frequency is proportional to the logarithm of the linear frequency, // reflecting similar effects in the human's subjective aural perception) var melFilter = new MelFilter(fftWindowsSize, sampleRate, melFilters, 0); var specNormalMelMat = melFilter.FilterWeights * specNormalMat; specNormalMelMat.DrawMatrixImage("spec_normal_mel.png", -1, -1, colorize, true); melFilter.FilterWeights.WriteCSV("melfilter_orig.csv"); melFilter.FilterWeights.DrawMatrixGraph("melfilter_orig.png"); var melFilterBank = new MelFilterBank(0, sampleRate / 2, melFilters, fftOverlap, sampleRate); var melFilterBankMat = melFilterBank.Matrix; melFilterBankMat.WriteCSV("melfilter_new.csv"); melFilterBankMat.DrawMatrixGraph("melfilter_new.png"); var specNormalMelMatNew = melFilterBankMat * specNormalMat; specNormalMelMatNew.DrawMatrixImage("spec_normal_mel_new.png", -1, -1, colorize, true); }
public static void TestSpectrograms() { const int fftWindowSize = 4096; const int overlap = 2048; var data = AudioUtilsNAudio.GenerateAudioTestData(44100, 10); double[][] spec1 = FFTUtils.CreateSpectrogramLomont(data, fftWindowSize, overlap); var spec1M = new Matrix(spec1); spec1M.WriteCSV("spec_lomont.csv"); double[][] spec2 = FFTUtils.CreateSpectrogramExocortex(data, fftWindowSize, overlap); var spec2M = new Matrix(spec2); spec2M.WriteCSV("spec_exocortex.csv"); Assert.That(spec2, Is.EqualTo(spec1).AsCollection.Within(0.001), "fail at [0]"); double[][] spec3 = FFTUtils.CreateSpectrogramFFTW(data, fftWindowSize, overlap); var spec3M = new Matrix(spec3); spec3M.WriteCSV("spec_fftw.csv"); //Assert.That(spec3, Is.EqualTo(spec1).AsCollection.Within(0.001), "fail at [0]"); double[][] spec4 = FFTUtils.CreateSpectrogramFFTWLIB(data, fftWindowSize, overlap); var spec4M = new Matrix(spec4); spec4M.WriteCSV("spec_fftwlib.csv"); //Assert.That(spec4, Is.EqualTo(spec1).AsCollection.Within(0.001), "fail at [0]"); double[][] spec5 = FFTUtils.CreateSpectrogramFFTWLIB_INPLACE(data, fftWindowSize, overlap); var spec5M = new Matrix(spec5); spec5M.WriteCSV("spec_fftwlib_inplace.csv"); //Assert.That(spec5, Is.EqualTo(spec1).AsCollection.Within(0.001), "fail at [0]"); }
public void TestFFTAudioMatrixMethod() { // harmor_HQ.bmp = 1645 (width) x 511 (height) 32 bit // test variables const string outputDirectoryFilePath = "test"; var audioSystem = BassProxy.Instance; // 0. Get Audio Data float[] audioSamples = BassProxy.ReadMonoFromFile(WAVE_INPUT_FILEPATH, SAMPLING_RATE); int width = 1645; //int width = (audioSamples.Length - WINDOW_SIZE)/ OVERLAP; int OVERLAP = (int)((double)(audioSamples.Length - WINDOW_SIZE) / (double)width); // 1. Explode samples to the range of 16 bit shorts (–32,768 to 32,767) // Matlab multiplies with 2^15 (32768) // e.g. if( max(abs(speech))<=1 ), speech = speech * 2^15; end; MathUtils.Multiply(ref audioSamples, AUDIO_MULTIPLIER); // zero pad if the audio file is too short to perform a fft if (audioSamples.Length < (WINDOW_SIZE + OVERLAP)) { int lenNew = WINDOW_SIZE + OVERLAP; Array.Resize <float>(ref audioSamples, lenNew); } // 2. Windowing // 3. FFT #region Windowing and FFT var stft = new STFT(FFTWindowType.HANNING, WINDOW_SIZE, OVERLAP); var stftdata = stft.Apply(audioSamples); // same as specgram(audio*32768, 2048, 44100, hanning(2048), 1024); stftdata.DrawMatrixImageLogValues(outputDirectoryFilePath + "_specgram.png", true, false, -1, -1, false); var spect2 = FFTUtils.CreateSpectrogramFFTW(audioSamples, WINDOW_SIZE, OVERLAP); var stftdata2 = new Matrix(spect2).Transpose(); // same as specgram(audio*32768, 2048, 44100, hanning(2048), 1024); stftdata2.DrawMatrixImageLogValues(outputDirectoryFilePath + "_specgram2.png", true, false, -1, -1, false); var spect3 = FFTUtils.CreateSpectrogramLomont(audioSamples, WINDOW_SIZE, OVERLAP); var stftdata3 = new Matrix(spect3).Transpose(); // same as specgram(audio*32768, 2048, 44100, hanning(2048), 1024); stftdata3.DrawMatrixImageLogValues(outputDirectoryFilePath + "_specgram3.png", true, false, -1, -1, false); #endregion // the matrix are too different so comparing them always fails! //Assert.That(stftdata2, Is.EqualTo(stftdata3).AsCollection.Within(0.001), "fail at [0]"); #region Inverse FFT // Perform inverse stft as well double[] audiodata_inverse_stft = stft.InverseStft(stftdata); // divide or normalize //MathUtils.Divide(ref audiodata_inverse_stft, AUDIO_MULTIPLIER); MathUtils.Normalize(ref audiodata_inverse_stft); Export.DrawGraph(audiodata_inverse_stft, outputDirectoryFilePath + "_audiodata_inverse_stft.png"); float[] audiodata_inverse_float = MathUtils.DoubleToFloat(audiodata_inverse_stft); BassProxy.SaveFile(audiodata_inverse_float, outputDirectoryFilePath + "_inverse_stft.wav", 1, SAMPLING_RATE, 32); #endregion Assert.Pass("This test was succesful."); }