Make MixVoice a member function

This commit is contained in:
Chris Robinson
2019-08-31 14:53:28 -07:00
parent 5b6772440a
commit a546343148
3 changed files with 55 additions and 58 deletions
+1 -5
View File
@@ -1368,11 +1368,7 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo)
[SamplesToDo,ctx](ALvoice &voice) -> void
{
const ALvoice::State vstate{voice.mPlayState.load(std::memory_order_acquire)};
if(vstate == ALvoice::Stopped) return;
const ALuint sid{voice.mSourceID.load(std::memory_order_relaxed)};
if(voice.mStep < 1) return;
MixVoice(&voice, vstate, sid, ctx, SamplesToDo);
if(vstate != ALvoice::Stopped) voice.mix(vstate, ctx, SamplesToDo);
}
);
+2 -2
View File
@@ -310,6 +310,8 @@ struct ALvoice {
return *this;
}
void mix(ALvoice::State vstate, ALCcontext *Context, const ALuint SamplesToDo);
};
@@ -444,8 +446,6 @@ inline std::array<ALfloat,MAX_AMBI_CHANNELS> GetAmbiIdentityRow(size_t i) noexce
}
void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCcontext *Context, const ALuint SamplesToDo);
void aluMixData(ALCdevice *device, ALvoid *OutBuffer, const ALuint NumSamples);
/* Caller must lock the device state, and the mixer must not be running. */
void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
+52 -51
View File
@@ -320,9 +320,6 @@ struct FmtTypeTraits<FmtAlaw> {
void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
{
ALbitfieldSOFT enabledevt{context->mEnabledEvts.load(std::memory_order_acquire)};
if(!(enabledevt&EventType_SourceStateChange)) return;
RingBuffer *ring{context->mAsyncEvents.get()};
auto evt_vec = ring->getWriteVector();
if(evt_vec.first.len < 1) return;
@@ -476,21 +473,22 @@ ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *Buf
} // namespace
void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCcontext *Context, const ALuint SamplesToDo)
void ALvoice::mix(State vstate, ALCcontext *Context, const ALuint SamplesToDo)
{
static constexpr ALfloat SilentTarget[MAX_OUTPUT_CHANNELS]{};
ASSUME(SamplesToDo > 0);
/* Get voice info */
const bool isstatic{(voice->mFlags&VOICE_IS_STATIC) != 0};
ALuint DataPosInt{voice->mPosition.load(std::memory_order_relaxed)};
ALsizei DataPosFrac{voice->mPositionFrac.load(std::memory_order_relaxed)};
ALbufferlistitem *BufferListItem{voice->mCurrentBuffer.load(std::memory_order_relaxed)};
ALbufferlistitem *BufferLoopItem{voice->mLoopBuffer.load(std::memory_order_relaxed)};
const ALsizei NumChannels{voice->mNumChannels};
const ALsizei SampleSize{voice->mSampleSize};
const ALint increment{voice->mStep};
const bool isstatic{(mFlags&VOICE_IS_STATIC) != 0};
ALuint DataPosInt{mPosition.load(std::memory_order_relaxed)};
ALsizei DataPosFrac{mPositionFrac.load(std::memory_order_relaxed)};
ALbufferlistitem *BufferListItem{mCurrentBuffer.load(std::memory_order_relaxed)};
ALbufferlistitem *BufferLoopItem{mLoopBuffer.load(std::memory_order_relaxed)};
const ALsizei NumChannels{mNumChannels};
const ALsizei SampleSize{mSampleSize};
const ALint increment{mStep};
if(increment < 1) return;
ASSUME(DataPosFrac >= 0);
ASSUME(NumChannels > 0);
@@ -505,24 +503,24 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
ASSUME(IrSize >= 0);
ResamplerFunc Resample{(increment == FRACTIONONE && DataPosFrac == 0) ?
Resample_<CopyTag,CTag> : voice->mResampler};
Resample_<CopyTag,CTag> : mResampler};
ALuint Counter{(voice->mFlags&VOICE_IS_FADING) ? SamplesToDo : 0};
ALuint Counter{(mFlags&VOICE_IS_FADING) ? SamplesToDo : 0};
if(!Counter)
{
/* No fading, just overwrite the old/current params. */
for(ALsizei chan{0};chan < NumChannels;chan++)
{
ALvoice::ChannelData &chandata = voice->mChans[chan];
ChannelData &chandata = mChans[chan];
DirectParams &parms = chandata.mDryParams;
if(!(voice->mFlags&VOICE_HAS_HRTF))
if(!(mFlags&VOICE_HAS_HRTF))
std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
std::begin(parms.Gains.Current));
else
parms.Hrtf.Old = parms.Hrtf.Target;
for(ALsizei send{0};send < NumSends;++send)
{
if(voice->mSend[send].Buffer.empty())
if(mSend[send].Buffer.empty())
continue;
SendParams &parms = chandata.mWetParams[send];
@@ -531,11 +529,11 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
}
}
}
else if((voice->mFlags&VOICE_HAS_HRTF))
else if((mFlags&VOICE_HAS_HRTF))
{
for(ALsizei chan{0};chan < NumChannels;chan++)
{
DirectParams &parms = voice->mChans[chan].mDryParams;
DirectParams &parms = mChans[chan].mDryParams;
if(!(parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD))
{
/* The old HRTF params are silent, so overwrite the old
@@ -584,7 +582,7 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
ASSUME(DstBufferSize > 0);
for(ALsizei chan{0};chan < NumChannels;chan++)
{
ALvoice::ChannelData &chandata = voice->mChans[chan];
ChannelData &chandata = mChans[chan];
const al::span<ALfloat> SrcData{Device->SourceData, SrcBufferSize};
/* Load the previous samples into the source data first, then load
@@ -619,10 +617,10 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
chandata.mPrevSamples.size(), chandata.mPrevSamples.begin());
/* Resample, then apply ambisonic upsampling as needed. */
const ALfloat *ResampledData{Resample(&voice->mResampleState,
const ALfloat *ResampledData{Resample(&mResampleState,
&SrcData[MAX_RESAMPLE_PADDING], DataPosFrac, increment,
{Device->ResampledData, DstBufferSize})};
if((voice->mFlags&VOICE_IS_AMBISONIC))
if((mFlags&VOICE_IS_AMBISONIC))
{
const ALfloat hfscale{chandata.mAmbiScale};
/* Beware the evil const_cast. It's safe since it's pointing to
@@ -639,10 +637,9 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
{
DirectParams &parms = chandata.mDryParams;
const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass,
Device->FilteredData, ResampledData, DstBufferSize,
voice->mDirect.FilterType)};
Device->FilteredData, ResampledData, DstBufferSize, mDirect.FilterType)};
if((voice->mFlags&VOICE_HAS_HRTF))
if((mFlags&VOICE_HAS_HRTF))
{
const int OutLIdx{GetChannelIdxByName(Device->RealOut, FrontLeft)};
const int OutRIdx{GetChannelIdxByName(Device->RealOut, FrontRight)};
@@ -705,9 +702,9 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
hrtfparams.Gain = 0.0f;
hrtfparams.GainStep = gain / static_cast<ALfloat>(fademix);
MixHrtfBlendSamples(voice->mDirect.Buffer[OutLIdx],
voice->mDirect.Buffer[OutRIdx], HrtfSamples, AccumSamples, OutPos,
IrSize, &parms.Hrtf.Old, &hrtfparams, fademix);
MixHrtfBlendSamples(mDirect.Buffer[OutLIdx], mDirect.Buffer[OutRIdx],
HrtfSamples, AccumSamples, OutPos, IrSize, &parms.Hrtf.Old,
&hrtfparams, fademix);
/* Update the old parameters with the result. */
parms.Hrtf.Old = parms.Hrtf.Target;
if(fademix < Counter)
@@ -738,9 +735,9 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
hrtfparams.Gain = parms.Hrtf.Old.Gain;
hrtfparams.GainStep = (gain - parms.Hrtf.Old.Gain) /
static_cast<ALfloat>(todo);
MixHrtfSamples(voice->mDirect.Buffer[OutLIdx],
voice->mDirect.Buffer[OutRIdx], HrtfSamples+fademix,
AccumSamples+fademix, OutPos+fademix, IrSize, &hrtfparams, todo);
MixHrtfSamples(mDirect.Buffer[OutLIdx], mDirect.Buffer[OutRIdx],
HrtfSamples+fademix, AccumSamples+fademix, OutPos+fademix, IrSize,
&hrtfparams, todo);
/* Store the interpolated gain or the final target gain
* depending if the fade is done.
*/
@@ -756,23 +753,23 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
std::copy_n(std::begin(AccumSamples) + DstBufferSize,
parms.Hrtf.State.Values.size(), parms.Hrtf.State.Values.begin());
}
else if((voice->mFlags&VOICE_HAS_NFC))
else if((mFlags&VOICE_HAS_NFC))
{
const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
SilentTarget : parms.Gains.Target};
const size_t outcount{Device->NumChannelsPerOrder[0]};
MixSamples({samples, DstBufferSize}, voice->mDirect.Buffer.first(outcount),
MixSamples({samples, DstBufferSize}, mDirect.Buffer.first(outcount),
parms.Gains.Current, TargetGains, Counter, OutPos);
const al::span<float> nfcsamples{Device->NfcSampleData, DstBufferSize};
size_t chanoffset{outcount};
using FilterProc = void (NfcFilter::*)(float*,const float*,const size_t);
auto apply_nfc = [voice,&parms,samples,TargetGains,Counter,OutPos,&chanoffset,nfcsamples](const FilterProc process, const size_t outcount) -> void
auto apply_nfc = [this,&parms,samples,TargetGains,Counter,OutPos,&chanoffset,nfcsamples](const FilterProc process, const size_t outcount) -> void
{
if(outcount < 1) return;
(parms.NFCtrlFilter.*process)(nfcsamples.data(), samples, nfcsamples.size());
MixSamples(nfcsamples, voice->mDirect.Buffer.subspan(chanoffset, outcount),
MixSamples(nfcsamples, mDirect.Buffer.subspan(chanoffset, outcount),
parms.Gains.Current+chanoffset, TargetGains+chanoffset, Counter,
OutPos);
chanoffset += outcount;
@@ -785,25 +782,25 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
{
const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
SilentTarget : parms.Gains.Target};
MixSamples({samples, DstBufferSize}, voice->mDirect.Buffer,
parms.Gains.Current, TargetGains, Counter, OutPos);
MixSamples({samples, DstBufferSize}, mDirect.Buffer, parms.Gains.Current,
TargetGains, Counter, OutPos);
}
}
ALfloat (&FilterBuf)[BUFFERSIZE] = Device->FilteredData;
for(ALsizei send{0};send < NumSends;++send)
{
if(voice->mSend[send].Buffer.empty())
if(mSend[send].Buffer.empty())
continue;
SendParams &parms = chandata.mWetParams[send];
const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass,
FilterBuf, ResampledData, DstBufferSize, voice->mSend[send].FilterType)};
FilterBuf, ResampledData, DstBufferSize, mSend[send].FilterType)};
const ALfloat *TargetGains{UNLIKELY(vstate==ALvoice::Stopping) ? SilentTarget :
parms.Gains.Target};
MixSamples({samples, DstBufferSize}, voice->mSend[send].Buffer,
parms.Gains.Current, TargetGains, Counter, OutPos);
MixSamples({samples, DstBufferSize}, mSend[send].Buffer, parms.Gains.Current,
TargetGains, Counter, OutPos);
};
}
/* Update positions */
@@ -863,28 +860,31 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
}
} while(OutPos < SamplesToDo);
voice->mFlags |= VOICE_IS_FADING;
mFlags |= VOICE_IS_FADING;
/* Don't update positions and buffers if we were stopping. */
if UNLIKELY(vstate == ALvoice::Stopping)
{
voice->mPlayState.store(ALvoice::Stopped, std::memory_order_release);
mPlayState.store(ALvoice::Stopped, std::memory_order_release);
return;
}
/* Capture the source ID in case it's reset for stopping. */
const ALuint SourceID{mSourceID.load(std::memory_order_relaxed)};
/* Update voice info */
voice->mPosition.store(DataPosInt, std::memory_order_relaxed);
voice->mPositionFrac.store(DataPosFrac, std::memory_order_relaxed);
voice->mCurrentBuffer.store(BufferListItem, std::memory_order_relaxed);
mPosition.store(DataPosInt, std::memory_order_relaxed);
mPositionFrac.store(DataPosFrac, std::memory_order_relaxed);
mCurrentBuffer.store(BufferListItem, std::memory_order_relaxed);
if(vstate == ALvoice::Stopped)
{
voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
voice->mSourceID.store(0u, std::memory_order_relaxed);
mLoopBuffer.store(nullptr, std::memory_order_relaxed);
mSourceID.store(0u, std::memory_order_relaxed);
}
std::atomic_thread_fence(std::memory_order_release);
/* Send any events now, after the position/buffer info was updated. */
ALbitfieldSOFT enabledevt{Context->mEnabledEvts.load(std::memory_order_acquire)};
const ALbitfieldSOFT enabledevt{Context->mEnabledEvts.load(std::memory_order_acquire)};
if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted))
{
RingBuffer *ring{Context->mAsyncEvents.get()};
@@ -904,7 +904,8 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
/* If the voice just ended, set it to Stopping so the next render
* ensures any residual noise fades to 0 amplitude.
*/
voice->mPlayState.store(ALvoice::Stopping, std::memory_order_release);
SendSourceStoppedEvent(Context, SourceID);
mPlayState.store(ALvoice::Stopping, std::memory_order_release);
if((enabledevt&EventType_SourceStateChange))
SendSourceStoppedEvent(Context, SourceID);
}
}