Saturday, 10 October 2009

NAudio 1.3 Release Notes

It has been well over a year since I last released a version of NAudio, and since then there have been loads of new features and bugfixes added, so I have decided it is time for a new drop. Another reason for releasing now is that NAudio has been getting a lot more attention recently, mainly due to StackOverflow (and even got a mention on This Week on Channel 9).

As always, head to CodePlex to download the latest source code and binaries.

What’s New?

  • WaveOut has a new constructor (this is breaking change), which allows three options for waveOut callbacks. This is because there is no “one size fits all” solution, but if you are creating WaveOut on the GUI thread of a Winforms or WPF application, then the default constructor should work just fine. WaveOut also allows better flexibility over controlling the number of buffers and desired latency.
  • Mp3FileReader and WaveFileReader can have a stream as input, and WaveFileWriter can write to a stream. These features are useful to those wanting to stream data over networks.
  • The new IWaveProvider interface is like a lightweight WaveStream. It doesn’t support repositioning or length and current position reporting, making the implementation of synthesizers much simpler. The IWavePlayer interface takes an IWaveProvider rather than WaveStream. WaveStream implements IWaveProvider, so existing code continues to work just fine.
  • Added in LoopStream, WaveProvider32 and WaveProvider16 helper classes. Expect more to be built upon these in the future.
  • I have also started using the WaveBuffer class. This clever idea from Alexandre Mutel allows us to trick the .NET type system into letting us cast from byte[] to float[] or short[]. This improves performance by eliminating unnecessary copying and converting of data.
  • There have been many bugfixes including better support for VBR MP3 file playback.
  • The mixer API has had a lot of bugs fixed and improvements, though differences between Vista and XP continue to prove frustrating.
  • The demo project (NAudioDemo) has been improved and includes audio wave-form drawing sample code.
  • There is now a WPF demo as well (NAudioWpfDemo), which also shows how to draw wave-forms in WPF, and even includes some preliminary FFT drawing code.
  • The WaveIn support has been updated and enhanced. WaveInStream is now obsolete.
  • WASAPI audio capture is now supported.
  • NAudio should now work correctly on x64 operating systems (accomplished this by setting Visual Studio to compile for x86).

As usual, I welcome any feedback on this release. Do let me know if you use NAudio to build anything cool.

58 comments:

n2o said...

I guess there is a problem in dsp/BiQuadFilter.cs Transform():
for(int n = 0; n < inBuffer.Length; n++)
{
y[n] = (float) (
(b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]
- (a1/a0)*y[n-1] - (a2/a0)*y[n-2]);
}

Index out of boudaries.

Mark H said...

hi n20 - I think you're the first person to use that function in about 6 years. I'm hoping to integrate a much better effects framework I did for the Skype Voice Changer project in the next version of NAudio

n2o said...

Thanks for replay,
I need simple low latency spectrum visualization just for 3-6 bands. So I guess several BiQuadFilters is the best choice.
It`s sad that I failed utilise this nice nubble from NAudio.

n2o said...

Seems it works since initial n value I changed from 0 to 2. Low pass filter seems to be working, maybe later I`ll check outputs quality.

Mark H said...

cool, let me know how you get on. I think the original algorithm came from musicdsp.org

Ramon said...

Congratulations with this new release!

n2o said...

Hi Mark,
Today I tried FFT function from NAudio, works fine. Seems simplier resort for my task than using BiQuadFilter.

I have another problm with selecting input device. WaveIn.DeviceCount shows only one input device however in windows Record Control panel i can pick from several(Mic, line-in etc). Maybe is any resort from selecting from own application? (running on XP)

Mark H said...

n2o, this is where it can get a bit confusing. The number of input sources your soundcard can support is not the same as the number of devices. In other words, you have a single input device, which can provide audio from a number of sources. It is possible to use the mixer API from NAudio to select which source you actually want to record from, although this can be a frustrating process.

n2o said...

One more obscurity about waveIn recording channels, how it works in mono mode, record only left or right or averages samples from both?

Mark H said...

