[AD] Somewhat comprehensive 3d sound tutorial

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Hi,

Forgive me for bringing up a 2-mo old thread... but I just joined :).

Anyway, for those interested in 3d-sound I've got quite a bit of info
(I've been looking into this for a year more or less now).

First off - IASIG(Interactive Audio Special Interest Group) publishes
standards for these kind  of things.  IIRC there are two levels -
http://www.iasig.org/pubs/3dl1v1.pdf
http://www.iasig.org/pubs/3dl2v1a.pdf

Level two is really difficult to do in just software - even openal
doesn't do it yet IIRC (DirectSound does though as does EAX).

On with the show -
What I'll do here is deal with the IASIG level 1 requirements
(on page 25 of the PDF) bit by bit, then level 2 (Page 11 on 2nd
PDF).

#################
IASIG Level 1
#################
* Playback of 8 simultaneous sources (16 recommended)
    - Easy by itself, with the following could be tricky

*  A minimum sample rate of 22050hz & 16bits (44.1khz recom.)
    - Easy

* object [referred to as a source in this doc]
and listener 3d (x,y,z) position
    -    Now the FUN starts :)

There are several ways to do the localazation part
(not a complete list, I'll weigh in afterwards) -

1.
Use a measured HRTF (Head-Related-Transfer-Function) in the frequency
domain.  This is fairly complex,
and involves taking a measurement from a database, like
http://interface.cipic.ucdavis.edu/CIL_html/CIL_HRTF_database.htm
for example - and filters it in
the sound signal - an example using midi -
http://sound.media.mit.edu/KEMAR.html.

I've got a small c file that does it also...

2.
Approximating the HRTF using a combination of generic transfer
functions.
http://interface.cipic.ucdavis.edu/CIL_tutorial/3D_home.htm

A pretty efficient example (speedy, but not 100% accurate) -
http://interface.cipic.ucdavis.edu/PAPERS/Brown1997(Efficient3dHRTFModels).pdf

3d audio programming has a better, but more costly implementation
using the HRIR (see references at end)
(Head Related Impulse Response - time domain version of the HRTF).

3.
Panning tricks.  This is what a lot (most prob.) of commercial games
do if
directsound3d fails.  This involves some simple trigonometry - like
getting where the sound source is and space (well, the angle of it)
and subtracting
that from the listener's position and attenuating as such.

Here's some psuedo-code:
float al3dvector_getyaw(al3dvector vec)
{
    float length = sqrt(vec.x*vec.x + vec.y*vec.y),
           yaw;

    if (length>0)
      yaw = acos(vec.x / length);
    else
      yaw = 0;

     if (y<0)
      return -(RadiansToDegrees(yaw));
    else
      return RadiansToDegrees(yaw);
}

long al_sourcepan(al3dvector sourcepos)
{
    al3dvector dir;
    float yaw, listenerYaw, relYaw;
    long pan;

    //listenerpos == sourcepos?
    if (!memcmp(&sourcepos, &listenerPos, sizeof(vector3)))
        return 0;

    //listenerPos - sourcepos
    al3dvector_subtract(&dir, &listenerPos, &sourcepos);
    yaw = al3dvector_getyaw(&dir);
    listenerYaw = GetYaw(&listenerFront); //(0,0,1) 0,1,0

    relYaw = yaw - listenerYaw;
    if (relYaw < -180.0f)
        relYaw += 360.0f;
    else if (relYaw > 180.0f)
        relYaw -= 360.0f;

    //figure out which quadrant the relative angle is in
    //alConvPan(pan) return (pan+1.0) * (255/2);
    if (relYaw > 90.0f)
    {
        //90 < relYaw < 180
        relYaw -= 90.0f;
        pan = -((long)
            (alConvPan(1.0f - (relYaw / 90.0f)) + 0.5f));
    }
    else if (relYaw > 0.0f)
    {
        pan = -((long)
            (alConvPan(relYaw / 90.0f) + 0.5f));
    }
    else if (relYaw > -90.0f)
    {
        pan = (long)
        (alConvPan(relYaw / -90.0f) + 0.5f);
    }
    else //relYaw >= -180.0f
    {
        relYaw += 90.0f;
        pan = (long)
        (alConvPan(1.0f - (relYaw / -90.0f)) + 0.5f);
    }
    return pan;
}

long al_sourcevolume(al3dvector sourcepos)
{
    al3dvector listenerPos;
    float dis, fraction;
    int logValue;
    long volume;

    dis = (float)al3dvector_distance(&listenerPos, pPos);
    if (dis <= al_mindistance)
        return 255;
    else if (dis >= al_maxdistance)
        return 0;
    else
    {
        fraction = 1.0f - (al_mindistance / dis);
        return (long) fraction * 255;
    }
}
--------------------
[1] is pretty slow.  DirectSound says it uses HRTFs, but I'm pretty
sure it just
approximates them [2].  For Allegro though, using native apis (DS3D on
Win,
AudioUnits on OSX, OpenAL on linux) is probably enough - falling
back to [3] if the native sound system doesn't support it.

Hope I didn't lose anybody yet - because all we've done so far is put
in
positional & distance information.  We still need some other things.

* object and listener velocity
    - What they are talking about is the doppler effect

Doppler Effect -
Used to simulate a plane flying overhead amoung other things -
OpenAL uses this equation (DopplerFactor is set by user,
DopplerVelocity is speed of sound, 343m/s by default in
20 deg. C weather) -

 NewSampleRate = DopplerFactor*
 OldSampleRate *
 (    DopplerVelocity- ListenerVelocity)/
        (DopplerVelocity+ SourceVelocity);

Listener/Source/Velocity are normalized vectors :).

