private void Timer_Tick(object sender, EventArgs e) { double[] newAudio = listener.GetNewAudio(); spec.Add(newAudio, process: false); double multiplier = Brightness / 20.0; if (spec.FftsToProcess > 0) { Stopwatch sw = Stopwatch.StartNew(); spec.Process(); //if (SpectrogamImageSource != null) spec.SetFixedWidth(1024);// (int)SpectrogamImageSource.Width); Bitmap bmpSpec = new Bitmap(spec.Width, spec.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); using (var bmpSpecIndexed = spec.GetBitmap(multiplier, Decibels, Roll)) using (var gfx = Graphics.FromImage(bmpSpec)) using (var pen = new System.Drawing.Pen(System.Drawing.Color.White)) { gfx.DrawImage(bmpSpecIndexed, 0, 0); if (Roll) { gfx.DrawLine(pen, spec.NextColumnIndex, 0, spec.NextColumnIndex, SpectrogramHeight); } } sw.Stop(); //SpectrogamImageSource.Dispose(); SpectrogamImageSource = ImageHelpers.BitmapToImageSource(bmpSpec); VerticalScaleImageSource = ImageHelpers.BitmapToImageSource(spec.GetVerticalScale(75)); RenderTime = $"Render time: {sw.ElapsedMilliseconds:D2} ms"; Peak = $"Peak (Hz): {spec.GetPeak().freqHz:N0}"; } TotalTime = $"Time: {listener.TotalTimeSec:N3} sec"; FftsProcessed = $"FFTs processed: {spec.FftsProcessed:N0}"; //Default max on the progressbar is 100 so hardcoding it here for now Amplitude = (int)(listener.AmplitudeFrac * 100); SpectrogramHeight = spec.Height; VerticalScaleImageSource = null; VerticalScaleImageSource = ImageHelpers.BitmapToImageSource(spec.GetVerticalScale(LEGEND_WIDTH)); }
private void DisplaySpectrogram() { //Display Settings double brightness = sliderBrightness.Value; double specGridWidth = this.ActualWidth - ControlsGrid.ActualWidth; specGridWidth = specGridWidth < 0 ? 0 : specGridWidth; ScrollBar scrollBar = (ScrollBar)scrollViewerSpec.Template.FindName("PART_VerticalScrollBar", scrollViewerSpec); double scrollBarSpace = scrollBar.ActualWidth * 2 + scrollViewerSpec.Margin.Left; SpecGrid.MaxWidth = specGridWidth; spec.SetFixedWidth((int)((specGridWidth - scrollBarSpace))); BitmapSource source = spec.GetBitmapSource(brightness, dB: false, roll: false); TransformedBitmap trans = new TransformedBitmap(source, new ScaleTransform(zoomFactor, zoomFactor)); imageSpec.Source = trans; }
private async Task audio2spectrum_saveVideoAsync(string path) { var progressHandler = new Progress <string>(value => { status_txt.Text = value; }); var progress = progressHandler as IProgress <string>; await Task.Run(() => { long frameCount; try { double samplesPerFrame = ((double)audio2spectrum_sampleRate) * frameRate.Denominator / frameRate.Numerator; double totalFrameCount = Math.Ceiling(audio2spectrum_samples.Length / samplesPerFrame); int roundedSamplesPerFrame = (int)Math.Ceiling(samplesPerFrame); int outputWidth = 50; int outputHeight = 50; double samplesPerPixel = samplesPerFrame / outputWidth; // Now find closest fft size (take next highest) int fftSize = (int)Math.Pow(2, Math.Ceiling(Math.Log(samplesPerPixel, 2.0))); progress.Report("Audio2Spectrum: Loading spectrogram library"); Spectrogram.Spectrogram spec = new Spectrogram.Spectrogram(audio2spectrum_sampleRate, fftSize: 2048, stepSize: 50); spec.SetFixedWidth(outputWidth); //outputWidth = spec.Width; progress.Report("Audio2Spectrum: Initializing video writer"); VideoFileWriter writer = new VideoFileWriter(); writer.Open(path, outputWidth, outputHeight, frameRate, VideoCodec.FFV1); /* * Console.WriteLine("width: " + reader.Width); * Console.WriteLine("height: " + reader.Height); * Console.WriteLine("fps: " + reader.FrameRate); * Console.WriteLine("codec: " + reader.CodecName); * Console.WriteLine("length: " + reader.FrameCount); */ frameCount = (long)totalFrameCount; // Enlarge the array to make sure we don't end up accessing nonexisting samples. We make it a tiny bit bigger than maybe necessary, just to be safe. (To be honest, I am just too lazy to calculate the precise number we need) /*if((long)Math.Ceiling(frameCount * samplesPerFrame) > audio2spectrum_samples.Length) * { * progress.Report("Audio2Spectrum: Resizing array"); * Array.Resize<double>(ref audio2spectrum_samples, (int)Math.Ceiling(frameCount * samplesPerFrame)); * }*/ double[] frameSampleBuffer = new double[roundedSamplesPerFrame]; int currentFrame = 0; long currentStartSample = 0; progress.Report("Audio2Spectrum: Starting video generation"); Bitmap tmp; for (int i = 0; i < frameCount; i++) { currentStartSample = (long)Math.Floor(i *samplesPerFrame); // Doing this branching here now because the resizing the array first was just way way too slow and memory hungry if (currentStartSample >= audio2spectrum_samples.Length) // Even the first sample is already outside the bounds, just make empty array. { frameSampleBuffer = new double[roundedSamplesPerFrame]; } else if ((currentStartSample + (roundedSamplesPerFrame - 1)) > (audio2spectrum_samples.Length - 1)) // Copy as many samples as possible { long difference = (currentStartSample + (roundedSamplesPerFrame - 1)) - (audio2spectrum_samples.Length - 1); frameSampleBuffer = new double[roundedSamplesPerFrame]; Array.Copy(audio2spectrum_samples, currentStartSample, frameSampleBuffer, 0, roundedSamplesPerFrame - difference); } else { Array.Copy(audio2spectrum_samples, currentStartSample, frameSampleBuffer, 0, roundedSamplesPerFrame); } spec.Add(frameSampleBuffer); tmp = spec.GetBitmapMel(dB: true, melBinCount: outputHeight); #if DEBUG Console.WriteLine(tmp.Width + "x" + tmp.Height); #endif writer.WriteVideoFrame(tmp); if (currentFrame % 1000 == 0) { progress.Report("Audio2Spectrum: Saving video: " + i + "/" + frameCount + " frames"); } } writer.Close(); } catch (Exception e) { MessageBox.Show(e.Message); } }); status_txt.Text = "Audio2Spectrum: Completed saving video."; videoIsLoaded = true; }