Restructure voice data members

This should improve access patters by packing each buffer channel's data
together, which is more inline with its use.
This commit is contained in:
Chris Robinson
2019-06-03 22:24:26 -07:00
parent 53e1415a67
commit c76fb714cc
5 changed files with 163 additions and 161 deletions
+23 -19
View File
@@ -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);
+74 -73
View File
@@ -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);
}
}
}
+26 -25
View File
@@ -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;
+19 -25
View File
@@ -253,39 +253,33 @@ struct ALvoice {
ALuint mFlags;
struct ResampleData {
struct DirectData {
int FilterType;
al::span<FloatBufferLine> Buffer;
ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
};
DirectData mDirect;
struct SendData {
int FilterType;
al::span<FloatBufferLine> Buffer;
};
std::array<SendData,MAX_SENDS> mSend;
struct ChannelData {
alignas(16) std::array<ALfloat,MAX_RESAMPLE_PADDING*2> mPrevSamples;
ALfloat mAmbiScale;
BandSplitter mAmbiSplitter;
DirectParams mDryParams;
std::array<SendParams,MAX_SENDS> mWetParams;
};
std::array<ResampleData,MAX_INPUT_CHANNELS> mResampleData;
std::array<ChannelData,MAX_INPUT_CHANNELS> mChans;
struct {
int FilterType;
DirectParams Params[MAX_INPUT_CHANNELS];
al::span<FloatBufferLine> Buffer;
ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
} mDirect;
struct SendData {
int FilterType;
SendParams Params[MAX_INPUT_CHANNELS];
al::span<FloatBufferLine> Buffer;
};
al::FlexArray<SendData> mSend;
ALvoice(size_t numsends) : mSend{numsends} { }
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;
+21 -19
View File
@@ -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);