Naudio: How to play MP3 and WAV file? - c#

Okay, I know this sounds like a very easy question to some but I am really stuck here. Indeed, I am building an audio player using Naudio and I have realized that in many tutorials people always show easy ways to get you started. However, in my opinion, they always forget to show how things are actually done in a real application. For example, when playing music with Naudio, I would do something like:
Void PlayAudioMusic(string FilePath)
{
using (var ms = File.OpenRead(FilePath))
using (var rdr = new Mp3FileReader(ms))
using (var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr))
using (var baStream = new BlockAlignReductionStream(wavStream))
using (var waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
{
waveOut.Init(baStream);
waveOut.Play();
}
}
This is great for testing in a simple console application. This however isn't useful if you're actually building a serious application. For example, what many tutorials never say is for example how to handle the most critical things such as:
Disposing resource and when to do it
The best ways to handle different exceptions
What to do before you pause, stop, rewind or even exit the application
Other stuffs I don't even know exist.
Since I am going through this process and have notice that my application has way too many exceptions thrown, can someone please share like a wrapper class around Naudio that he used to handle this. I am sure this will answer many of the trouble some of us have been going through when trying to use Naudio.
Thanks.

To Dispose the unmanaged resources, you call the Close method of the WaveStreams. The "when to do it" part is rather obvious... Do you really don't know when it is the right time to Dispose unmanaged resources? You Dispose them when you are not going to use them anymore.
I can't answer this one. Sorry.
To Pause, you call the Pause method of the WaveOut object. To rewind, you call the Seek method of the WaveStream. To Stop, don't call the Stop method of the WaveOut. You must call Pause and then call the Seek method of the WaveStream to go to the beginning of the buffer.
The most probable cause of all the Exceptions being thrown is because most of the code you shown is actually unnecessary. All you should need to do to play a MP3 file is:
WaveStream mainOutputStream = new Mp3FileReader(path_of_the_file_you_want_to_play);
WaveChannel32 volumeStream = new WaveChannel32(mainOutputStream);
WaveOutEvent player = new WaveOutEvent();
player.Init(volumeStream);
player.Play();
I personally prefer to use WaveOutEvent instead of WaveOut because it does not require you to be using Windows Forms or WPF, enabling you to use NAudio for absolutely any kind of application you want make with C#, even XNA games. Also, WaveOutEvent has a very fire-and-forget usability, and it's constructor does not even ask for a callback.
All these WaveStreams meant for changing stuff about the buffer (such as Sample Rate of Bit Depth) are just ways of asking for NAudio to throw an exception. They rarely work when used like this. If you want to convert some stuff of the buffers, you have to call some Static methods of the WaveFormatConversionStream (their names are self-explanatory, at least.)

Related

Diposal of SoundPlayer and Resource in C#

I am working on a kind of (at least closely related) Virtual Keyboard and want to include some clicking Sound. For testing I have just used
SoundPlayer player = new SoundPlayer(Resource2.click);
player .PlaySync();
Now I obviously do not want it to be Sync since it would freeze the keyboard.
Instead, if a new button gets clicked while the previous click-Sound is still playing, I would prefer the first one to stop and just start over with the new click. It is always the same sound for every button, approx. 1 sec long, but there might be a lot of events (typing speed)
So I planned to just go with
//Startup
SoundPlayer player = new SoundPlayer(Resource2.click);
player.Load();
and
//ButtonClickEvent
player.Stop()
player.Play()
//More stuff
Though while looking around I found this thread:
How to use System.Media.SoundPlayer to asynchronously play a sound file?
My way of doing it would be his Attempt #1, but he seems to have a problem:"SoundPlayer and the embedded resource stream are not immediately disposed".
Now I am not quite sure what is meant by this. Does this only concern memory issues if I have many different SoundPlayer objects? Or is this something else which might give me problems on the long term, which I did not see in my first tests. This is my main question. Additionally: Is there something else I overlooked that might give problems once in a while? E.g. stopping the player while it is not running multiple times?

repeatedly using a Local Variable with `using` statement vs. repeatedly calling a Non-Local Variable ?

