aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALu.c787
1 files changed, 392 insertions, 395 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index cafc3174..a2080f58 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -777,297 +777,258 @@ static __inline ALshort lerp(ALshort val1, ALshort val2, ALint frac)
return val1 + (((val2-val1)*frac)>>FRACTIONBITS);
}
-ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
+static void MixSomeSources(ALCcontext *ALContext, float (*DryBuffer)[OUTPUTCHANNELS], ALuint SamplesToDo)
{
- static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
static float DummyBuffer[BUFFERSIZE];
ALfloat *WetBuffer[MAX_SENDS];
ALfloat (*Matrix)[OUTPUTCHANNELS] = ALContext->ChannelMatrix;
ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
- ALfloat WetSend[MAX_SENDS];
- ALfloat DryGainHF = 0.0f;
- ALfloat WetGainHF[MAX_SENDS];
- ALuint rampLength;
ALfloat dryGainStep[OUTPUTCHANNELS];
ALfloat wetGainStep[MAX_SENDS];
- ALuint BlockAlign,BufferSize;
- ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
- ALuint Channels,Frequency,ulExtraSamples;
- ALfloat Pitch;
- ALint Looping,State;
- ALint increment;
- ALuint Buffer;
- ALuint SamplesToDo;
- ALsource *ALSource;
- ALbuffer *ALBuffer;
- ALeffectslot *ALEffectSlot;
ALfloat values[OUTPUTCHANNELS];
+ ALuint i, j, k, out;
+ ALsource *ALSource;
ALfloat value;
ALshort *Data;
- ALuint i,j,k,out;
- ALfloat cw, a, g;
ALbufferlistitem *BufferListItem;
- ALuint loop;
ALint64 DataSize64,DataPos64;
FILTER *DryFilter, *WetFilter[MAX_SENDS];
- int fpuState;
-
- SuspendContext(ALContext);
+ ALfloat WetSend[MAX_SENDS];
+ ALfloat DryGainHF = 0.0f;
+ ALfloat WetGainHF[MAX_SENDS];
+ ALuint rampLength;
+ ALint Looping,State;
+ ALint increment;
-#if defined(HAVE_FESETROUND)
- fpuState = fegetround();
- fesetround(FE_TOWARDZERO);
-#elif defined(HAVE__CONTROLFP)
- fpuState = _controlfp(0, 0);
- _controlfp(_RC_CHOP, _MCW_RC);
-#else
- (void)fpuState;
-#endif
+ if(!(ALSource=ALContext->Source))
+ return;
- //Figure output format variables
- BlockAlign = aluChannelsFromFormat(format);
- BlockAlign *= aluBytesFromFormat(format);
+ rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000;
+ rampLength = max(rampLength, SamplesToDo);
- size /= BlockAlign;
- while(size > 0)
+another_source:
+ j = 0;
+ State = ALSource->state;
+ while(State == AL_PLAYING && j < SamplesToDo)
{
- //Setup variables
- SamplesToDo = min(size, BUFFERSIZE);
- if(ALContext)
- {
- ALEffectSlot = ALContext->AuxiliaryEffectSlot;
- ALSource = ALContext->Source;
- rampLength = ALContext->Frequency * MIN_RAMP_LENGTH / 1000;
- }
- else
+ ALuint DataSize = 0;
+ ALuint DataPosInt = 0;
+ ALuint DataPosFrac = 0;
+ ALuint Buffer;
+ ALbuffer *ALBuffer;
+ ALuint Channels, Frequency;
+ ALuint BufferSize;
+ ALfloat Pitch;
+
+ /* Get buffer info */
+ if(!(Buffer = ALSource->ulBufferID))
+ goto skipmix;
+ ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
+
+ Data = ALBuffer->data;
+ Channels = aluChannelsFromFormat(ALBuffer->format);
+ DataSize = ALBuffer->size;
+ DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
+ Frequency = ALBuffer->frequency;
+
+ DataPosInt = ALSource->position;
+ DataPosFrac = ALSource->position_fraction;
+
+ if(DataPosInt >= DataSize)
+ goto skipmix;
+
+ /* Get source info */
+ DryFilter = &ALSource->iirFilter;
+ for(i = 0;i < MAX_SENDS;i++)
{
- ALEffectSlot = NULL;
- ALSource = NULL;
- rampLength = 0;
+ WetFilter[i] = &ALSource->Send[i].iirFilter;
+ WetBuffer[i] = (ALSource->Send[i].Slot ?
+ ALSource->Send[i].Slot->WetBuffer :
+ DummyBuffer);
}
- rampLength = max(rampLength, SamplesToDo);
- //Clear mixing buffer
- memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
+ CalcSourceParams(ALContext, ALSource, (Channels==1)?AL_TRUE:AL_FALSE,
+ DrySend, WetSend, &Pitch, &DryGainHF, WetGainHF);
+ Pitch = (Pitch*Frequency) / ALContext->Frequency;
- //Actual mixing loop
- while(ALSource)
+ if(Channels == 1)
{
- j = 0;
- State = ALSource->state;
+ ALfloat cw, a, g;
+
+ /* Update filter coefficients. Calculations based on the I3DL2
+ * spec. */
+ cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / ALContext->Frequency);
+ /* We use four chained one-pole filters, so we need to take the
+ * fourth root of the squared gain, which is the same as the square
+ * root of the base gain. */
+ /* Be careful with gains < 0.0001, as that causes the coefficient
+ * head towards 1, which will flatten the signal */
+ g = aluSqrt(__max(DryGainHF, 0.0001f));
+ a = 0.0f;
+ if(g < 0.9999f) /* 1-epsilon */
+ a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
+ (1 - g);
+ DryFilter->coeff = a;
- while(State == AL_PLAYING && j < SamplesToDo)
+ for(i = 0;i < MAX_SENDS;i++)
{
- DataSize = 0;
- DataPosInt = 0;
- DataPosFrac = 0;
-
- //Get buffer info
- if((Buffer = ALSource->ulBufferID))
- {
- ALBuffer = (ALbuffer*)ALTHUNK_LOOKUPENTRY(Buffer);
-
- Data = ALBuffer->data;
- Channels = aluChannelsFromFormat(ALBuffer->format);
- DataSize = ALBuffer->size;
- DataSize /= Channels * aluBytesFromFormat(ALBuffer->format);
- Frequency = ALBuffer->frequency;
- DataPosInt = ALSource->position;
- DataPosFrac = ALSource->position_fraction;
-
- if(DataPosInt >= DataSize)
- goto skipmix;
-
- //Get source info
- DryFilter = &ALSource->iirFilter;
- for(i = 0;i < MAX_SENDS;i++)
- {
- WetFilter[i] = &ALSource->Send[i].iirFilter;
- WetBuffer[i] = (ALSource->Send[i].Slot ?
- ALSource->Send[i].Slot->WetBuffer :
- DummyBuffer);
- }
+ /* The wet path uses two chained one-pole filters, so take the
+ * base gain (square root of the squared gain) */
+ g = __max(WetGainHF[i], 0.01f);
+ a = 0.0f;
+ if(g < 0.9999f) /* 1-epsilon */
+ a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
+ (1 - g);
+ WetFilter[i]->coeff = a;
+ }
+ }
+ else
+ {
+ ALfloat cw, a, g;
+
+ /* Multi-channel sources use two chained one-pole filters */
+ cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / ALContext->Frequency);
+ g = __max(DryGainHF, 0.01f);
+ a = 0.0f;
+ if(g < 0.9999f) /* 1-epsilon */
+ a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
+ (1 - g);
+ DryFilter->coeff = a;
+ for(i = 0;i < MAX_SENDS;i++)
+ WetFilter[i]->coeff = 0.0f;
- CalcSourceParams(ALContext, ALSource,
- (Channels==1) ? AL_TRUE : AL_FALSE,
- DrySend, WetSend, &Pitch,
- &DryGainHF, WetGainHF);
- Pitch = (Pitch*Frequency) / ALContext->Frequency;
+ if(DuplicateStereo && Channels == 2)
+ {
+ Matrix[FRONT_LEFT][SIDE_LEFT] = 1.0f;
+ Matrix[FRONT_RIGHT][SIDE_RIGHT] = 1.0f;
+ Matrix[FRONT_LEFT][BACK_LEFT] = 1.0f;
+ Matrix[FRONT_RIGHT][BACK_RIGHT] = 1.0f;
+ }
+ else if(DuplicateStereo)
+ {
+ Matrix[FRONT_LEFT][SIDE_LEFT] = 0.0f;
+ Matrix[FRONT_RIGHT][SIDE_RIGHT] = 0.0f;
+ Matrix[FRONT_LEFT][BACK_LEFT] = 0.0f;
+ Matrix[FRONT_RIGHT][BACK_RIGHT] = 0.0f;
+ }
+ }
- if(Channels == 1)
- {
- // Update filter coefficients. Calculations based on
- // the I3DL2 spec.
- cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / ALContext->Frequency);
- // We use four chained one-pole filters, so we need to
- // take the fourth root of the squared gain, which is
- // the same as the square root of the base gain.
- // Be careful with gains < 0.0001, as that causes the
- // coefficient to head towards 1, which will flatten
- // the signal
- g = aluSqrt(__max(DryGainHF, 0.0001f));
- a = 0.0f;
- if(g < 0.9999f) // 1-epsilon
- a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
- DryFilter->coeff = a;
-
- for(i = 0;i < MAX_SENDS;i++)
- {
- // The wet path uses two chained one-pole filters,
- // so take the base gain (square root of the
- // squared gain)
- g = __max(WetGainHF[i], 0.01f);
- a = 0.0f;
- if(g < 0.9999f) // 1-epsilon
- a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
- WetFilter[i]->coeff = a;
- }
- }
- else
- {
- // Multi-channel sources use two chained one-pole
- // filters
- cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / ALContext->Frequency);
- g = __max(DryGainHF, 0.01f);
- a = 0.0f;
- if(g < 0.9999f) // 1-epsilon
- a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
- DryFilter->coeff = a;
- for(i = 0;i < MAX_SENDS;i++)
- WetFilter[i]->coeff = 0.0f;
-
- if(DuplicateStereo && Channels == 2)
- {
- Matrix[FRONT_LEFT][SIDE_LEFT] = 1.0f;
- Matrix[FRONT_RIGHT][SIDE_RIGHT] = 1.0f;
- Matrix[FRONT_LEFT][BACK_LEFT] = 1.0f;
- Matrix[FRONT_RIGHT][BACK_RIGHT] = 1.0f;
- }
- else if(DuplicateStereo)
- {
- Matrix[FRONT_LEFT][SIDE_LEFT] = 0.0f;
- Matrix[FRONT_RIGHT][SIDE_RIGHT] = 0.0f;
- Matrix[FRONT_LEFT][BACK_LEFT] = 0.0f;
- Matrix[FRONT_RIGHT][BACK_RIGHT] = 0.0f;
- }
- }
+ /* Compute the gain steps for each output channel */
+ if(ALSource->FirstStart && DataPosInt == 0 && DataPosFrac == 0)
+ {
+ for(i = 0;i < OUTPUTCHANNELS;i++)
+ dryGainStep[i] = 0.0f;
+ for(i = 0;i < MAX_SENDS;i++)
+ wetGainStep[i] = 0.0f;
+ }
+ else
+ {
+ for(i = 0;i < OUTPUTCHANNELS;i++)
+ {
+ dryGainStep[i] = (DrySend[i]-ALSource->DryGains[i]) / rampLength;
+ DrySend[i] = ALSource->DryGains[i];
+ }
+ for(i = 0;i < MAX_SENDS;i++)
+ {
+ wetGainStep[i] = (WetSend[i]-ALSource->WetGains[i]) / rampLength;
+ WetSend[i] = ALSource->WetGains[i];
+ }
+ }
+ ALSource->FirstStart = AL_FALSE;
+
+ /* Compute 18.14 fixed point step */
+ if(Pitch > (float)MAX_PITCH)
+ Pitch = (float)MAX_PITCH;
+ increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
+ if(increment <= 0)
+ increment = (1<<FRACTIONBITS);
+
+ /* Figure out how many samples we can mix. */
+ DataSize64 = DataSize;
+ DataSize64 <<= FRACTIONBITS;
+ DataPos64 = DataPosInt;
+ DataPos64 <<= FRACTIONBITS;
+ DataPos64 += DataPosFrac;
+ BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
+
+ BufferListItem = ALSource->queue;
+ for(i = 0;i < ALSource->BuffersPlayed && BufferListItem;i++)
+ BufferListItem = BufferListItem->next;
+ if(BufferListItem)
+ {
+ ALbuffer *NextBuf;
+ ALuint ulExtraSamples;
- //Compute the gain steps for each output channel
- if(ALSource->FirstStart && DataPosInt == 0 && DataPosFrac == 0)
- {
- for(i = 0;i < OUTPUTCHANNELS;i++)
- dryGainStep[i] = 0.0f;
- for(i = 0;i < MAX_SENDS;i++)
- wetGainStep[i] = 0.0f;
- }
- else
- {
- for(i = 0;i < OUTPUTCHANNELS;i++)
- {
- dryGainStep[i] = (DrySend[i]-ALSource->DryGains[i]) / rampLength;
- DrySend[i] = ALSource->DryGains[i];
- }
- for(i = 0;i < MAX_SENDS;i++)
- {
- wetGainStep[i] = (WetSend[i]-ALSource->WetGains[i]) / rampLength;
- WetSend[i] = ALSource->WetGains[i];
- }
- }
- ALSource->FirstStart = AL_FALSE;
-
- //Compute 18.14 fixed point step
- if(Pitch > (float)MAX_PITCH)
- Pitch = (float)MAX_PITCH;
- increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
- if(increment <= 0)
- increment = (1<<FRACTIONBITS);
-
- //Figure out how many samples we can mix.
- DataSize64 = DataSize;
- DataSize64 <<= FRACTIONBITS;
- DataPos64 = DataPosInt;
- DataPos64 <<= FRACTIONBITS;
- DataPos64 += DataPosFrac;
- BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
+ if(BufferListItem->next)
+ {
+ NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
+ if(NextBuf && NextBuf->data)
+ {
+ ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
+ memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
+ }
+ }
+ else if(ALSource->bLooping)
+ {
+ NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
+ if(NextBuf && NextBuf->data)
+ {
+ ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
+ memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
+ }
+ }
+ else
+ memset(&Data[DataSize*Channels], 0, (ALBuffer->padding*Channels*2));
+ }
+ BufferSize = min(BufferSize, (SamplesToDo-j));
- BufferListItem = ALSource->queue;
- for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
- {
- if(BufferListItem)
- BufferListItem = BufferListItem->next;
- }
- if (BufferListItem)
- {
- if (BufferListItem->next)
- {
- ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
- if(NextBuf && NextBuf->data)
- {
- ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
- memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
- }
- }
- else if (ALSource->bLooping)
- {
- ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
- if (NextBuf && NextBuf->data)
- {
- ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
- memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
- }
- }
- else
- memset(&Data[DataSize*Channels], 0, (ALBuffer->padding*Channels*2));
- }
- BufferSize = min(BufferSize, (SamplesToDo-j));
+ /* Actual sample mixing loop */
+ k = 0;
+ Data += DataPosInt*Channels;
- //Actual sample mixing loop
- k = 0;
- Data += DataPosInt*Channels;
+ if(Channels == 1) /* Mono */
+ {
+ ALfloat outsamp;
- if(Channels == 1) /* Mono */
- {
- ALfloat outsamp;
+ while(BufferSize--)
+ {
+ for(i = 0;i < OUTPUTCHANNELS;i++)
+ DrySend[i] += dryGainStep[i];
+ for(i = 0;i < MAX_SENDS;i++)
+ WetSend[i] += wetGainStep[i];
+
+ /* First order interpolator */
+ value = lerp(Data[k], Data[k+1], DataPosFrac);
+
+ /* Direct path final mix buffer and panning */
+ outsamp = lpFilter4P(DryFilter, 0, value);
+ DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
+ DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
+ DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
+ DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
+ DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
+ DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
+ DryBuffer[j][FRONT_CENTER] += outsamp*DrySend[FRONT_CENTER];
+ DryBuffer[j][BACK_CENTER] += outsamp*DrySend[BACK_CENTER];
+
+ /* Room path final mix buffer and panning */
+ for(i = 0;i < MAX_SENDS;i++)
+ {
+ outsamp = lpFilter2P(WetFilter[i], 0, value);
+ WetBuffer[i][j] += outsamp*WetSend[i];
+ }
- while(BufferSize--)
- {
- for(i = 0;i < OUTPUTCHANNELS;i++)
- DrySend[i] += dryGainStep[i];
- for(i = 0;i < MAX_SENDS;i++)
- WetSend[i] += wetGainStep[i];
-
- //First order interpolator
- value = lerp(Data[k], Data[k+1], DataPosFrac);
-
- //Direct path final mix buffer and panning
- outsamp = lpFilter4P(DryFilter, 0, value);
- DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
- DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
- DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
- DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
- DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
- DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
- DryBuffer[j][FRONT_CENTER] += outsamp*DrySend[FRONT_CENTER];
- DryBuffer[j][BACK_CENTER] += outsamp*DrySend[BACK_CENTER];
-
- //Room path final mix buffer and panning
- for(i = 0;i < MAX_SENDS;i++)
- {
- outsamp = lpFilter2P(WetFilter[i], 0, value);
- WetBuffer[i][j] += outsamp*WetSend[i];
- }
-
- DataPosFrac += increment;
- k += DataPosFrac>>FRACTIONBITS;
- DataPosFrac &= FRACTIONMASK;
- j++;
- }
- }
- else if(Channels == 2) /* Stereo */
- {
- const int chans[] = {
- FRONT_LEFT, FRONT_RIGHT
- };
+ DataPosFrac += increment;
+ k += DataPosFrac>>FRACTIONBITS;
+ DataPosFrac &= FRACTIONMASK;
+ j++;
+ }
+ }
+ else if(Channels == 2) /* Stereo */
+ {
+ const int chans[] = {
+ FRONT_LEFT, FRONT_RIGHT
+ };
#define DO_MIX() do { \
for(i = 0;i < MAX_SENDS;i++) \
@@ -1097,161 +1058,197 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
} \
} while(0)
- DO_MIX();
- }
- else if(Channels == 4) /* Quad */
- {
- const int chans[] = {
- FRONT_LEFT, FRONT_RIGHT,
- BACK_LEFT, BACK_RIGHT
- };
+ DO_MIX();
+ }
+ else if(Channels == 4) /* Quad */
+ {
+ const int chans[] = {
+ FRONT_LEFT, FRONT_RIGHT,
+ BACK_LEFT, BACK_RIGHT
+ };
- DO_MIX();
- }
- else if(Channels == 6) /* 5.1 */
- {
- const int chans[] = {
- FRONT_LEFT, FRONT_RIGHT,
- FRONT_CENTER, LFE,
- BACK_LEFT, BACK_RIGHT
- };
+ DO_MIX();
+ }
+ else if(Channels == 6) /* 5.1 */
+ {
+ const int chans[] = {
+ FRONT_LEFT, FRONT_RIGHT,
+ FRONT_CENTER, LFE,
+ BACK_LEFT, BACK_RIGHT
+ };
- DO_MIX();
- }
- else if(Channels == 7) /* 6.1 */
- {
- const int chans[] = {
- FRONT_LEFT, FRONT_RIGHT,
- FRONT_CENTER, LFE,
- BACK_CENTER,
- SIDE_LEFT, SIDE_RIGHT
- };
-
- DO_MIX();
- }
- else if(Channels == 8) /* 7.1 */
- {
- const int chans[] = {
- FRONT_LEFT, FRONT_RIGHT,
- FRONT_CENTER, LFE,
- BACK_LEFT, BACK_RIGHT,
- SIDE_LEFT, SIDE_RIGHT
- };
-
- DO_MIX();
+ DO_MIX();
+ }
+ else if(Channels == 7) /* 6.1 */
+ {
+ const int chans[] = {
+ FRONT_LEFT, FRONT_RIGHT,
+ FRONT_CENTER, LFE,
+ BACK_CENTER,
+ SIDE_LEFT, SIDE_RIGHT
+ };
+
+ DO_MIX();
+ }
+ else if(Channels == 8) /* 7.1 */
+ {
+ const int chans[] = {
+ FRONT_LEFT, FRONT_RIGHT,
+ FRONT_CENTER, LFE,
+ BACK_LEFT, BACK_RIGHT,
+ SIDE_LEFT, SIDE_RIGHT
+ };
+
+ DO_MIX();
#undef DO_MIX
- }
- else /* Unknown? */
+ }
+ else /* Unknown? */
+ {
+ for(i = 0;i < OUTPUTCHANNELS;i++)
+ DrySend[i] += dryGainStep[i]*BufferSize;
+ for(i = 0;i < MAX_SENDS;i++)
+ WetSend[i] += wetGainStep[i]*BufferSize;
+ while(BufferSize--)
+ {
+ DataPosFrac += increment;
+ k += DataPosFrac>>FRACTIONBITS;
+ DataPosFrac &= FRACTIONMASK;
+ j++;
+ }
+ }
+ DataPosInt += k;
+
+ /* Update source info */
+ ALSource->position = DataPosInt;
+ ALSource->position_fraction = DataPosFrac;
+ for(i = 0;i < OUTPUTCHANNELS;i++)
+ ALSource->DryGains[i] = DrySend[i];
+ for(i = 0;i < MAX_SENDS;i++)
+ ALSource->WetGains[i] = WetSend[i];
+
+ skipmix:
+ /* Handle looping sources */
+ if(!Buffer || DataPosInt >= DataSize)
+ {
+ /* Queueing */
+ if(ALSource->queue)
+ {
+ Looping = ALSource->bLooping;
+ if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
+ {
+ BufferListItem = ALSource->queue;
+ for(i = 0;i <= ALSource->BuffersPlayed && BufferListItem;i++)
{
- for(i = 0;i < OUTPUTCHANNELS;i++)
- DrySend[i] += dryGainStep[i]*BufferSize;
- for(i = 0;i < MAX_SENDS;i++)
- WetSend[i] += wetGainStep[i]*BufferSize;
- while(BufferSize--)
- {
- DataPosFrac += increment;
- k += DataPosFrac>>FRACTIONBITS;
- DataPosFrac &= FRACTIONMASK;
- j++;
- }
+ if(!Looping)
+ BufferListItem->bufferstate = PROCESSED;
+ BufferListItem = BufferListItem->next;
}
- DataPosInt += k;
-
- //Update source info
- ALSource->position = DataPosInt;
+ if(BufferListItem)
+ ALSource->ulBufferID = BufferListItem->buffer;
+ ALSource->position = DataPosInt-DataSize;
ALSource->position_fraction = DataPosFrac;
- for(i = 0;i < OUTPUTCHANNELS;i++)
- ALSource->DryGains[i] = DrySend[i];
- for(i = 0;i < MAX_SENDS;i++)
- ALSource->WetGains[i] = WetSend[i];
-
- skipmix: ;
+ ALSource->BuffersPlayed++;
}
-
- //Handle looping sources
- if(!Buffer || DataPosInt >= DataSize)
+ else
{
- //queueing
- if(ALSource->queue)
+ if(!Looping)
{
- Looping = ALSource->bLooping;
- if(ALSource->BuffersPlayed < (ALSource->BuffersInQueue-1))
+ /* alSourceStop */
+ ALSource->state = AL_STOPPED;
+ ALSource->inuse = AL_FALSE;
+ ALSource->BuffersPlayed = ALSource->BuffersInQueue;
+ BufferListItem = ALSource->queue;
+ while(BufferListItem != NULL)
{
- BufferListItem = ALSource->queue;
- for(loop = 0; loop <= ALSource->BuffersPlayed; loop++)
- {
- if(BufferListItem)
- {
- if(!Looping)
- BufferListItem->bufferstate = PROCESSED;
- BufferListItem = BufferListItem->next;
- }
- }
- if(BufferListItem)
- ALSource->ulBufferID = BufferListItem->buffer;
- ALSource->position = DataPosInt-DataSize;
- ALSource->position_fraction = DataPosFrac;
- ALSource->BuffersPlayed++;
+ BufferListItem->bufferstate = PROCESSED;
+ BufferListItem = BufferListItem->next;
}
- else
+ ALSource->position = 0;
+ ALSource->position_fraction = 0;
+ }
+ else
+ {
+ /* alSourceRewind */
+ /* alSourcePlay */
+ ALSource->state = AL_PLAYING;
+ ALSource->inuse = AL_TRUE;
+ ALSource->play = AL_TRUE;
+ ALSource->BuffersPlayed = 0;
+ BufferListItem = ALSource->queue;
+ while(BufferListItem != NULL)
{
- if(!Looping)
- {
- /* alSourceStop */
- ALSource->state = AL_STOPPED;
- ALSource->inuse = AL_FALSE;
- ALSource->BuffersPlayed = ALSource->BuffersInQueue;
- BufferListItem = ALSource->queue;
- while(BufferListItem != NULL)
- {
- BufferListItem->bufferstate = PROCESSED;
- BufferListItem = BufferListItem->next;
- }
- ALSource->position = DataSize;
- ALSource->position_fraction = 0;
- }
- else
- {
- /* alSourceRewind */
- /* alSourcePlay */
- ALSource->state = AL_PLAYING;
- ALSource->inuse = AL_TRUE;
- ALSource->play = AL_TRUE;
- ALSource->BuffersPlayed = 0;
- BufferListItem = ALSource->queue;
- while(BufferListItem != NULL)
- {
- BufferListItem->bufferstate = PENDING;
- BufferListItem = BufferListItem->next;
- }
- ALSource->ulBufferID = ALSource->queue->buffer;
-
- if(ALSource->BuffersInQueue == 1)
- ALSource->position = DataPosInt%DataSize;
- else
- ALSource->position = DataPosInt-DataSize;
- ALSource->position_fraction = DataPosFrac;
- }
+ BufferListItem->bufferstate = PENDING;
+ BufferListItem = BufferListItem->next;
}
+ ALSource->ulBufferID = ALSource->queue->buffer;
+
+ if(ALSource->BuffersInQueue == 1)
+ ALSource->position = DataPosInt%DataSize;
+ else
+ ALSource->position = DataPosInt-DataSize;
+ ALSource->position_fraction = DataPosFrac;
}
}
-
- //Get source state
- State = ALSource->state;
}
-
- ALSource = ALSource->next;
}
- // effect slot processing
- while(ALEffectSlot)
+ /* Get source state */
+ State = ALSource->state;
+ }
+
+ if((ALSource=ALSource->next) != NULL)
+ goto another_source;
+}
+
+ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum format)
+{
+ static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
+ ALuint SamplesToDo;
+ ALeffectslot *ALEffectSlot;
+ ALuint BlockAlign;
+ int fpuState;
+ ALuint i;
+
+ SuspendContext(ALContext);
+
+#if defined(HAVE_FESETROUND)
+ fpuState = fegetround();
+ fesetround(FE_TOWARDZERO);
+#elif defined(HAVE__CONTROLFP)
+ fpuState = _controlfp(0, 0);
+ _controlfp(_RC_CHOP, _MCW_RC);
+#else
+ (void)fpuState;
+#endif
+
+ /* Figure output format variables */
+ BlockAlign = aluChannelsFromFormat(format);
+ BlockAlign *= aluBytesFromFormat(format);
+
+ size /= BlockAlign;
+ while(size > 0)
+ {
+ /* Setup variables */
+ SamplesToDo = min(size, BUFFERSIZE);
+
+ /* Clear mixing buffer */
+ memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
+
+ if(ALContext)
{
- if(ALEffectSlot->EffectState)
- ALEffect_Process(ALEffectSlot->EffectState, ALEffectSlot, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
+ MixSomeSources(ALContext, DryBuffer, SamplesToDo);
+
+ /* effect slot processing */
+ ALEffectSlot = ALContext->AuxiliaryEffectSlot;
+ while(ALEffectSlot)
+ {
+ if(ALEffectSlot->EffectState)
+ ALEffect_Process(ALEffectSlot->EffectState, ALEffectSlot, SamplesToDo, ALEffectSlot->WetBuffer, DryBuffer);
- for(i = 0;i < SamplesToDo;i++)
- ALEffectSlot->WetBuffer[i] = 0.0f;
- ALEffectSlot = ALEffectSlot->next;
+ for(i = 0;i < SamplesToDo;i++)
+ ALEffectSlot->WetBuffer[i] = 0.0f;
+ ALEffectSlot = ALEffectSlot->next;
+ }
}
//Post processing loop