- Separating Abstraction from Implementation
- Dice, and Visual Representations of Dice
- Playing Sound Files with API Calls
- Managing Object State Change with the Observer Pattern and Events
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.