Add methods to start and stop effect slot processing

A newly-created effect slot is in an AL_INITIAL state, in which processing is
stopped but will automatically become AL_PLAYING after successfully setting an
AL_EFFECTSLOT_EFFECT value (including AL_EFFECT_NULL or 0). Calling Play[v] or
Stop[v] will set the effect slot to AL_PLAYING or AL_STOPPED respectively.
While stopped, the effect won't produce audio and will not be processed.
This commit is contained in:
Chris Robinson
2020-09-05 19:11:57 -07:00
parent 7851f7d4ce
commit 9975aeb37f
2 changed files with 124 additions and 2 deletions
+113 -2
View File
@@ -369,6 +369,108 @@ START_API_FUNC
END_API_FUNC
AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context.get(), slotid)};
if UNLIKELY(!slot)
{
context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", slotid);
return;
}
AddActiveEffectSlots(&slotid, 1, context.get());
slot->mState = SlotState::Playing;
}
END_API_FUNC
AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if UNLIKELY(n < 0)
context->setError(AL_INVALID_VALUE, "Playing %d effect slots", n);
if UNLIKELY(n <= 0) return;
al::vector<ALeffectslot*> slots;
slots.reserve(static_cast<ALuint>(n));
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
auto validate_slot = [&context,&slots](const ALuint id) -> bool
{
ALeffectslot *slot{LookupEffectSlot(context.get(), id)};
if UNLIKELY(!slot)
{
context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", id);
return false;
}
slots.emplace_back(slot);
return true;
};
auto slotids_end = slotids + n;
auto bad_slot = std::find_if_not(slotids, slotids_end, validate_slot);
if UNLIKELY(bad_slot != slotids_end) return;
AddActiveEffectSlots(slotids, static_cast<ALuint>(n), context.get());
for(auto slot : slots)
slot->mState = SlotState::Playing;
}
END_API_FUNC
AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
ALeffectslot *slot{LookupEffectSlot(context.get(), slotid)};
if UNLIKELY(!slot)
{
context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", slotid);
return;
}
RemoveActiveEffectSlots(&slotid, 1, context.get());
slot->mState = SlotState::Stopped;
}
END_API_FUNC
AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if UNLIKELY(n < 0)
context->setError(AL_INVALID_VALUE, "Stopping %d effect slots", n);
if UNLIKELY(n <= 0) return;
std::lock_guard<std::mutex> _{context->mEffectSlotLock};
auto validate_slot = [&context](const ALuint id) -> bool
{
ALeffectslot *slot{LookupEffectSlot(context.get(), id)};
if UNLIKELY(!slot)
{
context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", id);
return false;
}
return true;
};
auto slotids_end = slotids + n;
auto bad_slot = std::find_if_not(slotids, slotids_end, validate_slot);
if UNLIKELY(bad_slot != slotids_end) return;
RemoveActiveEffectSlots(slotids, static_cast<ALuint>(n), context.get());
}
END_API_FUNC
AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
START_API_FUNC
{
@@ -397,12 +499,12 @@ START_API_FUNC
SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid effect ID %u", value);
err = slot->initEffect(effect, context.get());
}
if(err != AL_NO_ERROR)
if UNLIKELY(err != AL_NO_ERROR)
{
context->setError(err, "Effect initialization failed");
return;
}
if(slot->mState == SlotState::Initial)
if UNLIKELY(slot->mState == SlotState::Initial)
{
AddActiveEffectSlots(&slot->id, 1, context.get());
slot->mState = SlotState::Playing;
@@ -477,6 +579,9 @@ START_API_FUNC
}
break;
case AL_EFFECTSLOT_STATE_SOFT:
SETERR_RETURN(context, AL_INVALID_OPERATION,, "AL_EFFECTSLOT_STATE_SOFT is read-only");
default:
SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid effect slot integer property 0x%04x",
param);
@@ -493,6 +598,7 @@ START_API_FUNC
case AL_EFFECTSLOT_EFFECT:
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
case AL_EFFECTSLOT_TARGET_SOFT:
case AL_EFFECTSLOT_STATE_SOFT:
case AL_BUFFER:
alAuxiliaryEffectSloti(effectslot, param, values[0]);
return;
@@ -595,6 +701,10 @@ START_API_FUNC
*value = 0;
break;
case AL_EFFECTSLOT_STATE_SOFT:
*value = static_cast<int>(slot->mState);
break;
case AL_BUFFER:
if(auto *buffer = slot->Buffer)
*value = static_cast<ALint>(buffer->id);
@@ -616,6 +726,7 @@ START_API_FUNC
case AL_EFFECTSLOT_EFFECT:
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
case AL_EFFECTSLOT_TARGET_SOFT:
case AL_EFFECTSLOT_STATE_SOFT:
case AL_BUFFER:
alGetAuxiliaryEffectSloti(effectslot, param, values);
return;
+11
View File
@@ -102,6 +102,17 @@ AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid
#ifndef AL_SOFT_convolution_reverb
#define AL_SOFT_convolution_reverb
#define AL_EFFECT_CONVOLUTION_REVERB_SOFT 0xA000
#define AL_EFFECTSLOT_STATE_SOFT 0x199D
typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYSOFT)(ALuint slotid);
typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYVSOFT)(ALsizei n, const ALuint *slotids);
typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPSOFT)(ALuint slotid);
typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPVSOFT)(ALsizei n, const ALuint *slotids);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid);
AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids);
AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid);
AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids);
#endif
#endif
#ifdef __cplusplus