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.

Comments

  • Anonymous
    January 17, 2007
    This is my first blog post, so please feel free to leave feedback with questions or comments, especially

  • Anonymous
    February 23, 2007
    Hi Andy R. Thanks for the post!  Its very helpful as I am implementing our audio driver and am trying to figure out what to do with this message. My question here is that I am seeing in my code that MM_WOM_FORCESPEAKER is getting sent all the time.  Do you know what situations inside the WinCE would trigger this message? Thanks. j

  • Anonymous
    February 23, 2007
    The comment has been removed

  • Anonymous
    February 23, 2007
    Hi Andy, I missed to add one more point to the feedback:

  • Currently there is no way at the wave driver level to know whether a tone/stream played during a voice call is to be mixed with downlink only/uplink only/both.
  • Anonymous
    February 24, 2007
    Answers to the previous two comments: walnutchen: If the bSpeaker parameter to MM_WOM_FORCESPEAKER is FALSE, it means to turn off routing of this stream to the speaker. My guess is that the upper-layer shell code which plays system sounds just always calls MM_WOM_FORCESPEAKER for every sound, setting the bSpeaker parameter to an appropriate value. This might seem superfluous (which was my initial reaction), but I imagine it might make a difference on devices where the OEM has chosen by default to route all audio to the speaker rather than the headset. Thirupathi: There is no standard way to determine or control where audio will be routed during a voice call. Every device I've ever seen just plays it out the speaker (it is not routed to the far end, except insofar as the mic may pick up the sound from the speaker).

  • Anonymous
    February 25, 2007
    The comment has been removed

  • Anonymous
    February 25, 2007
    The comment has been removed

  • Anonymous
    March 22, 2007
    WRT to routing to the headset vs. the loudspeaker: The following assumes the headset/loudspeaker share the same DMA hardware, and can be independently switched. If they're different DMA channels/devices, you get a different set of problems. In the original Smartphone design we didn't specify a requirement for this behavior because (a) we don't control the OEM hardware and not all hardware supports the same set of features, and (b) different cellular carriers have their own requirements specifically regarding this behavior (and the carriers don't agree with one another!). Since then I believe there's an LTK requirement to do this a specific way (I believe it's to route to both, but you should verify that), but I think we've granted exceptions because (like I said) specific carriers have their own requirements and those often trump ours (since they sell the phones). There's a fifth option that should work well and gets you most of the benefits of option 2 without the negatives: when one stream sets the bForceSpeaker to TRUE, mute all the other streams in software and reroute the audio to the loudspeaker. Once the stream is finished playing, reroute the audio back to the headset and unmute the other streams. For example, suppose a user is listening to music via the headset and we play a ringtone. With this design, the music in the headset will be muted, and simultaneously the ringtone (and only the ringtone) will play from the loudspeaker). As soon as the ring finishes, the music will return (assuming the user hasn't picked up the call).

  • Anonymous
    March 30, 2007
    Andy, Thanks for the great post! I think I have a good understanding of the concepts and have implemented most of a solution for this api.  However, I've run into one issue.  When there is an incoming call, my driver never gets the MM_WOM_FORCESPEAKER message with bForce set to TRUE.  But, once the call ends, my driver receives the MM_WOM_FORCESPEAKER message with bForce set to FALSE. Why would I get the FALSE message, but not the TRUE?  Who is responsible for sending MM_WOM_FORCESPEAKER messages for the ringtone? Why do I not receive the FALSE message until the call ends?  Wouldn't this cause the entire call would be forced to the large speaker.  Shouldn't I see this FALSE message when the ring finishes? I'm using Windows Mobile 6 Professional. Thanks, Aaron

  • Anonymous
    June 04, 2007
    Dear Sir, May I know where can we find the definition of MM_WOM_FORCESPEAKER? And where is Audiosys.h? I have installed both CE 5.0 PPC and SmartPhone SDK. And I have CE5.0 Platform builder (under C:WINCE500) installed. I did a file search and also text search in those folders, but I didn’t find anything. Best regards, Zen

  • Anonymous
    July 10, 2007
    Your blob is great I have a question is  in wavedev2 define like    #define MM_WOM_FORCESPEAKER            (WM_USER+2) for microphone sensetivity and agc control??? I found some definition on win2003 based device but i couldn't find it for win5.0 Can you give me diraction ?

  • Anonymous
    July 10, 2007
    Your blob is great I have a question is  in wavedev2 definition like    #define MM_WOM_FORCESPEAKER            (WM_USER+2) for microphone sensetivity and agc control??? I found some definition on win2003 based device but i couldn't find it for win5.0 Can you give me diraction ?

  • Anonymous
    December 05, 2007
    Nice Blog. -- What happens if a sound file is played on the loud speaker and the incoming call is also forcefully routed to the loud speaker ? --Will both of them play at the same time or the incoming call would be given preference and would be played only ? --Is there any way to change priority of the audio ? Thanks