Track the virtual and real output buffers ecplicitly
This commit is contained in:
parent
3b9fe27cbe
commit
3e2672ec9f
35
Alc/ALc.c
35
Alc/ALc.c
@ -1855,6 +1855,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
|
||||
al_free(device->DryBuffer);
|
||||
device->DryBuffer = NULL;
|
||||
device->VirtOut.Buffer = NULL;
|
||||
device->VirtOut.NumChannels = 0;
|
||||
device->RealOut.Buffer = NULL;
|
||||
device->RealOut.NumChannels = 0;
|
||||
|
||||
UpdateClockBase(device);
|
||||
|
||||
@ -2124,6 +2128,21 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
return ALC_INVALID_DEVICE;
|
||||
}
|
||||
|
||||
if(device->Hrtf || device->Uhj_Encoder)
|
||||
{
|
||||
device->VirtOut.Buffer = device->DryBuffer;
|
||||
device->VirtOut.NumChannels = device->NumChannels;
|
||||
device->RealOut.Buffer = device->DryBuffer + device->NumChannels;
|
||||
device->RealOut.NumChannels = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
device->VirtOut.Buffer = NULL;
|
||||
device->VirtOut.NumChannels = 0;
|
||||
device->RealOut.Buffer = device->DryBuffer;
|
||||
device->RealOut.NumChannels = device->NumChannels;
|
||||
}
|
||||
|
||||
SetMixerFPUMode(&oldMode);
|
||||
V0(device->Backend,lock)();
|
||||
context = ATOMIC_LOAD(&device->ContextList);
|
||||
@ -2261,6 +2280,10 @@ static ALCvoid FreeDevice(ALCdevice *device)
|
||||
|
||||
al_free(device->DryBuffer);
|
||||
device->DryBuffer = NULL;
|
||||
device->VirtOut.Buffer = NULL;
|
||||
device->VirtOut.NumChannels = 0;
|
||||
device->RealOut.Buffer = NULL;
|
||||
device->RealOut.NumChannels = 0;
|
||||
|
||||
al_free(device);
|
||||
}
|
||||
@ -3361,6 +3384,10 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
|
||||
device->Render_Mode = NormalRender;
|
||||
AL_STRING_INIT(device->DeviceName);
|
||||
device->DryBuffer = NULL;
|
||||
device->VirtOut.Buffer = NULL;
|
||||
device->VirtOut.NumChannels = 0;
|
||||
device->RealOut.Buffer = NULL;
|
||||
device->RealOut.NumChannels = 0;
|
||||
|
||||
ATOMIC_INIT(&device->ContextList, NULL);
|
||||
|
||||
@ -3616,6 +3643,10 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
|
||||
|
||||
AL_STRING_INIT(device->DeviceName);
|
||||
device->DryBuffer = NULL;
|
||||
device->VirtOut.Buffer = NULL;
|
||||
device->VirtOut.NumChannels = 0;
|
||||
device->RealOut.Buffer = NULL;
|
||||
device->RealOut.NumChannels = 0;
|
||||
|
||||
InitUIntMap(&device->BufferMap, ~0);
|
||||
InitUIntMap(&device->EffectMap, ~0);
|
||||
@ -3806,6 +3837,10 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
|
||||
device->Render_Mode = NormalRender;
|
||||
AL_STRING_INIT(device->DeviceName);
|
||||
device->DryBuffer = NULL;
|
||||
device->VirtOut.Buffer = NULL;
|
||||
device->VirtOut.NumChannels = 0;
|
||||
device->RealOut.Buffer = NULL;
|
||||
device->RealOut.NumChannels = 0;
|
||||
|
||||
ATOMIC_INIT(&device->ContextList, NULL);
|
||||
|
||||
|
54
Alc/ALu.c
54
Alc/ALu.c
@ -581,8 +581,8 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
|
||||
* channels and write FrontLeft and FrontRight inputs to the
|
||||
* first and second outputs.
|
||||
*/
|
||||
voice->Direct.OutBuffer += voice->Direct.OutChannels;
|
||||
voice->Direct.OutChannels = 2;
|
||||
voice->Direct.OutBuffer = Device->RealOut.Buffer;
|
||||
voice->Direct.OutChannels = Device->RealOut.NumChannels;
|
||||
for(c = 0;c < num_channels;c++)
|
||||
{
|
||||
for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
|
||||
@ -632,8 +632,8 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
|
||||
/* Full HRTF rendering. Skip the virtual channels and render each
|
||||
* input channel to the real outputs.
|
||||
*/
|
||||
voice->Direct.OutBuffer += voice->Direct.OutChannels;
|
||||
voice->Direct.OutChannels = 2;
|
||||
voice->Direct.OutBuffer = Device->RealOut.Buffer;
|
||||
voice->Direct.OutChannels = Device->RealOut.NumChannels;
|
||||
for(c = 0;c < num_channels;c++)
|
||||
{
|
||||
if(chans[c].channel == LFE)
|
||||
@ -1131,8 +1131,8 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
|
||||
ALfloat dirfact = 1.0f;
|
||||
ALfloat coeffs[MAX_AMBI_COEFFS];
|
||||
|
||||
voice->Direct.OutBuffer += voice->Direct.OutChannels;
|
||||
voice->Direct.OutChannels = 2;
|
||||
voice->Direct.OutBuffer = Device->RealOut.Buffer;
|
||||
voice->Direct.OutChannels = Device->RealOut.NumChannels;
|
||||
|
||||
if(Distance > FLT_EPSILON)
|
||||
{
|
||||
@ -1393,26 +1393,13 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
|
||||
while(size > 0)
|
||||
{
|
||||
ALfloat (*OutBuffer)[BUFFERSIZE];
|
||||
ALuint OutChannels;
|
||||
|
||||
IncrementRef(&device->MixCount);
|
||||
|
||||
OutBuffer = device->DryBuffer;
|
||||
OutChannels = device->NumChannels;
|
||||
|
||||
SamplesToDo = minu(size, BUFFERSIZE);
|
||||
for(c = 0;c < OutChannels;c++)
|
||||
memset(OutBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
|
||||
if(device->Hrtf || device->Uhj_Encoder)
|
||||
{
|
||||
/* Set OutBuffer/OutChannels to correspond to the actual output
|
||||
* with HRTF. Make sure to clear them too. */
|
||||
OutBuffer += OutChannels;
|
||||
OutChannels = 2;
|
||||
for(c = 0;c < OutChannels;c++)
|
||||
memset(OutBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
|
||||
}
|
||||
for(c = 0;c < device->VirtOut.NumChannels;c++)
|
||||
memset(device->VirtOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
|
||||
for(c = 0;c < device->RealOut.NumChannels;c++)
|
||||
memset(device->RealOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
|
||||
|
||||
V0(device->Backend,lock)();
|
||||
|
||||
@ -1495,12 +1482,13 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
ALuint irsize = GetHrtfIrSize(device->Hrtf);
|
||||
MixHrtfParams hrtfparams;
|
||||
memset(&hrtfparams, 0, sizeof(hrtfparams));
|
||||
for(c = 0;c < device->NumChannels;c++)
|
||||
for(c = 0;c < device->VirtOut.NumChannels;c++)
|
||||
{
|
||||
hrtfparams.Current = &device->Hrtf_Params[c];
|
||||
hrtfparams.Target = &device->Hrtf_Params[c];
|
||||
HrtfMix(OutBuffer, device->DryBuffer[c], 0, device->Hrtf_Offset,
|
||||
0, irsize, &hrtfparams, &device->Hrtf_State[c], SamplesToDo
|
||||
HrtfMix(device->RealOut.Buffer, device->VirtOut.Buffer[c], 0,
|
||||
device->Hrtf_Offset, 0, irsize, &hrtfparams,
|
||||
&device->Hrtf_State[c], SamplesToDo
|
||||
);
|
||||
}
|
||||
device->Hrtf_Offset += SamplesToDo;
|
||||
@ -1510,7 +1498,8 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
if(device->Uhj_Encoder)
|
||||
{
|
||||
/* Encode to stereo-compatible 2-channel UHJ output. */
|
||||
EncodeUhj2(device->Uhj_Encoder, OutBuffer, device->DryBuffer, SamplesToDo);
|
||||
EncodeUhj2(device->Uhj_Encoder, device->RealOut.Buffer,
|
||||
device->VirtOut.Buffer, SamplesToDo);
|
||||
}
|
||||
if(device->Bs2b)
|
||||
{
|
||||
@ -1518,17 +1507,20 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
for(i = 0;i < SamplesToDo;i++)
|
||||
{
|
||||
float samples[2];
|
||||
samples[0] = OutBuffer[0][i];
|
||||
samples[1] = OutBuffer[1][i];
|
||||
samples[0] = device->RealOut.Buffer[0][i];
|
||||
samples[1] = device->RealOut.Buffer[1][i];
|
||||
bs2b_cross_feed(device->Bs2b, samples);
|
||||
OutBuffer[0][i] = samples[0];
|
||||
OutBuffer[1][i] = samples[1];
|
||||
device->RealOut.Buffer[0][i] = samples[0];
|
||||
device->RealOut.Buffer[1][i] = samples[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(buffer)
|
||||
{
|
||||
ALfloat (*OutBuffer)[BUFFERSIZE] = device->RealOut.Buffer;
|
||||
ALuint OutChannels = device->RealOut.NumChannels;;
|
||||
|
||||
#define WRITE(T, a, b, c, d) do { \
|
||||
Write_##T((a), (b), (c), (d)); \
|
||||
buffer = (T*)buffer + (c)*(d); \
|
||||
|
@ -364,6 +364,9 @@ static ALboolean ALreverbState_deviceUpdate(ALreverbState *State, ALCdevice *Dev
|
||||
if(!AllocLines(frequency, State))
|
||||
return AL_FALSE;
|
||||
|
||||
/* WARNING: This assumes the real output follows the virtual output in the
|
||||
* device's DryBuffer.
|
||||
*/
|
||||
State->ExtraChannels = (Device->Hrtf || Device->Uhj_Encoder) ? 2 : 0;
|
||||
|
||||
// Calculate the modulation filter coefficient. Notice that the exponent
|
||||
@ -666,16 +669,19 @@ static ALvoid UpdateMixedPanning(const ALCdevice *Device, const ALfloat *Reflect
|
||||
ALfloat length;
|
||||
ALuint i;
|
||||
|
||||
/* With HRTF, the normal output provides a panned reverb channel when a
|
||||
* non-0-length vector is specified, while the real stereo output provides
|
||||
* two other "direct" non-panned reverb channels.
|
||||
/* With HRTF or UHJ, the normal output provides a panned reverb channel
|
||||
* when a non-0-length vector is specified, while the real stereo output
|
||||
* provides two other "direct" non-panned reverb channels.
|
||||
*
|
||||
* WARNING: This assumes the real output follows the virtual output in the
|
||||
* device's DryBuffer.
|
||||
*/
|
||||
memset(State->Early.PanGain, 0, sizeof(State->Early.PanGain));
|
||||
length = sqrtf(ReflectionsPan[0]*ReflectionsPan[0] + ReflectionsPan[1]*ReflectionsPan[1] + ReflectionsPan[2]*ReflectionsPan[2]);
|
||||
if(!(length > FLT_EPSILON))
|
||||
{
|
||||
for(i = 0;i < 2;i++)
|
||||
State->Early.PanGain[i&3][Device->NumChannels+i] = Gain * EarlyGain;
|
||||
for(i = 0;i < Device->RealOut.NumChannels;i++)
|
||||
State->Early.PanGain[i&3][Device->VirtOut.NumChannels+i] = Gain * EarlyGain;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -691,19 +697,19 @@ static ALvoid UpdateMixedPanning(const ALCdevice *Device, const ALfloat *Reflect
|
||||
length = minf(length, 1.0f);
|
||||
|
||||
CalcDirectionCoeffs(pan, coeffs);
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, Gain, DirGains);
|
||||
for(i = 0;i < Device->NumChannels;i++)
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->VirtOut.NumChannels, coeffs, Gain, DirGains);
|
||||
for(i = 0;i < Device->VirtOut.NumChannels;i++)
|
||||
State->Early.PanGain[3][i] = DirGains[i] * EarlyGain * length;
|
||||
for(i = 0;i < 2;i++)
|
||||
State->Early.PanGain[i&3][Device->NumChannels+i] = Gain * EarlyGain * (1.0f-length);
|
||||
for(i = 0;i < Device->RealOut.NumChannels;i++)
|
||||
State->Early.PanGain[i&3][Device->VirtOut.NumChannels+i] = Gain * EarlyGain * (1.0f-length);
|
||||
}
|
||||
|
||||
memset(State->Late.PanGain, 0, sizeof(State->Late.PanGain));
|
||||
length = sqrtf(LateReverbPan[0]*LateReverbPan[0] + LateReverbPan[1]*LateReverbPan[1] + LateReverbPan[2]*LateReverbPan[2]);
|
||||
if(!(length > FLT_EPSILON))
|
||||
{
|
||||
for(i = 0;i < 2;i++)
|
||||
State->Late.PanGain[i&3][Device->NumChannels+i] = Gain * LateGain;
|
||||
for(i = 0;i < Device->RealOut.NumChannels;i++)
|
||||
State->Late.PanGain[i&3][Device->VirtOut.NumChannels+i] = Gain * LateGain;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -715,11 +721,11 @@ static ALvoid UpdateMixedPanning(const ALCdevice *Device, const ALfloat *Reflect
|
||||
length = minf(length, 1.0f);
|
||||
|
||||
CalcDirectionCoeffs(pan, coeffs);
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, Gain, DirGains);
|
||||
for(i = 0;i < Device->NumChannels;i++)
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->VirtOut.NumChannels, coeffs, Gain, DirGains);
|
||||
for(i = 0;i < Device->VirtOut.NumChannels;i++)
|
||||
State->Late.PanGain[3][i] = DirGains[i] * LateGain * length;
|
||||
for(i = 0;i < 2;i++)
|
||||
State->Late.PanGain[i&3][Device->NumChannels+i] = Gain * LateGain * (1.0f-length);
|
||||
for(i = 0;i < Device->RealOut.NumChannels;i++)
|
||||
State->Late.PanGain[i&3][Device->VirtOut.NumChannels+i] = Gain * LateGain * (1.0f-length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,9 +494,20 @@ struct ALCdevice_struct
|
||||
alignas(16) ALfloat ResampledData[BUFFERSIZE];
|
||||
alignas(16) ALfloat FilteredData[BUFFERSIZE];
|
||||
|
||||
/* Dry path buffer mix. */
|
||||
/* Dry path buffer mix (will be aliased by the virtual or real output). */
|
||||
alignas(16) ALfloat (*DryBuffer)[BUFFERSIZE];
|
||||
|
||||
/* Virtual output, to be post-processed to the real output. */
|
||||
struct {
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALuint NumChannels;
|
||||
} VirtOut;
|
||||
/* "Real" output, which will be written to the device buffer. */
|
||||
struct {
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALuint NumChannels;
|
||||
} RealOut;
|
||||
|
||||
/* Running count of the mixer invocations, in 31.1 fixed point. This
|
||||
* actually increments *twice* when mixing, first at the start and then at
|
||||
* the end, so the bottom bit indicates if the device is currently mixing
|
||||
|
Loading…
Reference in New Issue
Block a user