aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-12-16 11:34:52 -0800
committerChris Robinson <[email protected]>2017-12-16 11:34:52 -0800
commitebd42ab619feb36aab2b8828a391f0088d4f0620 (patch)
treee0a130b80c96f3df4bb5156046c8d3af2829a56c
parentb10780f119443eecb2a639bfc21530b579179f1c (diff)
Mix multiple buffers in each buffer list item
Basically now this just relies on being able to specify composited buffers.
-rw-r--r--Alc/mixer.c176
1 files changed, 112 insertions, 64 deletions
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 3e019ddb..1214169b 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -343,6 +343,9 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
if(DstBufferSize < SamplesToDo-OutPos)
DstBufferSize &= ~3;
+ /* It's impossible to have a buffer list item with no entries. */
+ assert(BufferListItem->num_buffers > 0);
+
for(chan = 0;chan < NumChannels;chan++)
{
const ALfloat *ResampledData;
@@ -354,54 +357,94 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
memset(SrcData+MAX_PRE_SAMPLES, 0, (SrcBufferSize-MAX_PRE_SAMPLES)*sizeof(ALfloat));
FilledAmt = MAX_PRE_SAMPLES;
- /* TODO: Handle multi-buffer items by adding them together in
- * SrcData. Need to work out how to deal with looping (loop
- * points).
- */
if(isstatic)
{
- const ALbuffer *ALBuffer = BufferListItem->buffers[0];
- const ALubyte *Data = ALBuffer->data;
- ALsizei DataSize;
-
- /* Offset buffer data to current channel */
- Data += chan*SampleSize;
+ /* TODO: For static sources, loop points are taken from the
+ * first buffer (should be adjusted by any buffer offset, to
+ * possibly be added later).
+ */
+ const ALbuffer *Buffer0 = BufferListItem->buffers[0];
+ const ALsizei LoopStart = Buffer0->LoopStart;
+ const ALsizei LoopEnd = Buffer0->LoopEnd;
+ const ALsizei LoopSize = LoopEnd - LoopStart;
/* If current pos is beyond the loop range, do not loop */
- if(!BufferLoopItem || DataPosInt >= ALBuffer->LoopEnd)
+ if(!BufferLoopItem || DataPosInt >= LoopEnd)
{
+ ALsizei SizeToDo = SrcBufferSize - FilledAmt;
+ ALsizei CompLen = 0;
+ ALsizei i;
+
BufferLoopItem = NULL;
- /* Load what's left to play from the source buffer, and
- * clear the rest of the temp buffer */
- DataSize = minu(SrcBufferSize - FilledAmt,
- ALBuffer->SampleLen - DataPosInt);
+ for(i = 0;i < BufferListItem->num_buffers;i++)
+ {
+ const ALbuffer *buffer = BufferListItem->buffers[i];
+ const ALubyte *Data = buffer->data;
+ ALsizei DataSize;
+
+ if(DataPosInt >= buffer->SampleLen)
+ continue;
+
+ /* Load what's left to play from the buffer */
+ DataSize = mini(SizeToDo, buffer->SampleLen - DataPosInt);
+ CompLen = maxi(CompLen, DataSize);
- LoadSamples(&SrcData[FilledAmt], &Data[DataPosInt * NumChannels*SampleSize],
- NumChannels, ALBuffer->FmtType, DataSize);
- FilledAmt += DataSize;
+ LoadSamples(&SrcData[FilledAmt],
+ &Data[(DataPosInt*NumChannels + chan)*SampleSize],
+ NumChannels, buffer->FmtType, DataSize
+ );
+ }
+ FilledAmt += CompLen;
}
else
{
- ALsizei LoopStart = ALBuffer->LoopStart;
- ALsizei LoopEnd = ALBuffer->LoopEnd;
+ ALsizei SizeToDo = mini(SrcBufferSize - FilledAmt, LoopEnd - DataPosInt);
+ ALsizei CompLen = 0;
+ ALsizei i;
- /* Load what's left of this loop iteration, then load
- * repeats of the loop section */
- DataSize = minu(SrcBufferSize - FilledAmt, LoopEnd - DataPosInt);
+ for(i = 0;i < BufferListItem->num_buffers;i++)
+ {
+ const ALbuffer *buffer = BufferListItem->buffers[i];
+ const ALubyte *Data = buffer->data;
+ ALsizei DataSize;
+
+ if(DataPosInt >= buffer->SampleLen)
+ continue;
- LoadSamples(&SrcData[FilledAmt], &Data[DataPosInt * NumChannels*SampleSize],
- NumChannels, ALBuffer->FmtType, DataSize);
- FilledAmt += DataSize;
+ /* Load what's left of this loop iteration */
+ DataSize = mini(SizeToDo, buffer->SampleLen - DataPosInt);
+ CompLen = maxi(CompLen, DataSize);
+
+ LoadSamples(&SrcData[FilledAmt],
+ &Data[(DataPosInt*NumChannels + chan)*SampleSize],
+ NumChannels, buffer->FmtType, DataSize
+ );
+ }
+ FilledAmt += CompLen;
- DataSize = LoopEnd-LoopStart;
while(SrcBufferSize > FilledAmt)
{
- DataSize = mini(SrcBufferSize - FilledAmt, DataSize);
+ const ALsizei SizeToDo = mini(SrcBufferSize - FilledAmt, LoopSize);
+
+ for(i = 0;i < BufferListItem->num_buffers;i++)
+ {
+ const ALbuffer *buffer = BufferListItem->buffers[i];
+ const ALubyte *Data = buffer->data;
+ ALsizei DataSize;
+
+ if(DataPosInt >= buffer->SampleLen)
+ continue;
- LoadSamples(&SrcData[FilledAmt], &Data[LoopStart * NumChannels*SampleSize],
- NumChannels, ALBuffer->FmtType, DataSize);
- FilledAmt += DataSize;
+ DataSize = mini(SizeToDo, buffer->SampleLen - DataPosInt);
+ CompLen = maxi(CompLen, DataSize);
+
+ LoadSamples(&SrcData[FilledAmt],
+ &Data[(DataPosInt*NumChannels + chan)*SampleSize],
+ NumChannels, buffer->FmtType, DataSize
+ );
+ }
+ FilledAmt += CompLen;
}
}
}
@@ -413,32 +456,37 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
while(tmpiter && SrcBufferSize > FilledAmt)
{
- const ALbuffer *ALBuffer;
- if(tmpiter->num_buffers >= 1 && (ALBuffer=tmpiter->buffers[0]) != NULL)
+ ALsizei SizeToDo = SrcBufferSize - FilledAmt;
+ ALsizei CompLen = 0;
+ ALsizei i;
+
+ for(i = 0;i < tmpiter->num_buffers;i++)
{
- const ALubyte *Data = ALBuffer->data;
- ALsizei DataSize = ALBuffer->SampleLen;
+ const ALbuffer *ALBuffer = tmpiter->buffers[i];
+ ALsizei DataSize = ALBuffer ? ALBuffer->SampleLen : 0;
+ CompLen = maxi(CompLen, DataSize);
- /* Skip the data already played */
- if(DataSize <= pos)
- pos -= DataSize;
- else
+ if(DataSize > pos)
{
+ const ALubyte *Data = ALBuffer->data;
Data += (pos*NumChannels + chan)*SampleSize;
- DataSize -= pos;
- pos -= pos;
- DataSize = minu(SrcBufferSize - FilledAmt, DataSize);
+ DataSize = minu(SizeToDo, DataSize - pos);
LoadSamples(&SrcData[FilledAmt], Data, NumChannels,
ALBuffer->FmtType, DataSize);
- FilledAmt += DataSize;
}
}
+ if(pos > CompLen)
+ pos -= CompLen;
+ else
+ {
+ FilledAmt += CompLen - pos;
+ pos = 0;
+ }
if(SrcBufferSize > FilledAmt)
{
tmpiter = ATOMIC_LOAD(&tmpiter->next, almemory_order_acquire);
- if(!tmpiter && BufferLoopItem)
- tmpiter = BufferLoopItem;
+ if(!tmpiter) tmpiter = BufferLoopItem;
}
}
}
@@ -620,31 +668,31 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
Counter = maxi(DstBufferSize, Counter) - DstBufferSize;
firstpass = false;
- /* Handle looping sources */
- while(1)
+ /* Handle looping source position */
+ if(isstatic && BufferLoopItem)
{
- const ALbuffer *ALBuffer;
- ALsizei DataSize = 0;
- ALsizei LoopStart = 0;
- ALsizei LoopEnd = 0;
-
- if(BufferListItem->num_buffers >= 1 && (ALBuffer=BufferListItem->buffers[0]) != NULL)
+ const ALbuffer *Buffer = BufferListItem->buffers[0];
+ ALsizei LoopStart = Buffer->LoopStart;
+ ALsizei LoopEnd = Buffer->LoopEnd;
+ if(DataPosInt >= LoopEnd)
{
- DataSize = ALBuffer->SampleLen;
- LoopStart = ALBuffer->LoopStart;
- LoopEnd = ALBuffer->LoopEnd;
- if(LoopEnd > DataPosInt)
- break;
+ assert(LoopEnd > LoopStart);
+ DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
}
+ }
+ else while(1)
+ {
+ /* Handle non-looping or buffer queue source position */
+ ALsizei CompLen = 0;
+ ALsizei i;
- if(isstatic && BufferLoopItem)
+ for(i = 0;i < BufferListItem->num_buffers;i++)
{
- assert(LoopEnd > LoopStart);
- DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
- break;
+ const ALbuffer *buffer = BufferListItem->buffers[i];
+ if(buffer) CompLen = maxi(CompLen, buffer->SampleLen);
}
- if(DataSize > DataPosInt)
+ if(CompLen > DataPosInt)
break;
BufferListItem = ATOMIC_LOAD(&BufferListItem->next, almemory_order_acquire);
@@ -660,7 +708,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
}
}
- DataPosInt -= DataSize;
+ DataPosInt -= CompLen;
}
} while(isplaying && OutPos < SamplesToDo);