Home > Articles > Programming > Windows Programming

  • Print
  • + Share This
Like this article? We recommend

Like this article? We recommend

Playing Sound Files with API Calls

We can add sound to enhance the animation effect. For example, we could record the sound of dice rolling, and play this sound while our die is rolling.

In addition to demonstrating how to import a Win32 API, listing 4 demonstrates .NET's multi-language capabilities.

The Windows Multimedia Library (winmm.dll) Win32 API already knows how to play sound files, and I already have a wrapper written in Visual Basic .NET for winmm.dll.

Listing 4: EasySound.dll is a wrapper for the Win32 API winmm.dll, and it already knows how to play .wav sound files.

Imports System
Imports System.Diagnostics
Imports System.IO
Imports System.Runtime.InteropServices

Public Class Sounds
    <Flags()> _
    Public Enum PlaySoundFlags
        SND_SYNC = 0
        SND_ASYNC = 1
        SND_FILENAME = &H20000
        SND_RESOURCE = &H40004
    End Enum

    Private Declare Function PlaySound Lib "winmm.dll" (ByVal fileName As String, _
      ByVal hmod As IntPtr, ByVal flags As PlaySoundFlags) As Integer

    Public Shared Sub Play(ByVal fileName As String)
        Try
            PlaySound(fileName, IntPtr.Zero, PlaySoundFlags.SND_FILENAME Or _
              PlaySoundFlags.SND_ASYNC)
        Catch
            Debug.WriteLine("Can't play sound file")
        End Try
    End Sub

    Public Shared Sub Beep()
        Try
            Const soundFile As String = "c:\winnt\media\chord.wav"
            If (File.Exists(soundFile)) Then Play(soundFile)

        Catch ex As Exception
            Debug.WriteLine(ex.Message)
            Throw
        End Try
    End Sub

End Class

The enumeration PlaySoundFlags uses the FlagsAttribute. The FlagsAttribute indicates that the enumeration can be treated as a bit field.

The Visual Basic .NET Declare modifier is a carry-over from VB6; underneath the covers, it is supported by the DllImportAttribute. For example, in C# we would use [DllImport(dllname.dll)] to map a local method signature to an API method.

Finally, our local Play method wraps a call to the wnmmd.ll PlaySound method, passing the file name and a request that the sound be played asynchronously. By sending PlaySoundFlags.SND_ASYNC, the method returns immediately while another thread actually plays the wave file if it can.

If you want to play sounds or video files in non-WIN32 systems, such as Windows 95, you will need to import the mmsystem.dll.

Unfortunately, in the current implementation the call to PlaySound may return before an error actually occurs in the API. As a result, we have left the local try block before an API exception might occur resulting in an unhandled error. (This is a known defect in listing 4.)

To actually hear some sound, provide the complete filename, including path, to a call to the shared (static in C#) method, Play. As a temporary measure, you can use the implementation of Beep to test the API wrapper, but you will need to find a good .wav file that sounds like rolling dice to get the full effect.

  • + Share This
  • 🔖 Save To Your Account