diff options
author | Chris Robinson <[email protected]> | 2012-09-26 17:16:25 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2012-09-26 17:16:25 -0700 |
commit | ed82194260ad8e5b0f65b503b775d488edc58a94 (patch) | |
tree | e7b8bfc64b4533310c3b1e66d1eb9f3de6d5e8c7 /Alc | |
parent | 012e61b1054403655d70bc52b57f2ce1b5776f1d (diff) |
Deinterlace audio when loading it into the stack.
It may be better to deinterlace it on load into the buffer, though I don't
imagine this will affect much. It could be nice for consistency's sake, though
it would also complicate things if we ever want to support direct access to
buffer data.
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) |