9.12 Synchronizing Sounds to Events

NN n/a, IE 5(Win)

9.12.1 Problem

You want to play a sound associated with the occurrence of an event on an element.

9.12.2 Solution

For the sake of simplicity, this solution works only in Internet Explorer for Windows, with its ability to control the Windows Media Player. The hard work goes in the HTML, making sure the object element has the correct information to load the player.

We'll add a pair of subtle sounds to the drop-down menu navigation interface described in Recipe 10.8. A higher tone sounds when the menu header is highlighted; a lower tone sounds when an item in the menu is highlighted. Browsers do not offer any built-in sounds, so this recipe assumes that you have recorded or acquired two short and small sound files, called hi.wav and lo.wav.

Starting with the HTML, add two <object> tags, one for each sound:

<object id="hiPing" width="1" height="1" 
    <param name="FileName" value="hi.wav">
    <param name="AutoStart" value="false">
<object id="loPing" width="1" height="1" 
    <param name="FileName" value="lo.wav">
    <param name="AutoStart" value="false">

Next, add the following function to the page's scripts:

function playSound(id) {
    if (document.all && document.all[id].FileName) {
        document.all[id].Play( );

Finally, wherever you want one of the sounds to play, invoke the function and pass the ID of the sound object you wish to play:


In the case of the drop-down menu of Recipe 10.8, you should add playSound("hiPing"); to the swap( ) function just before the call the showMenu( ). Then add playSound("loPing"); to the toggleHighlight( ) function immediately before the keepMenu( ) statement.

9.12.3 Discussion

Details in the <object> tag shown in the Solution are for a relatively early version of Windows Media Player (6.4), to ensure it works with IE 5 and later. The Play( ) command is forward-compatible with newer versions of the player, but the classid attribute loads the old player anyway. By repeating the tag for each sound, you help preload both sounds as the page loads, minimizing any delay in the first utterance of both sounds.

It's tricky to truly synchronize a sound with a rapidly occurring event. First, the sound file must be of extremely short duration, with virtually no attack delay or decay to it. A short sound makes it more likely that the Player is ready for the next command to play the sound while the user quickly rolls the mouse pointer through a menu list. Even so, you may still not achieve pinpoint precision in the attempted synchronicity. Controlling the Media Player adds some latency to the equation. That's why it's a good idea to issue the Play( ) command prior to a visual change triggered by the event.

Adding sound of any kind is a controversial topic among web designers. Gratuitous background music that accompanies someone reading a web site may be distracting, and perhaps enough to get an employee in trouble for visiting your site during working hours. Treat sound like any DHTML enhancement: something that should add value to the presentation for those users equipped to take advantage of it. This frequently means giving the user the opportunity to turn off sound effects (or better yet, start with sound effects off, and provide a button to turn them on).

Controlling sounds through other plug-ins or ActiveX controls is also possible, but the range of browsers that support such activity is somewhat limited. IE for the Macintosh (through Version 5.x) provides no connection between scripts and plug-ins. The Netscape browsers do provide such connections (Navigator 4 on Windows and Mac; Netscape 6 or later reliably only in Windows), but the mechanism for communicating with plug-ins is entirely different than shown in the Media Player example in the Solution.

9.12.4 See Also

Recipe 10.8 for the drop-down navigation menu used for this example.