By Brian
Schmidt
Gamasutra
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, theres 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
its not optimal on slower or non-accelerated systems. There are two
ways around this problem:
-
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.
-
Automatically detect when acceleration is present.
If theres 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 users 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 youre shipping your game with DirectX 3,
dwMaxHw3DAllBuffers will always return 0. That is because DirectX
3 doesnt support 3D audio acceleration (see below). However, thats
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 A3Ds
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 youre
assured that youll 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. Youre 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 listeners
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 wont 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 dont 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 youre 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 3s 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
couldnt use them in their sound cards. Microsoft had done a great service
by establishing a standard API, but now the sound card companies couldnt
use it to create products based on their own 3D audio technology. Since Microsoft
wasnt ready with their own 3D audio acceleration plans (and wouldnt
allow third parties to accelerate), the result was DirectX 3s 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 didnt take the Microsoft decision lying down.
Though they were grateful for Microsofts 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 didnt 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 3s 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
3s 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, Microsofts 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. Heres 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 ICs. He currently
serves as Director of Technology and Planning for
QSound Labs. Brian graduated Northwestern
University in 1985 with bachelors 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.
|