n2o, that is entirely dependent on your sound card driver. I would guess left channel only, but I don't know for sure. Some inputs really are mono already, such as those on pro audio cards.

box86rowh said...

Hey Mark,
Looks like some amazing work you've got into NAudio.

I am looking at your re-sampler project example and wondering if there is a simple way to use a similar set of commands to loop through a wave file's samples and tweak the volume before writing out to a new file. I would like to not just reset the volume level on the entire file, but have a minute control over the volume at any given moment in the audio so I can fade in and out throughout the file and whatnot.
Thanks for any input!
Jason

@lx - Alexandre MUTEL said...

Hi Mark, cool to see that NAudio is constantly being improved!

Justin said...

Is there anyway of converting wma file into a MuLaw wav format

Mark H said...

hi Justin,
I'm afraid NAudio doesn't decode WMA at the moment

victorantos said...

I noticed the IAudioSessionManager2 is not yet implemented in your code.

Can you please advise me what tools you are using to get method signatures generated?

Mark H said...

hi victorantos,

the core audio code was not generated using tools but simply by examining the Windows SDK header files and trial and error. It is a slow process, and after a while I discovered that Ray Molenkamp had already done a lot of the work, so much of what is used in NAudio I have taken from his work.

Mark H said...

Hi Jason,
yes this is possible with NAudio, but will require a bit of custom code. I'm hoping to blog about how to do this in the future.

Alex Kintner said...

Mark,
NAudio looks pretty cool. I'm looking for a replacement for DirectSound now that MS has deprecated it. My app uses most of the DirectSound API. Is there an API manual or programmers guide for NAudio? I didn't see a manual on CodePlex. Thanks.

Mark H said...

Hi Alex,
the only documentation is what is on this blog (also Sebastien Gray has blogged a bit about NAudio). The best way in is to look at the source code for the NAudioDemo application.

Mark

Alex Kintner said...

Ok, thanks Mark. I'll check out the source code.

Andrey said...

Can i use your library to play an online radio streaming in MP3/WMA/OGG formats?

Mark H said...

I'm afraid we don't have ogg and wma playback support yet. We might get mp3 support in there in the future

Paul said...

Hi Mark,

Reading the release notes, I came accross this:

"Mp3FileReader and WaveFileReader can have a stream as input, and WaveFileWriter can write to a stream. These features are useful to those wanting to stream data over networks."

Are there any examples of how to have WaveFileWriter write to a stream? This would make NAudio the missing link in my project. Any help here would be greatly appreciated.

Mark H said...

Hi Paul,
WaveFileWriter does have a constructor that takes a stream. However, it does need to be repositionable, as Wave Files store the length of the data at the beginning, making a Wave file stream less flexible than it might otherwise be

CD said...

Mark,

Just want to say a big thanks for all your hard work on NAudio, have found it an incredibly useful tool. One question - now that WaveInStream is obsolete in favour of WaveIn, is it possible to change the default input device? Is there a WaveIn equivalent to WaveInStream(int deviceNumber ... ...) where deviceNumber is the mixer I wish to use?

Just to be clear, I am not asking how to change between e.g. Stereo Mix and Microphone sources (know how to do that via the Mixer API). But I have multiple WaveIn devices and want to choose between them.

Thanks in advance

CD

Mark H said...

Hi CD,
glad you're finding it useful. simply set the DeviceNumber property on WaveIn before you call StartRecording

CD said...

So simple, thanks.

