diff options
author | Chris Robinson <[email protected]> | 2019-06-03 22:24:26 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-06-03 22:24:26 -0700 |
commit | c76fb714ccd44584f18c1be7c8366c462c493831 (patch) | |
tree | 53ada8c82651596d51b82e06cbccd390eee7d00a | |
parent | 53e1415a6709140654b5d70cc277d25fafa0bf66 (diff) |
Restructure voice data members
This should improve access patters by packing each buffer channel's data
together, which is more inline with its use.
-rw-r--r-- | Alc/alc.cpp | 42 | ||||
-rw-r--r-- | Alc/alu.cpp | 147 | ||||
-rw-r--r-- | Alc/mixvoice.cpp | 51 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 38 | ||||
-rw-r--r-- | OpenAL32/alSource.cpp | 40 |
5 files changed, 160 insertions, 158 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index 6d09b118..6ade082e 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -2161,12 +2161,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(device->AvgSpeakerDist > 0.0f) { /* Reinitialize the NFC filters for new parameters. */ - ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC / - (device->AvgSpeakerDist * device->Frequency); - std::for_each(voice->mDirect.Params, voice->mDirect.Params+voice->mNumChannels, - [w1](DirectParams ¶ms) noexcept -> void - { params.NFCtrlFilter.init(w1); } - ); + const ALfloat w1{SPEEDOFSOUNDMETRESPERSEC / + (device->AvgSpeakerDist * device->Frequency)}; + auto init_nfc = [w1](ALvoice::ChannelData &chandata) -> void + { chandata.mDryParams.NFCtrlFilter.init(w1); }; + std::for_each(voice->mChans.begin(), voice->mChans.begin()+voice->mNumChannels, + init_nfc); } } ); @@ -2591,7 +2591,7 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) * property set (including the dynamically-sized Send[] array) in one * chunk. */ - const size_t sizeof_voice{RoundUp(ALvoice::Sizeof(num_sends), 16)}; + const size_t sizeof_voice{RoundUp(sizeof(ALvoice), 16)}; const size_t size{sizeof(ALvoice*) + sizeof_voice}; auto voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16))); @@ -2605,9 +2605,9 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) const ALsizei s_count = mini(old_sends, num_sends); /* Copy the old voice data to the new storage. */ - auto copy_voice = [&voice,num_sends,sizeof_voice,s_count](ALvoice *old_voice) -> ALvoice* + auto copy_voice = [&voice,s_count](ALvoice *old_voice) -> ALvoice* { - voice = new (voice) ALvoice{static_cast<size_t>(num_sends)}; + voice = new (voice) ALvoice{}; /* Make sure the old voice's Update (if any) is cleared so it * doesn't get deleted on deinit. @@ -2647,16 +2647,21 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) voice->mFlags = old_voice->mFlags; - std::copy(old_voice->mResampleData.begin(), old_voice->mResampleData.end(), - voice->mResampleData.end()); - voice->mDirect = old_voice->mDirect; - std::copy_n(old_voice->mSend.begin(), s_count, voice->mSend.begin()); + voice->mSend = old_voice->mSend; + voice->mChans = old_voice->mChans; + + /* Clear old send data/params. */ + std::fill(voice->mSend.begin()+s_count, voice->mSend.end(), ALvoice::SendData{}); + auto clear_chan_sends = [s_count](ALvoice::ChannelData &chandata) -> void + { + std::fill(chandata.mWetParams.begin()+s_count, chandata.mWetParams.end(), + SendParams{}); + }; + std::for_each(voice->mChans.begin(), voice->mChans.end(), clear_chan_sends); /* Set this voice's reference. */ - ALvoice *ret = voice; - /* Increment pointer to the next storage space. */ - voice = reinterpret_cast<ALvoice*>(reinterpret_cast<char*>(voice) + sizeof_voice); + ALvoice *ret{voice++}; return ret; }; viter = std::transform(context->Voices, context->Voices+v_count, viter, copy_voice); @@ -2666,10 +2671,9 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) std::for_each(context->Voices, voices_end, DeinitVoice); } /* Finish setting the voices and references. */ - auto init_voice = [&voice,num_sends,sizeof_voice]() -> ALvoice* + auto init_voice = [&voice]() -> ALvoice* { - ALvoice *ret = new (voice) ALvoice{static_cast<size_t>(num_sends)}; - voice = reinterpret_cast<ALvoice*>(reinterpret_cast<char*>(voice) + sizeof_voice); + ALvoice *ret{new (voice++) ALvoice{}}; return ret; }; std::generate(viter, voices+num_voices, init_voice); diff --git a/Alc/alu.cpp b/Alc/alu.cpp index befddd9a..d41a66aa 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -554,22 +554,14 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo } ASSUME(num_channels > 0); - std::for_each(std::begin(voice->mDirect.Params), - std::begin(voice->mDirect.Params)+num_channels, - [](DirectParams ¶ms) -> void + std::for_each(voice->mChans.begin(), voice->mChans.begin()+num_channels, + [NumSends](ALvoice::ChannelData &chandata) -> void { - params.Hrtf.Target = HrtfParams{}; - ClearArray(params.Gains.Target); - } - ); - std::for_each(voice->mSend.begin(), voice->mSend.end(), - [num_channels](ALvoice::SendData &send) -> void - { - std::for_each(std::begin(send.Params), std::begin(send.Params)+num_channels, - [](SendParams ¶ms) -> void { ClearArray(params.Gains.Target); } - ); - } - ); + chandata.mDryParams.Hrtf.Target = HrtfParams{}; + ClearArray(chandata.mDryParams.Gains.Target); + std::for_each(chandata.mWetParams.begin(), chandata.mWetParams.begin()+NumSends, + [](SendParams ¶ms) -> void { ClearArray(params.Gains.Target); }); + }); voice->mFlags &= ~(VOICE_HAS_HRTF | VOICE_HAS_NFC); if(isbformat) @@ -592,7 +584,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo const ALfloat w0{SPEEDOFSOUNDMETRESPERSEC / (mdist * Frequency)}; /* Only need to adjust the first channel of a B-Format source. */ - voice->mDirect.Params[0].NFCtrlFilter.adjust(w0); + voice->mChans[0].mDryParams.NFCtrlFilter.adjust(w0); std::copy(std::begin(Device->NumChannelsPerOrder), std::end(Device->NumChannelsPerOrder), @@ -622,12 +614,12 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo /* NOTE: W needs to be scaled due to FuMa normalization. */ const ALfloat &scale0 = AmbiScale::FromFuMa[0]; ComputePanGains(&Device->Dry, coeffs, DryGain*scale0, - voice->mDirect.Params[0].Gains.Target); + voice->mChans[0].mDryParams.Gains.Target); for(ALsizei i{0};i < NumSends;i++) { if(const ALeffectslot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs, WetGain[i]*scale0, - voice->mSend[i].Params[0].Gains.Target); + voice->mChans[0].mWetParams[i].Gains.Target); } } else @@ -638,7 +630,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo * is what we want for FOA input. The first channel may have * been previously re-adjusted if panned, so reset it. */ - voice->mDirect.Params[0].NFCtrlFilter.adjust(0.0f); + voice->mChans[0].mDryParams.NFCtrlFilter.adjust(0.0f); voice->mDirect.ChannelsPerOrder[0] = 1; voice->mDirect.ChannelsPerOrder[1] = minz(voice->mDirect.Buffer.size()-1, 3); @@ -681,14 +673,16 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo }; for(ALsizei c{0};c < num_channels;c++) - ComputePanGains(&Device->Dry, matrix[c], DryGain, - voice->mDirect.Params[c].Gains.Target); - for(ALsizei i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) - for(ALsizei c{0};c < num_channels;c++) + ComputePanGains(&Device->Dry, matrix[c], DryGain, + voice->mChans[c].mDryParams.Gains.Target); + + for(ALsizei i{0};i < NumSends;i++) + { + if(const ALeffectslot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, matrix[c], WetGain[i], - voice->mSend[i].Params[c].Gains.Target); + voice->mChans[c].mWetParams[i].Gains.Target); + } } } } @@ -703,7 +697,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo for(ALsizei c{0};c < num_channels;c++) { int idx{GetChannelIdxByName(Device->RealOut, chans[c].channel)}; - if(idx != -1) voice->mDirect.Params[c].Gains.Target[idx] = DryGain; + if(idx != -1) voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain; } /* Auxiliary sends still use normal channel panning since they mix to @@ -718,7 +712,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo { if(const ALeffectslot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs, WetGain[i], - voice->mSend[i].Params[c].Gains.Target); + voice->mChans[c].mWetParams[i].Gains.Target); } } } @@ -739,16 +733,16 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo * source direction. */ GetHrtfCoeffs(Device->mHrtf, ev, az, Distance, Spread, - voice->mDirect.Params[0].Hrtf.Target.Coeffs, - voice->mDirect.Params[0].Hrtf.Target.Delay); - voice->mDirect.Params[0].Hrtf.Target.Gain = DryGain * downmix_gain; + voice->mChans[0].mDryParams.Hrtf.Target.Coeffs, + voice->mChans[0].mDryParams.Hrtf.Target.Delay); + voice->mChans[0].mDryParams.Hrtf.Target.Gain = DryGain * downmix_gain; /* Remaining channels use the same results as the first. */ for(ALsizei c{1};c < num_channels;c++) { /* Skip LFE */ - if(chans[c].channel != LFE) - voice->mDirect.Params[c].Hrtf.Target = voice->mDirect.Params[0].Hrtf.Target; + if(chans[c].channel == LFE) continue; + voice->mChans[c].mDryParams.Hrtf.Target = voice->mChans[0].mDryParams.Hrtf.Target; } /* Calculate the directional coefficients once, which apply to all @@ -757,16 +751,17 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo ALfloat coeffs[MAX_AMBI_CHANNELS]; CalcDirectionCoeffs({xpos, ypos, zpos}, Spread, coeffs); - for(ALsizei i{0};i < NumSends;i++) + for(ALsizei c{0};c < num_channels;c++) { - if(const ALeffectslot *Slot{SendSlots[i]}) - for(ALsizei c{0};c < num_channels;c++) - { - /* Skip LFE */ - if(chans[c].channel != LFE) - ComputePanGains(&Slot->Wet, coeffs, WetGain[i] * downmix_gain, - voice->mSend[i].Params[c].Gains.Target); - } + /* Skip LFE */ + if(chans[c].channel == LFE) + continue; + for(ALsizei i{0};i < NumSends;i++) + { + if(const ALeffectslot *Slot{SendSlots[i]}) + ComputePanGains(&Slot->Wet, coeffs, WetGain[i] * downmix_gain, + voice->mChans[c].mWetParams[i].Gains.Target); + } } } else @@ -786,9 +781,9 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo */ GetHrtfCoeffs(Device->mHrtf, chans[c].elevation, chans[c].angle, std::numeric_limits<float>::infinity(), Spread, - voice->mDirect.Params[c].Hrtf.Target.Coeffs, - voice->mDirect.Params[c].Hrtf.Target.Delay); - voice->mDirect.Params[c].Hrtf.Target.Gain = DryGain; + voice->mChans[c].mDryParams.Hrtf.Target.Coeffs, + voice->mChans[c].mDryParams.Hrtf.Target.Delay); + voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain; /* Normal panning for auxiliary sends. */ ALfloat coeffs[MAX_AMBI_CHANNELS]; @@ -798,7 +793,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo { if(const ALeffectslot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs, WetGain[i], - voice->mSend[i].Params[c].Gains.Target); + voice->mChans[c].mWetParams[i].Gains.Target); } } } @@ -822,7 +817,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo /* Adjust NFC filters. */ for(ALsizei c{0};c < num_channels;c++) - voice->mDirect.Params[c].NFCtrlFilter.adjust(w0); + voice->mChans[c].mDryParams.NFCtrlFilter.adjust(w0); std::copy(std::begin(Device->NumChannelsPerOrder), std::end(Device->NumChannelsPerOrder), @@ -851,25 +846,26 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo if(Device->Dry.Buffer == Device->RealOut.Buffer) { int idx = GetChannelIdxByName(Device->RealOut, chans[c].channel); - if(idx != -1) voice->mDirect.Params[c].Gains.Target[idx] = DryGain; + if(idx != -1) voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain; } continue; } ComputePanGains(&Device->Dry, coeffs, DryGain * downmix_gain, - voice->mDirect.Params[c].Gains.Target); + voice->mChans[c].mDryParams.Gains.Target); } - for(ALsizei i{0};i < NumSends;i++) + for(ALsizei c{0};c < num_channels;c++) { - if(const ALeffectslot *Slot{SendSlots[i]}) - for(ALsizei c{0};c < num_channels;c++) - { - /* Skip LFE */ - if(chans[c].channel != LFE) - ComputePanGains(&Slot->Wet, coeffs, WetGain[i] * downmix_gain, - voice->mSend[i].Params[c].Gains.Target); - } + /* Skip LFE */ + if(chans[c].channel == LFE) + continue; + for(ALsizei i{0};i < NumSends;i++) + { + if(const ALeffectslot *Slot{SendSlots[i]}) + ComputePanGains(&Slot->Wet, coeffs, WetGain[i] * downmix_gain, + voice->mChans[c].mWetParams[i].Gains.Target); + } } } else @@ -884,7 +880,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo const ALfloat w0{SPEEDOFSOUNDMETRESPERSEC / (Device->AvgSpeakerDist * Frequency)}; for(ALsizei c{0};c < num_channels;c++) - voice->mDirect.Params[c].NFCtrlFilter.adjust(w0); + voice->mChans[c].mDryParams.NFCtrlFilter.adjust(w0); std::copy(std::begin(Device->NumChannelsPerOrder), std::end(Device->NumChannelsPerOrder), @@ -900,7 +896,7 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo if(Device->Dry.Buffer == Device->RealOut.Buffer) { int idx = GetChannelIdxByName(Device->RealOut, chans[c].channel); - if(idx != -1) voice->mDirect.Params[c].Gains.Target[idx] = DryGain; + if(idx != -1) voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain; } continue; } @@ -913,12 +909,12 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo ); ComputePanGains(&Device->Dry, coeffs, DryGain, - voice->mDirect.Params[c].Gains.Target); + voice->mChans[c].mDryParams.Gains.Target); for(ALsizei i{0};i < NumSends;i++) { if(const ALeffectslot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs, WetGain[i], - voice->mSend[i].Params[c].Gains.Target); + voice->mChans[c].mWetParams[i].Gains.Target); } } } @@ -933,14 +929,16 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo voice->mDirect.FilterType = AF_None; if(gainHF != 1.0f) voice->mDirect.FilterType |= AF_LowPass; if(gainLF != 1.0f) voice->mDirect.FilterType |= AF_HighPass; - voice->mDirect.Params[0].LowPass.setParams(BiquadType::HighShelf, - gainHF, hfScale, BiquadFilter::rcpQFromSlope(gainHF, 1.0f)); - voice->mDirect.Params[0].HighPass.setParams(BiquadType::LowShelf, - gainLF, lfScale, BiquadFilter::rcpQFromSlope(gainLF, 1.0f)); + auto &lowpass = voice->mChans[0].mDryParams.LowPass; + auto &highpass = voice->mChans[0].mDryParams.HighPass; + lowpass.setParams(BiquadType::HighShelf, gainHF, hfScale, + lowpass.rcpQFromSlope(gainHF, 1.0f)); + highpass.setParams(BiquadType::LowShelf, gainLF, lfScale, + highpass.rcpQFromSlope(gainLF, 1.0f)); for(ALsizei c{1};c < num_channels;c++) { - voice->mDirect.Params[c].LowPass.copyParamsFrom(voice->mDirect.Params[0].LowPass); - voice->mDirect.Params[c].HighPass.copyParamsFrom(voice->mDirect.Params[0].HighPass); + voice->mChans[c].mDryParams.LowPass.copyParamsFrom(lowpass); + voice->mChans[c].mDryParams.HighPass.copyParamsFrom(highpass); } } for(ALsizei i{0};i < NumSends;i++) @@ -953,14 +951,17 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat xpos, const ALfloat ypo voice->mSend[i].FilterType = AF_None; if(gainHF != 1.0f) voice->mSend[i].FilterType |= AF_LowPass; if(gainLF != 1.0f) voice->mSend[i].FilterType |= AF_HighPass; - voice->mSend[i].Params[0].LowPass.setParams(BiquadType::HighShelf, - gainHF, hfScale, BiquadFilter::rcpQFromSlope(gainHF, 1.0f)); - voice->mSend[i].Params[0].HighPass.setParams(BiquadType::LowShelf, - gainLF, lfScale, BiquadFilter::rcpQFromSlope(gainLF, 1.0f)); + + auto &lowpass = voice->mChans[0].mWetParams[i].LowPass; + auto &highpass = voice->mChans[0].mWetParams[i].HighPass; + lowpass.setParams(BiquadType::HighShelf, gainHF, hfScale, + lowpass.rcpQFromSlope(gainHF, 1.0f)); + highpass.setParams(BiquadType::LowShelf, gainLF, lfScale, + highpass.rcpQFromSlope(gainLF, 1.0f)); for(ALsizei c{1};c < num_channels;c++) { - voice->mSend[i].Params[c].LowPass.copyParamsFrom(voice->mSend[i].Params[0].LowPass); - voice->mSend[i].Params[c].HighPass.copyParamsFrom(voice->mSend[i].Params[0].HighPass); + voice->mChans[c].mWetParams[i].LowPass.copyParamsFrom(lowpass); + voice->mChans[c].mWetParams[i].HighPass.copyParamsFrom(highpass); } } } diff --git a/Alc/mixvoice.cpp b/Alc/mixvoice.cpp index fc70fa2e..33ea00bb 100644 --- a/Alc/mixvoice.cpp +++ b/Alc/mixvoice.cpp @@ -540,8 +540,10 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc ASSUME(increment > 0); ALCdevice *Device{Context->Device}; + const ALsizei NumSends{Device->NumAuxSends}; const ALsizei IrSize{Device->mHrtf ? Device->mHrtf->irSize : 0}; + ASSUME(NumSends >= 0); ASSUME(IrSize >= 0); ResamplerFunc Resample{(increment == FRACTIONONE && DataPosFrac == 0) ? @@ -553,29 +555,29 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc /* No fading, just overwrite the old/current params. */ for(ALsizei chan{0};chan < NumChannels;chan++) { - DirectParams &parms = voice->mDirect.Params[chan]; + ALvoice::ChannelData &chandata = voice->mChans[chan]; + DirectParams &parms = chandata.mDryParams; if(!(voice->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; - auto set_current = [chan](ALvoice::SendData &send) -> void + for(ALsizei send{0};send < NumSends;++send) { - if(send.Buffer.empty()) - return; + if(voice->mSend[send].Buffer.empty()) + continue; - SendParams &parms = send.Params[chan]; + SendParams &parms = chandata.mWetParams[chan]; std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target), std::begin(parms.Gains.Current)); - }; - std::for_each(voice->mSend.begin(), voice->mSend.end(), set_current); + } } } else if((voice->mFlags&VOICE_HAS_HRTF)) { for(ALsizei chan{0};chan < NumChannels;chan++) { - DirectParams &parms = voice->mDirect.Params[chan]; + DirectParams &parms = voice->mChans[chan].mDryParams; if(!(parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD)) { /* The old HRTF params are silent, so overwrite the old @@ -626,14 +628,14 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc const al::span<ALfloat> SrcData{Device->SourceData, SrcBufferSize}; /* Load the previous samples into the source data first, and clear the rest. */ - auto srciter = std::copy_n(voice->mResampleData[chan].mPrevSamples.begin(), + auto srciter = std::copy_n(voice->mChans[chan].mPrevSamples.begin(), MAX_RESAMPLE_PADDING, SrcData.begin()); std::fill(srciter, SrcData.end(), 0.0f); if(UNLIKELY(!BufferListItem)) srciter = std::copy( - voice->mResampleData[chan].mPrevSamples.begin()+MAX_RESAMPLE_PADDING, - voice->mResampleData[chan].mPrevSamples.end(), srciter); + voice->mChans[chan].mPrevSamples.begin()+MAX_RESAMPLE_PADDING, + voice->mChans[chan].mPrevSamples.end(), srciter); else if(isstatic) srciter = LoadBufferStatic(BufferListItem, BufferLoopItem, NumChannels, SampleSize, chan, DataPosInt, srciter, SrcData.end()); @@ -654,8 +656,8 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc /* Store the last source samples used for next time. */ std::copy_n(&SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS], - voice->mResampleData[chan].mPrevSamples.size(), - voice->mResampleData[chan].mPrevSamples.begin()); + voice->mChans[chan].mPrevSamples.size(), + voice->mChans[chan].mPrevSamples.begin()); /* Resample, then apply ambisonic upsampling as needed. */ const ALfloat *ResampledData{Resample(&voice->mResampleState, @@ -663,20 +665,20 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc Device->ResampledData, DstBufferSize)}; if((voice->mFlags&VOICE_IS_AMBISONIC)) { - const ALfloat hfscale{voice->mResampleData[chan].mAmbiScale}; + const ALfloat hfscale{voice->mChans[chan].mAmbiScale}; /* Beware the evil const_cast. It's safe since it's pointing to * either SourceData or ResampledData (both non-const), but the * resample method takes the source as const float* and may * return it without copying to output, making it currently * unavoidable. */ - voice->mResampleData[chan].mAmbiSplitter.applyHfScale( - const_cast<ALfloat*>(ResampledData), hfscale, DstBufferSize); + voice->mChans[chan].mAmbiSplitter.applyHfScale(const_cast<ALfloat*>(ResampledData), + hfscale, DstBufferSize); } /* Now filter and mix to the appropriate outputs. */ { - DirectParams &parms = voice->mDirect.Params[chan]; + DirectParams &parms = voice->mChans[chan].mDryParams; const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass, Device->FilteredData, ResampledData, DstBufferSize, voice->mDirect.FilterType)}; @@ -832,21 +834,20 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc } ALfloat (&FilterBuf)[BUFFERSIZE] = Device->FilteredData; - auto mix_send = [vstate,Counter,OutPos,DstBufferSize,chan,ResampledData,&FilterBuf](ALvoice::SendData &send) -> void + for(ALsizei send{0};send < NumSends;++send) { - if(send.Buffer.empty()) - return; + if(voice->mSend[send].Buffer.empty()) + continue; - SendParams &parms = send.Params[chan]; + SendParams &parms = voice->mChans[chan].mWetParams[send]; const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass, - FilterBuf, ResampledData, DstBufferSize, send.FilterType)}; + FilterBuf, ResampledData, DstBufferSize, voice->mSend[send].FilterType)}; const ALfloat *TargetGains{UNLIKELY(vstate==ALvoice::Stopping) ? SilentTarget : parms.Gains.Target}; - MixSamples(samples, send.Buffer, parms.Gains.Current, TargetGains, Counter, OutPos, - DstBufferSize); + MixSamples(samples, voice->mSend[send].Buffer, parms.Gains.Current, TargetGains, + Counter, OutPos, DstBufferSize); }; - std::for_each(voice->mSend.begin(), voice->mSend.end(), mix_send); } /* Update positions */ DataPosFrac += increment*DstBufferSize; diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index cb0b675c..25a1d422 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -253,39 +253,33 @@ struct ALvoice { ALuint mFlags; - struct ResampleData { - alignas(16) std::array<ALfloat,MAX_RESAMPLE_PADDING*2> mPrevSamples; - - ALfloat mAmbiScale; - BandSplitter mAmbiSplitter; - }; - std::array<ResampleData,MAX_INPUT_CHANNELS> mResampleData; - - struct { + struct DirectData { int FilterType; - DirectParams Params[MAX_INPUT_CHANNELS]; - al::span<FloatBufferLine> Buffer; ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1]; - } mDirect; + }; + DirectData mDirect; struct SendData { int FilterType; - SendParams Params[MAX_INPUT_CHANNELS]; - al::span<FloatBufferLine> Buffer; }; - al::FlexArray<SendData> mSend; + std::array<SendData,MAX_SENDS> mSend; + + struct ChannelData { + alignas(16) std::array<ALfloat,MAX_RESAMPLE_PADDING*2> mPrevSamples; - ALvoice(size_t numsends) : mSend{numsends} { } + ALfloat mAmbiScale; + BandSplitter mAmbiSplitter; + + DirectParams mDryParams; + std::array<SendParams,MAX_SENDS> mWetParams; + }; + std::array<ChannelData,MAX_INPUT_CHANNELS> mChans; + + ALvoice() = default; ALvoice(const ALvoice&) = delete; ALvoice& operator=(const ALvoice&) = delete; - - static constexpr size_t Sizeof(size_t numsends) noexcept - { - return maxz(sizeof(ALvoice), - al::FlexArray<SendData>::Sizeof(numsends, offsetof(ALvoice, mSend))); - } }; void DeinitVoice(ALvoice *voice) noexcept; diff --git a/OpenAL32/alSource.cpp b/OpenAL32/alSource.cpp index 02396fd0..d2414e50 100644 --- a/OpenAL32/alSource.cpp +++ b/OpenAL32/alSource.cpp @@ -2938,40 +2938,42 @@ START_API_FUNC BandSplitter splitter{400.0f / static_cast<ALfloat>(device->Frequency)}; const auto scales = BFormatDec::GetHFOrderScales(1, device->mAmbiOrder); - auto init_ambi = [scales,&OrderFromChan,&splitter](ALvoice::ResampleData &resdata) -> void + auto init_ambi = [scales,&OrderFromChan,&splitter](ALvoice::ChannelData &chandata) -> void { - resdata.mPrevSamples.fill(0.0f); - resdata.mAmbiScale = scales[*(OrderFromChan++)]; - resdata.mAmbiSplitter = splitter; + chandata.mPrevSamples.fill(0.0f); + chandata.mAmbiScale = scales[*(OrderFromChan++)]; + chandata.mAmbiSplitter = splitter; }; - std::for_each(voice->mResampleData.begin(), - voice->mResampleData.begin()+voice->mNumChannels, init_ambi); + std::for_each(voice->mChans.begin(), voice->mChans.begin()+voice->mNumChannels, + init_ambi); voice->mFlags |= VOICE_IS_AMBISONIC; } else { /* Clear previous samples. */ - auto clear_prevs = [](ALvoice::ResampleData &resdata) -> void - { resdata.mPrevSamples.fill(0.0f); }; - std::for_each(voice->mResampleData.begin(), - voice->mResampleData.begin()+voice->mNumChannels, clear_prevs); + auto clear_prevs = [](ALvoice::ChannelData &chandata) -> void + { chandata.mPrevSamples.fill(0.0f); }; + std::for_each(voice->mChans.begin(), voice->mChans.begin()+voice->mNumChannels, + clear_prevs); } - std::fill_n(std::begin(voice->mDirect.Params), voice->mNumChannels, DirectParams{}); - std::for_each(voice->mSend.begin(), voice->mSend.end(), - [voice](ALvoice::SendData &send) -> void - { std::fill_n(std::begin(send.Params), voice->mNumChannels, SendParams{}); } - ); + auto clear_params = [device](ALvoice::ChannelData &chandata) -> void + { + chandata.mDryParams = DirectParams{}; + std::fill_n(chandata.mWetParams.begin(), device->NumAuxSends, SendParams{}); + }; + std::for_each(voice->mChans.begin(), voice->mChans.begin()+voice->mNumChannels, + clear_params); if(device->AvgSpeakerDist > 0.0f) { const ALfloat w1{SPEEDOFSOUNDMETRESPERSEC / (device->AvgSpeakerDist * device->Frequency)}; - std::for_each(voice->mDirect.Params+0, voice->mDirect.Params+voice->mNumChannels, - [w1](DirectParams &parms) noexcept -> void - { parms.NFCtrlFilter.init(w1); } - ); + auto init_nfc = [w1](ALvoice::ChannelData &chandata) -> void + { chandata.mDryParams.NFCtrlFilter.init(w1); }; + std::for_each(voice->mChans.begin(), voice->mChans.begin()+voice->mNumChannels, + init_nfc); } voice->mSourceID.store(source->id, std::memory_order_relaxed); |