This project has moved. For the latest updates, please go here.

Stopped playing event

Jul 25, 2016 at 9:09 PM
I have a problem knowing when a source stream has stopped playing. If one is playing a single source stream into a WaveOut device then it is easy, just catch the event the WaveOut raises. My signal chain is a little more complex than that since I have multiple source streams being played through a mixer to the WaveOut. Basically what I have is Other providers may be added later):

<AudioFileReader><FadeInOutSampleProvider><MixingSampleProvider><WaveOut>

The MixingSampleProvider can have multiple inputs.

The FadeInOutSampleProvider I have modified to return zero bytes when it enters "Silence" state.

My issue is that I need to know when the source is silenced at the end of a fade out so that the source and that signal chain may be disposed where necessary. The fade out can occur at almost any time because the application sequences a number of files and some of the files are marked to be "exclusive" so any playing file must be faded out and then any resources used by it disposed.

Is there a way of detecting this? It seems that the "MixingSampleProvider" is almost doing this when the "ReadFully" property is true, it removes the input from the mixer. Maybe a solution is to add an event when this occurs?

Any ideas would be much appreciated,
Sid
Coordinator
Aug 1, 2016 at 11:55 AM
yes, for playback to stop, the provider being passed to WaveOut must return 0 from the Read method. To dispose mixer inputs, I've sometimes created a simple wrapper using the decorator pattern, that converts an ISampleProvider into something that can run a custom action after its Read method returns 0. In the future I'd like to add a better way of handling this in the MixingSampleProvider (probably raising events when inputs are removed).
Aug 4, 2016 at 11:36 PM
Mark, Since I wrote this I have reorganized my signal chain a little because I needed to have sample rate conversion and also handle mono files seamlessly. Inspired by your SampleChannel I have put together a channel signal flow that meets my needs. Each of these channels feeds the MixiingSampleProvider and I made a small change to that class to add an EndOfMedia event that is raised when the "read" method returns zero samples My mixer class then catches this event and takes the required action. It was very simple to add requiring only the definition of the event and raising it at the appropriate place.
    public class MixerEndOfMediaEventArgs : EventArgs
    {
        /// <summary>
        /// The stream that ended
        /// </summary>
        public ISampleProvider source {get;set;}
    }

    public event EventHandler<MixerEndOfMediaEventArgs> EndOfMedia;
And this small update to the "Read" method of MixingSampleProvider:
                    if (samplesRead == 0)
                    {
                        args.source = sources[index];
                        EndOfMedia(this,args);
                        sources.RemoveAt(index);
                    }
                    index--;
Sid
Coordinator
Sep 9, 2016 at 10:43 PM
hi Sid, I've just added something similar to this. Let me know if it meets your needs. Thanks for the suggestion
Sep 12, 2016 at 4:05 PM

Thanks Mark, I am focused on a different part of my project right now but I have pulled the updates and will take a look ASAP.

Thanks again,

Sid

Sid Price

Desktop Application and Embedded System Design