Do the filtering separately from the mixing

This commit is contained in:
Chris Robinson 2012-09-11 05:24:19 -07:00
parent aaa81e00b7
commit 98ff6f990a
5 changed files with 44 additions and 60 deletions

View File

@ -191,6 +191,16 @@ static void Resample(enum Resampler Resampler, const ALfloat *data, ALuint frac,
}
static void Filter2P(FILTER *filter, ALuint chan, ALfloat *RESTRICT dst,
const ALfloat *RESTRICT src, ALuint numsamples)
{
ALuint i;
for(i = 0;i < numsamples;i++)
dst[i] = lpFilter2P(filter, chan, src[i]);
dst[i] = lpFilter2PC(filter, chan, src[i]);
}
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
{
ALbufferlistitem *BufferListItem;
@ -432,20 +442,29 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
SrcData += BufferPrePadding*NumChannels;
for(i = 0;i < NumChannels;i++)
{
DirectParams *directparms = &Source->Params.Direct;
ALIGN(16) ALfloat FilteredData[BUFFERSIZE];
ALfloat ResampledData[BUFFERSIZE];
Resample(Resampler, SrcData+i, DataPosFrac, increment,
NumChannels, ResampledData, BufferSize);
Source->Params.DryMix(Source, Device, &Source->Params.Direct,
ResampledData, i, OutPos, SamplesToDo,
Filter2P(&directparms->iirFilter, i, FilteredData, ResampledData,
BufferSize);
Source->Params.DryMix(Source, Device, directparms,
FilteredData, i, OutPos, SamplesToDo,
BufferSize);
for(j = 0;j < Device->NumAuxSends;j++)
{
if(!Source->Params.Send[j].Slot)
SendParams *sendparms = &Source->Params.Send[j];
if(!sendparms->Slot)
continue;
Source->Params.WetMix(&Source->Params.Send[j], ResampledData, i,
OutPos, SamplesToDo, BufferSize);
Filter2P(&sendparms->iirFilter, i, FilteredData, ResampledData,
BufferSize);
Source->Params.WetMix(sendparms, FilteredData, OutPos,
SamplesToDo, BufferSize);
}
}
for(i = 0;i < BufferSize;i++)

View File

@ -13,16 +13,16 @@ struct SendParams;
/* C mixers */
void MixDirect_Hrtf_C(struct ALsource*,ALCdevice*,struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixDirect_C(struct ALsource*,ALCdevice*,struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_C(struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_C(struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint);
/* SSE mixers */
void MixDirect_Hrtf_SSE(struct ALsource*,ALCdevice*,struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixDirect_SSE(struct ALsource*,ALCdevice*,struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_SSE(struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_SSE(struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint);
/* Neon mixers */
void MixDirect_Hrtf_Neon(struct ALsource*,ALCdevice*,struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixDirect_Neon(struct ALsource*,ALCdevice*,struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_Neon(struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_Neon(struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint);
#endif /* MIXER_DEFS_H */

View File

@ -53,15 +53,12 @@ void MixDirect_Hrtf(ALsource *Source, ALCdevice *Device, DirectParams *params,
ALIGN(16) ALfloat Coeffs[HRIR_LENGTH][2];
ALuint Delay[2];
ALfloat left, right;
FILTER *DryFilter;
ALfloat value;
ALuint pos;
ALuint c;
DryBuffer = Device->DryBuffer;
ClickRemoval = Device->ClickRemoval;
PendingClicks = Device->PendingClicks;
DryFilter = &params->iirFilter;
pos = 0;
for(c = 0;c < IrSize;c++)
@ -75,9 +72,7 @@ void MixDirect_Hrtf(ALsource *Source, ALCdevice *Device, DirectParams *params,
if(LIKELY(OutPos == 0))
{
value = lpFilter2PC(DryFilter, srcchan, data[pos]);
History[Offset&SRC_HISTORY_MASK] = value;
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
(Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
@ -92,9 +87,7 @@ void MixDirect_Hrtf(ALsource *Source, ALCdevice *Device, DirectParams *params,
}
for(pos = 0;pos < BufferSize && Counter > 0;pos++)
{
value = lpFilter2P(DryFilter, srcchan, data[pos]);
History[Offset&SRC_HISTORY_MASK] = value;
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
(Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
@ -121,9 +114,7 @@ void MixDirect_Hrtf(ALsource *Source, ALCdevice *Device, DirectParams *params,
Delay[1] >>= HRTFDELAY_BITS;
for(;pos < BufferSize;pos++)
{
value = lpFilter2P(DryFilter, srcchan, data[pos]);
History[Offset&SRC_HISTORY_MASK] = value;
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
@ -139,9 +130,7 @@ void MixDirect_Hrtf(ALsource *Source, ALCdevice *Device, DirectParams *params,
}
if(LIKELY(OutPos == SamplesToDo))
{
value = lpFilter2PC(DryFilter, srcchan, data[pos]);
History[Offset&SRC_HISTORY_MASK] = value;
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
@ -161,16 +150,13 @@ void MixDirect(ALsource *Source, ALCdevice *Device, DirectParams *params,
ALfloat (*RESTRICT DryBuffer)[MaxChannels];
ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
ALIGN(16) ALfloat DrySend[MaxChannels];
FILTER *DryFilter;
ALuint pos;
ALfloat value;
ALuint c;
(void)Source;
DryBuffer = Device->DryBuffer;
ClickRemoval = Device->ClickRemoval;
PendingClicks = Device->PendingClicks;
DryFilter = &params->iirFilter;
for(c = 0;c < MaxChannels;c++)
DrySend[c] = params->Gains[srcchan][c];
@ -178,28 +164,25 @@ void MixDirect(ALsource *Source, ALCdevice *Device, DirectParams *params,
pos = 0;
if(OutPos == 0)
{
value = lpFilter2PC(DryFilter, srcchan, data[pos]);
for(c = 0;c < MaxChannels;c++)
ClickRemoval[c] -= value*DrySend[c];
ClickRemoval[c] -= data[pos]*DrySend[c];
}
for(pos = 0;pos < BufferSize;pos++)
{
value = lpFilter2P(DryFilter, srcchan, data[pos]);
for(c = 0;c < MaxChannels;c++)
DryBuffer[OutPos][c] += value*DrySend[c];
DryBuffer[OutPos][c] += data[pos]*DrySend[c];
OutPos++;
}
if(OutPos == SamplesToDo)
{
value = lpFilter2PC(DryFilter, srcchan, data[pos]);
for(c = 0;c < MaxChannels;c++)
PendingClicks[c] += value*DrySend[c];
PendingClicks[c] += data[pos]*DrySend[c];
}
}
#endif
#ifndef NO_MIXSEND
void MixSend(SendParams *params, const ALfloat *RESTRICT data, ALuint srcchan,
void MixSend(SendParams *params, const ALfloat *RESTRICT data,
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
{
ALeffectslot *Slot;
@ -207,33 +190,27 @@ void MixSend(SendParams *params, const ALfloat *RESTRICT data, ALuint srcchan,
ALfloat *WetBuffer;
ALfloat *WetClickRemoval;
ALfloat *WetPendingClicks;
FILTER *WetFilter;
ALuint pos;
ALfloat value;
Slot = params->Slot;
WetBuffer = Slot->WetBuffer;
WetClickRemoval = Slot->ClickRemoval;
WetPendingClicks = Slot->PendingClicks;
WetFilter = &params->iirFilter;
WetSend = params->Gain;
pos = 0;
if(OutPos == 0)
{
value = lpFilter2PC(WetFilter, srcchan, data[pos]);
WetClickRemoval[0] -= value * WetSend;
WetClickRemoval[0] -= data[pos] * WetSend;
}
for(pos = 0;pos < BufferSize;pos++)
{
value = lpFilter2P(WetFilter, srcchan, data[pos]);
WetBuffer[OutPos] += value * WetSend;
WetBuffer[OutPos] += data[pos] * WetSend;
OutPos++;
}
if(OutPos == SamplesToDo)
{
value = lpFilter2PC(WetFilter, srcchan, data[pos]);
WetPendingClicks[0] += value * WetSend;
WetPendingClicks[0] += data[pos] * WetSend;
}
}
#endif

View File

@ -134,9 +134,8 @@ void MixDirect_SSE(ALsource *Source, ALCdevice *Device, DirectParams *params,
{
ALfloat (*RESTRICT DryBuffer)[MaxChannels];
ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;
ALIGN(16) ALfloat DrySend[MaxChannels];
ALfloat DrySend[MaxChannels];
ALIGN(16) ALfloat value[4];
FILTER *DryFilter;
ALuint pos;
ALuint c;
(void)Source;
@ -144,7 +143,6 @@ void MixDirect_SSE(ALsource *Source, ALCdevice *Device, DirectParams *params,
DryBuffer = Device->DryBuffer;
ClickRemoval = Device->ClickRemoval;
PendingClicks = Device->PendingClicks;
DryFilter = &params->iirFilter;
for(c = 0;c < MaxChannels;c++)
DrySend[c] = params->Gains[srcchan][c];
@ -152,20 +150,12 @@ void MixDirect_SSE(ALsource *Source, ALCdevice *Device, DirectParams *params,
pos = 0;
if(OutPos == 0)
{
value[0] = lpFilter2PC(DryFilter, srcchan, data[pos]);
for(c = 0;c < MaxChannels;c++)
ClickRemoval[c] -= value[0]*DrySend[c];
ClickRemoval[c] -= data[pos]*DrySend[c];
}
for(pos = 0;pos < BufferSize-3;pos += 4)
{
__m128 val4;
value[0] = lpFilter2P(DryFilter, srcchan, data[pos ]);
value[1] = lpFilter2P(DryFilter, srcchan, data[pos+1]);
value[2] = lpFilter2P(DryFilter, srcchan, data[pos+2]);
value[3] = lpFilter2P(DryFilter, srcchan, data[pos+3]);
val4 = _mm_load_ps(value);
const __m128 val4 = _mm_load_ps(&data[pos]);
for(c = 0;c < MaxChannels;c++)
{
const __m128 gain = _mm_set1_ps(DrySend[c]);
@ -190,16 +180,14 @@ void MixDirect_SSE(ALsource *Source, ALCdevice *Device, DirectParams *params,
}
for(;pos < BufferSize;pos++)
{
value[0] = lpFilter2P(DryFilter, srcchan, data[pos]);
for(c = 0;c < MaxChannels;c++)
DryBuffer[OutPos][c] += value[0]*DrySend[c];
DryBuffer[OutPos][c] += data[pos]*DrySend[c];
OutPos++;
}
if(OutPos == SamplesToDo)
{
value[0] = lpFilter2PC(DryFilter, srcchan, data[pos]);
for(c = 0;c < MaxChannels;c++)
PendingClicks[c] += value[0]*DrySend[c];
PendingClicks[c] += data[pos]*DrySend[c];
}
}
#define NO_MIXDIRECT

View File

@ -88,7 +88,7 @@ typedef ALvoid (*DryMixerFunc)(struct ALsource *self, ALCdevice *Device,
ALuint OutPos, ALuint SamplesToDo,
ALuint BufferSize);
typedef ALvoid (*WetMixerFunc)(struct SendParams *params,
const ALfloat *RESTRICT data, ALuint srcchan,
const ALfloat *RESTRICT data,
ALuint OutPos, ALuint SamplesToDo,
ALuint BufferSize);