diff options
-rw-r--r-- | Alc/ALu.c | 2 | ||||
-rw-r--r-- | Alc/mixer.c | 10 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 3 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 210 |
4 files changed, 153 insertions, 72 deletions
@@ -1450,7 +1450,7 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, bool force) while(BufferListItem != NULL) { const ALbuffer *buffer; - if((buffer=BufferListItem->buffer) != NULL) + if(BufferListItem->num_buffers >= 1 && (buffer=BufferListItem->buffers[0]) != NULL) { if(props->SpatializeMode == SpatializeOn || (props->SpatializeMode == SpatializeAuto && buffer->FmtChannels == FmtMono)) diff --git a/Alc/mixer.c b/Alc/mixer.c index c77488bc..37bdf6ac 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -362,9 +362,13 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat)); SrcDataSize = 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->buffer; + const ALbuffer *ALBuffer = BufferListItem->buffers[0]; const ALubyte *Data = ALBuffer->data; ALsizei DataSize; @@ -421,7 +425,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei while(tmpiter && SrcBufferSize > SrcDataSize) { const ALbuffer *ALBuffer; - if((ALBuffer=tmpiter->buffer) != NULL) + if(tmpiter->num_buffers >= 1 && (ALBuffer=tmpiter->buffers[0]) != NULL) { const ALubyte *Data = ALBuffer->data; ALsizei DataSize = ALBuffer->SampleLen; @@ -637,7 +641,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei ALsizei LoopStart = 0; ALsizei LoopEnd = 0; - if((ALBuffer=BufferListItem->buffer) != NULL) + if(BufferListItem->num_buffers >= 1 && (ALBuffer=BufferListItem->buffers[0]) != NULL) { DataSize = ALBuffer->SampleLen; LoopStart = ALBuffer->LoopStart; diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 03034ce8..970ea07c 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -19,8 +19,9 @@ struct ALsource; typedef struct ALbufferlistitem { - struct ALbuffer *buffer; ATOMIC(struct ALbufferlistitem*) next; + ALsizei num_buffers; + struct ALbuffer *buffers[]; } ALbufferlistitem; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index cc19a0c3..f4d82c68 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -774,9 +774,11 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p if(buffer != NULL) { /* Add the selected buffer to a one-item queue */ - ALbufferlistitem *newlist = al_calloc(DEF_ALIGN, sizeof(ALbufferlistitem)); - newlist->buffer = buffer; + ALbufferlistitem *newlist = al_calloc(DEF_ALIGN, + FAM_SIZE(ALbufferlistitem, buffers, 1)); ATOMIC_INIT(&newlist->next, NULL); + newlist->num_buffers = 1; + newlist->buffers[0] = buffer; IncrementRef(&buffer->ref); /* Source is now Static */ @@ -795,11 +797,15 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p /* Delete all elements in the previous queue */ while(oldlist != NULL) { + ALsizei i; ALbufferlistitem *temp = oldlist; oldlist = ATOMIC_LOAD(&temp->next, almemory_order_relaxed); - if(temp->buffer) - DecrementRef(&temp->buffer->ref); + for(i = 0;i < temp->num_buffers;i++) + { + if(temp->buffers[i]) + DecrementRef(&temp->buffers[i]->ref); + } al_free(temp); } return AL_TRUE; @@ -1219,12 +1225,18 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p ALint length = 0; ALsizei freq = 1; do { - ALbuffer *buffer = BufferList->buffer; - if(buffer && buffer->SampleLen > 0) + ALsizei max_len = 0; + ALsizei i; + for(i = 0;i < BufferList->num_buffers;i++) { - freq = buffer->Frequency; - length += buffer->SampleLen; + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer && buffer->SampleLen > 0) + { + freq = buffer->Frequency; + max_len = maxi(max_len, buffer->SampleLen); + } } + length += max_len; BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } while(BufferList != NULL); *values = (ALdouble)length / (ALdouble)freq; @@ -1344,7 +1356,8 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p case AL_BUFFER: ReadLock(&Source->queue_lock); BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : NULL; - *values = (BufferList && BufferList->buffer) ? BufferList->buffer->id : 0; + *values = (BufferList && BufferList->num_buffers >= 1 && BufferList->buffers[0]) ? + BufferList->buffers[0]->id : 0; ReadUnlock(&Source->queue_lock); return AL_TRUE; @@ -1360,31 +1373,38 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p { ALint length = 0; do { - ALbuffer *buffer = BufferList->buffer; - if(buffer && buffer->SampleLen > 0) + ALsizei max_len = 0; + ALsizei i; + for(i = 0;i < BufferList->num_buffers;i++) { - ALuint byte_align, sample_align; - if(buffer->OriginalType == UserFmtIMA4) - { - ALsizei align = (buffer->OriginalAlign-1)/2 + 4; - byte_align = align * ChannelsFromFmt(buffer->FmtChannels); - sample_align = buffer->OriginalAlign; - } - else if(buffer->OriginalType == UserFmtMSADPCM) - { - ALsizei align = (buffer->OriginalAlign-2)/2 + 7; - byte_align = align * ChannelsFromFmt(buffer->FmtChannels); - sample_align = buffer->OriginalAlign; - } - else + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer && buffer->SampleLen > 0) { - ALsizei align = buffer->OriginalAlign; - byte_align = align * ChannelsFromFmt(buffer->FmtChannels); - sample_align = buffer->OriginalAlign; + ALuint byte_align, sample_align; + if(buffer->OriginalType == UserFmtIMA4) + { + ALsizei align = (buffer->OriginalAlign-1)/2 + 4; + byte_align = align * ChannelsFromFmt(buffer->FmtChannels); + sample_align = buffer->OriginalAlign; + } + else if(buffer->OriginalType == UserFmtMSADPCM) + { + ALsizei align = (buffer->OriginalAlign-2)/2 + 7; + byte_align = align * ChannelsFromFmt(buffer->FmtChannels); + sample_align = buffer->OriginalAlign; + } + else + { + ALsizei align = buffer->OriginalAlign; + byte_align = align * ChannelsFromFmt(buffer->FmtChannels); + sample_align = buffer->OriginalAlign; + } + + max_len = maxi(max_len, buffer->SampleLen / sample_align * byte_align); } - - length += buffer->SampleLen / sample_align * byte_align; } + length += max_len; + BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } while(BufferList != NULL); *values = length; @@ -1400,8 +1420,14 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p { ALint length = 0; do { - ALbuffer *buffer = BufferList->buffer; - if(buffer) length += buffer->SampleLen; + ALsizei max_len = 0; + ALsizei i; + for(i = 0;i < BufferList->num_buffers;i++) + { + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer) max_len = maxi(max_len, buffer->SampleLen); + } + length += max_len; BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } while(BufferList != NULL); *values = length; @@ -2503,8 +2529,13 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) BufferList = source->queue; while(BufferList) { - if((buffer=BufferList->buffer) != NULL && buffer->SampleLen > 0) - break; + ALsizei b; + for(b = 0;b < BufferList->num_buffers;b++) + { + buffer = BufferList->buffers[b]; + if(buffer && buffer->SampleLen > 0) break; + } + if(buffer && buffer->SampleLen > 0) break; BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } @@ -2804,11 +2835,12 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferList = source->queue; while(BufferList) { - if(BufferList->buffer) + for(i = 0;i < BufferList->num_buffers;i++) { - BufferFmt = BufferList->buffer; - break; + if((BufferFmt=BufferList->buffers[i]) != NULL) + break; } + if(BufferFmt) break; BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } @@ -2826,17 +2858,20 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu if(!BufferListStart) { - BufferListStart = al_calloc(DEF_ALIGN, sizeof(ALbufferlistitem)); + BufferListStart = al_calloc(DEF_ALIGN, + FAM_SIZE(ALbufferlistitem, buffers, 1)); BufferList = BufferListStart; } else { - ALbufferlistitem *item = al_calloc(DEF_ALIGN, sizeof(ALbufferlistitem)); + ALbufferlistitem *item = al_calloc(DEF_ALIGN, + FAM_SIZE(ALbufferlistitem, buffers, 1)); ATOMIC_STORE(&BufferList->next, item, almemory_order_relaxed); BufferList = item; } - BufferList->buffer = buffer; ATOMIC_INIT(&BufferList->next, NULL); + BufferList->num_buffers = 1; + BufferList->buffers[0] = buffer; if(!buffer) continue; /* Hold a read lock on each buffer being queued while checking all @@ -2861,10 +2896,13 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu { ALbufferlistitem *next = ATOMIC_LOAD(&BufferListStart->next, almemory_order_relaxed); - if((buffer=BufferListStart->buffer) != NULL) + for(i = 0;i < BufferListStart->num_buffers;i++) { - DecrementRef(&buffer->ref); - ReadUnlock(&buffer->lock); + if((buffer=BufferListStart->buffers[i]) != NULL) + { + DecrementRef(&buffer->ref); + ReadUnlock(&buffer->lock); + } } al_free(BufferListStart); BufferListStart = next; @@ -2877,8 +2915,11 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferList = BufferListStart; while(BufferList != NULL) { - ALbuffer *buffer = BufferList->buffer; - if(buffer) ReadUnlock(&buffer->lock); + for(i = 0;i < BufferList->num_buffers;i++) + { + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer) ReadUnlock(&buffer->lock); + } BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } UnlockBuffersRead(device); @@ -2940,12 +2981,12 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint Current = ATOMIC_LOAD_SEQ(&voice->current_buffer); else if(ATOMIC_LOAD_SEQ(&source->state) == AL_INITIAL) Current = OldTail; - if(OldTail != Current) + if(OldTail != Current && OldTail->num_buffers == 1) { for(i = 1;i < nb;i++) { ALbufferlistitem *next = ATOMIC_LOAD(&OldTail->next, almemory_order_relaxed); - if(!next || next == Current) break; + if(!next || next == Current || next->num_buffers != 1) break; OldTail = next; } } @@ -2964,7 +3005,7 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint while(OldHead != NULL) { ALbufferlistitem *next = ATOMIC_LOAD(&OldHead->next, almemory_order_relaxed); - ALbuffer *buffer = OldHead->buffer; + ALbuffer *buffer = OldHead->buffers[0]; if(!buffer) *(buffers++) = 0; @@ -3073,8 +3114,11 @@ static void DeinitSource(ALsource *source, ALsizei num_sends) while(BufferList != NULL) { ALbufferlistitem *next = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); - if(BufferList->buffer != NULL) - DecrementRef(&BufferList->buffer->ref); + for(i = 0;i < BufferList->num_buffers;i++) + { + if(BufferList->buffers[i] != NULL) + DecrementRef(&BufferList->buffers[i]->ref); + } al_free(BufferList); BufferList = next; } @@ -3235,8 +3279,15 @@ static ALint64 GetSourceSampleOffset(ALsource *Source, ALCcontext *context, ALui const ALbufferlistitem *BufferList = Source->queue; while(BufferList && BufferList != Current) { - if(BufferList->buffer) - readPos += (ALuint64)BufferList->buffer->SampleLen << 32; + ALsizei max_len = 0; + ALsizei i; + + for(i = 0;i < BufferList->num_buffers;i++) + { + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer) max_len = maxi(max_len, buffer->SampleLen); + } + readPos += (ALuint64)max_len << 32; BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next, almemory_order_relaxed); } @@ -3288,19 +3339,28 @@ static ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, ALuint const ALbuffer *BufferFmt = NULL; while(BufferList && BufferList != Current) { - const ALbuffer *buffer = BufferList->buffer; - if(buffer != NULL) + ALsizei max_len = 0; + ALsizei i; + + for(i = 0;i < BufferList->num_buffers;i++) { - if(!BufferFmt) BufferFmt = buffer; - readPos += (ALuint64)buffer->SampleLen << FRACTIONBITS; + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer) + { + if(!BufferFmt) BufferFmt = buffer; + max_len = maxi(max_len, buffer->SampleLen); + } } + readPos += (ALuint64)max_len << FRACTIONBITS; BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next, almemory_order_relaxed); } while(BufferList && !BufferFmt) { - BufferFmt = BufferList->buffer; + ALsizei i; + for(i = 0;i < BufferList->num_buffers && !BufferFmt;i++) + BufferFmt = BufferList->buffers[i]; BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next, almemory_order_relaxed); } @@ -3357,14 +3417,22 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *conte while(BufferList != NULL) { - const ALbuffer *buffer; + ALsizei max_len = 0; + ALsizei i; + readFin = readFin || (BufferList == Current); - if((buffer=BufferList->buffer) != NULL) + for(i = 0;i < BufferList->num_buffers;i++) { - if(!BufferFmt) BufferFmt = buffer; - totalBufferLen += buffer->SampleLen; - if(!readFin) readPos += buffer->SampleLen; + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer) + { + if(!BufferFmt) BufferFmt = buffer; + max_len = maxi(max_len, buffer->SampleLen); + } } + totalBufferLen += max_len; + if(!readFin) readPos += max_len; + BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next, almemory_order_relaxed); } @@ -3432,7 +3500,6 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *conte static ALboolean ApplyOffset(ALsource *Source, ALvoice *voice) { ALbufferlistitem *BufferList; - const ALbuffer *Buffer; ALuint bufferLen, totalBufferLen; ALuint offset = 0; ALsizei frac = 0; @@ -3445,8 +3512,15 @@ static ALboolean ApplyOffset(ALsource *Source, ALvoice *voice) BufferList = Source->queue; while(BufferList && totalBufferLen <= offset) { - Buffer = BufferList->buffer; - bufferLen = Buffer ? Buffer->SampleLen : 0; + ALsizei max_len = 0; + ALsizei i; + + for(i = 0;i < BufferList->num_buffers;i++) + { + ALbuffer *buffer = BufferList->buffers[i]; + if(buffer) max_len = maxi(max_len, buffer->SampleLen); + } + bufferLen = max_len; if(bufferLen > offset-totalBufferLen) { @@ -3483,8 +3557,10 @@ static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALsizei *frac BufferList = Source->queue; while(BufferList) { - if((BufferFmt=BufferList->buffer) != NULL) - break; + ALsizei i; + for(i = 0;i < BufferList->num_buffers && !BufferFmt;i++) + BufferFmt = BufferList->buffers[i]; + if(BufferFmt) break; BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next, almemory_order_relaxed); } |