Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PlaybackState remain at Playing after PlaybackStopped fires?

I'm a little new to using NAudio so I'm surely missing something important, hence this question.

Starting with example/demo code, I put together a class as simple as I could make it to play MP3 or WAV files:

public class AudioPlayer : IDisposable
{
    WaveStream _waveStream; // sound data stream
    WaveChannel32 _waveChannel32; // sound channel ??
    IWavePlayer _iWavePlayer; // sound output driver

    public bool IsPlaying
    {
        get { return _iWavePlayer != null 
                     && _iWavePlayer.PlaybackState 
                         != Wave.PlaybackState.Stopped; }
    }

    public PlaybackState PlaybackState
    {
        get { return _iWavePlayer.PlaybackState; }
    }

    public void LoadMp3(byte[] mp3Bytes)
    {
        Load(CreateInputStreamFromMp3Bytes(mp3Bytes));
    }

    public void LoadFile(string filename)
    {
        Load(CreateInputStream(filename));
    }

    void Load(WaveStream waveStream)
    {
        if (_iWavePlayer != null)
            Dispose();
        _iWavePlayer = new WaveOut();
        _iWavePlayer.PlaybackStopped += 
            new EventHandler(_iWavePlayer_PlaybackStopped);
        _waveStream = waveStream;
        _waveChannel32 = new WaveChannel32(_waveStream);
        _waveChannel32.PadWithZeroes = false;
        _iWavePlayer.Init(_waveChannel32);
    }

    void _iWavePlayer_PlaybackStopped(object sender, EventArgs e)
    {
        Stop();
    }

    static WaveStream CreateInputStreamFromMp3Bytes(byte[] mp3Bytes)
    {
        return new Mp3FileReader(new MemoryStream(mp3Bytes), false);
    }

    static WaveStream CreateInputStream(string fileName)
    {
        if (fileName.EndsWith(".wav"))
            return new WaveFileReader(fileName);
        else if (fileName.EndsWith(".mp3"))
            return new Mp3FileReader(fileName);
        else
            throw new InvalidOperationException("Unsupported extension");
    }

    public void Play()
    {
        _iWavePlayer.Play();
    }

    public void Stop()
    {
        if (_iWavePlayer != null 
                && _iWavePlayer.PlaybackState != PlaybackState.Stopped) { 
            _iWavePlayer.Stop();
            _waveStream.Position = 0;
        }
    }

    public void Dispose()
    {
        Stop();
        if (_iWavePlayer != null) {
            _iWavePlayer.Dispose();
            _iWavePlayer = null;
        }
        if (_waveChannel32 != null) {
            _waveChannel32.Dispose();
            _waveChannel32 = null;
        }
        if (_waveStream != null) {
            _waveStream.Dispose();
            _waveStream = null;
        }
    }
}

I'm using the code in question to play MP3 files (not WAVs).

It works ok for the most part, which is pretty awesome considering that I'll be able to replace MediaElements in my project. The issue I'm having is that the PlaybackState stays at Playing rather than changing to Stopped once PlaybackStopped fires. To go around that, I subscribe to PlaybackStopped and call Stop() from there.

Is it normal that I have to call Stop() like that, or is there is something I am missing here?


1 Answers

Looks like a bug. If you look at NAudio code WaveOut will not change PlaybackState in RaisePlaybackStoppedEvent. But DirectSoundOut will change it to stopped. A little crazy.

like image 63
apocalypse Avatar answered Dec 15 '25 04:12

apocalypse