Support B-Format source rotation with AL_ORIENTATION

This commit is contained in:
Chris Robinson 2014-10-31 22:43:13 -07:00
parent 336aba6f1f
commit 3d2853274d
5 changed files with 151 additions and 14 deletions

View File

@ -288,6 +288,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
ALfloat WetGainHF[MAX_SENDS]; ALfloat WetGainHF[MAX_SENDS];
ALfloat WetGainLF[MAX_SENDS]; ALfloat WetGainLF[MAX_SENDS];
ALuint NumSends, Frequency; ALuint NumSends, Frequency;
ALboolean Relative;
const struct ChanMap *chans = NULL; const struct ChanMap *chans = NULL;
ALuint num_channels = 0; ALuint num_channels = 0;
ALboolean DirectChannels; ALboolean DirectChannels;
@ -307,6 +308,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
MinVolume = ALSource->MinGain; MinVolume = ALSource->MinGain;
MaxVolume = ALSource->MaxGain; MaxVolume = ALSource->MaxGain;
Pitch = ALSource->Pitch; Pitch = ALSource->Pitch;
Relative = ALSource->HeadRelative;
DirectChannels = ALSource->DirectChannels; DirectChannels = ALSource->DirectChannels;
voice->Direct.OutBuffer = Device->DryBuffer; voice->Direct.OutBuffer = Device->DryBuffer;
@ -414,12 +416,51 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
if(isbformat) if(isbformat)
{ {
ALfloat N[3], V[3], U[3];
ALfloat matrix[4][4];
/* AT then UP */
N[0] = ALSource->Orientation[0][0];
N[1] = ALSource->Orientation[0][1];
N[2] = ALSource->Orientation[0][2];
aluNormalize(N);
V[0] = ALSource->Orientation[1][0];
V[1] = ALSource->Orientation[1][1];
V[2] = ALSource->Orientation[1][2];
aluNormalize(V);
if(!Relative)
{
ALfloat (*restrict lmatrix)[4] = ALContext->Listener->Params.Matrix;
aluMatrixVector(N, 0.0f, lmatrix);
aluMatrixVector(V, 0.0f, lmatrix);
}
/* Build and normalize right-vector */
aluCrossproduct(N, V, U);
aluNormalize(U);
matrix[0][0] = 1.0f;
matrix[0][1] = 0.0f;
matrix[0][2] = 0.0f;
matrix[0][3] = 0.0f;
matrix[1][0] = 0.0f;
matrix[1][1] = -N[2];
matrix[1][2] = -N[0];
matrix[1][3] = N[1];
matrix[2][0] = 0.0f;
matrix[2][1] = U[2];
matrix[2][2] = U[0];
matrix[2][3] = -U[1];
matrix[3][0] = 0.0f;
matrix[3][1] = -V[2];
matrix[3][2] = -V[0];
matrix[3][3] = V[1];
for(c = 0;c < num_channels;c++) for(c = 0;c < num_channels;c++)
{ {
MixGains *gains = voice->Direct.Mix.Gains[c]; MixGains *gains = voice->Direct.Mix.Gains[c];
ALfloat Target[MaxChannels]; ALfloat Target[MaxChannels];
ComputeBFormatGains(Device, c, DryGain, Target); ComputeBFormatGains(Device, matrix[c], DryGain, Target);
for(i = 0;i < MaxChannels;i++) for(i = 0;i < MaxChannels;i++)
gains[i].Target = Target[i]; gains[i].Target = Target[i];
} }

View File

@ -81,16 +81,18 @@ void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfl
} }
} }
void ComputeBFormatGains(const ALCdevice *device, ALuint channum, ALfloat ingain, ALfloat gains[MaxChannels]) void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MaxChannels])
{ {
ALuint i; ALuint i, j;
for(i = 0;i < MaxChannels;i++) for(i = 0;i < MaxChannels;i++)
gains[i] = 0.0f; gains[i] = 0.0f;
for(i = 0;i < device->NumSpeakers;i++) for(i = 0;i < device->NumSpeakers;i++)
{ {
enum Channel chan = device->Speaker[i].ChanName; enum Channel chan = device->Speaker[i].ChanName;
gains[chan] = device->Speaker[i].FOACoeff[channum] * ingain; for(j = 0;j < 4;j++)
gains[chan] += device->Speaker[i].FOACoeff[j] * mtx[j];
gains[chan] *= ingain;
} }
} }

View File