I just got notice about using "Using", as it´s very efficient in it´s way to handle disposable objects. As it will only use them in that certain command, then it will be removed.
But i don´t know where the limit goes, as i can´t see that you Always want´s to use it, and It´s Always efficient.
So my question here is. Is this a good way to use it, or is it unnecessary or will it even hurt my performance in any way?
void Sending(object sender, NAudio.Wave.WaveInEventArgs e)
{
using (UdpClient udpclient = new UdpClient())
{
if (connect == true && MuteMic.Checked == false)
{
udpclient.Send(e.Buffer, e.BytesRecorded, otherPartyIP.Address.ToString(), 1500);
}
}
}
It´s an event from NAudio, and what it does is, While WaveInEvent has any data, do this.
WaveInEvent is from an input device, so if i start recording with it (example mic), data will be available (the mic audio), and then i can do what i want with that data. In this case i am sending it over UDP.
But as you can see, i am using a local udpclient.
I don´t know if i should be using it there, or if i should have one created before so it can reuse it all the time, instead of making a new.
Hope i didn´t mess up my explanation to bad.
Is this a good way to use it, or is it unnecessary or will it even hurt my performance in any way?
You should always use it when any object implementes IDisposable. It doesn't have any negative impact on performance. All it will do is to ensure that object is properly disposed.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. Your code will more or less look like this for the compliler.
{
UdpClient udpclient = new UdpClient();
try
{
if (connect == true && MuteMic.Checked == false)
{
udpclient.Send(e.Buffer, e.BytesRecorded, otherPartyIP.Address.ToString(), 1500);
}
}
finally
{
if (udpclient!= null)
((IDisposable)udpclient).Dispose();
}
}
You can read the details of using here.
As Microsoft says, generally "As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement."using Statement (C# Reference) - MSDN - Microsoft. But sometimes, its a better idea to define your object as a non-local variable and call it in your local code whenever you need it rather than instantiate the object every time you want to use it and then dispose it. In your case, because you want to constantly send data with your UdpClient, repeatedly instantiating and disposing the object (that is done by using statement), might reduce the performance (in your words hurts your performance :) ); So I prefer to define a non-local variable in my application, call it whenever I want and then Dispose it when no longer needed.

FMOD gapless loop and sequence playback

I started using FMOD library, because I need to play sounds without gaps in C# application (both one sound in a loop and many sounds in a sequence). Can anyone show me the correct way to do it? I tried make something based on examples, but it's not working as I would like it to work.
Firstly, when I try to set if the sound is looped, while it's playing,
if (value)
sound1.setMode(FMOD.MODE.LOOP_NORMAL);
else
sound1.setMode(FMOD.MODE.LOOP_OFF);
nothing is going on. It only works fine, when I set th mode, before I start playback.
The second issue is: how can I be notified that the sound has reached the end? I tried to do it this way:
channel.setCallback(eofCallback);
where eofCallback is a reference to SoundEndCallback
private FMOD.RESULT SoundEndCallback(IntPtr channelraw, FMOD.CHANNEL_CALLBACKTYPE type, IntPtr commanddata1, IntPtr commanddata2)
{
FMOD.RESULT result;
if (type == FMOD.CHANNEL_CALLBACKTYPE.END)
{
//logic here
}
return FMOD.RESULT.OK;
}
But this callback is reached only when I manually invoke stop() on channel, not when the track ends.
Or eventually do you know any other library that would give me easily what I need? I chose FMOD, because it's quite popular, but I don't like its oldschool C++-like way of coding (no events, no exceptions, etc.).
And I have teh answer for my second question: to get notified you have to firstly set callback as mentioned before, and after that you've got to use System.update() method (it must be called periodically in a loop). This is a kind of polling,
To set the loop mode of a sound at runtime use Channel::setMode, Sound::setMode is like setting the defaults for any channels played from that sound (it won't affect currently playing sounds).
As for Channel::setCallback, make sure you are calling System::update regularly to have the callbacks fire for events like the sound playing to the end.

Memory problem with application in C# Windows Forms

I have an application in C# which reserves too much memory when it wasn't supposed to. The executable is ~100Kb and the whole application is a couple thousands lines of code.
It's main component, has a timer which is responsible of creating events (instances of a class with a couple of attributes) and sending them to this http://timeline.codeplex.com/. The way the timeline accepts events, is by calling a ResetEvents function and passing a list of events. Because I have a timer, I put that inside the timer's code.
Running it like this, the application goes up to 300Mb of memory and I just end it to avoid crashing. If I remove the call of ResetEvents from the timer, then the application runs more smoothly consuming 60-70Mb. The application without the timeline, should run at 10-20Mb. There are no graphics or anything that could possibly use more than that. My guess is that something might be wrong with the timeline.
EDIT:
Here's a part of the code:
List<TimelineEvent> events = new List<TimelineEvent>();
...
inside timer
TimelineLibrary.TimelineEvent newevent = new TimelineLibrary.TimelineEvent();
...
newevent.StartDate = starttime;
newevent.EndDate = endtime;
newevent.Id = id;
newevent.Title = title;
newevent.Description = description;
newevent.Link = url;
newevent.EventColor = color;
events.Add(newevent);
timeline.ResetEvents(events);
...
This code is inside the timer. I just create a TimelineEvent, add it to a list and call ResetEvents. Removing that last line, doesn't cause the memory problem.
Since it is very hard to see what your problem is without more code, I suggest trying some kind of memory profiler to locate where and when the memory gets allocated.
Try for example RedGates Memory Profiler, they have a time-based trial.
Follow this walk-through to get up to speed and learn a bit what to look for and how.
For more options regarding .NET memory profilers, see this thread.
Good luck!
What is the type of the events variable you passed to ResetEvents?
Without seeing the code, the only suspicious behavior I can in what you did post, is that perhaps the ResetEvents method does not really clear the collection it receives, but instead does something on the state of the timeline variable.
Using a memory profiler is a great idea. If you expect people here to help you find a memory leak otherwise, please post more of your code. Ideally, you could reproduce the problem with minimal code and then post that.

Should I use exceptions in C# to enforce base class compatibility?

On one hand, I'm told that exceptions in C# are 'expensive', but on the other, I'm stuck on how to implement this.
My problem is this: I'm making a Stream derivitive, that wraps a NetworkStream. Now, the problem I'm facing is this: Read(byte[] buffer, int offset, int count). From the Stream docs for the function:
Returns:
... or zero (0) if the end of the stream has been reached.
The problem is, in the protocol I'm implementing the remote side can send an "end of record" token, or a "please respond" token. Obviously, if this happens at the start of the Read() this causes problems, since I need to return from the function, and I havn't read anything, so I need to return 0, which means the stream is finished, but it isn't... is a EndOfRecordException or similar justified in this case? And in this case, should it aways be thrown when this token is encountered (at the start of the Read() call and make sure these tokens are always at the start by returning early) so that there is some sort of pattern to how these tokens should be handled.
Edit: For what it's worth, these tokens generally come through 3-10 times a second. At the most, I wouldn't expect more than 25 a second.
Exceptions aren't really all that expensive - but they also aren't necessarily the best way to manage expected/normal flow.
To me, it sounds like you aren't actually implementing a Stream - you are encapsulating a stream into a "reader". I might be inclined to write a protocol-specific reader class with suitable methods to detect the end of a record, or Try... methods to get data or return false.
It sounds like you shouldn't really be deriving from Stream if your class is concerned with records. Streams don't generally interpret their data at all - they're just a transport mechanism of data from one place to another.
There have been cases like ZipInputStream in Java which end up being very confusing when a single InputStream effectively has several streams within it, and you can skip between them. Such APIs have been awful to use in my experience. Providing a separate class to implement the "record splitting" which can provide a stream for the data within a record sounds cleaner to me. Then each stream can behave consistently with normal streams. No need for new exceptions.
However, I'm just guessing at your context based on the limited information available. If you could give more details of the bigger picture, that would help.
It's not such a big deal performance-wise, but still... Exceptions are intended for, well, exceptions. Situations that are "unusual". If that is the way the underlying stream behaves, then your stream should be able to handle it. If it can, it should handle it on its own. If not, you can have the user set some callback or something which will get called when you receive a "please respond" token.
I believe that Stream-derived class should deal only with streaming issues and adhere to Stream semantic contract. All higher-level logic (interpreting EOF and EOR tokens) should be placed in some other class.
Maybe you can create an enum that you return, this enum can contain items for EndOfRecord, EndOfStream, ReadOk or whatever you need.
The actual read data can be passed as an out parameter.

Categories