Working with winmm.dll to play audio files in .NET

I’m working on a little utility application that will transfer audio files from a recorder to a computer drive.  Part of the functionality is to display the audio files, and let users listen to a little snippet of the audio file if they so desire.  A quick google search led me to this page containing a good description of the process, with example code.  Using the examples, I came up with the utility class shown below.  And here’s how I’d use the class in a button event handler:

Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked
    Using player As New PlayAudioFile(“C:MiscWS400001.WMA”)
         player.PlaySnippet(5)
    End Using
End Sub

Public Class PlayAudioFile
    Implements IDisposable

    ‘Private data member – file path
    Private fileToPlay As String

    ‘Private function to send commands to the Windows OS MultiMedia API
    Private Declare Function mciSendString Lib “winmm.dll” Alias “mciSendStringA” _
    (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _
    ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer

    ‘Private wrapper method for API function
    Private Sub SendCommand(ByVal command As String)
        mciSendString(String.Format(“{0} {1}”, command, fileToPlay), Nothing, 0, 0)
    End Sub

    ”’ <summary>
    ”’ Class Constructor – accepts an audio file (must be MP3, WAV or WMA file)
    ”’ </summary>
    ”’ <param name=”soundFile”>Full path of audio file to be played</param>
    Public Sub New(ByVal soundFile As String)
        Dim ext As String = IO.Path.GetExtension(soundFile)
        Select Case ext.ToLower
            Case “.mp3”, “.wav”, “.wma”
                fileToPlay = Chr(34) + soundFile + Chr(34)
            Case Else
                Throw New ArgumentException(“File must be an .MP3, .wav or .WMA file”)
        End Select
    End Sub

    ”’ <summary>
    ”’ Play audio file
    ”’ </summary>
    Public Sub Play()
        Me.SendCommand(“open”)
        Me.SendCommand(“play”)
    End Sub

    ”’ <summary>
    ”’ Stop audio file playback
    ”’ </summary>
    Public Sub StopPlay()
        Me.SendCommand(“stop”)
    End Sub

    ”’ <summary>
    ”’ Pause audio file playback
    ”’ </summary>
    Public Sub PausePlay()
        Me.SendCommand(“pause”)
    End Sub

    ”’ <summary>
    ”’ Resume playback of paused audio file
    ”’ </summary>
    Public Sub ResumePlay()
        Me.SendCommand(“resume”)
    End Sub

    ”’ <summary>
    ”’ Close audio file
    ”’ </summary>
    Public Sub CloseFile()
        Me.SendCommand(“close”)
    End Sub

    ”’ <summary>
    ”’ Play the first part of the sound file (default 15 seconds)
    ”’ </summary>
    Public Sub PlaySnippet()
        PlaySnippet(15)
    End Sub

    ”’ <summary>
    ”’ Play the first part of the sound file
    ”’ </summary>
    ”’ <param name=”snippetLength”>Length of snippet (in seconds)</param>
    Public Sub PlaySnippet(ByVal snippetLength As Integer)
        Me.Play()
        System.Threading.Thread.Sleep(snippetLength * 1000)
        Me.StopPlay()
    End Sub

#Region ” IDisposable Support ”

    Private disposedValue As Boolean = False        ‘ To detect redundant calls

    ‘ IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ‘ TODO: free unmanaged resources when explicitly called
                Me.CloseFile()
            End If

            ‘ TODO: free shared unmanaged resources
            Me.CloseFile()
        End If
        Me.disposedValue = True
    End Sub

    ‘ This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ‘ Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class

There should probably be more error handling in the class (for example, to make sure that the file is opened before calling ResumePlay, that sort of thing), but I thought this was a good start.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s