diff options
author | Chris Robinson <[email protected]> | 2023-01-04 22:02:29 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-01-04 23:03:15 -0800 |
commit | 078b50e0ed6a0b89aa2e1f84bbbebbf24b885a4e (patch) | |
tree | db7bee5d11af40ae01d6210cfd41f6fa60a247f9 /alc/effects/vmorpher.cpp | |
parent | e38413a4fbb0b4f85950c929141856a767993f4f (diff) |
Simplify handling effect output for spatial effects
Effects are given a 3D ambisonic buffer of the same order as the device, for
processing surround sound. Effects that pass input channels to matching output
channels as it processes them don't need to mix each input channel to all
output channels.
At most, an input channel may mix to a different output channel, if the target
buffer uses a different channel layout, and need a gain adjustment, if it uses
a different scaling. With a 2D output buffer, a number of channels can be
skipped altogether.
Diffstat (limited to 'alc/effects/vmorpher.cpp')
-rw-r--r-- | alc/effects/vmorpher.cpp | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/alc/effects/vmorpher.cpp b/alc/effects/vmorpher.cpp index 9834c335..869c004e 100644 --- a/alc/effects/vmorpher.cpp +++ b/alc/effects/vmorpher.cpp @@ -143,12 +143,14 @@ struct FormantFilter struct VmorpherState final : public EffectState { struct { + uint mTargetChannel{INVALID_CHANNEL_INDEX}; + /* Effect parameters */ - FormantFilter Formants[NUM_FILTERS][NUM_FORMANTS]; + FormantFilter mFormants[NUM_FILTERS][NUM_FORMANTS]; /* Effect gains for each channel */ - float CurrentGains[MaxAmbiChannels]{}; - float TargetGains[MaxAmbiChannels]{}; + float mCurrentGain{}; + float mTargetGain{}; } mChans[MaxAmbiChannels]; void (*mGetSamples)(float*RESTRICT, uint, const uint, size_t){}; @@ -229,11 +231,12 @@ void VmorpherState::deviceUpdate(const DeviceBase*, const Buffer&) { for(auto &e : mChans) { - std::for_each(std::begin(e.Formants[VOWEL_A_INDEX]), std::end(e.Formants[VOWEL_A_INDEX]), + e.mTargetChannel = INVALID_CHANNEL_INDEX; + std::for_each(std::begin(e.mFormants[VOWEL_A_INDEX]), std::end(e.mFormants[VOWEL_A_INDEX]), std::mem_fn(&FormantFilter::clear)); - std::for_each(std::begin(e.Formants[VOWEL_B_INDEX]), std::end(e.Formants[VOWEL_B_INDEX]), + std::for_each(std::begin(e.mFormants[VOWEL_B_INDEX]), std::end(e.mFormants[VOWEL_B_INDEX]), std::mem_fn(&FormantFilter::clear)); - std::fill(std::begin(e.CurrentGains), std::end(e.CurrentGains), 0.0f); + e.mCurrentGain = 0.0f; } } @@ -265,14 +268,17 @@ void VmorpherState::update(const ContextBase *context, const EffectSlot *slot, /* Copy the filter coefficients to the input channels. */ for(size_t i{0u};i < slot->Wet.Buffer.size();++i) { - std::copy(vowelA.begin(), vowelA.end(), std::begin(mChans[i].Formants[VOWEL_A_INDEX])); - std::copy(vowelB.begin(), vowelB.end(), std::begin(mChans[i].Formants[VOWEL_B_INDEX])); + std::copy(vowelA.begin(), vowelA.end(), std::begin(mChans[i].mFormants[VOWEL_A_INDEX])); + std::copy(vowelB.begin(), vowelB.end(), std::begin(mChans[i].mFormants[VOWEL_B_INDEX])); } mOutTarget = target.Main->Buffer; - auto set_gains = [slot,target](auto &chan, al::span<const float,MaxAmbiChannels> coeffs) - { ComputePanGains(target.Main, coeffs.data(), slot->Gain, chan.TargetGains); }; - SetAmbiPanIdentity(std::begin(mChans), slot->Wet.Buffer.size(), set_gains); + auto set_channel = [this](size_t idx, uint target, float gain) + { + mChans[idx].mTargetChannel = target; + mChans[idx].mTargetGain = gain; + }; + target.Main->setAmbiMixParams(slot->Wet, slot->Gain, set_channel); } void VmorpherState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) @@ -291,8 +297,15 @@ void VmorpherState::process(const size_t samplesToDo, const al::span<const Float auto chandata = std::begin(mChans); for(const auto &input : samplesIn) { - auto& vowelA = chandata->Formants[VOWEL_A_INDEX]; - auto& vowelB = chandata->Formants[VOWEL_B_INDEX]; + const size_t outidx{chandata->mTargetChannel}; + if(outidx == INVALID_CHANNEL_INDEX) + { + ++chandata; + continue; + } + + auto& vowelA = chandata->mFormants[VOWEL_A_INDEX]; + auto& vowelB = chandata->mFormants[VOWEL_B_INDEX]; /* Process first vowel. */ std::fill_n(std::begin(mSampleBufferA), td, 0.0f); @@ -313,8 +326,8 @@ void VmorpherState::process(const size_t samplesToDo, const al::span<const Float blended[i] = lerpf(mSampleBufferA[i], mSampleBufferB[i], mLfo[i]); /* Now, mix the processed sound data to the output. */ - MixSamples({blended, td}, samplesOut, chandata->CurrentGains, chandata->TargetGains, - samplesToDo-base, base); + MixSamples({blended, td}, {&samplesOut[outidx], 1}, &chandata->mCurrentGain, + &chandata->mTargetGain, samplesToDo-base, base); ++chandata; } |