0 Comments

I spent a couple of hours this evening adding two features to NAudio that I have been meaning to add for a long time. They are two Windows Forms controls, one to display volume levels, and the other to display audio waveforms. They are still in a very raw state, and I will probably make some enhancements to their appearance as well as how they calculate their volume levels in the future, but they work pretty well for basic visualisation purposes. I'm also looking forward to creating their equivalents in WPF.

winforms-waveform

I've made a very short screencast to show them in action. Watch it here: http://screencast.com/t/m13tSFGAG

Want to get up to speed with the the fundamentals principles of digital audio and how to got about writing audio applications with NAudio? Be sure to check out my Pluralsight courses, Digital Audio Fundamentals, and Audio Programming with NAudio.
Vote on HN

Comments

Comment by Anonymous

Great application!

Can you display the complete waveform of the audio track in a control?

Anonymous
Comment by Mark H

that's not a specific feature, although the code wouldn't be too hard to change to do it.
I'm hoping to add some better waveform drawing support in the future including some WPF rendering

Comment by Iron Yuppie

this really is cool... did you ever get the waveform working in SL?

Comment by Mark H

I have WaveForm display working in WPF. We need to wait for Silverlight 3 before there is any point doing waveform display, as only in SL3 do we get access to the samples during playback.

Comment by splaxtek

Hi Mark been looking to use your Volume meter but i can't get them working. Tried also doing the ones with kaxaml but without success. Yours seems to be easier to use. But the thing is i need them to preview the input level before i start recording. can you please help me how i'm going to do it pls

thanks

Comment by Mark H

hi Splaxtek,
have a look at my .NET Voice Recorder project (http://voicerecorder.codeplex.com) to see how you preview volume with NAudio. It's quite simple really, just start 'recording' but only use the data you get to update the meter, don't write it to a file.

Comment by Anonymous

Hi Mark!

May I clarify that what you mean for your waveform painter is that the amplitude (I assume thats what it is painting) will never become negative? Because for waveforms, their shape when zoomed in on is usually an 'up-down' shape from the middle (which when looked at normally will result in your waveform shape).

So basically, what it does is, you read data from the WAV file, get a block from the data, and get and display the maximum amplitude or peak for that block. Is this right?

Thanks!

Anonymous
Comment by Mark H

@anonymous, yes this makes a symetric waveform based on the absolute peak over the period aggregated.

Comment by Anonymous

hi mark,
may i ask, 'have a look at my .NET Voice Recorder project to see how you preview volume with NAudio' as u stated above, i've seen them but i cant really get it. can u pls pinpoint out the functions for me? thanks a lot.

Anonymous
Comment by ben

private float lastPeak;

void recorder_MaximumCalculated(object sender, MaxSampleEventArgs e)
{
lastPeak = Math.Max(e.MaxSample, Math.Abs(e.MinSample));
}

public float CurrentInputLevel { get { return lastPeak * 100; } }

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new EventHandler(waveIn_DataAvailable), sender, e);
}
else
{
writer.WriteData(e.Buffer, 0, e.BytesRecorded);
int secondsRecorded = (int)(writer.Length / writer.WaveFormat.AverageBytesPerSecond);
waveformPainter2.AddMax(CurrentInputLevel);
if (secondsRecorded >= 30)
{
StopRecording();
}
}
}

I'm wondering y this does not work?

ben
Comment by ben

private float lastPeak;

void recorder_MaximumCalculated(object sender, MaxSampleEventArgs e)
{
lastPeak = Math.Max(e.MaxSample, Math.Abs(e.MinSample));
}

public float CurrentInputLevel { get { return lastPeak * 100; } }

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new EventHandler(waveIn_DataAvailable), sender, e);
}
else
{
writer.WriteData(e.Buffer, 0, e.BytesRecorded);
int secondsRecorded = (int)(writer.Length / writer.WaveFormat.AverageBytesPerSecond);
waveformPainter2.AddMax(CurrentInputLevel);
if (secondsRecorded >= 30)
{
StopRecording();
}
}
}

I'm wondering y this does not work?

ben
comments powered by Disqus