Release 1.20.1
[openal-soft.git] / common / alcomplex.cpp
blobe5cbe8a0a33f961b1766522968aada7f7980c1ae
2 #include "config.h"
4 #include "alcomplex.h"
6 #include <algorithm>
7 #include <cmath>
8 #include <cstddef>
9 #include <utility>
11 #include "math_defs.h"
14 void complex_fft(const al::span<std::complex<double>> buffer, const double sign)
16 const size_t fftsize{buffer.size()};
17 /* Bit-reversal permutation applied to a sequence of FFTSize items */
18 for(size_t i{1u};i < fftsize-1;i++)
20 size_t j{0u};
21 for(size_t mask{1u};mask < fftsize;mask <<= 1)
23 if((i&mask) != 0)
24 j++;
25 j <<= 1;
27 j >>= 1;
29 if(i < j)
30 std::swap(buffer[i], buffer[j]);
33 /* Iterative form of Danielson–Lanczos lemma */
34 size_t step{2u};
35 for(size_t i{1u};i < fftsize;i<<=1, step<<=1)
37 const size_t step2{step >> 1};
38 double arg{al::MathDefs<double>::Pi() / static_cast<double>(step2)};
40 std::complex<double> w{std::cos(arg), std::sin(arg)*sign};
41 std::complex<double> u{1.0, 0.0};
42 for(size_t j{0};j < step2;j++)
44 for(size_t k{j};k < fftsize;k+=step)
46 std::complex<double> temp{buffer[k+step2] * u};
47 buffer[k+step2] = buffer[k] - temp;
48 buffer[k] += temp;
51 u *= w;
56 void complex_hilbert(const al::span<std::complex<double>> buffer)
58 complex_fft(buffer, 1.0);
60 const double inverse_size = 1.0/static_cast<double>(buffer.size());
61 auto bufiter = buffer.begin();
62 const auto halfiter = bufiter + (buffer.size()>>1);
64 *bufiter *= inverse_size; ++bufiter;
65 bufiter = std::transform(bufiter, halfiter, bufiter,
66 [inverse_size](const std::complex<double> &c) -> std::complex<double>
67 { return c * (2.0*inverse_size); });
68 *bufiter *= inverse_size; ++bufiter;
70 std::fill(bufiter, buffer.end(), std::complex<double>{});
72 complex_fft(buffer, -1.0);