There is a bit of code in the VCV Noise module I’ve been looking at, and there are a few little things I am trying to understand.
Here is the code below with my thoughts added as comments, am I on the right track?
struct InverseAWeightingFFTFilter {
/* The buffer length is how many bins we want the FFT to have */
static constexpr int BUFFER_LEN = 1024;
/* Define an input and output buffer.
Accumulate the signal in the input buffer each sample.
Process the signal using the FFT into the output buffer. */
alignas(16) float inputBuffer[BUFFER_LEN] = {};
alignas(16) float outputBuffer[BUFFER_LEN] = {};
/* frame == sample ? */
int frame = 0;
/* The VCV API also has a ComplexFFT, whats the use case for that? */
dsp::RealFFT fft;
/* Constructor, set the size of the FFT */
InverseAWeightingFFTFilter() : fft(BUFFER_LEN) {}
/* Process function, call each sample passing in the sample time and signal value. */
float process(float deltaTime, float x) {
/* Add the current signal value to the input buffer. */
inputBuffer[frame] = x;
/* When the buffer is full, then process it with the FFT. */
if (++frame >= BUFFER_LEN) {
/* Reset the counter so the samples in the buffer will be overwritten. */
frame = 0;
/* Define a frequency buffer that will hold the result of the FFT.
Why is this buffer is twice the size of the others? */
alignas(16) float freqBuffer[BUFFER_LEN * 2];
/* Calculate the FFT */
fft.rfft(inputBuffer, freqBuffer);
/* A loop the same length as the input buffer. */
for (int i = 0; i < BUFFER_LEN; i++) {
/* I would guess f is for the frequency of the FFT bin,
but I don't understand this calculation */
float f = 1 / deltaTime / 2 / BUFFER_LEN * i;
/* amp is going to be a number that we multiple this frequency by */
float amp = 0.f;
/* For this particular transform we only modify FFT bins between 80hz and 20khz */
if (80.f <= f && f <= 20000.f) {
/* The next few lines calculate the equation that determines the amp */
float f2 = f * f;
// Inverse A-weighted curve
amp = ((424.36f + f2) * std::sqrt((11599.3f + f2) * (544496.f + f2)) * (148693636.f + f2)) / (148693636.f * f2 * f2);
}
/* The buffer index here is because the frequency buffer is twice the size
Is setting both to the same value a loss of precision that doesn't matter?
why is the amp multiplied by the buffer length here? */
freqBuffer[2 * i + 0] *= amp / BUFFER_LEN;
freqBuffer[2 * i + 1] *= amp / BUFFER_LEN;
}
/* Reverse the FFT */
fft.irfft(freqBuffer, outputBuffer);
}
/* FFT has to be calculated over a number of samples
but we only need the result for the current sample,
if the input buffer is not full then we are returning the value from the previously calculated FFT,
does this mean the FFT calculation delays the processed signal by the length of the buffer? */
return outputBuffer[frame];
}
};