FFT feature
Supported bindings: ossia
FFT operates on complex numbers ; you can expect a real()
and complex()
members.
Here is a simple example, which looks for the band with the most amplitude.
#pragma once
#include <cmath>
#include <halp/audio.hpp>
#include <halp/controls.hpp>
#include <halp/fft.hpp>
#include <halp/meta.hpp>
namespace examples::helpers
{
/**
* This examples shows how one can get an FFT implementation to be
* dependency-injected at compile-time. Check the Logger example for more explanations.
*
* The idea is that the host software / plugin wrapper will provide its own FFT implementation.
* This way, we don't end up with 450 different FFT implementations in a single binary,
* and the algorithm is abstracted from the actual way to compute the FFT which does not
* matter - it could be FFTW, MKL, etc... depending on the licensing requirements
* of the project, or be left up to the host which will instantiate the plug-in.
*/
template <halp::has_fft_1d<double> C>
struct PeakBand
{
halp_meta(name, "Peak band")
halp_meta(c_name, "avnd_peak_band")
halp_meta(uuid, "5610b62e-ef1f-4a34-abe0-e57816bc44c2")
struct
{
halp::audio_channel<"In", double> audio;
} inputs;
struct
{
halp::val_port<"Peak", double> peak;
halp::val_port<"Band", int> band;
} outputs;
// Instantiate the FFT provided by the configuration.
// Syntax is a bit ugly as we are already in a template
// causing the need for the "::template " thing ; in C++23
// it should be possible to omit typename.
using fft_type = typename C::template fft_type<double>;
fft_type fft;
void prepare(halp::setup info)
{
// Initialize potential internal FFT buffers
fft.reset(info.frames);
}
void operator()(int frames)
{
outputs.peak = 0.;
// Process the fft
auto cplx = fft.execute(inputs.audio.channel, frames);
// Compute the band with the highest amplitude
for(int k = 0; k < frames / 2; k++)
{
const double mag_squared = std::norm(cplx[k]);
if(mag_squared > outputs.peak)
{
outputs.peak = mag_squared;
outputs.band = k;
}
}
outputs.peak = std::sqrt(outputs.peak);
}
};
}
Avendish currently provides a very simple and unoptimized FFT for the sake of testing. Contributions of bindings to more efficient FFT libraries are very welcome :-)