25 #include "lv_fourier.h"
26 #include "lv_common.h"
30 #include <unordered_map>
33 #define AMP_LOG_SCALE_THRESHOLD0 0.001f
34 #define AMP_LOG_SCALE_DIVISOR 6.908f // divisor = -log threshold
42 DFT_METHOD_BRUTE_FORCE,
54 std::vector<float> bitrevtable;
55 std::vector<float> sintable;
56 std::vector<float> costable;
61 Entry (DFTMethod method,
unsigned int sample_count);
65 void fft_bitrev_table_init (
unsigned int sample_count);
66 void fft_cossin_table_init (
unsigned int sample_count);
67 void dft_cossin_table_init (
unsigned int sample_count);
70 Entry
const& get_entry (DFTMethod method,
unsigned int sample_count);
74 typedef std::unordered_map<unsigned int, Entry> Table;
87 unsigned int sample_count;
88 unsigned int spectrum_size;
89 unsigned int samples_out;
91 std::vector<float> real;
92 std::vector<float> imag;
94 Impl (
unsigned int samples_out,
unsigned int samples_in);
96 void perform_brute_force (
float const* input);
97 void perform_fft_radix2_dit (
float const* input);
99 DFTMethod best_method (
unsigned int sample_count);
105 DFTCache::Entry
const& DFTCache::get_entry (DFTMethod method,
unsigned int sample_count)
107 auto entry = m_cache.find (sample_count);
108 if (entry != m_cache.end ())
109 return entry->second;
112 m_cache[sample_count] = Entry (method, sample_count);
114 return m_cache[sample_count];
117 DFTCache::Entry::Entry (DFTMethod method,
unsigned int sample_count)
120 case DFT_METHOD_BRUTE_FORCE:
121 dft_cossin_table_init (sample_count);
125 fft_bitrev_table_init (sample_count);
126 fft_cossin_table_init (sample_count);
131 void DFTCache::Entry::fft_bitrev_table_init (
unsigned int sample_count)
133 bitrevtable.clear ();
134 bitrevtable.reserve (sample_count);
136 for (
unsigned int i = 0; i < sample_count; i++)
137 bitrevtable.push_back (i);
141 for (
unsigned int i = 0; i < sample_count; i++) {
143 std::swap (bitrevtable[i], bitrevtable[j]);
146 unsigned int m = sample_count >> 1;
148 while (m >= 1 && j >= m) {
157 void DFTCache::Entry::fft_cossin_table_init (
unsigned int sample_count)
159 unsigned int dft_size = 2;
160 unsigned int tab_size = 0;
162 while (dft_size <= sample_count) {
168 sintable.reserve (tab_size);
171 costable.reserve (tab_size);
175 while (dft_size <= sample_count) {
176 float theta = -2.0f * VISUAL_MATH_PI / dft_size;
178 costable.push_back (std::cos (theta));
179 sintable.push_back (std::sin (theta));
185 void DFTCache::Entry::dft_cossin_table_init (
unsigned int sample_count)
188 sintable.reserve (sample_count);
191 costable.reserve (sample_count);
193 for (
unsigned int i = 0; i < sample_count; i++) {
194 float theta = (-2.0f * VISUAL_MATH_PI * i) / sample_count;
196 costable.push_back (std::cos (theta));
197 sintable.push_back (std::sin (theta));
203 DFT::DFT (
unsigned int samples_out,
unsigned int samples_in)
204 : m_impl (new Impl (samples_out, samples_in))
210 : m_impl {std::move (rhs.m_impl)}
222 m_impl.swap (rhs.m_impl);
228 visual_return_if_fail (output !=
nullptr);
229 visual_return_if_fail (input !=
nullptr);
231 switch (m_impl->method) {
232 case DFT_METHOD_BRUTE_FORCE:
233 m_impl->perform_brute_force (input);
237 m_impl->perform_fft_radix2_dit (input);
242 1.0 / m_impl->sample_count, m_impl->samples_out);
247 visual_return_if_fail (output !=
nullptr);
248 visual_return_if_fail (input !=
nullptr);
250 return log_scale_standard (output, input, size);
253 void DFT::log_scale_standard (
float *output,
float const* input,
unsigned int size)
255 visual_return_if_fail (output !=
nullptr);
256 visual_return_if_fail (input !=
nullptr);
258 return log_scale_custom (output, input, size, AMP_LOG_SCALE_DIVISOR);
261 void DFT::log_scale_custom (
float* output,
float const* input,
unsigned int size,
float log_scale_divisor)
263 visual_return_if_fail (output !=
nullptr);
264 visual_return_if_fail (input !=
nullptr);
266 for (
unsigned int i = 0; i < size; i++) {
267 if (input[i] > AMP_LOG_SCALE_THRESHOLD0)
268 output[i] = 1.0f + log (input[i]) / log_scale_divisor;
274 DFT::Impl::Impl (
unsigned int samples_out_,
unsigned int samples_in_)
275 : sample_count (samples_in_),
276 spectrum_size (sample_count/2 + 1),
277 samples_out (std::min (samples_out_, spectrum_size)),
278 method (best_method (sample_count)),
285 DFTMethod DFT::Impl::best_method (
unsigned int sample_count)
288 return DFT_METHOD_FFT;
290 return DFT_METHOD_BRUTE_FORCE;
293 void DFT::Impl::perform_brute_force (
float const* input)
295 DFTCache::Entry
const& fcache = dft_cache.get_entry (method, sample_count);
297 for (
unsigned int i = 0; i < spectrum_size; i++) {
304 for (
unsigned int j = 0; j < sample_count; j++) {
310 wr = wr * fcache.costable[i] - wi * fcache.sintable[i];
311 wi = wtemp * fcache.sintable[i] + wi * fcache.costable[i];
319 void DFT::Impl::perform_fft_radix2_dit (
float const* input)
321 DFTCache::Entry
const& fcache = dft_cache.get_entry (method, sample_count);
323 for (
unsigned int i = 0; i < sample_count; i++) {
324 unsigned int idx = fcache.bitrevtable[i];
326 if (idx < sample_count)
327 real[i] = input[idx];
332 unsigned int dft_size = 2;
335 while (dft_size <= sample_count) {
336 float wpr = fcache.costable[t];
337 float wpi = fcache.sintable[t];
342 unsigned int half_dft_size = dft_size >> 1;
344 for (
unsigned int m = 0; m < half_dft_size; m++) {
345 for (
unsigned int i = m; i < sample_count; i += dft_size) {
346 unsigned int j = i + half_dft_size;
348 float tempr = wr * real[j] - wi * imag[j];
349 float tempi = wr * imag[j] + wi * real[j];
351 real[j] = real[i] - tempr;
352 imag[j] = imag[i] - tempi;
360 wr = (wtemp = wr) * wpr - wi * wpi;
361 wi = wi * wpr + wtemp * wpi;