diff options
-rw-r--r-- | OpenAL32/alSource.cpp | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/OpenAL32/alSource.cpp b/OpenAL32/alSource.cpp index 463d2438..42f05131 100644 --- a/OpenAL32/alSource.cpp +++ b/OpenAL32/alSource.cpp @@ -2682,44 +2682,51 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) if(n == 0) return; std::lock_guard<std::mutex> _{context->SourceLock}; - for(ALsizei i{0};i < n;i++) - { - if(!LookupSource(context.get(), sources[i])) - SETERR_RETURN(context.get(), AL_INVALID_NAME,, "Invalid source ID %u", sources[i]); - } + auto sources_end = sources+n; + auto bad_sid = std::find_if_not(sources, sources_end, + [&context](ALuint sid) -> bool + { + ALsource *source{LookupSource(context.get(), sid)}; + return LIKELY(source != nullptr); + } + ); + if(UNLIKELY(bad_sid != sources+n)) + SETERR_RETURN(context.get(), AL_INVALID_NAME,, "Invalid source ID %u", *bad_sid); ALCdevice *device{context->Device}; ALCdevice_Lock(device); /* If the device is disconnected, go right to stopped. */ - if(!device->Connected.load(std::memory_order_acquire)) + if(UNLIKELY(!device->Connected.load(std::memory_order_acquire))) { /* TODO: Send state change event? */ - for(ALsizei i{0};i < n;i++) - { - ALsource *source{LookupSource(context.get(), sources[i])}; - source->OffsetType = AL_NONE; - source->Offset = 0.0; - source->state = AL_STOPPED; - } + std::for_each(sources, sources_end, + [&context](ALuint sid) -> void + { + ALsource *source{LookupSource(context.get(), sid)}; + source->OffsetType = AL_NONE; + source->Offset = 0.0; + source->state = AL_STOPPED; + } + ); ALCdevice_Unlock(device); return; } while(n > context->MaxVoices-context->VoiceCount.load(std::memory_order_relaxed)) { - ALsizei newcount = context->MaxVoices << 1; - if(context->MaxVoices >= newcount) + if(UNLIKELY(context->MaxVoices > std::numeric_limits<ALsizei>::max()>>1)) { ALCdevice_Unlock(device); SETERR_RETURN(context.get(), AL_OUT_OF_MEMORY,, - "Overflow increasing voice count %d -> %d", context->MaxVoices, newcount); + "Overflow increasing voice count from %d", context->MaxVoices); } + ALsizei newcount = context->MaxVoices << 1; AllocateVoices(context.get(), newcount, device->NumAuxSends); } - for(ALsizei i{0};i < n;i++) + auto start_source = [&context,device](ALuint sid) -> void { - ALsource *source{LookupSource(context.get(), sources[i])}; + ALsource *source{LookupSource(context.get(), sid)}; /* Check that there is a queue containing at least one valid, non zero * length buffer. */ @@ -2742,34 +2749,34 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) source->state = AL_STOPPED; SendStateChangeEvent(context.get(), source->id, AL_STOPPED); } - continue; + return; } ALvoice *voice{GetSourceVoice(source, context.get())}; switch(GetSourceState(source, voice)) { - case AL_PLAYING: - assert(voice != nullptr); - /* A source that's already playing is restarted from the beginning. */ - voice->current_buffer.store(BufferList, std::memory_order_relaxed); - voice->position.store(0u, std::memory_order_relaxed); - voice->position_fraction.store(0, std::memory_order_release); - continue; - - case AL_PAUSED: - assert(voice != nullptr); - /* A source that's paused simply resumes. */ - voice->Playing.store(true, std::memory_order_release); - source->state = AL_PLAYING; - SendStateChangeEvent(context.get(), source->id, AL_PLAYING); - continue; - - default: - break; + case AL_PLAYING: + assert(voice != nullptr); + /* A source that's already playing is restarted from the beginning. */ + voice->current_buffer.store(BufferList, std::memory_order_relaxed); + voice->position.store(0u, std::memory_order_relaxed); + voice->position_fraction.store(0, std::memory_order_release); + return; + + case AL_PAUSED: + assert(voice != nullptr); + /* A source that's paused simply resumes. */ + voice->Playing.store(true, std::memory_order_release); + source->state = AL_PLAYING; + SendStateChangeEvent(context.get(), source->id, AL_PLAYING); + return; + + default: + assert(voice == nullptr); + break; } /* Look for an unused voice to play this source with. */ - assert(voice == nullptr); auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed); auto voice_iter = std::find_if(context->Voices, voices_end, [](const ALvoice *voice) noexcept -> bool @@ -2821,15 +2828,21 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) voice->Flags = start_fading ? VOICE_IS_FADING : 0; if(source->SourceType == AL_STATIC) voice->Flags |= VOICE_IS_STATIC; - memset(voice->Direct.Params, 0, sizeof(voice->Direct.Params[0])*voice->NumChannels); - for(ALsizei j{0};j < device->NumAuxSends;j++) - memset(voice->Send[j].Params, 0, sizeof(voice->Send[j].Params[0])*voice->NumChannels); + + std::fill_n(std::begin(voice->Direct.Params), voice->NumChannels, DirectParams{}); + std::for_each(voice->Send+0, voice->Send+source->Send.size(), + [voice](ALvoice::SendData &send) -> void + { std::fill_n(std::begin(send.Params), voice->NumChannels, SendParams{}); } + ); + if(device->AvgSpeakerDist > 0.0f) { ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC / (device->AvgSpeakerDist * device->Frequency); - for(ALsizei j{0};j < voice->NumChannels;j++) - NfcFilterCreate(&voice->Direct.Params[j].NFCtrlFilter, 0.0f, w1); + std::for_each(voice->Direct.Params+0, voice->Direct.Params+voice->NumChannels, + [w1](DirectParams &parms) -> void + { NfcFilterCreate(&parms.NFCtrlFilter, 0.0f, w1); } + ); } voice->SourceID.store(source->id, std::memory_order_relaxed); @@ -2838,7 +2851,8 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) source->VoiceIdx = vidx; SendStateChangeEvent(context.get(), source->id, AL_PLAYING); - } + }; + std::for_each(sources, sources_end, start_source); ALCdevice_Unlock(device); } |