]> git.tdb.fi Git - ext/openal.git/blob - core/mixer/hrtfbase.h
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / core / mixer / hrtfbase.h
1 #ifndef CORE_MIXER_HRTFBASE_H
2 #define CORE_MIXER_HRTFBASE_H
3
4 #include <algorithm>
5 #include <cmath>
6
7 #include "almalloc.h"
8 #include "hrtfdefs.h"
9 #include "opthelpers.h"
10
11
12 using uint = unsigned int;
13
14 using ApplyCoeffsT = void(&)(float2 *RESTRICT Values, const size_t irSize,
15     const ConstHrirSpan Coeffs, const float left, const float right);
16
17 template<ApplyCoeffsT ApplyCoeffs>
18 inline void MixHrtfBase(const float *InSamples, float2 *RESTRICT AccumSamples, const size_t IrSize,
19     const MixHrtfFilter *hrtfparams, const size_t BufferSize)
20 {
21     ASSUME(BufferSize > 0);
22
23     const ConstHrirSpan Coeffs{hrtfparams->Coeffs};
24     const float gainstep{hrtfparams->GainStep};
25     const float gain{hrtfparams->Gain};
26
27     size_t ldelay{HrtfHistoryLength - hrtfparams->Delay[0]};
28     size_t rdelay{HrtfHistoryLength - hrtfparams->Delay[1]};
29     float stepcount{0.0f};
30     for(size_t i{0u};i < BufferSize;++i)
31     {
32         const float g{gain + gainstep*stepcount};
33         const float left{InSamples[ldelay++] * g};
34         const float right{InSamples[rdelay++] * g};
35         ApplyCoeffs(AccumSamples+i, IrSize, Coeffs, left, right);
36
37         stepcount += 1.0f;
38     }
39 }
40
41 template<ApplyCoeffsT ApplyCoeffs>
42 inline void MixHrtfBlendBase(const float *InSamples, float2 *RESTRICT AccumSamples,
43     const size_t IrSize, const HrtfFilter *oldparams, const MixHrtfFilter *newparams,
44     const size_t BufferSize)
45 {
46     ASSUME(BufferSize > 0);
47
48     const ConstHrirSpan OldCoeffs{oldparams->Coeffs};
49     const float oldGainStep{oldparams->Gain / static_cast<float>(BufferSize)};
50     const ConstHrirSpan NewCoeffs{newparams->Coeffs};
51     const float newGainStep{newparams->GainStep};
52
53     if(oldparams->Gain > GainSilenceThreshold) LIKELY
54     {
55         size_t ldelay{HrtfHistoryLength - oldparams->Delay[0]};
56         size_t rdelay{HrtfHistoryLength - oldparams->Delay[1]};
57         auto stepcount = static_cast<float>(BufferSize);
58         for(size_t i{0u};i < BufferSize;++i)
59         {
60             const float g{oldGainStep*stepcount};
61             const float left{InSamples[ldelay++] * g};
62             const float right{InSamples[rdelay++] * g};
63             ApplyCoeffs(AccumSamples+i, IrSize, OldCoeffs, left, right);
64
65             stepcount -= 1.0f;
66         }
67     }
68
69     if(newGainStep*static_cast<float>(BufferSize) > GainSilenceThreshold) LIKELY
70     {
71         size_t ldelay{HrtfHistoryLength+1 - newparams->Delay[0]};
72         size_t rdelay{HrtfHistoryLength+1 - newparams->Delay[1]};
73         float stepcount{1.0f};
74         for(size_t i{1u};i < BufferSize;++i)
75         {
76             const float g{newGainStep*stepcount};
77             const float left{InSamples[ldelay++] * g};
78             const float right{InSamples[rdelay++] * g};
79             ApplyCoeffs(AccumSamples+i, IrSize, NewCoeffs, left, right);
80
81             stepcount += 1.0f;
82         }
83     }
84 }
85
86 template<ApplyCoeffsT ApplyCoeffs>
87 inline void MixDirectHrtfBase(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut,
88     const al::span<const FloatBufferLine> InSamples, float2 *RESTRICT AccumSamples,
89     float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize)
90 {
91     ASSUME(BufferSize > 0);
92
93     for(const FloatBufferLine &input : InSamples)
94     {
95         /* For dual-band processing, the signal needs extra scaling applied to
96          * the high frequency response. The band-splitter applies this scaling
97          * with a consistent phase shift regardless of the scale amount.
98          */
99         ChanState->mSplitter.processHfScale({input.data(), BufferSize}, TempBuf,
100             ChanState->mHfScale);
101
102         /* Now apply the HRIR coefficients to this channel. */
103         const float *RESTRICT tempbuf{al::assume_aligned<16>(TempBuf)};
104         const ConstHrirSpan Coeffs{ChanState->mCoeffs};
105         for(size_t i{0u};i < BufferSize;++i)
106         {
107             const float insample{tempbuf[i]};
108             ApplyCoeffs(AccumSamples+i, IrSize, Coeffs, insample, insample);
109         }
110
111         ++ChanState;
112     }
113
114     /* Add the HRTF signal to the existing "direct" signal. */
115     float *RESTRICT left{al::assume_aligned<16>(LeftOut.data())};
116     float *RESTRICT right{al::assume_aligned<16>(RightOut.data())};
117     for(size_t i{0u};i < BufferSize;++i)
118         left[i]  += AccumSamples[i][0];
119     for(size_t i{0u};i < BufferSize;++i)
120         right[i] += AccumSamples[i][1];
121
122     /* Copy the new in-progress accumulation values to the front and clear the
123      * following samples for the next mix.
124      */
125     auto accum_iter = std::copy_n(AccumSamples+BufferSize, HrirLength, AccumSamples);
126     std::fill_n(accum_iter, BufferSize, float2{});
127 }
128
129 #endif /* CORE_MIXER_HRTFBASE_H */