Sound and Music

Gamasutra - Configuring Hardware-Accelerated DirectSound3D

By Brian Schmidt
September 5, 1997
Vol. 1: Issue 5
When Microsoft released DirectX 3 in September 1996, there were both cheers and jeers for the inclusion of DirectSound3D, the new 3D audio API. Since then, there’s been much confusion over differing "standards" such as DirectSound3D, A3D, Dev3D and 3Dxp. In this article I'll give some suggestions for programming 3D audio into your game as well as briefly describe how and why these differing pseudo-standards came into being and why they are no longer necessary. This should give you a better understanding of DirectSound3D so you can make better choices when deciding how to program audio in your DirectX game. It will also ensure that your game supports the entire range of coming sound cards that support DirectSound3D acceleration. This article assumes you possess know the basics of DirectSound programming.

Using The DirectSound3D API

This year, several companies will be shipping sound cards that are designed to accelerate DirectSound3D. In fact, many computer systems will likely be shipping with DirectSound3D accelerators pre-installed. To take full advantage of these cards, and make your game sound the best it can, you should start using the DirectSound3D API whenever it makes sense in your game. DirectSound3D is a set of DirectSound API calls that allows for the placement of sounds using a 3D-coordinate system instead of a simple "left-right" pan. DirectSound3D also automatically calculates things like attenuation due to distance and Doppler shift to easily enhance sound realism in a game. (See Microsoft's DirectSound documentation for a full explanation of DirectSound3D).

It would be nice to simply use the DirectSound3D API for every sound all the time. However, the software 3D audio algorithm that ships with DirectSound3D is somewhat CPU intensive (about 5.5% per channel on a Pentium-100MHz), so it’s not optimal on slower or non-accelerated systems. There are two ways around this problem:

  1. Leave it up to the user. One game that used DirectSound3D gave the player a "sound realism" slider. At one end, all sounds were mono, using the normal stereo DirectSound API, at the other; more sounds are played and all sounds used the DirectSound3D API.
  2. Automatically detect when acceleration is present. If there’s no 3D audio acceleration, use the less-CPU intensive stereo DirectSound API; if there is acceleration, use the DirectSound3D API, and use more sounds (DirectSound can tell you how many 3D sounds can be accelerated).

Solution #1 is easy; if the realism slider is set high, use DirectSound3D, otherwise, use DirectSound. Solution #2 is also easy and may be the best general solution.

Determining Whether Hardware Acceleration is Present

You can query DirectSound to see if 3D audio acceleration is present by using IDirectSound::GetCaps. If the value of dwMaxHw3DAllBuffers (a member of IDirectSound::GetCaps)is anything other than 0, it indicates that accelerated 3D audio is present in the user’s system, and you can use the DirectSound3D API without worrying about processor usage. While the game is playing, you can also make additional calls to IDirectSound::GetCaps, checking the dwFreeHw3DAllBuffers to determine how many 3d audio buffers are available for additional sounds.

If you’re shipping your game with DirectX 3, dwMaxHw3DAllBuffers will always return 0. That is because DirectX 3 doesn’t support 3D audio acceleration (see below). However, that’s all right. When players buy new sound cards and install them, or they install your game on a newer PC that is equipped with DirectSound3D acceleration, their systems will be upgraded to DirectX 5, dwMaxHw3DAllBuffers will return a non-zero value and viola, the 3D audio will be accelerated.

When using DirectSound3D, it is important that you not set the DSBCAPS_LOCSOFTWARE flag when you create the sound buffer. Doing so will force DirectSound to use its own 3D audio algorithm in software, disabling any hardware acceleration for that buffer. If no flag is set, DirectSound will accelerate the buffer if it can, or you can explicitly set the DBSCAPS_LOCHARDWARE flag. Note that by explicitly setting the DBSCAPS_LOCHARDWARE flag, that the buffer creation will fail if no accelerating resources are available.

In an attempt to jump-start the use of 3D audio, Aureal Semiconductor, a 3D audio company, added an extension called A3D to the DirectSound3D API to enable the use of their hardware when using the DS3D. Some programmers may be using A3D’s A3D-_Create and checking its return value to see if hardware acceleration is present. With DirectX 5, this extension is not longer necessary; You are better off using the GetCaps method instead. By using GetCaps, you will be able to determine if the 3D audio is accelerated on the system, possibly by a board that does not support A3D. The rule is all boards will support GetCaps; an A3D board will support GetCaps as well as A3D. At the very least, if you still use A3D_Create, also check GetCaps. Then you’re assured that you’ll cover all 3D audio accelerators. Note that with DirectX 5, A3D, Dev3D and 3Dxp become unnecessary -- even if you ship your game with DirectX 3 (see below). If you are using A3D, do not use the A3D resource manager. Since the resource manager is not standard DirectSound, it will not be supported by all sound cards. You’re much better off using GetCaps, and checking dwFreeHw3DAllBuffers for additional buffers.

Selecting Speaker Configuration

In 3D audio, different processes must be used depending on the listener’s playback. For this reason, a sound card may use one algorithm for headphone playback and a very different algorithm for speaker playback. The sound card needs to know which algorithm to use, or the player won’t hear proper 3D. For example, if the player is wearing headphones and the sound card is set for speaker playback, the player will hear little or no 3D audio effects. For this reason, it becomes very important for games to support and query the user for their listening configuration, usually in a configuration screen.

DirectSound provides a method for telling the sound card which output device the player is using the IDirectSound::SetSpeakerConfig method. The single parameter is a mask with defined parameters like DSSPEAKER_HEADPHONE, or DSSPEAKER_STEREO. If you are more detail orientated, you can also set the specific angle separation between the listener and the speakers. By allowing the user to set this parameter, you can be more assured that they will be able to get the best 3D audio effects from your game.

Note that some sound card control panels also allow output configuration selection. In these cases the control panel may conflict with the setting made by SetSpeakerConfig. A good solution to this may be the following: Use GetSpeakerConfig to get the current setting, which may have been changed by an external control panel and reflect the current setting in your sound control panel. Only use SetSpeakerConfig if the player explicitly sets it. Also, make sure the manual and help commands clearly explain the speaker/headphone configuration you offer.

Supporting Special Features of Particular Soundcards

Suppose you know that a particular model of DirectSound3D accelerator supports a feature not currently defined by the DirectSound API (reverb, for example). How can your game utilize reverberation if the player has a sound card that supports it and yet not blow up on cards that don’t offer reverb support? There's a method that takes care of that. The IKsPropertySet (formerly called IDirectSoundPropertySet) interface allows a programmer to support extended services offered by sound cards and their associated drivers such as reverberation or other features. To use the special features on sound cards, you must first see if the card supports the IKsPropertySet interface, and obtain a pointer to the interface if it is supported. You do this by calling the QueryInterface method of an IDirectSound3DBuffer interface.

The query will succeed only if the 3D buffer is accelerated. If it does succeed, you can now look for a particular property set or property within a set, using the IKsPropertySet:QuerySupport method. The meanings and values of the property set parameters (PropertySetID and PropertyID) are defined by the hardware vendor and are published by them. Parameters for the property sets can also be passed to and from the driver by using the pPropertyParams structure. The data is again defined by the particular hardware vendor.

The Story of DirectSound3D, A3D, Dev3D and 3Dxp

If you’re interested how DirectSound3D came about (as well as A3D and others), I'll briefly explain.

In the beginning there was DirectSound, which shipped with DirectX 1 and 2. DirectSound supported basic wave file mixing along with the control of pitch, volume and simple left/right pan. The basic mixer, performed all in software, was moderately efficient, getting the job done on most systems. DirectSound also supported the offloading of the mixing, panning and pitch-shifting to external hardware, or "audio acceleration." However, due to the limitations of the ISA bus, accelerating the audio meant that the sound card manufacturers had to place (at the time) expensive dedicated audio RAM on their soundcards. Therefore, few mainstream soundcards (the AWE being the notable exception) actually supported audio acceleration. Besides, processors were getting faster, so the benefit of acceleration was less dramatic (DirectSound mixes normal stereo at about 0.6%/voice on a P200).

When DirectSound3D was announced, the 3D audio industry, including makers of audio cards, were very excited. Microsoft would provide a standard API for 3D Sound that developers could use that would work with any sound card. DirectSound3D would provide a basic 3D audio algorithm in software and allow for the acceleration of that algorithm, in the same manner that "regular" stereo DirectSound can be accelerated. The sound card companies had various algorithms (QSound, Aureal, Creative Labs, etc.) that performed 3D audio processing, and they were ready to create audio cards to accelerate DirectSound3D.

The big problem was that several months prior to the release of DirectX 3 and DirectSound3D, Microsoft announced that they would not allow third-party 3D audio algorithms to accelerate DirectSound3D; Microsoft would provide the 3D audio algorithm that sound card companies had to use. In addition, DirectX 3’s DirectSound3D was not designed in a way that made it even possible to use third-party algorithms. To say that the sound card companies were not happy about this is quite an understatement. These vendors had invested years into developing their own 3D audio algorithms and were told that they couldn’t use them in their sound cards. Microsoft had done a great service by establishing a standard API, but now the sound card companies couldn’t use it to create products based on their own 3D audio technology. Since Microsoft wasn’t ready with their own 3D audio acceleration plans (and wouldn’t allow third parties to accelerate), the result was DirectX 3’s DirectSound3D had no provision for 3D audio acceleration. Sound card manufacturers were faced with the prospect of not being able to use their own 3D audio technologies to accelerate DirectSound3D.

The soundcard companies didn’t take the Microsoft decision lying down. Though they were grateful for Microsoft’s release of a standard API, they went looking for some way to allow the creation of audio cards that would perform 3D audio acceleration despite the DirectX 3 DirectSound3D architecture, which didn’t allow it. They liked the idea of using the Microsoft API; they just needed some kind of ‘workaround.’ (For those interested, the problem with DirectX 3’s DirectSound3D was that it did not pass the x,y,z source and listener parameters from the API down to the device driver, where the information is needed to do acceleration). Completely separately, two different companies, Aureal Semiconductor and VLSI Technologies, created two different ‘workarounds’ for the problem, called A3D and Dev3D respectively. They each involve adding a small number of non-Microsoft API calls to game source code that support the use of the DirectSound3D API by spoofing various parts of DirectSound. During this time, the Interactive Audio Special Interest Group's 3D Audio Working Group (IA-SIG 3DWG), a group of 3D audio and sound card professionals, was also working on two fronts:

  • Get Microsoft to change their "no third-party 3D audio acceleration" stance
  • Come up with an industry-standard ‘workaround’ to address the current situation

The bottom line was that the consortium created an industry standard called 3Dxp, which combined the A3D and Dev3D solutions and made them into an open standard. So A3D, Dev3D and 3Dxp were all created for the sole purpose of getting 3D audio acceleration to work with DirectX 3’s DirectSound3D, in a sense thwarting Microsoft's stance on the issue.

Apparently folks at Microsoft decided they had made a mistake by adopting their policy against third-party accleration. After a lot of discussion, both internally and externally, Microsoft’s DirectSound team, The IA-SIG 3DWG, and the individual 3D sound companies came to agreement that DirectSound3D in DirectX 5 would support third party acceleration of 3D sound. With DirectX 5, DirectSound3D supports sound cards that use third party 3D audio algorithms to accelerate DirectSound3D properly, through Microsoft-approved methods (x,y,z parameters now get sent from the API to the driver). In addition, Microsoft provided a standard means for extending the capabilities of the API without requiring elaborate ‘work-arounds,’ allowing soundcard vendors to add distinctive functionality to their products. Therefore, with DirectX 5, the workarounds A3D, Dev3D and 3Dxp become unnecessary. You can now use 100% Microsoft DirectSound/DirectSound3D API calls and your code will work on all 3D sound cards. This will even work on games that were written with DirectX 3. Here’s how it works.

You write a game using DirectX 3. You use the DirectSound3D API (perhaps checking to see if 3D audio acceleration is present using GetCaps). You ship your game with DirectX 3. If the game is played on a DirectX 3 system, GetCaps will return a zero value for the dwMaxHw3DAllBuffers member, and your game will play sounds using the DirectSound stereo API (if you chose not to use the DirectSound3D API), or with unaccelerated DirectSound3D.

Now that DirectX 5 is available, when a consumer buys new 3D audio sound card and install it, their system is updated with that version of the API. With DirectX 5 installed, GetCaps returns a non-zero value for dwMaxHw3DAllBuffers, and their game begins using the hardware accelerated DirectSound3D API.

3D audio can add a whole new dimension to the soundtrack for you game. Immersing the player with 3D sound makes for a more exciting experience. By checking for accelerated systems and using the DirectSound3D API, your application will be able to support and take advantage of this exciting new technology.

Brian Schmidt has been in the multimedia audio industry for over 10 years. He has created soundtracks and done sound design for more than 100 arcade, consumer and PC games including John Madden Football, Desert Strike, The X-Files and Jurassic Park. As a consultant, he has worked for a wide range of media and game companies such as Sony, Electronic Arts, Sega, Data East, Capcom and others on projects ranging from writing music to designing custom audio IC’s. He currently serves as Director of Technology and Planning for QSound Labs. Brian graduated Northwestern University in 1985 with bachelor’s degrees in Computer Science and Music Composition and a Masters in Computer Applications in Music in 1987. A bit of a pinball freak, he currently resides in Wilmette Illinois.