* listener orientation
 - Already implicitly discussed in the positioning bit
When using panning tricks ([3])  and such only
part of the orientation gets taken into play

* object orientation/radiation pattern
 - What this means is that you need to support cones
Look at -
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directX/htm/soundcones.asp

Involves tricky geometry but is fairly straightforward.

More psuedo-code (really rough this time...):
al3dvector_subtract(&s2l, &listenerPos, &sourcepos);
int theta = (int) 180 *
    acos(alvector3d_dotproduct(sourcedirection, s2l) / M_PI);
 int outer = coneouter / 2;
 int inner = coneinner / 2;

 if ( theta <= inner )
  return sourcevolume;
 else if ( sThetaAngle >= sOuterAngle )
  return coneoutervolume;
 else
  return   (255 - (255-coneoutervolume)*
  ((theta - inner)/(outer-inner)));
------------------------
The rest of the level 1 specs re-iterate what we've
just said and state that it has to be real-time (duh!).

#################
IASIG Level 2
#################

* object and listener dynamic reverberation effects
    - Basically room reverberation

Room Reverberations -
This is EAX stuff.  You can do it in software too using dsp
reverb tricks - look at the IASIG level 2.0 specifications for info
(look at musicdsp and other places for info on reverb) and check
out the Direct3D api appendex which has the echo values
and such.

* occlusion and obstruction
IIRC the level 2 pdf gives a filter or something to deal
with this.  This is the only thing at the moment that is totally
beyond my knowledge...

-----------------
References:
Mit has a $$$$120$$$ book at amazon.com under the name
spatialization or something

The original 210+ page reference (no code :\)
3-D Sound for Virtual Reality and Multimedia by
Durand R. Begault
Is available at NASA.org for free in pdf format
if you can find it (I'll e-mail the 2mb pdf to anyone
who wants it...).

3d audio programming by daryl sartain is only 20$,
but isn't exactly a linear reading experience -
is more of a collection of thesises than anything else,
does have some snippets of code though.
------------------
Anyway, there's my late-night 3d sound tutorial.
Accuracy not gaurunteed.

IMHO after all this simple panning tricks are probably
ok for allegro ([3]) all by themselves.

I'll be happy to answer questions :).

Best Regards,
Ryan





Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/