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

Clarify WaveOutEvent.Init

Oct 4, 2012 at 7:59 PM

I am using WaveOutEvent on Windows 7, in a web application hosted by IIS. The docs say that .init should only be called once; but I don't understand why. In fact, when I tried to dispose and recreate, I ran into a roadblock. So, I have been calling init for each new file I want to play, and so far it is working fine. Can someone clarify what is the problem with reusing the instance of WaveOutEvent?

FYI - here is the wrapper class I am using:

Imports NAudio.WindowsMediaFormat

Public Class WebAudio
    Public Shared Event FileDone()

    Private WithEvents waveOutDevice As IWavePlayer
    Private mainOutputStream As WaveChannel32
    Private fReader As WaveStream

    Public Sub New()
        'waveOutDevice = New WaveOut()
        waveOutDevice = New WaveOutEvent()
        'waveOutDevice = New DirectSoundOut()
    End Sub

    Protected Overrides Sub Finalize()                  ' Finalize; rarely called in web application
        CloseDispose()                                  ' Try to shutdown cleanly
        MyBase.Finalize()
    End Sub

    Public Sub CloseDispose()
        If (mainOutputStream IsNot Nothing) Then       ' clean up any leftover output streams
            mainOutputStream.Close()
        End If

        If (waveOutDevice IsNot Nothing) Then          ' clean up the waveout device
            waveOutDevice.Dispose()
        End If
    End Sub

    Public Sub PlayFile(ByRef fileName As String)       ' play one file
        Dim fileExt As String
        fileExt = fileName.Substring(fileName.LastIndexOf("."c))
        Select Case fileExt.ToLower                     ' pick the appropriate file reader
            Case ".aif", ".aiff"
                fReader = New AiffFileReader(fileName)
            Case ".mp3"
                fReader = New Mp3FileReader(fileName)
            Case ".wma"
                fReader = New WMAFileReader(fileName)
            Case Else
                Debug.WriteLine("WebAudio: Invalid File Extension: " + fileExt)
                Return
        End Select
        mainOutputStream = New WaveChannel32(fReader)       ' tie the file reader to the output stream
        mainOutputStream.PadWithZeroes = False              ' need this to detect eof
        waveOutDevice.Init(mainOutputStream)                ' tie output stream to output device
        waveOutDevice.Play()
    End Sub

    Public Sub PauseFile()
        If Not waveOutDevice Is Nothing Then
            If waveOutDevice.PlaybackState = PlaybackState.Stopped Then
                Return                          ' ignore if already stopped
            End If
            If waveOutDevice.PlaybackState = PlaybackState.Paused Then
                waveOutDevice.Play()
            Else
                waveOutDevice.Pause()
            End If
        End If
    End Sub

    Public Sub StopFile()
        If Not (waveOutDevice Is Nothing) Then
            If Not (waveOutDevice.PlaybackState = PlaybackState.Stopped) Then
                waveOutDevice.Stop()
            End If
        End If
    End Sub

    Private Sub waveOutDevice_PlaybackStopped(sender As Object, e As System.EventArgs) Handles waveOutDevice.PlaybackStopped
        RaiseEvent FileDone()
    End Sub

End Class

Coordinator
Oct 6, 2012 at 7:54 PM

If you call Init twice, various things that have been initialised won't be properly disposed of. It may work, but it will leak memory.