By Robert
Basler
Gamasutra
December 18, 1998
Vol. 2: Issue 49
|
If you're like me and have a laptop and
a Dolby Pro-Logic decoder for your television, you have probably tried
hooking your computer up to the TV's audio system to see how all those
games with the Dolby Pro-Logic logo at the start sound with three hundred
watts of amplification and a room full of speakers.
So far I've been disappointed, the cut-scenes sound great, but as soon
as the action starts I'm back to listening to the front speakers only.
For my game I thought it would be really cool if I could create the effect
of hearing someone shooting from behind, or when a ship finally explodes
in a ball of flames the player could hear the sound of engines exploding
from behind, followed the roar of the fireball rushing forward to surround
the player in before the blackness of your final demise. A trip to the
Dolby Labs World Wide Web site (www.dolby.com)
introduced me to the theory behind Dolby Pro-Logic encoding and gave me
the basis for adding support for it to my game.
Dolby Pro-Logic is a four channel system. Left, center, right and surround.
The center channel is designed to anchor voices where the screen is. The
left and right are designed for music and sound effects, and the surround
channel is primarily for sound effects. Those four channels are encoded
on the left and right stereo channels so that they can be decoded into
four separate channels using some special circuitry inside a Dolby Pro-Logic
amplifier.
The center channel in a Dolby Pro-Logic system is encoded by reducing
the volume of the center channel by 3dB to maintain constant acoustic
power across the front, and then putting that signal on both the left
and right channels. To decode it, the amplifier takes the elements that
are common to the left and right channels, filters them out, and feeds
them through the center speaker. The neat thing about this design is that
I don't need to do anything clever in my audio engine to get smooth panning
from left to center to right and back since the Dolby Pro-Logic decoder
takes care of this.
Encoding the surround channel is a little trickier, but now that I found
the secret of Dolby's ingenious design, it was straightforward to implement.
The formal Dolby specification says that the signal for the surround channel
should be in the range of 100Hz to 7KHz and that the phase of the signal
must be encoded as +90 degrees out of phase on the left channel and -90
degrees out of phase on the right, resulting in a 180 degree phase differential
between the surround components of the left and right channels. The 90
degree phase shifts help mitigate cancellation effects, which we'll talk
about in a moment.
Through experimentation I found that as long as the signal is 180 degrees
out of phase between the left and right channels, it doesn't matter whether
there is that +90 and -90 degree phase shift or not. Doing a +/- 90 degree
phase shift in software would be tricky. However, doing a 180 degree phase
shift is easily achieved by negating the sample before mixing it with
one of the output channels. To encode
a WAV file to play through the surround speakers, mix the sample normally
with the left channel, then NEG the sample and mix it with the right.
Being a fan of big explosions, I wanted to be able to mix a track into
more than one output channel so that an effect could fill the room from
the side and surround speakers simultaneously. The first time I tried
this, I discovered the joy of signal cancellation. When I mixed my audio
for left, right, or surround individually it worked great, left and surround
worked, but for right and surround, my effect came out the left speaker,
the right and surround speakers stayed silent. About half a second of
thought brought the realization that by adding the negated sample to the
right channel, I had inadvertently cancelled out the original sample that
I had added into the right channel.
I had to find a way to avoid this cancellation effect. Using a separate
track for the surround channel was a ineffective since all tracks start
at buffer boundaries so even a separate surround track would cause cancellation.
With a little experimentation with my Dolby Pro-Logic decoder I discovered
that if I mixed the surround signal as little as one sample later than
the normal left and right signals (a 1/11000 second delay at 11KHz playback!),
that it could pick out the surround signal.
Since most surround decoders generate delays of several milliseconds for
the surround channel anyway, this delay is unnoticeable. My initial implementation
took advantage of this, but I soon discovered that with only one or two
sample difference, the output suffered from signal leakage between the
left, right and surround channels. A minor architecture change and a complete
rewrite of the assembler routines later, and I could mix the surround
channel an arbitrary number of samples later than the left and right channels.
I settled on mixing the surround data 10 samples late although I found
that 3 samples was adequate to obtain good separation between channels
at 11KHz playback. Listing 5 shows two
of the mixing functions in assembler along with their C declarations.
One thing I found playing with these routines was they don't always do
what I expected. For instance, I expected the playback to come through
the center and surround speakers when I played a loud effect on the surround
channel, as well as on the left and right channels. In fact, it comes
out the left, right and surround signals, while the center stays silent.
This is great for big explosions since many surround amplifiers have the
bulk of their power on the left and right channels. By lowering the volume
of the effect on the surround channel, I caused the sound to converge
from the left and right speakers to the center speaker.
[In the interest of conserving
editorial space, code listings are available for download here.]
|