aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2019-06-03 22:24:26 -0700
committerChris Robinson <[email protected]>2019-06-03 22:24:26 -0700
commitc76fb714ccd44584f18c1be7c8366c462c493831 (patch)
tree53ada8c82651596d51b82e06cbccd390eee7d00a
parent53e1415a6709140654b5d70cc277d25fafa0bf66 (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.cpp42
-rw-r--r--Alc/alu.cpp147
-rw-r--r--Alc/mixvoice.cpp51
-rw-r--r--OpenAL32/Include/alu.h38
-rw-r--r--OpenAL32/alSource.cpp40
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 &params) 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 &params) -> 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 &params) -> 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 &params) -> 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);