From ee40a2e7e4867a769765d447a15ac88832eb8aa0 Mon Sep 17 00:00:00 2001 From: Chris Robinson <chris.kcat@gmail.com> Date: Fri, 21 Oct 2022 10:33:41 -0700 Subject: Add an IIR filter option for UHJ encoding/decoding This uses the reversed-allpass trick to maintain linear phase. with a 256- sample look-ahead/delay to minimize distortion. This should better preserve low frequencies while maintaining a proper phase response. --- core/voice.cpp | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'core/voice.cpp') diff --git a/core/voice.cpp b/core/voice.cpp index 74363fc1..ae8582da 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -852,37 +852,44 @@ void Voice::prepare(DeviceBase *device) mPrevSamples.reserve(maxu(2, num_channels)); mPrevSamples.resize(num_channels); + mDecoder = nullptr; + mDecoderPadding = 0; if(mFmtChannels == FmtSuperStereo) { - if(UhjQuality >= UhjLengthHq) - { - mDecoder = std::make_unique<UhjStereoDecoder<UhjLengthHq>>(); - mDecoderPadding = UhjStereoDecoder<UhjLengthHq>::sFilterDelay; - } - else + switch(UhjQuality) { + case UhjQualityType::IIR: + mDecoder = std::make_unique<UhjStereoDecoderIIR>(); + mDecoderPadding = UhjStereoDecoderIIR::sFilterDelay; + break; + case UhjQualityType::FIR256: mDecoder = std::make_unique<UhjStereoDecoder<UhjLengthLq>>(); mDecoderPadding = UhjStereoDecoder<UhjLengthLq>::sFilterDelay; + break; + case UhjQualityType::FIR512: + mDecoder = std::make_unique<UhjStereoDecoder<UhjLengthHq>>(); + mDecoderPadding = UhjStereoDecoder<UhjLengthHq>::sFilterDelay; + break; } } else if(IsUHJ(mFmtChannels)) { - if(UhjQuality >= UhjLengthHq) - { - mDecoder = std::make_unique<UhjDecoder<UhjLengthHq>>(); - mDecoderPadding = UhjDecoder<UhjLengthHq>::sFilterDelay; - } - else + switch(UhjQuality) { + case UhjQualityType::IIR: + mDecoder = std::make_unique<UhjDecoderIIR>(); + mDecoderPadding = UhjDecoderIIR::sFilterDelay; + break; + case UhjQualityType::FIR256: mDecoder = std::make_unique<UhjDecoder<UhjLengthLq>>(); mDecoderPadding = UhjDecoder<UhjLengthLq>::sFilterDelay; + break; + case UhjQualityType::FIR512: + mDecoder = std::make_unique<UhjDecoder<UhjLengthHq>>(); + mDecoderPadding = UhjDecoder<UhjLengthHq>::sFilterDelay; + break; } } - else - { - mDecoder = nullptr; - mDecoderPadding = 0; - } /* Clear the stepping value explicitly so the mixer knows not to mix this * until the update gets applied. @@ -925,11 +932,11 @@ void Voice::prepare(DeviceBase *device) if(mFmtChannels == FmtUHJ2) { mChans[0].mAmbiHFScale = 1.0f; - mChans[0].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sWLFScale; + mChans[0].mAmbiLFScale = DecoderBase::sWLFScale; mChans[1].mAmbiHFScale = 1.0f; - mChans[1].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sXYLFScale; + mChans[1].mAmbiLFScale = DecoderBase::sXYLFScale; mChans[2].mAmbiHFScale = 1.0f; - mChans[2].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sXYLFScale; + mChans[2].mAmbiLFScale = DecoderBase::sXYLFScale; } mFlags.set(VoiceIsAmbisonic); } @@ -949,9 +956,9 @@ void Voice::prepare(DeviceBase *device) chandata.mDryParams.NFCtrlFilter = device->mNFCtrlFilter; std::fill_n(chandata.mWetParams.begin(), device->NumAuxSends, SendParams{}); } - mChans[0].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sWLFScale; - mChans[1].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sXYLFScale; - mChans[2].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sXYLFScale; + mChans[0].mAmbiLFScale = DecoderBase::sWLFScale; + mChans[1].mAmbiLFScale = DecoderBase::sXYLFScale; + mChans[2].mAmbiLFScale = DecoderBase::sXYLFScale; mFlags.set(VoiceIsAmbisonic); } else -- cgit v1.2.3