diff options
author | Chris Robinson <[email protected]> | 2022-08-26 00:11:50 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2022-08-26 00:11:50 -0700 |
commit | 1ee81ab3f020bb057e100b9d36ffaa16e470334d (patch) | |
tree | 7c0491e4c965b6ca3e130e575f16469cff80c431 /alc | |
parent | e48c294a69c60cfa5b83b9a27e96caa2c207cd46 (diff) |
Fix W input mixing when non-0 coverage
When upsampling certain ambisonic formats, the W channel may contribute to
other output channels even with full coverage. Make sure they're taken into
account.
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alu.cpp | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp index db7c9017..bfbc6ead 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -859,22 +859,27 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con */ return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, 0.0f); }; + auto&& scales = GetAmbiScales(voice->mAmbiScaling); auto coeffs = calc_coeffs(Device->mRenderMode); - std::transform(coeffs.begin()+1, coeffs.end(), coeffs.begin()+1, - std::bind(std::multiplies<float>{}, _1, 1.0f-coverage)); + /* Scale the panned W signal based on the coverage (full coverage means + * no panned signal). Scale the panned W signal according to channel + * scaling. + */ + std::transform(coeffs.begin(), coeffs.end(), coeffs.begin(), + std::bind(std::multiplies<float>{}, _1, (1.0f-coverage)*scales[0])); - /* NOTE: W needs to be scaled according to channel scaling. */ - auto&& scales = GetAmbiScales(voice->mAmbiScaling); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base*scales[0], - voice->mChans[0].mDryParams.Gains.Target); - for(uint i{0};i < NumSends;i++) + if(!(coverage > 0.0f)) { - if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0], - voice->mChans[0].mWetParams[i].Gains.Target); + ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + voice->mChans[0].mDryParams.Gains.Target); + for(uint i{0};i < NumSends;i++) + { + if(const EffectSlot *Slot{SendSlots[i]}) + ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0], + voice->mChans[0].mWetParams[i].Gains.Target); + } } - - if(coverage > 0.0f) + else { /* Local B-Format sources have their XYZ channels rotated according * to the orientation. @@ -945,15 +950,18 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con GetAmbiLayout(voice->mAmbiLayout).data()}; static const uint8_t OrderOffset[MaxAmbiOrder+1]{0, 1, 4, 9,}; - for(size_t c{1};c < num_channels;c++) + for(size_t c{0};c < num_channels;c++) { const size_t acn{index_map[c]}; const size_t order{AmbiIndex::OrderFromChannel()[acn]}; const float scale{scales[acn] * coverage}; - coeffs = std::array<float,MaxAmbiChannels>{}; + /* For channel 0, combine the B-Format signal (scaled according + * to the coverage amount) with the directional pan. For all + * other channels, use just the (scaled) B-Format signal. + */ for(size_t x{OrderOffset[order]};x < MaxAmbiChannels;++x) - coeffs[x] = shrot[x][acn] * scale; + coeffs[x] += shrot[x][acn] * scale; ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); @@ -964,6 +972,8 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } + + coeffs = std::array<float,MaxAmbiChannels>{}; } } } |