/// <summary> /// Initializes a new windower for the specified stream with the specified window and hop size. /// </summary> /// <param name="stream">the stream to read the audio data to process from</param> /// <param name="windowSize">the window size in the dimension of samples</param> /// <param name="hopSize">the hop size in the dimension of samples</param> /// <param name="windowType">the type of the window function to apply</param> public StreamWindower(IAudioStream stream, int windowSize, int hopSize, WindowType windowType) { this.stream = stream; this.windowSize = windowSize; this.hopSize = hopSize; this.windowFunction = WindowUtil.GetFunction(windowType, WindowSize); Initialize(); }
/// <summary> /// Initializes a new windower for the specified stream with the specified window and hop size. /// </summary> /// <param name="stream">the stream to read the audio data to process from</param> /// <param name="windowSize">the window size in the dimension of samples</param> /// <param name="hopSize">the hop size in the dimension of samples</param> /// <param name="windowType">the type of the window function to apply</param> public StreamWindower(IAudioStream stream, int windowSize, int hopSize, WindowType windowType, int bufferSize = DEFAULT_STREAM_INPUT_BUFFER_SIZE) { this.stream = stream; this.windowSize = windowSize; this.hopSize = hopSize; this.windowFunction = WindowUtil.GetFunction(windowType, WindowSize); this.bufferSize = bufferSize; Initialize(); }
public InverseSTFT(IAudioWriterStream stream, int windowSize, int hopSize, int fftSize, WindowType windowType, float windowNormalizationFactor) : base(stream, windowSize, hopSize) { if (fftSize < windowSize) { throw new ArgumentOutOfRangeException("fftSize must be >= windowSize"); } frameBuffer = new float[fftSize]; fft = FFTFactory.CreateInstance(fftSize); synthesisWindow = WindowUtil.GetFunction(windowType, windowSize, windowNormalizationFactor); }
private void Window_Loaded(object sender, RoutedEventArgs e) { Title = Title + (Environment.Is64BitProcess ? " (x64)" : " (x86)"); multiTrackViewer1.ItemsSource = trackList; // INIT COMMAND BINDINGS CommandBinding playBinding = new CommandBinding(MediaCommands.Play); CommandBindings.Add(playBinding); playBinding.CanExecute += new CanExecuteRoutedEventHandler(playCommandBinding_CanExecute); playBinding.Executed += new ExecutedRoutedEventHandler(playCommandBinding_Executed); CommandBinding pauseBinding = new CommandBinding(MediaCommands.Pause); CommandBindings.Add(pauseBinding); pauseBinding.CanExecute += new CanExecuteRoutedEventHandler(pauseCommandBinding_CanExecute); pauseBinding.Executed += new ExecutedRoutedEventHandler(pauseCommandBinding_Executed); CommandBinding playToggleBinding = new CommandBinding(Commands.PlayToggle); CommandBindings.Add(playToggleBinding); playToggleBinding.Executed += new ExecutedRoutedEventHandler(playToggleBinding_Executed); //// INIT TRACKLIST STUFF //trackList.PropertyChanged += delegate(object sender2, PropertyChangedEventArgs e2) { // if (e2.PropertyName == "TotalLength") { // multiTrackViewer1.VirtualViewportMaxWidth = trackList.TotalLength.Ticks; // } //}; // INIT PLAYER player = new MultitrackPlayer(trackList); player.VolumeAnnounced += Player_VolumeAnnounced_VolumeMeter; player.CurrentTimeChanged += new EventHandler <ValueEventArgs <TimeSpan> >( delegate(object sender2, ValueEventArgs <TimeSpan> e2) { multiTrackViewer1.Dispatcher.BeginInvoke((Action) delegate { multiTrackViewer1.VirtualCaretOffset = e2.Value.Ticks; // autoscroll if (multiTrackViewer1.VirtualViewportInterval.To <= multiTrackViewer1.VirtualCaretOffset) { multiTrackViewer1.VirtualViewportOffset = multiTrackViewer1.VirtualCaretOffset; } }); }); player.PlaybackStateChanged += new EventHandler( delegate(object sender2, EventArgs e2) { multiTrackViewer1.Dispatcher.BeginInvoke((Action) delegate { // CommandManager must be called on the GUI-thread, else it won't do anything CommandManager.InvalidateRequerySuggested(); }); }); volumeSlider.ValueChanged += new RoutedPropertyChangedEventHandler <double>( delegate(object sender2, RoutedPropertyChangedEventArgs <double> e2) { player.Volume = (float)e2.NewValue; }); // INIT PROGRESSBAR progressBar1.IsEnabled = false; ProgressMonitor.GlobalInstance.ProcessingStarted += new EventHandler( delegate(object sender2, EventArgs e2) { progressBar1.Dispatcher.BeginInvoke((Action) delegate { progressBar1.IsEnabled = true; progressBar1Label.Text = ProgressMonitor.GlobalInstance.StatusMessage; win7TaskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal; win7TaskBar.ProgressValue = 0; }); }); ProgressMonitor.GlobalInstance.ProcessingProgressChanged += new EventHandler <ValueEventArgs <float> >( delegate(object sender2, ValueEventArgs <float> e2) { progressBar1.Dispatcher.BeginInvoke((Action) delegate { progressBar1.Value = e2.Value; win7TaskBar.ProgressValue = e2.Value / 100; progressBar1Label.Text = ProgressMonitor.GlobalInstance.StatusMessage; }); }); ProgressMonitor.GlobalInstance.ProcessingFinished += new EventHandler( delegate(object sender2, EventArgs e2) { progressBar1.Dispatcher.BeginInvoke((Action) delegate { progressBar1.Value = 0; progressBar1.IsEnabled = false; progressBar1Label.Text = ""; win7TaskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None; }); }); // INIT RANDOM STUFF multiTrackViewer1.KeyUp += new KeyEventHandler(delegate(object sender2, KeyEventArgs e2) { if (e2.Key == Key.Delete) { // create temporary list to avoid concurrent modification exception var selectedAudioTracks = new List <AudioTrack>(multiTrackViewer1.SelectedItems.Cast <AudioTrack>()); // delete tracks foreach (AudioTrack audioTrack in selectedAudioTracks) { if (audioTrack != null) { // 1. delete all related matches List <Match> deleteList = new List <Match>(); // 1a find all related matches foreach (Match m in multiTrackViewer1.Matches) { if (m.Track1 == audioTrack || m.Track2 == audioTrack) { deleteList.Add(m); } } // 1b delete foreach (Match m in deleteList) { multiTrackViewer1.Matches.Remove(m); } // 2. delete track trackList.Remove(audioTrack); } } e2.Handled = true; } }); // INIT FFT int fftSize = 1024; double correlation = 0; fftAnalyzer = new FFTAnalyzer(fftSize); fftAnalyzerConsumer = 2; correlationConsumer = 1; WindowFunction fftWindow = WindowUtil.GetFunction(WindowType.BlackmanHarris, fftSize); fftAnalyzer.WindowFunction = fftWindow; fftAnalyzer.WindowAnalyzed += FftAnalyzer_WindowAnalyzed_FrequencyGraph; fftAnalyzer.WindowAnalyzed += FftAnalyzer_WindowAnalyzed_Spectrogram; player.SamplesMonitored += new EventHandler <StreamDataMonitorEventArgs>(delegate(object sender2, StreamDataMonitorEventArgs e2) { if (fftAnalyzerConsumer > 0 || correlationConsumer > 0) { float[][] uninterleaved = AudioUtil.Uninterleave(e2.Properties, e2.Buffer, e2.Offset, e2.Length, true); if (fftAnalyzerConsumer > 0) { fftAnalyzer.PutSamples(uninterleaved[0]); // put the summed up mono samples into the analyzer } if (correlationConsumer > 0) { correlation = CrossCorrelation.Correlate(uninterleaved[1], uninterleaved[2]); Dispatcher.BeginInvoke((Action) delegate { correlationMeter.Value = correlation; }); } } }); spectrogram.SpectrogramSize = fftSize / 2; }
public static double FrequencyDistribution(byte[] x, byte[] y) { if (x.Length != y.Length) { throw new ArgumentException("interval lengths do not match"); } int samples = x.Length / 4; float[] xF = new float[samples]; float[] yF = new float[samples]; Buffer.BlockCopy(x, 0, xF, 0, x.Length); Buffer.BlockCopy(y, 0, yF, 0, y.Length); int fftSize = 2048; // max FFT size // if there are less samples to analyze, find a fitting FFT size while (fftSize > samples) { fftSize /= 2; } int hopSize = fftSize / 8; if (fftSize < 64) { throw new Exception("FFT might be too small to get a meaningful result"); } double[] xSum = new double[fftSize / 2]; double[] ySum = new double[fftSize / 2]; float[] buffer = new float[fftSize]; if (windowFunction == null || windowFunction.Size != fftSize) { windowFunction = WindowUtil.GetFunction(WindowType.Hann, fftSize); } var fft = new PFFFT.PFFFT(fftSize, PFFFT.Transform.Real); int blocks = (samples - fftSize) / hopSize; for (int block = 0; block < blocks; block++) { Array.Copy(xF, block * hopSize, buffer, 0, buffer.Length); FrequencyDistributionBlockProcess(buffer, xSum, fft); Array.Copy(yF, block * hopSize, buffer, 0, buffer.Length); FrequencyDistributionBlockProcess(buffer, ySum, fft); } fft.Dispose(); // remove DC offset xSum[0] = 0; ySum[0] = 0; double xScalarSum = xSum.Sum(); double yScalarSum = ySum.Sum(); double result = 0; for (int i = 0; i < fftSize / 2; i++) { result += Math.Abs(xSum[i] / xScalarSum - ySum[i] / yScalarSum); } return(1 - result); }
private void Generate(FFTLibrary fftLib) { // FFT resources: // http://www.mathworks.de/support/tech-notes/1700/1702.html // http://stackoverflow.com/questions/6627288/audio-spectrum-analysis-using-fft-algorithm-in-java // http://stackoverflow.com/questions/1270018/explain-the-fft-to-me // http://stackoverflow.com/questions/6666807/how-to-scale-fft-output-of-wave-file /* * FFT max value test: * 16Hz, 1024 samplerate, 512 samples, rectangle window * -> input min/max: -1/1 * -> FFT max: 256 * -> FFT result max: ~1 * -> FFT dB result max: ~1 * * source: "Windowing Functions Improve FFT Results, Part I" * => kann zum Normalisieren für Fensterfunktionen verwendet werden */ float frequency = float.Parse(frequencyTextBox.Text); int ws = (int)windowSize.Value; float frequencyFactor = ws / frequency; int sampleRate = int.Parse(sampleRateTextBox.Text); SineGeneratorStream sine = new SineGeneratorStream(sampleRate, frequency, new TimeSpan(0, 0, 1)); float[] input = new float[ws]; sine.Read(input, 0, ws); //// add second frequency //SineGeneratorStream sine2 = new SineGeneratorStream(44100, 700, new TimeSpan(0, 0, 1)); //float[] input2 = new float[ws]; //sine2.Read(input2, 0, ws); //for (int x = 0; x < input.Length; x++) { // input[x] += input2[x]; // input[x] /= 2; //} //// add dc offset //for (int x = 0; x < input.Length; x++) { // input[x] += 0.5f; //} inputGraph.Values = input; WindowFunction wf = WindowUtil.GetFunction((WindowType)windowTypes.SelectedValue, ws); float[] window = (float[])input.Clone(); wf.Apply(window); input2Graph.Values = window; float[] fftIO = (float[])window.Clone(); if (fftLib == FFTLibrary.ExocortexDSP) { // This function call indirection is needed to allow this method execute even when the // Exocortex FFT assembly is missing. ApplyExocortexDSP(fftIO); } else if (fftLib == FFTLibrary.FFTW) { FFTW.FFTW fftw = new FFTW.FFTW(fftIO.Length); fftw.Execute(fftIO); } else if (fftLib == FFTLibrary.PFFFT) { PFFFT.PFFFT pffft = new PFFFT.PFFFT(fftIO.Length, PFFFT.Transform.Real); pffft.Forward(fftIO, fftIO); } //// convert real input to complex input with im part set to zero //float[] fftIO = new float[ws * 2]; //int i = 0; //for (int j = 0; j < window.Length; j++) { // fftIO[i] = window[j]; // i += 2; //} //Fourier.FFT(fftIO, fftIO.Length / 2, FourierDirection.Forward); fftOutputGraph.Values = fftIO; float[] fftResult = new float[ws / 2]; //FFTUtil.Results(fftIO, fftResult); // transform complex output to magnitudes float sum = 0; int y = 0; for (int x = 0; x < fftIO.Length; x += 2) // / 2 { fftResult[y] = FFTUtil.CalculateMagnitude(fftIO[x], fftIO[x + 1]) / ws * 2; sum += fftResult[y++]; } //FFTUtil.Results(fftIO, fftResult); //// adjust values for the sum to become 1 //float sum2 = 0; //for (int x = 0; x < fftResult.Length; x++) { // fftResult[x] /= sum; // sum2 += fftResult[x]; //} //Debug.WriteLine("sum / sum2: {0} / {1}", sum, sum2); fftNormalizedOutputGraph.Values = fftResult; // convert magnitudes to decibel float[] fftResultdB = new float[fftResult.Length]; //for (int x = 0; x < fftResult.Length; x++) { // fftResultdB[x] = (float)VolumeUtil.LinearToDecibel(fftResult[x]); //} FFTUtil.Results(fftIO, fftResultdB); fftdBOutputGraph.Values = fftResultdB; summary.Text = String.Format( "input min/max: {0}/{1} -> window min/max: {2}/{3} -> fft min/max: {4}/{5} -> result min/max/bins/sum: {6}/{7}/{8}/{9} -> dB min/max: {10:0.000000}/{11:0.000000}", input.Min(), input.Max(), window.Min(), window.Max(), fftIO.Min(), fftIO.Max(), fftResult.Min(), fftResult.Max(), fftResult.Length, sum, fftResultdB.Min(), fftResultdB.Max()); }