Open nkonopinski opened 4 years ago
@jepler may be of interest for ulab
@dhalbert thanks! I think ulab already handles this with the spectrum
function, though you can also get the real and imaginary parts and work with them independently if that's important for your use case
though .. the optimization might be nice to have
@v923z thoughts?
I think ulab already handles this with the spectrum function,
That's correct. We could rename it to spectrogram
, if you want: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html
@v923z thoughts?
A 1024-point FFT costs approx. 2 ms on the pyboard. spectrum
returns in 2.2 ms with the same data, so the square/square root operation costs 200 us. That is 10%. I am not sure this is worth the effort, especially that the speed-up comes at a price in accuracy. One should also keep in mind that values in an FFT vary wildly (this is why logarithmic plots are much more useful), so the variations in accuracy might be uncontrolled (since there is no obvious scaling).
And I think the comparison of https://github.com/nkonopinski/Adafruit_ZeroFFT/ to ulab
is not entirely fair: ulab
calculates the twiddle factors on the fly, because there is no way we could store those in flash. The function in question seems to take the factors from https://github.com/nkonopinski/Adafruit_ZeroFFT/blob/topic/return_magnitude/arm_common_tables.c.
Having said that, I am not totally against the approximation, but if the 10% gain is deemed necessary, I would rather implement it as a keyword option to spectrum
. I would be OK with fast = True
, or something similar in spectrum
.
This changes the output of the function to return the value users would expect from an FFT, it's magnitude.
The previous behavior was to discard the imaginary data, which can cause the output to vary sinusoidally over time. Returning the magnitude of the real and imaginary vector produces a consistent result.
Calculating the magnitude with multiplications and square roots can be computationally expensive. It can slow the function down by 4x for a 1024 length input. This approach uses the alpha max plus beta min algorithm (https://en.wikipedia.org/wiki/Alpha_max_plus_beta_min_algorithm) to efficiently return the magnitude. Using this method produced no measurable differences in the function's runtime.