David Olofson <david.olofson at reologica.se> schrieb am 24 Feb 2001:

Further, I’d also like to address advanced audio/video integration and other

issues that seem to be totally ignored in anything but commercial top titles.

Why doesn’t anyone play anything more interesting that music + one-shot

sampled sound effects? With the CPU power we have nowadays, there should be

no problem having every single event affect the sound effects dynamically;

space ships should have engine sound that’s directly affected by the movement

of the ship, doppler effect etc.

GLtron does the following for it’s engine sound:

- distance & speed based volume
- panning according to sound source
- doppler effects

It goes something like this:

Compute the angle between your viewing vector and the direction to the

sound source. Use that to compute a panning value between -1 and 1

(something like sin(angle)).

Compute distance and scale volume accordingly. Code snippet:

#define VOLSCALE_BASE 1000

*vol =

(dist2 > VOLSCALE_BASE * game->settings->game_speed) ?

(VOLSCALE_BASE * game->settings->game_speed / dist2) : (1.0);

dist2 is the distance squared. Sound volume is proportional to 1/r^2

where r is the distance. Since this has a singularity, we just clamped the

volume scale to 1.0 from a certain point on.

Compute frequency shift for doppler effect: The new frequency is:

v1,v2: speed

r: vector to the sound source

u: speed of sound

f’ = f * ( u + v1*r/|r| ) / (u + v2*r/|r| )

Then I pan the sound in a temporary buffer and frequency shift it on the fly

(using SDL_mixers Mix_SetPostMix functions) to the general audio stream.

The code for mixing the frequency shifted sound effect is as follows

(assumes signed 16 bit audio format):

void fxShift(float shift, Uint8 *target, Uint8 *source, int len, int *consumed) {

int i, j, k;

float l;

float pa = 0;

len /= 4;

for(i = 0; i < len; i++) { // LR pairs

for(j = 0; j < 2; j++) { // channels

pa = i * shift;

k = (int) pa;

l = pa - k;

```
*(Sint16*) (target + 2 * j + 4 * i) +=
( *(Sint16*) (source + 2 * j + 4 * (k + 0) ) * ( 1 - l ) +
*(Sint16*) (source + 2 * j + 4 * (k + 2) ) * ( l ) );
}
```

}

*consumed = ( (int)(len * shift + 0.49999) ) * 4;

}

Panning in-place:

void fxPan(float pan, float vol, Uint8 *buf, int len) {

int i;

float left_vol = - vol * ( -1.0 + pan ) / 2.0;

float right_vol = vol * ( 1.0 + pan ) / 2.0;

for(i = 0; i < len; i += 4) {

*(Sint16*) (buf + i) *= left_vol;

*(Sint16*) (buf + i + 2) *= right_vol;

}

}

Word of caution: this code does not check for overflowing Sint16’s

One thing that worried me a little was how to deal with the

3rd person camera. Do I make calculations based on camera or 'character’

position? I decided to use the character position troughout, but

use the camera viewing vector for panning.

- Andreas