diff options
author | Chris Robinson <[email protected]> | 2019-03-28 09:29:20 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-03-28 09:34:31 -0700 |
commit | dfb81ff42de27b474d27e5d9e30c8fbe538db5ca (patch) | |
tree | 8bc8f3b53eaa6e2fc52b5d5c5d75f9dfeb69a888 | |
parent | e7bfe1ebd00fe01514f590f4b143c676034fcf6e (diff) |
Avoid using the HRTF history buffer as a ring buffer
The HRTF mixers now get a full input buffer with the history prepended, so the
delay offsets just need to account for the start point and read forward for
each sample.
-rw-r--r-- | Alc/mixer/hrtfbase.h | 49 | ||||
-rw-r--r-- | Alc/mixvoice.cpp | 17 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 6 |
3 files changed, 37 insertions, 35 deletions
diff --git a/Alc/mixer/hrtfbase.h b/Alc/mixer/hrtfbase.h index 52d939f7..8ad4a99c 100644 --- a/Alc/mixer/hrtfbase.h +++ b/Alc/mixer/hrtfbase.h @@ -23,10 +23,10 @@ inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, c const ALfloat gain{hrtfparams->Gain}; ALfloat stepcount{0.0f}; - ALsizei HistOffset{Offset&HRTF_HISTORY_MASK}; ALsizei Delay[2]{ - (HistOffset-hrtfparams->Delay[0])&HRTF_HISTORY_MASK, - (HistOffset-hrtfparams->Delay[1])&HRTF_HISTORY_MASK }; + HRTF_HISTORY_LENGTH - hrtfparams->Delay[0], + HRTF_HISTORY_LENGTH - hrtfparams->Delay[1] }; + ASSUME(Delay[0] >= 0 && Delay[1] >= 0); Offset &= HRIR_MASK; ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK}; @@ -38,9 +38,8 @@ inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, c /* Calculate the number of samples we can do until one of the indices * wraps on its buffer, or we reach the end. */ - const ALsizei todo_hist{HRTF_HISTORY_LENGTH - maxi(maxi(HistOffset, Delay[0]), Delay[1])}; const ALsizei todo_hrir{HRIR_LENGTH - maxi(HeadOffset, Offset)}; - const ALsizei todo{mini(BufferSize-i, mini(todo_hist, todo_hrir)) + i}; + const ALsizei todo{mini(BufferSize-i, todo_hrir) + i}; ASSUME(todo > i); for(;i < todo;++i) @@ -49,11 +48,9 @@ inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, c hrtfstate->Values[HeadOffset][1] = 0.0f; ++HeadOffset; - hrtfstate->History[HistOffset++] = *(data++); - const ALfloat g{gain + gainstep*stepcount}; - const ALfloat left{hrtfstate->History[Delay[0]++] * g}; - const ALfloat right{hrtfstate->History[Delay[1]++] * g}; + const ALfloat left{data[Delay[0]++] * g}; + const ALfloat right{data[Delay[1]++] * g}; ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right); *(LeftOut++) += hrtfstate->Values[Offset][0]; @@ -64,9 +61,6 @@ inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, c } HeadOffset &= HRIR_MASK; - HistOffset &= HRTF_HISTORY_MASK; - Delay[0] &= HRTF_HISTORY_MASK; - Delay[1] &= HRTF_HISTORY_MASK; Offset &= HRIR_MASK; } hrtfparams->Gain = gain + gainstep*stepcount; @@ -89,13 +83,14 @@ inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightO ASSUME(IrSize >= 4); ASSUME(BufferSize > 0); - ALsizei HistOffset{Offset&HRTF_HISTORY_MASK}; ALsizei OldDelay[2]{ - (HistOffset-oldparams->Delay[0])&HRTF_HISTORY_MASK, - (HistOffset-oldparams->Delay[1])&HRTF_HISTORY_MASK }; + HRTF_HISTORY_LENGTH - oldparams->Delay[0], + HRTF_HISTORY_LENGTH - oldparams->Delay[1] }; + ASSUME(OldDelay[0] >= 0 && OldDelay[1] >= 0); ALsizei NewDelay[2]{ - (HistOffset-newparams->Delay[0])&HRTF_HISTORY_MASK, - (HistOffset-newparams->Delay[1])&HRTF_HISTORY_MASK }; + HRTF_HISTORY_LENGTH - newparams->Delay[0], + HRTF_HISTORY_LENGTH - newparams->Delay[1] }; + ASSUME(NewDelay[0] >= 0 && NewDelay[1] >= 0); Offset &= HRIR_MASK; ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK}; @@ -104,11 +99,8 @@ inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightO RightOut += OutPos; for(ALsizei i{0};i < BufferSize;) { - const ALsizei todo_hist{HRTF_HISTORY_LENGTH - - maxi(maxi(maxi(maxi(HistOffset, OldDelay[0]), OldDelay[1]), NewDelay[0]), NewDelay[1]) - }; const ALsizei todo_hrir{HRIR_LENGTH - maxi(HeadOffset, Offset)}; - const ALsizei todo{mini(BufferSize-i, mini(todo_hist, todo_hrir)) + i}; + const ALsizei todo{mini(BufferSize-i, todo_hrir) + i}; ASSUME(todo > i); for(;i < todo;++i) @@ -117,16 +109,14 @@ inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightO hrtfstate->Values[HeadOffset][1] = 0.0f; ++HeadOffset; - hrtfstate->History[HistOffset++] = *(data++); - ALfloat g{oldGain + oldGainStep*stepcount}; - ALfloat left{hrtfstate->History[OldDelay[0]++] * g}; - ALfloat right{hrtfstate->History[OldDelay[1]++] * g}; + ALfloat left{data[OldDelay[0]++] * g}; + ALfloat right{data[OldDelay[1]++] * g}; ApplyCoeffs(Offset, hrtfstate->Values, IrSize, OldCoeffs, left, right); g = newGainStep*stepcount; - left = hrtfstate->History[NewDelay[0]++] * g; - right = hrtfstate->History[NewDelay[1]++] * g; + left = data[NewDelay[0]++] * g; + right = data[NewDelay[1]++] * g; ApplyCoeffs(Offset, hrtfstate->Values, IrSize, NewCoeffs, left, right); *(LeftOut++) += hrtfstate->Values[Offset][0]; @@ -137,11 +127,6 @@ inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightO } HeadOffset &= HRIR_MASK; - HistOffset &= HRTF_HISTORY_MASK; - OldDelay[0] &= HRTF_HISTORY_MASK; - OldDelay[1] &= HRTF_HISTORY_MASK; - NewDelay[0] &= HRTF_HISTORY_MASK; - NewDelay[1] &= HRTF_HISTORY_MASK; Offset &= HRIR_MASK; } newparams->Gain = newGainStep*stepcount; diff --git a/Alc/mixvoice.cpp b/Alc/mixvoice.cpp index fcd08d0b..558586d3 100644 --- a/Alc/mixvoice.cpp +++ b/Alc/mixvoice.cpp @@ -624,10 +624,23 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc if((voice->mFlags&VOICE_HAS_HRTF)) { + auto &HrtfSamples = Device->HrtfSourceData; const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f : parms.Hrtf.Target.Gain}; ALsizei fademix{0}; + /* Copy the HRTF history and new input samples into a temp + * buffer. + */ + auto src_iter = std::copy(parms.Hrtf.State.History.begin(), + parms.Hrtf.State.History.end(), std::begin(HrtfSamples)); + std::copy_n(samples, DstBufferSize, src_iter); + /* Copy the last used samples back into the history buffer + * for later. + */ + std::copy_n(std::begin(HrtfSamples) + DstBufferSize, + parms.Hrtf.State.History.size(), parms.Hrtf.State.History.begin()); + /* If fading, the old gain is not silence, and this is the * first mixing pass, fade between the IRs. */ @@ -657,7 +670,7 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc MixHrtfBlendSamples( voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx], - samples, voice->mOffset, OutPos, IrSize, &parms.Hrtf.Old, + HrtfSamples, voice->mOffset, OutPos, IrSize, &parms.Hrtf.Old, &hrtfparams, &parms.Hrtf.State, fademix); /* Update the old parameters with the result. */ parms.Hrtf.Old = parms.Hrtf.Target; @@ -691,7 +704,7 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc static_cast<ALfloat>(todo); MixHrtfSamples( voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx], - samples+fademix, voice->mOffset+fademix, OutPos+fademix, IrSize, + HrtfSamples+fademix, voice->mOffset+fademix, OutPos+fademix, IrSize, &hrtfparams, &parms.Hrtf.State, todo); /* Store the interpolated gain or the final target gain * depending if the fade is done. diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index fe3a8bdc..3226e582 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -30,6 +30,7 @@ #include "alnumeric.h" #include "threads.h" #include "ambidefs.h" +#include "hrtf.h" template<typename T, size_t N> @@ -402,7 +403,10 @@ struct ALCdevice { alignas(16) ALfloat SourceData[BUFFERSIZE + MAX_RESAMPLE_PADDING*2]; alignas(16) ALfloat ResampledData[BUFFERSIZE]; alignas(16) ALfloat FilteredData[BUFFERSIZE]; - alignas(16) ALfloat NfcSampleData[BUFFERSIZE]; + union { + alignas(16) ALfloat HrtfSourceData[BUFFERSIZE + HRTF_HISTORY_LENGTH]; + alignas(16) ALfloat NfcSampleData[BUFFERSIZE]; + }; /* Mixing buffer used by the Dry mix and Real output. */ al::vector<std::array<ALfloat,BUFFERSIZE>, 16> MixBuffer; |