What's the deal with 3D sound under DirectX
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. This document will give some suggestions for programming 3D audio into your application as well as briefly describe how and why these differing pseudo-standards came into being as well as 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 application. It will also help you ensure that your application can support the entire range of coming sound cards that will support DirectSound3D acceleration. This brief assumes you already 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 (DS3D) 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. DS3D also automatically calculates things like attenuation due to distance and Doppler shift to easily enhance sound realism in a game. (See the 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 slow (about 5.5%/channel on a P100), so it's not optimal on slower or non-accelerated systems. There are two ways around this problem:
Solution #1 is easy; if the realism slider is set high, use DirectSound3D, otherwise, use the lower-CPU-using DirectSound.
Solution #2 is also easy and may be the best general solution.
You can query DirectSound to see if 3D audio acceleration is present by using IDirectSound::GetCaps.
Of interest is the dwMaxHw3DAllBuffers member. If it is non-0, you have accelerated 3D audio present in the user's system and can use the DirectSound3D API without worrying about CPU 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.
Of course, 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 ok. When the player buys a new soundcard and installs it, their system will be upgraded to DirectX 5 (or they install your game on a newer PC that comes with DS3D acceleration), dwMaxHw3DAllBuffers will return a non-0 value and viola, your 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.
Some programmers may be using A3D's, A3Dcreate and checking its return value to see if hardware acceleration is present. However, you are better off in the long run by 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 A3Dcreate, 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, it is recommended that you NOT use the A3D resource manager. Since the resource manager is not standard DirectSound, it will not supported by all sound cards. You're much better off using GetCaps, and checking dwFreeHw3DAllBuffers for additional buffers.
Selecting Speaker Configuration
It's the nature of 3D audio that different processes must be used depending on what the listener's playback configuration is. For example, a sound card may use one algorithm for headphone playback and a very different algorithm for speaker playback. If, for example, the player is wearing headphones, but 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. DirectSound object. The single parameter is a mask with defined parameters like DSSPEAKER_HEADPHONE, or DSSPEAKER_STEREO. For those 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: 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 DS3D accelerator supports a feature not currently defined by the DirectSound API; reverb, for example. How can you have your game utilize reverberation if the player has a sound card that supports it and not blow up on cards that don't? Fortunately, Microsoft has created a method that allows for just that. The 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 IDirectSoundPropertySet 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 3-D buffer is accelerated. If it does succeed, you can now look for a particular property set or property within a set, using the IDirectSoundPropertySet::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.
That's about all you need to know how to best use DirectSound3D in your game. All of the details are in dsound.doc in the DirectX 5 SDK. If you're interested in a bit of history of how DirectSound3D came about (as well as A3D and others), it's summarized here:
The story of DirectSound3D, A3D, Dev3D and 3Dxp.
DirectX 1 and 2 shipped with DirectSound. DirectSound supported basic wavefile 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).
DirectX 3's DirectSound3D: The Big Controversy
When DirectSound3D was announced, the 3D audio companies and 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, just like "regular" stereo DirectSound. 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 for 3rd party 3D audio algorithms to be used to accelerate DirectSound3D; Microsoft would provide the 3D audio algorithm that was to be used. They then structured DirectX 3's DirectSound3D to make it 'impossible' to use 3rd party algorithms. To say that the sound card companies were not happy about this would be quite an understatement. They each 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. The result was
The Workarounds: A3D, Dev3D, 3Dxp
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). Separately, 2 different companies created two different 'workarounds' for the problem, called A3D and Dev3D. They involve adding a small number of non-Microsoft API calls to game source code that allow for the use of the DirectSound3D API by spoofing various parts of DirectSound. During this time, the ia-sig 3dwg (Interactive Audio- special interest group: 3D audio working group, a voluntary consortium of 3d audio and sound card companies) was working on 2 fronts:
Bottom line: The consortium created an industry standard called 3Dxp that combined A3D and Dev3D and made it 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, since Microsoft said it wasn't going to allow it by 'approved' methods..
Better bottom line: Microsoft changed its mind.
DirectX 5: DX5 allows 3rd party 3D audio
After a lot of discussion, both internally and externally, Microsoft's DirectSound team, The IASIG 3DWG, and the individual 3D sound companies came into agreement that DS5 will support third party acceleration of 3D sound. With DirectX 5, DirectSound3D has the capability of having sound cards that use third party 3D audio algorithms accelerate DirectSound3D properly, through Microsoft-approved methods (xyz parameters now get sent from the API to the driver). Therefore, with DirectX 5, the workarounds A3D, Dev3D and 3Dxp become unnecessary. This is because the workarounds are no longer needed; you can 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 (maybe 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 always return 0 for the dwMaxHw3DAllBuffers member. So your game decides to play sounds with the DirectSound stereo API. This summer, the player of your game buys a new XYZ 3D audio sound card. When they install the sound card, DirectX 5 is also installed, updating DirectX on their system. Now, GetCaps returns some non-0 value for dwMaxHw3DAllBuffers. Your game then decides to use the DirectSound3D API. Then, when they play the game their 3D audio will be accelerated by their new card.
So, by using GetCaps, your application can see if 3D audio acceleration is present, allowing you to use the benefits of the new generation of 3D audio soundcards that are starting to appear in the market.
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.