tags:

views:

569

answers:

3

Here is the situation:
User looks something up.

  • Alert sound is played because there is a notice on the item he looked up
  • User closes the notice - the application continues to retrieve information
  • User is sent a 'ding' telling them the information has finished retrieving
  • Application begins sending certain attributes to TextToSpeech
  • The application encounters a notice second, internal notice on the data and sends another alert (texttospeech is paused, then resumed after the alert finishes)
  • Text to speech is finished, another 'ding' is played letting the user know that is has read everything

We currently use a queue to process sounds in an orderly fashion to prevent overlapping of sounds. We currently only play a sound from the queue when the SoundAdded event is called. This is a custom event we made to be raised when we add a sound to the queue. Currently, only one sound will be played per calling of the event. We have run into the problem where after certain sounds are played, they will 'lock' the queue, preventing further sounds from being process. We got around this by always 'unlocking' the queue even if a sound doesn't play. However, this still leaves us with the problem of the queue getting backed up with sounds to play.

The only method I can think of to solve this is to add a loop to keep trying to play the sound if there is still a sound waiting to be played. Currently, the main thread is handling sounds, I would probably need to move sound handling to a separate thread, but I'm not sure what the best method of handing the sound would be.

So... my question... Is there a good sound library that we can use that includes an event for the end of a sound. Or... what would be the best way to create such a thing?

+2  A: 

I don't know if there's already a .NET library that would let you do this, but I think you could pretty easily P/Invoke PlaySound from the Windows API and use it to play your sounds. As long as you don't specify the SND_ASYNC flag, it should block until the sound is done playing at which point you can play the next sound. As you mentioned, you'll definitely want to do this in a different thread.

Jon Norton
We are currently using PlaySound from the windows API, and we will almost certainly move sounds to another thread and play them SND_SYNC. One of the other developers suggested using a consumer thread that sleeps until the SoundAdded event is raised in the queue.
Justin Drury
Thanks for all the help. We've finally gotten the sounds working the way we wanted.
Justin Drury
+2  A: 

Extending Jon's answer: in .NET 2.0 and above, you can use My.Computer.Audio.Play with the AudioPlayMode.WaitToComplete option.

edit: To use this in a C# context, see How to: Use the My Namespace (C# Programming Guide) from Microsoft.

Stobor
I'm not entirely sure how I would get this to work in C#. Looking at it in the MSDN, it looks like it is VB.NET only.
Justin Drury
You can still use things in the Microsoft.VisualBasic namespace from C# or any other .NET language so I would go this way rather than P/Invoke with PlaySound.
Jon Norton
@Justin: Here's a sample from MS: http://msdn.microsoft.com/en-us/library/ms173136.aspx
Stobor
A: 

If you play the sounds synchronously (on new threads, that you manage) you will know when they complete.

But you seem to have two problems; one is knowing when sounds finish, and the other is the queue building up. If you have sounds that can be customised, how will your application be affected if your users choose very long recordings (10 seconds+ for example) as the sound?

I would suggest that you should adopt the same approach as displaying filenames on a UI during processing. That is to say, you show the most recent filename, not every single one (otherwise the queue of filenames grows and your UI lags). If you can, you should either play sounds for events as and when they occur (allowing overlapping sounds) or you should drop (not play) sounds if the sound is not the most recent in the queue.

Bernhard Hofmann