diff options
author | Chris Robinson <[email protected]> | 2019-01-06 06:50:58 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-01-06 06:50:58 -0800 |
commit | f5b6d761ffb002532ee08e008cfd5fb87fdf6cfd (patch) | |
tree | 6c007c8f6d98b0449a095e435bd1f1f1eb578152 | |
parent | 13056b45b05386097af1416f773522cc9840c3bb (diff) |
Apply an all-pass on the existing output when upsampling ambisonics
-rw-r--r-- | Alc/alu.cpp | 12 | ||||
-rw-r--r-- | Alc/bformatdec.cpp | 25 | ||||
-rw-r--r-- | Alc/bformatdec.h | 9 |
3 files changed, 35 insertions, 11 deletions
diff --git a/Alc/alu.cpp b/Alc/alu.cpp index e5fa0c89..7d2709ea 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -128,8 +128,8 @@ inline HrtfDirectMixerFunc SelectHrtfMixer(void) void ProcessHrtf(ALCdevice *device, ALsizei SamplesToDo) { if(AmbiUpsampler *ambiup{device->AmbiUp.get()}) - ambiup->process(device->Dry.Buffer, device->FOAOut.Buffer, device->FOAOut.NumChannels, - SamplesToDo); + ambiup->process(device->Dry.Buffer, device->Dry.NumChannels, device->FOAOut.Buffer, + device->FOAOut.NumChannels, SamplesToDo); /* HRTF is stereo output only. */ const int lidx{(device->RealOut.ChannelName[0]==FrontLeft) ? 0 : 1}; @@ -147,16 +147,16 @@ void ProcessAmbiDec(ALCdevice *device, ALsizei SamplesToDo) { BFormatDec *ambidec{device->AmbiDecoder.get()}; if(device->Dry.Buffer != device->FOAOut.Buffer) - ambidec->upSample(device->Dry.Buffer, device->FOAOut.Buffer, device->FOAOut.NumChannels, - SamplesToDo); + ambidec->upSample(device->Dry.Buffer, device->Dry.NumChannels, device->FOAOut.Buffer, + device->FOAOut.NumChannels, SamplesToDo); ambidec->process(device->RealOut.Buffer, device->RealOut.NumChannels, device->Dry.Buffer, SamplesToDo); } void ProcessAmbiUp(ALCdevice *device, ALsizei SamplesToDo) { - device->AmbiUp->process(device->RealOut.Buffer, device->FOAOut.Buffer, - device->FOAOut.NumChannels, SamplesToDo); + device->AmbiUp->process(device->RealOut.Buffer, device->RealOut.NumChannels, + device->FOAOut.Buffer, device->FOAOut.NumChannels, SamplesToDo); } void ProcessUhj(ALCdevice *device, ALsizei SamplesToDo) diff --git a/Alc/bformatdec.cpp b/Alc/bformatdec.cpp index 1aa4211c..e5265203 100644 --- a/Alc/bformatdec.cpp +++ b/Alc/bformatdec.cpp @@ -171,6 +171,9 @@ void BFormatDec::reset(const ALsizei inchans, const ALfloat xover_norm, const AL mUpsampler[1].Gains[HF_BAND] = Ambi3DDecoderHFScale[1] / hfscales[1]; mUpsampler[1].Gains[LF_BAND] = 1.0f; std::fill(std::begin(mUpsampler)+2, std::end(mUpsampler), mUpsampler[1]); + + mUpAllpass[0].init(xover_norm); + std::fill(std::begin(mUpAllpass)+1, std::end(mUpAllpass), mUpAllpass[0]); } for(ALsizei i{0};i < chancount;i++) @@ -220,9 +223,10 @@ void BFormatDec::process(ALfloat (*OutBuffer)[BUFFERSIZE], const ALsizei OutChan } } -void BFormatDec::upSample(ALfloat (*OutBuffer)[BUFFERSIZE], const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo) +void BFormatDec::upSample(ALfloat (*OutBuffer)[BUFFERSIZE], const ALsizei OutChannels, const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo) { ASSUME(InChannels > 0); + ASSUME(OutChannels > InChannels); /* This up-sampler leverages the differences observed in dual-band higher- * order decoder matrices compared to first-order. For the same output @@ -236,11 +240,21 @@ void BFormatDec::upSample(ALfloat (*OutBuffer)[BUFFERSIZE], const ALfloat (*InSa */ for(ALsizei i{0};i < InChannels;i++) { + /* NOTE: Because we can't treat the first-order signal as completely + * decorrelated from the existing output (it may contain the reverb, + * echo, etc, portion) phase interference is a possibility if not kept + * coherent. As such, we need to apply an all-pass on the existing + * output so that it stays aligned with the upsampled signal. + */ + mUpAllpass[i].process(OutBuffer[i], SamplesToDo); + mUpsampler[i].Splitter.process(mSamples[HF_BAND].data(), mSamples[LF_BAND].data(), InSamples[i], SamplesToDo); MixRowSamples(OutBuffer[i], mUpsampler[i].Gains, &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(mSamples[0]), sNumBands, 0, SamplesToDo); } + for(ALsizei i{InChannels};i < OutChannels;i++) + mUpAllpass[i].process(OutBuffer[i], SamplesToDo); } @@ -255,16 +269,23 @@ void AmbiUpsampler::reset(const ALsizei out_order, const ALfloat xover_norm) mInput[1].Gains[HF_BAND] = Ambi3DDecoderHFScale[1] / hfscales[1]; mInput[1].Gains[LF_BAND] = 1.0f; std::fill(std::begin(mInput)+2, std::end(mInput), mInput[1]); + + mAllpass[0].init(xover_norm); + std::fill(std::begin(mAllpass)+1, std::end(mAllpass), mAllpass[0]); } -void AmbiUpsampler::process(ALfloat (*OutBuffer)[BUFFERSIZE], const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo) +void AmbiUpsampler::process(ALfloat (*OutBuffer)[BUFFERSIZE], const ALsizei OutChannels, const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo) { ASSUME(InChannels > 0); + ASSUME(OutChannels > InChannels); for(ALsizei i{0};i < InChannels;i++) { + mAllpass[i].process(OutBuffer[i], SamplesToDo); mInput[i].Splitter.process(mSamples[HF_BAND], mSamples[LF_BAND], InSamples[i], SamplesToDo); MixRowSamples(OutBuffer[i], mInput[i].Gains, mSamples, sNumBands, 0, SamplesToDo); } + for(ALsizei i{InChannels};i < OutChannels;i++) + mAllpass[i].process(OutBuffer[i], SamplesToDo); } diff --git a/Alc/bformatdec.h b/Alc/bformatdec.h index 753c2b6f..9fd57b36 100644 --- a/Alc/bformatdec.h +++ b/Alc/bformatdec.h @@ -36,6 +36,7 @@ private: BandSplitter Splitter; ALfloat Gains[sNumBands]; } mUpsampler[4]; + SplitterAllpass mUpAllpass[MAX_OUTPUT_CHANNELS]; ALsizei mNumChannels; ALboolean mDualBand; @@ -49,7 +50,7 @@ public: void process(ALfloat (*OutBuffer)[BUFFERSIZE], const ALsizei OutChannels, const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei SamplesToDo); /* Up-samples a first-order input to the decoder's configuration. */ - void upSample(ALfloat (*OutBuffer)[BUFFERSIZE], const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo); + void upSample(ALfloat (*OutBuffer)[BUFFERSIZE], const ALsizei OutChannels, const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo); DEF_NEWDEL(BFormatDec) }; @@ -60,15 +61,17 @@ public: */ class AmbiUpsampler { static constexpr ALsizei sNumBands{2}; + + alignas(16) ALfloat mSamples[sNumBands][BUFFERSIZE]; struct { BandSplitter Splitter; ALfloat Gains[sNumBands]; } mInput[4]; - alignas(16) ALfloat mSamples[sNumBands][BUFFERSIZE]; + SplitterAllpass mAllpass[MAX_OUTPUT_CHANNELS]; public: void reset(const ALsizei out_order, const ALfloat xover_norm); - void process(ALfloat (*OutBuffer)[BUFFERSIZE], const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo); + void process(ALfloat (*OutBuffer)[BUFFERSIZE], const ALsizei OutChannels, const ALfloat (*InSamples)[BUFFERSIZE], const ALsizei InChannels, const ALsizei SamplesToDo); DEF_NEWDEL(AmbiUpsampler) }; |