3d sound source size, listener direction cone

Started by Miran,

Miran

I'm trying to implement sound source size simulation for 3d streams.
Reasoning is for 3d game sound source can be given some radius. If listener is within the radius the sound volume is maximum, there is no Doppler and stereo effects. It is meant to simulate for example building with music inside.

I had it working but users with 5.1 speakers started reporting some issues.
Well, no wonder as I implemented blending between regular stereo and playing in center as interpolation between sound's real position and one adjusted to be at same distance, but dead center to the listener.
Worked well, but in case of 2 speakers only...


I tried simpler solution:
perceivedPos = lerp(soundPos, listenerPos, blend)Where blend is 1.0 if inside, 0.0 outsite and there is some gradual transition between.
Works as intended for corner cases, but soft blending between them is impossible.
If source position is exactly same as listener's then sound is played in center, any little offset causes it instantly to switch into full stereo.

I'm out of ideas how to solve that. Is there any way to configure listener's ears directional characteristics? Apparently BASS uses dotProduct > 0.
There is projection cone configuration for sound sources but I did not seen anything like that for listener.

Ian @ un4seen

A 3D sound is at full volume within its minimum distance (set via BASS_ChannelGet3DAttributes). So if I understand correctly, you basically want any position within the minimum distance to be treated as exactly the same position as the listener, so that the sound is coming equally from all speakers?

Miran

Yes, you are probably going to propose 'mindist' param, but it does not affect stereo panning.

I was already calculating perceived volume, velocity and fake stream position to achieve desired result.

It is bit frustrating that I do not want achieve some extraordinary features, meanwhile I have to add extra complexity to create something that counteracts internal BASS logic and produces desired result.

Solution would probably be to have two synchronized streams, one 3d and other regular, then bled their volume depending on listener's position. That's just another costly and problematic walk around...


I spend some time thinking how to even provide user with ability to do such things.
Most flexible solution would be to add ability to register user callback for listener ear processing, like:
float processEar(
    int earIndex, BASS_3DVECTOR* earDir,
    HSTREAM stream,
    float volume)
{
    return volume; // no effect
}
Such callback would be called for each speaker. User already knows listener's and streams' 3d params, as he is the one updating them each frame. volume param would be value already calculated by default BASS 3d processing so user can for example just clamp it.

Such callback would open way for user to simple implementation of features like:
- user distance decay curves
- ear/microphone directional patterns
- sound source directional patterns other than cone
- simulate different configuration of listener's ear placement, including simulating head dimensions
more advanced when using one instance of stream per ear:
- ear's frequency directional patterns (EQ fx)
- sound delay between ears

Ian @ un4seen

Quote from: MiranYes, you are probably going to propose 'mindist' param, but it does not affect stereo panning.

What I was going to propose is an option that centers a sound when its distance is within "mindist". Alternatively, you could achieve the same result by setting the sound to the same position as the listener.

Quote from: MiranI was already calculating perceived volume, velocity and fake stream position to achieve desired result.

If you're basically already calculating everything, then perhaps you would like to be able to set your own per-speaker levels? You could do that by using the BASSmix add-on's matrix mixing instead of BASS's 3D processing. You would create a mixer and play the sounds through that, and update a sound's matrix each time you want to change its levels. You would also need to calculate the Doppler effect then. The code could look something like this:

// create mixer
BASS_INFO info;
BASS_GetInfo(&info); // get output device info
mixer = BASS_Mixer_StreamCreate(info.freq, info.speakers, BASS_SAMPLE_FLOAT); // create mixer with same sample format
BASS_ChannelSetAttribute(mixer, BASS_ATTRIB_BUFFER, 0); // disable playback buffering to minimize latency
BASS_ChannelStart(mixer); // start the mixer

// add a sound to the mixer with matrix mixing enabled
BASS_Mixer_StreamAddChannel(mixer, source, BASS_MIXER_CHAN_MATRIX);

// remove a sound from the mixer
BASS_Mixer_ChannelRemove(source);

// update a sound's state
BASS_Mixer_ChannelSetMatrix(source, matrix); // set the matrix (use BASS_Mixer_ChannelSetMatrixEx for ramping)
BASS_ChannelSetAttribute(source, BASS_ATTRIB_FREQ, freq); // apply Doppler effect to playback rate

Please see the documentation for details on the mentioned functions (also see the "Matrix mixing" section). Note that mixer sources need to be decoding channels, ie. have BASS_STREAM_DECODE set. If you are currently using sample channels (HCHANNEL) then you can use the BASS_SAMCHAN_STREAM flag with BASS_SampleGetChannel to get a stream instead.

QuentinC

Hello,

I think you should adjust the sound position manually and don't make it reflect the actual position of the object. More specifically:

- If the listener is within the range / "inside" the object, then set the sound position to the same position as the listener. This will make the sound implicitly centered and at full volume.
- If the listener is outside, set the sound position to be the nearest surface point, or otherwise said the intersection between the object bounding box / radius and listener.

Let's take an example in 2D to keep it simple:
we have our object in 0;0 and its radius is 10.

- IF the listener is in 5;5, so inside the object, set the sound position to 5;5.
- IF the listener is in 10;10, which is outside the circle, set the sound position to be the nearest point from the listener which touches the circle. It should be ~7.07;7.07 (= 10*cos(pi/2); 10 * sin(pi/2)).

However, if we start tweaking like this, I'm seriously wondering if it's still well worth it to keep using BASS 3D calculation. I don't like either that it instantly goes full left or full right as soon as the listener and object positions vary slightly, assuming that the object has a zero size.

I'm more and more trying to do without BASS 3D support and compute myself volume, pan and freq.
I had the same problem with rectangle bounding boxes instead of circles, and I wanted also to add other specific effects. Finally, computing everything yourself isn't so hard.
I'm not sure if I'm doing it really correctly for doppler effect, I don't yet support inner/outer angles, and I will only ever support stereo (because I set the pan via BASS_ATTRIB_PAN), but otherwise it isn't so bad. I can share what I did if interested.

By the way, a question for Yann: at the time, BASS was using DirectSound3D to do all its 3D calculations.
Knowing that DS3D has been replaced by WASAPI in Windows Vista and newer, does BASS still rely on DS3D nowadays when using BASS 3D ? Or it is in fact completely emulated since then ?

Miran

Thank Ian, this looks like what I need.
Is there way to get information about user's speaker setup?
I mean are speaker directions always hard coded for stereo/quatro/5.1 setups or can these be configured?

@Quentin - as mentioned I already had such calculations, and these worked fine in stereo setup. In with 5.1 system fake position will be noticeable, so blending stereo panning this way is no longer possible.

Ian @ un4seen

Quote from: QuentinCBy the way, a question for Yann: at the time, BASS was using DirectSound3D to do all its 3D calculations.
Knowing that DS3D has been replaced by WASAPI in Windows Vista and newer, does BASS still rely on DS3D nowadays when using BASS 3D ? Or it is in fact completely emulated since then ?

When BASS (2.4.13) started generating the final output mix itself (instead of DirectSound doing it), it also started doing the 3D processing.

Quote from: MiranIs there way to get information about user's speaker setup?
I mean are speaker directions always hard coded for stereo/quatro/5.1 setups or can these be configured?

BASS assumes certain standard speaker positions depending on the number of them. These are listed in the STREAMPROC documentation.