[openal] Porting from XAudio2 to OpenAL - few questions
Chris Robinson
chris.kcat at gmail.com
Wed Mar 26 05:06:07 EDT 2014
On 03/25/2014 09:32 AM, Mariusz 'MX' Szaflik wrote:
> ***HERE*** -- matrix [NumberOfChannelsInSource x NumberOfChannelsInOutput]
> two sets of float[a x b] one for multiplying each element of original
> matryx and one for adding to the result
The main problem there is that OpenAL is purposely designed to hide the
number of output channels, and its configuration. OpenAL virtualizes
sound positions so it will work regardless of whatever standard or
exotic setup a user may have now or in the future. Apps just place
sounds somewhere and OpenAL will do the best it can to "render" it in
that position, regardless if it's using stereo, 3-channel, 2.1, 5.1,
7.1, etc... or even things like HRTF, which is really only stereo but
provides for dozens of distinct points around the listener.
There's a few things I can think of to do for an extension to provide
more per-channel control with multi-channel buffers, and I'm CC'ing the
list in hopes of getting more feedback.
One idea is to be able to set angles and gains for each buffer channel
on a source, with the number of angles and gains dependent on the buffer
format. For example, to load a 5.1 buffer, and rotate it 90 degrees
around the listener:
alBufferData(buffer, AL_FORMAT_51CHN16, ...);
alSourcei(source, AL_BUFFER, buffer);
ALint angles[6] = { // buffer is 5.1, so there's 6 channels
-30 + 90, // front left
30 + 90, // front right
0 + 90, // front center
0, // lfe (angle ignored, always goes to the lfe output
// if preset)
-110 + 90, // back left
110 + 90 // back right
};
alSourceiv(source, AL_MC_ANGLES, angles);
And with a stereo buffer, reducing the gain of the right channel by half
and leaving the left gain at full:
alBufferData(buffer, AL_FORMAT_STEREO16, ...);
alSourcei(source, AL_BUFFER, buffer);
// buffer is stereo, so there's 2 channels
ALfloat gains[2] = { 1.0f, 0.5f };
alSourceiv(source, AL_MC_GAINS, gains);
Another idea is similar to the above, except instead of setting angles
and gains for each channel, you set a (source relative) position and
OpenAL's distance attenuation and panning rules would apply -- with an
exception for LFE, which would distance attenuate but not pan. However,
at this point it really feels like you just want to manipulate discrete
sources.
And that brings me to a third idea. The ability to have multiple sources
sharing a single multi-channel buffer, and each source acting as a 3D
mono source using only one of the buffer channels. So for instance, say
you have a stereo buffer and two sources. You could assign the same
buffer to each source, and specify that each source would... well,
source from the left or right buffer channel. e.g.
alBufferData(buffer, AL_FORMAT_STEREO16, ...);
alSourcei(sources[0], AL_BUFFER, buffer);
alSourcei(sources[0], AL_CHANNEL_SOURCE, AL_FRONT_LEFT);
alSourcei(sources[1], AL_BUFFER, buffer);
alSourcei(sources[1], AL_CHANNEL_SOURCE, AL_FRONT_RIGHT);
alSourcePlayv(2, sources);
Then move the sources around, use cones, whatever... treat them as if
they were they were mono. The only practical difference from a mono
source is that source[0] would be playing the buffer's left channel, and
source[1] would be playing the buffer's right channel. The one caveat
here would be that a source using the LFE channel would only ever mix to
an LFE output, but would otherwise act like a mono source (attenuate
with distance, be occluded by a cone, etc).
If a channel source is specified that doesn't exist in the buffer, the
source is silent. Setting the channel source to AL_NONE would revert
back to normal behavior.
Of the three options, I think the 3rd is the sanest. Although the first
two would work, they feel rather messy with the buffer format
determining how many elements get read or written, and resetting it back
to defaults wouldn't quite be that straight forward either. But I also
recognize that the third option puts a bit more work on the application
to manage multiple sources.
More information about the openal
mailing list