diff options
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/mixer.c | 350 |
1 files changed, 168 insertions, 182 deletions
diff --git a/Alc/mixer.c b/Alc/mixer.c index 3ef41aa9..c3ed5d64 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -47,11 +47,11 @@ static __inline ALfloat Sample_ALfloat(ALfloat val) { return val; } #define DECL_TEMPLATE(T) \ -static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \ +static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\ { \ ALuint i; \ for(i = 0;i < samples;i++) \ - dst[i] = Sample_##T(src[i]); \ + dst[i] = Sample_##T(src[i*srcstep]); \ } DECL_TEMPLATE(ALbyte) @@ -60,18 +60,18 @@ DECL_TEMPLATE(ALfloat) #undef DECL_TEMPLATE -static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples) +static void LoadStack(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples) { switch(srctype) { case FmtByte: - Load_ALbyte(dst, src, samples); + Load_ALbyte(dst, src, srcstep, samples); break; case FmtShort: - Load_ALshort(dst, src, samples); + Load_ALshort(dst, src, srcstep, samples); break; case FmtFloat: - Load_ALfloat(dst, src, samples); + Load_ALfloat(dst, src, srcstep, samples); break; } } @@ -105,9 +105,9 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) ALenum State; ALuint OutPos; ALuint NumChannels; - ALuint FrameSize; + ALuint SampleSize; ALint64 DataSize64; - ALuint i, j; + ALuint chan, j; /* Get source info */ State = Source->state; @@ -118,21 +118,18 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) increment = Source->Params.Step; Resampler = Source->Resampler; NumChannels = Source->NumChannels; - FrameSize = NumChannels * Source->SampleSize; + SampleSize = Source->SampleSize; /* Get current buffer queue item */ BufferListItem = Source->queue; - for(i = 0;i < BuffersPlayed;i++) + for(j = 0;j < BuffersPlayed;j++) BufferListItem = BufferListItem->next; OutPos = 0; do { const ALuint BufferPrePadding = ResamplerPrePadding[Resampler]; const ALuint BufferPadding = ResamplerPadding[Resampler]; - ALfloat StackData[BUFFERSIZE]; - ALfloat *SrcData = StackData; - ALuint SrcDataSize = 0; - ALuint BufferSize; + ALuint SrcBufferSize, DstBufferSize; /* Figure out how many buffer bytes will be needed */ DataSize64 = SamplesToDo-OutPos+1; @@ -140,214 +137,202 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) DataSize64 += DataPosFrac+FRACTIONMASK; DataSize64 >>= FRACTIONBITS; DataSize64 += BufferPadding+BufferPrePadding; - DataSize64 *= NumChannels; - BufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE); - BufferSize /= NumChannels; + SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE); - if(Source->SourceType == AL_STATIC) + /* Figure out how many samples we can actually mix from this. */ + DataSize64 = SrcBufferSize; + DataSize64 -= BufferPadding+BufferPrePadding; + DataSize64 <<= FRACTIONBITS; + DataSize64 -= increment; + DataSize64 -= DataPosFrac; + + DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment); + DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos)); + + /* Some mixers like having a multiple of 4, so try to give that unless + * this is the last update. */ + if(OutPos+DstBufferSize < SamplesToDo) + DstBufferSize &= ~3; + + for(chan = 0;chan < NumChannels;chan++) { - const ALbuffer *ALBuffer = Source->queue->buffer; - const ALubyte *Data = ALBuffer->data; - ALuint DataSize; - ALuint pos; + ALIGN(16) ALfloat SrcData[BUFFERSIZE]; + ALIGN(16) ALfloat ResampledData[BUFFERSIZE]; + ALuint SrcDataSize = 0; - /* If current pos is beyond the loop range, do not loop */ - if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd) + if(Source->SourceType == AL_STATIC) { - Looping = AL_FALSE; + const ALbuffer *ALBuffer = Source->queue->buffer; + const ALubyte *Data = ALBuffer->data; + ALuint DataSize; + ALuint pos; - if(DataPosInt >= BufferPrePadding) - pos = DataPosInt - BufferPrePadding; - else + /* If current pos is beyond the loop range, do not loop */ + if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd) { - DataSize = BufferPrePadding - DataPosInt; - DataSize = minu(BufferSize, DataSize); + Looping = AL_FALSE; - SilenceStack(&SrcData[SrcDataSize*NumChannels], - DataSize*NumChannels); - SrcDataSize += DataSize; - BufferSize -= DataSize; + if(DataPosInt >= BufferPrePadding) + pos = DataPosInt - BufferPrePadding; + else + { + DataSize = BufferPrePadding - DataPosInt; + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - pos = 0; - } + SilenceStack(&SrcData[SrcDataSize], DataSize); + SrcDataSize += DataSize; - /* Copy what's left to play in the source buffer, and clear the - * rest of the temp buffer */ - DataSize = ALBuffer->SampleLen - pos; - DataSize = minu(BufferSize, DataSize); + pos = 0; + } - LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize], - ALBuffer->FmtType, DataSize*NumChannels); - SrcDataSize += DataSize; - BufferSize -= DataSize; + /* Copy what's left to play in the source buffer, and clear the + * rest of the temp buffer */ + DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos); - SilenceStack(&SrcData[SrcDataSize*NumChannels], - BufferSize*NumChannels); - SrcDataSize += BufferSize; - BufferSize -= BufferSize; - } - else - { - ALuint LoopStart = ALBuffer->LoopStart; - ALuint LoopEnd = ALBuffer->LoopEnd; + LoadStack(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); + SrcDataSize += DataSize; - if(DataPosInt >= LoopStart) - { - pos = DataPosInt-LoopStart; - while(pos < BufferPrePadding) - pos += LoopEnd-LoopStart; - pos -= BufferPrePadding; - pos += LoopStart; + SilenceStack(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); + SrcDataSize += SrcBufferSize - SrcDataSize; } - else if(DataPosInt >= BufferPrePadding) - pos = DataPosInt - BufferPrePadding; else { - DataSize = BufferPrePadding - DataPosInt; - DataSize = minu(BufferSize, DataSize); - - SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels); - SrcDataSize += DataSize; - BufferSize -= DataSize; + ALuint LoopStart = ALBuffer->LoopStart; + ALuint LoopEnd = ALBuffer->LoopEnd; - pos = 0; - } + if(DataPosInt >= LoopStart) + { + pos = DataPosInt-LoopStart; + while(pos < BufferPrePadding) + pos += LoopEnd-LoopStart; + pos -= BufferPrePadding; + pos += LoopStart; + } + else if(DataPosInt >= BufferPrePadding) + pos = DataPosInt - BufferPrePadding; + else + { + DataSize = BufferPrePadding - DataPosInt; + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - /* Copy what's left of this loop iteration, then copy repeats - * of the loop section */ - DataSize = LoopEnd - pos; - DataSize = minu(BufferSize, DataSize); + SilenceStack(&SrcData[SrcDataSize], DataSize); + SrcDataSize += DataSize; - LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize], - ALBuffer->FmtType, DataSize*NumChannels); - SrcDataSize += DataSize; - BufferSize -= DataSize; + pos = 0; + } - DataSize = LoopEnd-LoopStart; - while(BufferSize > 0) - { - DataSize = minu(BufferSize, DataSize); + /* Copy what's left of this loop iteration, then copy repeats + * of the loop section */ + DataSize = LoopEnd - pos; + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize], - ALBuffer->FmtType, DataSize*NumChannels); + LoadStack(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); SrcDataSize += DataSize; - BufferSize -= DataSize; + + DataSize = LoopEnd-LoopStart; + while(SrcBufferSize > SrcDataSize) + { + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); + + LoadStack(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); + SrcDataSize += DataSize; + } } } - } - else - { - /* Crawl the buffer queue to fill in the temp buffer */ - ALbufferlistitem *tmpiter = BufferListItem; - ALuint pos; - - if(DataPosInt >= BufferPrePadding) - pos = DataPosInt - BufferPrePadding; else { - pos = BufferPrePadding - DataPosInt; - while(pos > 0) + /* Crawl the buffer queue to fill in the temp buffer */ + ALbufferlistitem *tmpiter = BufferListItem; + ALuint pos; + + if(DataPosInt >= BufferPrePadding) + pos = DataPosInt - BufferPrePadding; + else { - if(!tmpiter->prev && !Looping) + pos = BufferPrePadding - DataPosInt; + while(pos > 0) { - ALuint DataSize = minu(BufferSize, pos); + if(!tmpiter->prev && !Looping) + { + ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos); - SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels); - SrcDataSize += DataSize; - BufferSize -= DataSize; + SilenceStack(&SrcData[SrcDataSize], DataSize); + SrcDataSize += DataSize; - pos = 0; - break; - } + pos = 0; + break; + } - if(tmpiter->prev) - tmpiter = tmpiter->prev; - else - { - while(tmpiter->next) - tmpiter = tmpiter->next; - } + if(tmpiter->prev) + tmpiter = tmpiter->prev; + else + { + while(tmpiter->next) + tmpiter = tmpiter->next; + } - if(tmpiter->buffer) - { - if((ALuint)tmpiter->buffer->SampleLen > pos) + if(tmpiter->buffer) { - pos = tmpiter->buffer->SampleLen - pos; - break; + if((ALuint)tmpiter->buffer->SampleLen > pos) + { + pos = tmpiter->buffer->SampleLen - pos; + break; + } + pos -= tmpiter->buffer->SampleLen; } - pos -= tmpiter->buffer->SampleLen; } } - } - while(tmpiter && BufferSize > 0) - { - const ALbuffer *ALBuffer; - if((ALBuffer=tmpiter->buffer) != NULL) + while(tmpiter && SrcBufferSize > SrcDataSize) { - const ALubyte *Data = ALBuffer->data; - ALuint DataSize = ALBuffer->SampleLen; - - /* Skip the data already played */ - if(DataSize <= pos) - pos -= DataSize; - else + const ALbuffer *ALBuffer; + if((ALBuffer=tmpiter->buffer) != NULL) { - Data += pos*FrameSize; - DataSize -= pos; - pos -= pos; + const ALubyte *Data = ALBuffer->data; + ALuint DataSize = ALBuffer->SampleLen; - DataSize = minu(BufferSize, DataSize); - LoadStack(&SrcData[SrcDataSize*NumChannels], Data, - ALBuffer->FmtType, DataSize*NumChannels); - SrcDataSize += DataSize; - BufferSize -= DataSize; + /* Skip the data already played */ + if(DataSize <= pos) + pos -= DataSize; + else + { + Data += (pos*NumChannels + chan)*SampleSize; + DataSize -= pos; + pos -= pos; + + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); + LoadStack(&SrcData[SrcDataSize], Data, NumChannels, + ALBuffer->FmtType, DataSize); + SrcDataSize += DataSize; + } + } + tmpiter = tmpiter->next; + if(!tmpiter && Looping) + tmpiter = Source->queue; + else if(!tmpiter) + { + SilenceStack(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); + SrcDataSize += SrcBufferSize - SrcDataSize; } - } - tmpiter = tmpiter->next; - if(!tmpiter && Looping) - tmpiter = Source->queue; - else if(!tmpiter) - { - SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels); - SrcDataSize += BufferSize; - BufferSize -= BufferSize; } } - } - - /* Figure out how many samples we can mix. */ - DataSize64 = SrcDataSize; - DataSize64 -= BufferPadding+BufferPrePadding; - DataSize64 <<= FRACTIONBITS; - DataSize64 -= increment; - DataSize64 -= DataPosFrac; - - BufferSize = (ALuint)((DataSize64+(increment-1)) / increment); - BufferSize = minu(BufferSize, (SamplesToDo-OutPos)); - /* Some mixers like having a multiple of 4, so try to give that unless - * this is the last update. */ - if(OutPos+BufferSize < SamplesToDo) - BufferSize &= ~3; + /* Now resample, then filter and mix to the appropriate outputs. */ + Source->Params.Resample(&SrcData[BufferPrePadding], DataPosFrac, + increment, 1, ResampledData, DstBufferSize); - SrcData += BufferPrePadding*NumChannels; - for(i = 0;i < NumChannels;i++) - { - DirectParams *directparms = &Source->Params.Direct; - ALIGN(16) ALfloat FilteredData[BUFFERSIZE]; - ALIGN(16) ALfloat ResampledData[BUFFERSIZE]; - - Source->Params.Resample(SrcData+i, DataPosFrac, increment, - NumChannels, ResampledData, BufferSize); - - Filter2P(&directparms->iirFilter, i, FilteredData, ResampledData, - BufferSize); + { + DirectParams *directparms = &Source->Params.Direct; - Source->Params.DryMix(Source, Device, directparms, - FilteredData, i, OutPos, SamplesToDo, - BufferSize); + Filter2P(&directparms->iirFilter, chan, SrcData, ResampledData, + DstBufferSize); + Source->Params.DryMix(Source, Device, directparms, SrcData, + chan, OutPos, SamplesToDo, DstBufferSize); + } for(j = 0;j < Device->NumAuxSends;j++) { @@ -355,19 +340,20 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) if(!sendparms->Slot) continue; - Filter2P(&sendparms->iirFilter, i, FilteredData, ResampledData, - BufferSize); - Source->Params.WetMix(sendparms, FilteredData, OutPos, - SamplesToDo, BufferSize); + Filter2P(&sendparms->iirFilter, chan, SrcData, ResampledData, + DstBufferSize); + Source->Params.WetMix(sendparms, SrcData, OutPos, + SamplesToDo, DstBufferSize); } } - for(i = 0;i < BufferSize;i++) + /* Update positions */ + for(j = 0;j < DstBufferSize;j++) { DataPosFrac += increment; DataPosInt += DataPosFrac>>FRACTIONBITS; DataPosFrac &= FRACTIONMASK; - OutPos++; } + OutPos += DstBufferSize; /* Handle looping sources */ while(1) |