@ -60,6 +60,7 @@ typedef struct ALsource {
volatile ALfloat Position[3]; volatile ALfloat Position[3];
volatile ALfloat Velocity[3]; volatile ALfloat Velocity[3];
volatile ALfloat Direction[3]; volatile ALfloat Direction[3];
volatile ALfloat Orientation[2][3];
volatile ALboolean HeadRelative; volatile ALboolean HeadRelative;
volatile ALboolean Looping; volatile ALboolean Looping;
volatile enum DistanceModel DistanceModel; volatile enum DistanceModel DistanceModel;

View File

@ -220,10 +220,11 @@ void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation
/** /**
* ComputeBFormatGains * ComputeBFormatGains
* *
* Sets channel gains for a given (first-order) B-Format channel. The channel * Sets channel gains for a given (first-order) B-Format channel. The matrix is
* number must not be greater than 4, and the resulting gains may be negative. * a 1x4 'slice' of the rotation matrix for a given channel used to orient the
* coefficients.
*/ */
void ComputeBFormatGains(const ALCdevice *device, ALuint channum, ALfloat ingain, ALfloat gains[MaxChannels]); void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MaxChannels]);
/** /**
* SetGains * SetGains

View File

@ -108,6 +108,9 @@ typedef enum SrcFloatProp {
/* AL_SOFT_source_latency */ /* AL_SOFT_source_latency */
sfSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT, sfSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
/* AL_EXT_BFORMAT */
sfOrientation = AL_ORIENTATION,
} SrcFloatProp; } SrcFloatProp;
typedef enum SrcIntProp { typedef enum SrcIntProp {
@ -153,6 +156,9 @@ typedef enum SrcIntProp {
/* AL_SOFT_source_latency */ /* AL_SOFT_source_latency */
siSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT, siSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT,
/* AL_EXT_BFORMAT */
siOrientation = AL_ORIENTATION,
} SrcIntProp; } SrcIntProp;
static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values); static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values);
@ -210,6 +216,9 @@ static ALint FloatValsByProp(ALenum prop)
case sfDirection: case sfDirection:
return 3; return 3;
case sfOrientation:
return 6;
case sfSecOffsetLatencySOFT: case sfSecOffsetLatencySOFT:
break; /* Double only */ break; /* Double only */
} }
@ -262,6 +271,9 @@ static ALint DoubleValsByProp(ALenum prop)
case sfVelocity: case sfVelocity:
case sfDirection: case sfDirection:
return 3; return 3;
case sfOrientation:
return 6;
} }
return 0; return 0;
} }
@ -308,6 +320,9 @@ static ALint IntValsByProp(ALenum prop)
case siAuxSendFilter: case siAuxSendFilter:
return 3; return 3;
case siOrientation:
return 6;
case siSampleOffsetLatencySOFT: case siSampleOffsetLatencySOFT:
break; /* i64 only */ break; /* i64 only */
} }
@ -355,6 +370,9 @@ static ALint Int64ValsByProp(ALenum prop)
case siDirection: case siDirection:
case siAuxSendFilter: case siAuxSendFilter:
return 3; return 3;
case siOrientation:
return 6;
} }
return 0; return 0;
} }
@ -530,6 +548,20 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp
ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
return AL_TRUE; return AL_TRUE;
case AL_ORIENTATION:
CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) &&
isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5]));
LockContext(Context);
Source->Orientation[0][0] = values[0];
Source->Orientation[0][1] = values[1];
Source->Orientation[0][2] = values[2];
Source->Orientation[1][0] = values[3];
Source->Orientation[1][1] = values[4];
Source->Orientation[1][2] = values[5];
UnlockContext(Context);
ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
return AL_TRUE;
case sfSampleRWOffsetsSOFT: case sfSampleRWOffsetsSOFT:
case sfByteRWOffsetsSOFT: case sfByteRWOffsetsSOFT:
@ -567,7 +599,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p
ALeffectslot *slot = NULL; ALeffectslot *slot = NULL;
ALbufferlistitem *oldlist; ALbufferlistitem *oldlist;
ALbufferlistitem *newlist; ALbufferlistitem *newlist;
ALfloat fvals[3]; ALfloat fvals[6];
switch(prop) switch(prop)
{ {
@ -791,6 +823,15 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p
fvals[2] = (ALfloat)values[2]; fvals[2] = (ALfloat)values[2];
return SetSourcefv(Source, Context, (int)prop, fvals); return SetSourcefv(Source, Context, (int)prop, fvals);
case AL_ORIENTATION:
fvals[0] = (ALfloat)values[0];
fvals[1] = (ALfloat)values[1];
fvals[2] = (ALfloat)values[2];
fvals[3] = (ALfloat)values[3];
fvals[4] = (ALfloat)values[4];
fvals[5] = (ALfloat)values[5];
return SetSourcefv(Source, Context, (int)prop, fvals);
case siSampleOffsetLatencySOFT: case siSampleOffsetLatencySOFT:
/* i64 only */ /* i64 only */
break; break;
@ -802,7 +843,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p
static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values) static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values)
{ {
ALfloat fvals[3]; ALfloat fvals[6];
ALint ivals[3]; ALint ivals[3];
switch(prop) switch(prop)
@ -873,6 +914,16 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp
fvals[1] = (ALfloat)values[1]; fvals[1] = (ALfloat)values[1];
fvals[2] = (ALfloat)values[2]; fvals[2] = (ALfloat)values[2];
return SetSourcefv(Source, Context, (int)prop, fvals); return SetSourcefv(Source, Context, (int)prop, fvals);
/* 6x float */
case AL_ORIENTATION:
fvals[0] = (ALfloat)values[0];
fvals[1] = (ALfloat)values[1];
fvals[2] = (ALfloat)values[2];
fvals[3] = (ALfloat)values[3];
fvals[4] = (ALfloat)values[4];
fvals[5] = (ALfloat)values[5];
return SetSourcefv(Source, Context, (int)prop, fvals);
} }
ERR("Unexpected property: 0x%04x\n", prop); ERR("Unexpected property: 0x%04x\n", prop);
@ -1025,6 +1076,17 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp
UnlockContext(Context); UnlockContext(Context);
return AL_TRUE; return AL_TRUE;
case AL_ORIENTATION:
LockContext(Context);
values[0] = Source->Orientation[0][0];
values[1] = Source->Orientation[0][1];
values[2] = Source->Orientation[0][2];
values[3] = Source->Orientation[1][0];
values[4] = Source->Orientation[1][1];
values[5] = Source->Orientation[1][2];
UnlockContext(Context);
return AL_TRUE;
case AL_SOURCE_RELATIVE: case AL_SOURCE_RELATIVE:
case AL_LOOPING: case AL_LOOPING:
case AL_BUFFER: case AL_BUFFER:
@ -1049,7 +1111,7 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp
static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values) static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values)
{ {
ALbufferlistitem *BufferList; ALbufferlistitem *BufferList;
ALdouble dvals[3]; ALdouble dvals[6];
ALboolean err; ALboolean err;
switch(prop) switch(prop)
@ -1224,6 +1286,18 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p
} }
return err; return err;
case AL_ORIENTATION:
if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
{
values[0] = (ALint)dvals[0];
values[1] = (ALint)dvals[1];
values[2] = (ALint)dvals[2];
values[3] = (ALint)dvals[3];
values[4] = (ALint)dvals[4];
values[5] = (ALint)dvals[5];
}
return err;
case siSampleOffsetLatencySOFT: case siSampleOffsetLatencySOFT:
/* i64 only */ /* i64 only */
break; break;
@ -1240,7 +1314,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p
static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values) static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values)
{ {
ALdouble dvals[3]; ALdouble dvals[6];
ALint ivals[3]; ALint ivals[3];
ALboolean err; ALboolean err;
@ -1288,6 +1362,18 @@ static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp
} }
return err; return err;
case AL_ORIENTATION:
if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
{
values[0] = (ALint64)dvals[0];
values[1] = (ALint64)dvals[1];
values[2] = (ALint64)dvals[2];
values[3] = (ALint64)dvals[3];
values[4] = (ALint64)dvals[4];
values[5] = (ALint64)dvals[5];
}
return err;
case AL_SOURCE_RELATIVE: case AL_SOURCE_RELATIVE:
case AL_LOOPING: case AL_LOOPING:
case AL_SOURCE_STATE: case AL_SOURCE_STATE:
@ -2381,12 +2467,18 @@ static ALvoid InitSourceParams(ALsource *Source)
Source->Position[0] = 0.0f; Source->Position[0] = 0.0f;
Source->Position[1] = 0.0f; Source->Position[1] = 0.0f;
Source->Position[2] = 0.0f; Source->Position[2] = 0.0f;
Source->Direction[0] = 0.0f;
Source->Direction[1] = 0.0f;
Source->Direction[2] = 0.0f;
Source->Velocity[0] = 0.0f; Source->Velocity[0] = 0.0f;
Source->Velocity[1] = 0.0f; Source->Velocity[1] = 0.0f;
Source->Velocity[2] = 0.0f; Source->Velocity[2] = 0.0f;
Source->Direction[0] = 0.0f;
Source->Direction[1] = 0.0f;
Source->Direction[2] = 0.0f;
Source->Orientation[0][0] = 0.0f;
Source->Orientation[0][1] = 0.0f;
Source->Orientation[0][2] = -1.0f;
Source->Orientation[1][0] = 0.0f;
Source->Orientation[1][1] = 1.0f;
Source->Orientation[1][2] = 0.0f;
Source->RefDistance = 1.0f; Source->RefDistance = 1.0f;
Source->MaxDistance = FLT_MAX; Source->MaxDistance = FLT_MAX;
Source->RollOffFactor = 1.0f; Source->RollOffFactor = 1.0f;