One feature I have been toying with is the use of loopback capture (basically recording directly from the speakers, thus getting round soundcards that don't have e.g. Stereo Mix or the like). Have had some success thanks to a couple of links on Codeplex (most notably
http://naudio.codeplex.com/Thread/View.aspx?ThreadId=75005)
. However, this solution seems limited in C# because the GC seems to be unable to cope if there is any silence at all in the audio (basically it does record audio, but the recorded clip skips and jumps all the time). I saw a suggestion here of how to fix it -

http://blogs.msdn.com/matthew_van_eerde/archive/2008/12/10/sample-playing-silence-via-wasapi-event-driven-pull-mode.aspx

but my C++ interop skills are nowhere near good enough. Wondered if you had any other ideas of how to solve this? Would love to see this feature in the future if you are looking for ways to improve an already excellent library.

Thanks once again

CD

Anonymous said...

hi mark,

first of all thanks for this wonderful library, its really useful. secondly im currently working on my final year project and i need a real time live audio input so that i can save it to an array. how is the best way to implement this using the NAudio library?

thanks tristan

Mark H said...

hi tristan, check out my voice recorder sample application

Anonymous said...

thanks for the quick replay

i managed to do the first tutorial on sound recording and saving the file to .wav, know i dont want to save the recorded file as .wav, but i want to save the data to an array. know im using this part of the code:

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
byte[] buffer = e.Buffer;
int bytesRecorded = e.BytesRecorded;
WriteToFile(buffer, bytesRecorded);

will the recorded audio be sent to array e.buffer?

thanks tristan

Mark H said...

hi tristan,
yes e.Buffer contains the recorded audio. Just copy it into your own buffer (will need to be bug enough, and make sure you don't write over the top of what you read the previous time)

Anonymous said...

hi mark,
i just need to create a button which allows me to record from a line in from the pc sound card and save the contains into a buffer...any help? i already tried but im a newbie and i got no idea what im doing

thanks tristan

Mark H said...

hi Tristan,
you should look at my .NET voice recorder project which does exactly this.

Anonymous said...

Hi Mark,

Excellent project, professionally done.

NAudio 1.3 has problems playing an MP3 file where the MP3Header does not immediately follow the ID3Tags.

The MP3Header must be scanned after all known headers/tags have been found.
// try for a header
long headerStartPosition = input.Position;
byte[] headerBytes = reader.ReadBytes(4);

// Added -jam to play wrapped mp3 files via RIFF
headerBytes = CheckForRiff(input, reader, headerBytes);

bool bHeaderFound = false;

long readsToTry = 4000;
if (readsToTry > input.Length)
readsToTry = input.Length;

while (bHeaderFound == false && readsToTry > 0)
{

if ((headerBytes[0] == 0xFF) && ((headerBytes[1] & 0xE0) == 0xE0))
{
bHeaderFound = DecodeMpegHeader(headerBytes);
}

if(bHeaderFound == false)
{
--readsToTry;
headerBytes[0] = headerBytes[1];
headerBytes[1] = headerBytes[2];
headerBytes[2] = headerBytes[3];
headerBytes[3] = reader.ReadByte();
}
}

if (!bHeaderFound)
{
input.Position = headerStartPosition;
throw new FormatException("Not a recognised MP3 block");
}

Ron Nelson

SeanR said...

Hi Mark, firstly great library! I'm planning to use it in a 'batch mode' to create individual amplitude sample sets for a large mp3 library. I notice that your demo MeteringStream class does exactly what I need, but in realtime as it intercepts the stream en route to the WavePlayer. Do you have any example code showing simple consumption of the WaveStream with creation of volume samples - I'm getting confused by the multi channel aspects and index += 4; nature of the stream's low level format.

Again, thanks for a great library!

regards

SeanR

Icanusewindowspaint said...

Hi Mark - Tom, Sarah, Dan and Jennie here. We think that the key issue is the low latency spectrum visualisation algorithm. Really what you want to do is improve your C++ interop skills to be honest. See you in the morning!

dehghan said...

Great job, but I have a question. I searched all your blog and NAudio Discussion threads but found nothing.
I have a GSM file (recorded by asterisk), how can I play it with NAudio?

Mark H said...

@dehghan NAudio can read WAV files and use ACM codecs to decompress them. Is a GSM file a custom file format, or is it inside a WAV file? If so, you may be able to use the WaveFormatConversionStream to convert it.

Maud & Lennart said...

Hi Mark,
just like CD mentioned above,
I'd like to be able to use loopback-capturing to capture any sound output from the soundcard.

Lots of machines / drivers do not support "Record from stereomix",
so loopback is the only option in those cases.

What would be the correct way to do loopback recording with NAudio ?

Frostman said...

Hi!

First of all insanely great stuff!!
Can you tell me how could i default to 89db volume all mp3 that i play ?

Regards,
Alen

Anonymous said...

Hi Mark, Can you make YouTube Videos demonstrating how to youse NAudio?
Can you upgrade the code to use all the new features of .Net 4.0? C# 4.0?

Anonymous said...

how can I use Speex Codec With NAudio Over the internet?

So I will record audio from mic then send it to player over the internet?

Anonymous said...

can you explain NAudio internals and how stuff works in it? for beginners?

What is a wave file, and what does it consist of, etc.. and how to does NAudio work? If you can make an introduction to NAudio in YouTube it will be good. with demos.

Mark H said...

hi anonoymous, there are several articles about NAudio on this blog that you should read. Also, see the NAudio codeplex page for links to other tutorials as well as sample projects.

yousuf hasan said...

I have developed a sound capturing winform application using NAudio 1.3
on c#. The idea is to capture streaming songs through sound card. It is
working perfectly fine on windows xp.
But On vista and windows7 machine if there is no sound driver installed it also take mic voice with it
which is a big issue(i have checked it on dell laptop and if i mute the microphone than it does not capture any sound
)i just want to capture streaming song sound .NAudio 1.3 uses WASAPI audio capture for windows vista and 7.I need to solve this
issue urgently.

said...

Hi Mark,
I have downloaded the Naudio.dll (1.3). but when i try to play .mp3 file it gives "Not a recognised mp3 Block.". Please Provide me the new version of Naudio.dll so i can play mp3 files.

Thanks
Umesh(umesh.prajapati@tatvasoft.com)

Anonymous said...

Hi Mark, your work is really amazing! I would like to ask you a question ... Is there any possibility to translate the source code to vb.net 2008? I have no knowledge they in c # and I would work together to debug and optimize code, and collaborate with the project. I'm working on a radio automation software. Alejandro (alenet444@hotmail.com)

Mark H said...

hi Alejandro,
I'm afraid I won't be porting NAudio to VB.NET. It is quite usable as a library from within VB.NET if you require though.

If you want to try your hand at learning C# you will find that it is not too difficult if you know VB.NET

said...

Hi Mark,
I have downloaded the Naudio.dll (1.3). but when i try to play .mp3 file it gives "Not a recognised mp3 Block.". Please Provide me the new version of Naudio.dll so i can play mp3 files.

Thanks
Umesh(umesh.prajapati@tatvasoft.com)

Mark H said...

hi Umesh,

go to the source code tab on CodePlex and download the latest NAudio source code. I have checked in some improvements to MP3 file reading recently that might fix your issue.

Aaron de Windt said...

I am trying to get the pitch of a sound using the fft function. I created an array with the intensity of each frequency and I can get the index of the pitch. Now my problem is. How can I convert this index to a frequency.

Tor said...

Hi Mark, I'm developing a voip application and would like to use NAudio with Wasapi for low latency. However I need to do sample rate conversion. Do you have any recommendations? Can I use the resampler in Speex for real time conversion?

Mark H said...

hi Tor,
NAudio has two options for Resampling:
the DmoResamplerStream
or the WaveFormatConversionStream (uses ACM)

nastaran said...

hi I just need a simple code to use naudio so that I can play a music and then by the track bar I can change the volume

Mark H said...

@nastaran - look at the NAudioDemo project in the source code

detect peaks said...

does anyone know a way to detect for example the highest 10 peaks? I have implemented FFT Radix2.
I am using an amplitude threshold but in most cases the amplitude threshold is too high and it doesn't detect all peaks.From what I see in excel, after recording peaks, they decrease in time.
Does anyone know another way to detect the highest 10, 11 peaks( or peaks)?

Need help...PLSS

Lex Tserenjav said...

I downloaded your library from the official site. http://naudio.codeplex.com/releases/view/34249

But I couldn`t find any BufferedWaveProvider. This is not even in the source code. Can you check please?

Mark H said...

@Lex, BufferedWaveProvider is new in NAudio 1.4