13 #include "alnumbers.h"
14 #include "alnumeric.h"
15 #include "opthelpers.h"
20 using ushort
= unsigned short;
21 using ushort2
= std::pair
<ushort
,ushort
>;
23 /* Because std::array doesn't have constexpr non-const accessors in C++14. */
24 template<typename T
, size_t N
>
29 constexpr size_t BitReverseCounter(size_t log2_size
) noexcept
31 /* Some magic math that calculates the number of swaps needed for a
32 * sequence of bit-reversed indices when index < reversed_index.
34 return (1u<<(log2_size
-1)) - (1u<<((log2_size
-1u)/2u));
38 constexpr auto GetBitReverser() noexcept
40 static_assert(N
<= sizeof(ushort
)*8, "Too many bits for the bit-reversal table.");
42 our_array
<ushort2
, BitReverseCounter(N
)> ret
{};
43 const size_t fftsize
{1u << N
};
46 /* Bit-reversal permutation applied to a sequence of fftsize items. */
47 for(size_t idx
{1u};idx
< fftsize
-1;++idx
)
49 size_t revidx
{0u}, imask
{idx
};
50 for(size_t i
{0};i
< N
;++i
)
52 revidx
= (revidx
<<1) | (imask
&1);
58 ret
.mData
[ret_i
].first
= static_cast<ushort
>(idx
);
59 ret
.mData
[ret_i
].second
= static_cast<ushort
>(revidx
);
63 assert(ret_i
== al::size(ret
.mData
));
67 /* These bit-reversal swap tables support up to 10-bit indices (1024 elements),
68 * which is the largest used by OpenAL Soft's filters and effects. Larger FFT
69 * requests, used by some utilities where performance is less important, will
70 * use a slower table-less path.
72 constexpr auto BitReverser2
= GetBitReverser
<2>();
73 constexpr auto BitReverser3
= GetBitReverser
<3>();
74 constexpr auto BitReverser4
= GetBitReverser
<4>();
75 constexpr auto BitReverser5
= GetBitReverser
<5>();
76 constexpr auto BitReverser6
= GetBitReverser
<6>();
77 constexpr auto BitReverser7
= GetBitReverser
<7>();
78 constexpr auto BitReverser8
= GetBitReverser
<8>();
79 constexpr auto BitReverser9
= GetBitReverser
<9>();
80 constexpr auto BitReverser10
= GetBitReverser
<10>();
81 constexpr al::span
<const ushort2
> gBitReverses
[11]{
96 void complex_fft(const al::span
<std::complex<double>> buffer
, const double sign
)
98 const size_t fftsize
{buffer
.size()};
99 /* Get the number of bits used for indexing. Simplifies bit-reversal and
100 * the main loop count.
102 const size_t log2_size
{static_cast<size_t>(al::countr_zero(fftsize
))};
104 if(unlikely(log2_size
>= al::size(gBitReverses
)))
106 for(size_t idx
{1u};idx
< fftsize
-1;++idx
)
108 size_t revidx
{0u}, imask
{idx
};
109 for(size_t i
{0};i
< log2_size
;++i
)
111 revidx
= (revidx
<<1) | (imask
&1);
116 std::swap(buffer
[idx
], buffer
[revidx
]);
119 else for(auto &rev
: gBitReverses
[log2_size
])
120 std::swap(buffer
[rev
.first
], buffer
[rev
.second
]);
122 /* Iterative form of Danielson-Lanczos lemma */
123 const double pi
{al::numbers::pi
* sign
};
125 for(size_t i
{0};i
< log2_size
;++i
)
127 const double arg
{pi
/ static_cast<double>(step2
)};
129 /* TODO: Would std::polar(1.0, arg) be any better? */
130 const std::complex<double> w
{std::cos(arg
), std::sin(arg
)};
131 std::complex<double> u
{1.0, 0.0};
132 const size_t step
{step2
<< 1};
133 for(size_t j
{0};j
< step2
;j
++)
135 for(size_t k
{j
};k
< fftsize
;k
+=step
)
137 std::complex<double> temp
{buffer
[k
+step2
] * u
};
138 buffer
[k
+step2
] = buffer
[k
] - temp
;
149 void complex_hilbert(const al::span
<std::complex<double>> buffer
)
153 const double inverse_size
= 1.0/static_cast<double>(buffer
.size());
154 auto bufiter
= buffer
.begin();
155 const auto halfiter
= bufiter
+ (buffer
.size()>>1);
157 *bufiter
*= inverse_size
; ++bufiter
;
158 bufiter
= std::transform(bufiter
, halfiter
, bufiter
,
159 [inverse_size
](const std::complex<double> &c
) -> std::complex<double>
160 { return c
* (2.0*inverse_size
); });
161 *bufiter
*= inverse_size
; ++bufiter
;
163 std::fill(bufiter
, buffer
.end(), std::complex<double>{});