From 3ee9d24c3f7fb94fb98d87c0c360e3365e87c67e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 22 Sep 2010 09:38:24 -0700 Subject: [PATCH] Use separate macros for the different mixing loops --- Alc/mixer.c | 402 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 202 insertions(+), 200 deletions(-) diff --git a/Alc/mixer.c b/Alc/mixer.c index 127df3a7..1a89737a 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -78,148 +78,7 @@ static __inline ALfloat cos_lerp(ALfloat val1, ALfloat val2, ALint frac) } -static void MixSource(ALsource *ALSource, ALCcontext *ALContext, - float (*DryBuffer)[OUTPUTCHANNELS], ALuint SamplesToDo, - ALfloat *ClickRemoval, ALfloat *PendingClicks) -{ - static float DummyBuffer[BUFFERSIZE]; - static ALfloat DummyClickRemoval[OUTPUTCHANNELS]; - ALfloat *WetBuffer[MAX_SENDS]; - ALfloat DrySend[OUTPUTCHANNELS]; - ALfloat *WetClickRemoval[MAX_SENDS]; - ALfloat *WetPendingClicks[MAX_SENDS]; - ALuint i, j, out; - ALfloat value, outsamp; - ALbufferlistitem *BufferListItem; - ALint64 DataSize64,DataPos64; - FILTER *DryFilter, *WetFilter[MAX_SENDS]; - ALfloat WetSend[MAX_SENDS]; - ALint increment; - ALuint DataPosInt, DataPosFrac; - resampler_t Resampler; - ALuint BuffersPlayed; - ALboolean Looping; - ALenum State; - - if(ALSource->NeedsUpdate) - { - ALsource_Update(ALSource, ALContext); - ALSource->NeedsUpdate = AL_FALSE; - } - - /* Get source info */ - Resampler = ALSource->Resampler; - State = ALSource->state; - BuffersPlayed = ALSource->BuffersPlayed; - DataPosInt = ALSource->position; - DataPosFrac = ALSource->position_fraction; - Looping = ALSource->bLooping; - - for(i = 0;i < OUTPUTCHANNELS;i++) - DrySend[i] = ALSource->Params.DryGains[i]; - for(i = 0;i < MAX_SENDS;i++) - WetSend[i] = ALSource->Params.WetGains[i]; - - /* Get fixed point step */ - increment = ALSource->Params.Step; - - DryFilter = &ALSource->Params.iirFilter; - for(i = 0;i < MAX_SENDS;i++) - { - WetFilter[i] = &ALSource->Params.Send[i].iirFilter; - if(ALSource->Send[i].Slot) - { - WetBuffer[i] = ALSource->Send[i].Slot->WetBuffer; - WetClickRemoval[i] = ALSource->Send[i].Slot->ClickRemoval; - WetPendingClicks[i] = ALSource->Send[i].Slot->PendingClicks; - } - else - { - WetBuffer[i] = DummyBuffer; - WetClickRemoval[i] = DummyClickRemoval; - WetPendingClicks[i] = DummyClickRemoval; - } - } - - /* Get current buffer queue item */ - BufferListItem = ALSource->queue; - for(i = 0;i < BuffersPlayed;i++) - BufferListItem = BufferListItem->next; - - j = 0; - do { - const ALbuffer *ALBuffer; - ALfloat *Data = NULL; - ALuint DataSize = 0; - ALuint LoopStart = 0; - ALuint LoopEnd = 0; - ALuint Channels, Bytes; - ALuint BufferSize; - - /* Get buffer info */ - if((ALBuffer=BufferListItem->buffer) != NULL) - { - Data = ALBuffer->data; - DataSize = ALBuffer->size; - DataSize /= aluFrameSizeFromFormat(ALBuffer->format); - Channels = aluChannelsFromFormat(ALBuffer->format); - Bytes = aluBytesFromFormat(ALBuffer->format); - - LoopStart = 0; - LoopEnd = DataSize; - if(Looping && ALSource->lSourceType == AL_STATIC) - { - /* If current pos is beyond the loop range, do not loop */ - if(DataPosInt >= LoopEnd) - Looping = AL_FALSE; - else - { - LoopStart = ALBuffer->LoopStart; - LoopEnd = ALBuffer->LoopEnd; - } - } - } - - if(DataPosInt >= DataSize) - goto skipmix; - - if(BufferListItem->next) - { - ALbuffer *NextBuf = BufferListItem->next->buffer; - if(NextBuf && NextBuf->size) - { - ALint ulExtraSamples = BUFFER_PADDING*Channels*Bytes; - ulExtraSamples = min(NextBuf->size, ulExtraSamples); - memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples); - } - } - else if(Looping) - { - ALbuffer *NextBuf = ALSource->queue->buffer; - if(NextBuf && NextBuf->size) - { - ALint ulExtraSamples = BUFFER_PADDING*Channels*Bytes; - ulExtraSamples = min(NextBuf->size, ulExtraSamples); - memcpy(&Data[DataSize*Channels], &NextBuf->data[LoopStart*Channels], ulExtraSamples); - } - } - else - memset(&Data[DataSize*Channels], 0, (BUFFER_PADDING*Channels*Bytes)); - - /* Figure out how many samples we can mix. */ - DataSize64 = LoopEnd; - DataSize64 <<= FRACTIONBITS; - DataPos64 = DataPosInt; - DataPos64 <<= FRACTIONBITS; - DataPos64 += DataPosFrac; - BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment); - - BufferSize = min(BufferSize, (SamplesToDo-j)); - - /* Actual sample mixing loops */ - if(Channels == 1) /* Mono */ - { -#define DO_MIX(resampler) do { \ +#define DO_MIX_MONO(resampler) do { \ if(j == 0) \ { \ value = (resampler)(Data[DataPosInt], Data[DataPosInt+1], \ @@ -295,29 +154,7 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, } \ } while(0) - switch(Resampler) - { - case POINT_RESAMPLER: - DO_MIX(point); break; - case LINEAR_RESAMPLER: - DO_MIX(lerp); break; - case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; - case RESAMPLER_MIN: - case RESAMPLER_MAX: - break; - } -#undef DO_MIX - } - else if(Channels == 2) /* Stereo */ - { - const int chans[] = { - FRONT_LEFT, FRONT_RIGHT, - SIDE_LEFT, SIDE_RIGHT, - BACK_LEFT, BACK_RIGHT - }; - -#define DO_MIX(resampler) do { \ +#define DO_MIX_STEREO(resampler) do { \ const ALfloat scaler = 1.0f/Channels; \ if(j == 0) \ { \ @@ -389,28 +226,7 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, } \ } while(0) - switch(Resampler) - { - case POINT_RESAMPLER: - DO_MIX(point); break; - case LINEAR_RESAMPLER: - DO_MIX(lerp); break; - case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; - case RESAMPLER_MIN: - case RESAMPLER_MAX: - break; - } -#undef DO_MIX - } - else if(Channels == 4) /* Quad */ - { - const int chans[] = { - FRONT_LEFT, FRONT_RIGHT, - BACK_LEFT, BACK_RIGHT - }; - -#define DO_MIX(resampler) do { \ +#define DO_MIX_MC(resampler) do { \ const ALfloat scaler = 1.0f/Channels; \ if(j == 0) \ { \ @@ -476,14 +292,197 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, } \ } while(0) + +static void MixSource(ALsource *ALSource, ALCcontext *ALContext, + float (*DryBuffer)[OUTPUTCHANNELS], ALuint SamplesToDo, + ALfloat *ClickRemoval, ALfloat *PendingClicks) +{ + static float DummyBuffer[BUFFERSIZE]; + static ALfloat DummyClickRemoval[OUTPUTCHANNELS]; + ALfloat *WetBuffer[MAX_SENDS]; + ALfloat DrySend[OUTPUTCHANNELS]; + ALfloat *WetClickRemoval[MAX_SENDS]; + ALfloat *WetPendingClicks[MAX_SENDS]; + ALuint i, j, out; + ALfloat value, outsamp; + ALbufferlistitem *BufferListItem; + ALint64 DataSize64,DataPos64; + FILTER *DryFilter, *WetFilter[MAX_SENDS]; + ALfloat WetSend[MAX_SENDS]; + ALint increment; + ALuint DataPosInt, DataPosFrac; + resampler_t Resampler; + ALuint BuffersPlayed; + ALboolean Looping; + ALenum State; + + if(ALSource->NeedsUpdate) + { + ALsource_Update(ALSource, ALContext); + ALSource->NeedsUpdate = AL_FALSE; + } + + /* Get source info */ + Resampler = ALSource->Resampler; + State = ALSource->state; + BuffersPlayed = ALSource->BuffersPlayed; + DataPosInt = ALSource->position; + DataPosFrac = ALSource->position_fraction; + Looping = ALSource->bLooping; + + for(i = 0;i < OUTPUTCHANNELS;i++) + DrySend[i] = ALSource->Params.DryGains[i]; + for(i = 0;i < MAX_SENDS;i++) + WetSend[i] = ALSource->Params.WetGains[i]; + + /* Get fixed point step */ + increment = ALSource->Params.Step; + + DryFilter = &ALSource->Params.iirFilter; + for(i = 0;i < MAX_SENDS;i++) + { + WetFilter[i] = &ALSource->Params.Send[i].iirFilter; + if(ALSource->Send[i].Slot) + { + WetBuffer[i] = ALSource->Send[i].Slot->WetBuffer; + WetClickRemoval[i] = ALSource->Send[i].Slot->ClickRemoval; + WetPendingClicks[i] = ALSource->Send[i].Slot->PendingClicks; + } + else + { + WetBuffer[i] = DummyBuffer; + WetClickRemoval[i] = DummyClickRemoval; + WetPendingClicks[i] = DummyClickRemoval; + } + } + + /* Get current buffer queue item */ + BufferListItem = ALSource->queue; + for(i = 0;i < BuffersPlayed;i++) + BufferListItem = BufferListItem->next; + + j = 0; + do { + const ALbuffer *ALBuffer; + ALfloat *Data = NULL; + ALuint DataSize = 0; + ALuint LoopStart = 0; + ALuint LoopEnd = 0; + ALuint Channels, Bytes; + ALuint BufferSize; + + /* Get buffer info */ + if((ALBuffer=BufferListItem->buffer) != NULL) + { + Data = ALBuffer->data; + DataSize = ALBuffer->size; + DataSize /= aluFrameSizeFromFormat(ALBuffer->format); + Channels = aluChannelsFromFormat(ALBuffer->format); + Bytes = aluBytesFromFormat(ALBuffer->format); + + LoopStart = 0; + LoopEnd = DataSize; + if(Looping && ALSource->lSourceType == AL_STATIC) + { + /* If current pos is beyond the loop range, do not loop */ + if(DataPosInt >= LoopEnd) + Looping = AL_FALSE; + else + { + LoopStart = ALBuffer->LoopStart; + LoopEnd = ALBuffer->LoopEnd; + } + } + } + + if(DataPosInt >= DataSize) + goto skipmix; + + if(BufferListItem->next) + { + ALbuffer *NextBuf = BufferListItem->next->buffer; + if(NextBuf && NextBuf->size) + { + ALint ulExtraSamples = BUFFER_PADDING*Channels*Bytes; + ulExtraSamples = min(NextBuf->size, ulExtraSamples); + memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples); + } + } + else if(Looping) + { + ALbuffer *NextBuf = ALSource->queue->buffer; + if(NextBuf && NextBuf->size) + { + ALint ulExtraSamples = BUFFER_PADDING*Channels*Bytes; + ulExtraSamples = min(NextBuf->size, ulExtraSamples); + memcpy(&Data[DataSize*Channels], &NextBuf->data[LoopStart*Channels], ulExtraSamples); + } + } + else + memset(&Data[DataSize*Channels], 0, (BUFFER_PADDING*Channels*Bytes)); + + /* Figure out how many samples we can mix. */ + DataSize64 = LoopEnd; + DataSize64 <<= FRACTIONBITS; + DataPos64 = DataPosInt; + DataPos64 <<= FRACTIONBITS; + DataPos64 += DataPosFrac; + BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment); + + BufferSize = min(BufferSize, (SamplesToDo-j)); + + /* Actual sample mixing loops */ + if(Channels == 1) /* Mono */ + { + switch(Resampler) + { + case POINT_RESAMPLER: + DO_MIX_MONO(point); break; + case LINEAR_RESAMPLER: + DO_MIX_MONO(lerp); break; + case COSINE_RESAMPLER: + DO_MIX_MONO(cos_lerp); break; + case RESAMPLER_MIN: + case RESAMPLER_MAX: + break; + } + } + else if(Channels == 2) /* Stereo */ + { + const int chans[] = { + FRONT_LEFT, FRONT_RIGHT, + SIDE_LEFT, SIDE_RIGHT, + BACK_LEFT, BACK_RIGHT + }; + + switch(Resampler) + { + case POINT_RESAMPLER: + DO_MIX_STEREO(point); break; + case LINEAR_RESAMPLER: + DO_MIX_STEREO(lerp); break; + case COSINE_RESAMPLER: + DO_MIX_STEREO(cos_lerp); break; + case RESAMPLER_MIN: + case RESAMPLER_MAX: + break; + } + } + else if(Channels == 4) /* Quad */ + { + const int chans[] = { + FRONT_LEFT, FRONT_RIGHT, + BACK_LEFT, BACK_RIGHT + }; + switch(Resampler) { case POINT_RESAMPLER: - DO_MIX(point); break; + DO_MIX_MC(point); break; case LINEAR_RESAMPLER: - DO_MIX(lerp); break; + DO_MIX_MC(lerp); break; case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; + DO_MIX_MC(cos_lerp); break; case RESAMPLER_MIN: case RESAMPLER_MAX: break; @@ -500,11 +499,11 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, switch(Resampler) { case POINT_RESAMPLER: - DO_MIX(point); break; + DO_MIX_MC(point); break; case LINEAR_RESAMPLER: - DO_MIX(lerp); break; + DO_MIX_MC(lerp); break; case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; + DO_MIX_MC(cos_lerp); break; case RESAMPLER_MIN: case RESAMPLER_MAX: break; @@ -522,11 +521,11 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, switch(Resampler) { case POINT_RESAMPLER: - DO_MIX(point); break; + DO_MIX_MC(point); break; case LINEAR_RESAMPLER: - DO_MIX(lerp); break; + DO_MIX_MC(lerp); break; case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; + DO_MIX_MC(cos_lerp); break; case RESAMPLER_MIN: case RESAMPLER_MAX: break; @@ -544,16 +543,15 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, switch(Resampler) { case POINT_RESAMPLER: - DO_MIX(point); break; + DO_MIX_MC(point); break; case LINEAR_RESAMPLER: - DO_MIX(lerp); break; + DO_MIX_MC(lerp); break; case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; + DO_MIX_MC(cos_lerp); break; case RESAMPLER_MIN: case RESAMPLER_MAX: break; } -#undef DO_MIX } else /* Unknown? */ { @@ -604,6 +602,10 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, ALSource->Buffer = BufferListItem->buffer; } +#undef DO_MIX_MC +#undef DO_MIX_STEREO +#undef DO_MIX_MONO + ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) { float (*DryBuffer)[OUTPUTCHANNELS]; -- 2.11.4.GIT