The Wavedev2 ForceSpeaker API

This is just a quick note describing the behavior of the MM_WOM_FORCESPEAKER API built into the wavedev2 wave driver.

 

One issue in Smartphone devices is determining where to route ringtones and other high-priority notifications. This is driven by two scenarios:

 

1. A fairly common design feature of Smartphone devices is a separate "high-volume" speaker on the rear of the device to play ringtones or fairly loud notifications. The OEM may want most system sounds to play through the normal handset speaker, but to have incoming call ringtones routed through the rear speaker.

 

2. When the user has a headset plugged in, all audio is routed to that headset. However, what about the situation where the headset is plugged in but the user isn't wearing it? For this reason, some OEMs may choose to play ringtones through the device speaker even if a headset is attached.

 

The common thread to each of these scenarios is that the audio device driver needs to make some decision about where to route the audio based on whether the sound being played is a ringtone (or other high-priority notification), or is just normal audio such as music being played through media player.

 

The wave API doesn't include any built-in provision for the wave driver to determine who is trying to play a sound or where it should be routed. One might use the mixer API to address this, but the mixer API is somewhat complicated and doesn't lend itself to handling this on a per-wave-stream basis. Instead, when we first developed the wavedev2 driver back in 2000, we defined a proprietary wave message, MM_WOM_FORCESPEAKER, which is sent to the driver as a hint that the associated wave stream is a ringtone or notification that should possibly be played over over the device's speaker.

 

The format of this call is: 

 

                waveOutMessage(<DeviceID | hWaveOut >, MM_WOM_FORCESPEAKER, bSpeaker, 0);

The first parameter can be either a Device ID (e.g. 0 through N-1 if there are N devices in the system), or the handle of an open wave device.

The third param tells the driver whether to route sound to the speaker (TRUE) or not (FALSE).

If param1 is a wave handle (and bSpeaker is TRUE), the sound will be routed to the speaker until you either call the API again with the same handle and bSpeaker==FALSE, or you close the wave handle (or your app exits). If an application calls this API with bSpeaker==FALSE, audio should be routed to the earpiece rather than the speaker.

If param1 is a device ID and bSpeaker==TRUE, all audio is routed to the speaker until there's a matching call to the API with that device ID and bSpeaker==FALSE. This behavior will persist even if the application that made the original call exits. We generally never use this form of the API.

Other design details:

 

- This API is more of a hint than a command to the driver. It’s up to the OEM to decide how to interpret this message; we don’t place any requirements on how it is interpreted. Some drivers might just ignore it.

 

- The sample driver does a pretty good job of refcounting which steams have enabled the speaker, so if you turn the speaker on twice for a specific stream it won't really do any harm (we'll ignore the second call).

 

- If multiple streams are playing and only one of them has turned the speaker on, all of the streams will be routed out the speaker until the stream that turned it on either goes away or turns it back off. As an example, if you're listening to music over WMP and an a ringtone gets played, while the incoming ring is being played you may hear both the incoming ring and the music being played through the speaker. If this is objectionable, OEMs may choose to mute (in software) these other streams for the duration that the ringtone is being played over the speaker.

 

- Most of this design is geared toward hardware implementations where a single piece of audio hardware is multiplexed between one or more speakers and headset jacks (which was the only thing available when the API was designed).

- The EventSound subsystem (which manages playback of ringtones) keeps track of which tones should be played with ForceSpeaker turned on via a set of reg keys. OEMs can therefore customize which notifications should play over the speaker.

- Don't be surprised if this goes away or gets redesigned in some future release; it's really a Smartphone/PPC proprietary feature, and after 7 years it's getting a little long in the tooth.

Feel free to leave feedback (does anyone read this stuff?).

 

-Andy

Responses to questions:

1. Where is MM_WOM_FORCESPEAKER defined?

- It should be in audiosys.h, but that might have moved around a bit. The definitions you're looking for are:

#define MM_WOM_SETSECONDARYGAINCLASS (WM_USER)

    #define MM_WOM_SETSECONDARYGAINLIMIT (WM_USER+1)

    #define MM_WOM_FORCESPEAKER (WM_USER+2)

Keep in mind that these are very likely to change or go away in future release of the operating system.