Hi I hope you all doing great!
So i m trying to make a plugin which will boost specific frequencies. I m able to find fundamental freq and audio which goes through whole chain sounds good (no clliping etc) but when i want to change a magnitude of specific freq i cant hear the diffrence (and i think i should). So when i m debbuging i can see that the magnitude is being multiplied but it doesnt make any difference. The plan is:
-
Push samples into fifo. My buffer is 441 samples btw. Rest of fifo I fill with zeros to get better resolution.
-
do FFT to my array of samples. ( what I found is that when even i have 441 samples on which i do fft the whole array of FFT is being filled with numbers. Maybe it should just have 882 samples after FFT and being filled with zerros after last sample?)
-
get magnitude from FFT
-
get fundamental freq ( to know which bins should i boost)
-
boosting multiples of the fundamental frequency
-
get phase to calculate complex numbers ( real, imag,real, imag) ( i m getting phase from FFT data before processing)
-
changing fftData with data with changed magnitude
-
inverse FFT
-
put modified data to output.
Can anyone tell me what I m doing wrong? Maybe i have wrong sizes of arrays in my for loops? Maybe i should do magnitude. boosting etc on my 882 samples not on the whole buffer and rest of the buffer i should fill with zeros.
My code:
header file:
juce::dsp::FFT my_FFT;
static constexpr auto fftOrder = 12, fftSize = 1 << fftOrder;
float sampleRate_sizeDiv;
std::array <float, fftSize> fifo;
std::array <float, fftSize * 2 > fftData;
std::array <float, fftSize> magnitudeData;
int magnitudeDataSize = magnitudeData.size();
float fftHalfSize = fftSize / 2 + 1;
float sizeMaxInv = (1.f / float(fftSize - 1));
float sizeMaxInvPi = sizeMaxInv * juce::MathConstants<float>::pi;
int fifoIndex = 0;
float resolution = 1.f;
float m_sampleRate = 0;
float fundamentalFreq = 0;
int idx; /// bin's index
float max = 0.f; /// max amplitude of freq
float magnitude;
std::array<float, 8> multiVariables =
{ 1.65 ,4.875, 3.136, 1.787, 6.6, 5.489, 1.382, 4.214 };
cpp file:
//// mono /////
for (int channel = 0; channel < 1; ++channel)
{
auto* channelData = buffer.getWritePointer(1);
for (int s = 0; s < buffer.getNumSamples(); s++)
{
channelData[s] = 0;
}
auto* channelData_0 = buffer.getWritePointer(0);
for (int s = 0; s < buffer.getNumSamples(); s++)
{
float currentSample = channelData_0[s];
if (fifoIndex == buffer.getNumSamples())
{
std::fill(fftData.begin(), fftData.end(), 0.0f);
std::fill(fifo.begin() + fifoIndex, fifo.end(), 0.f);
std::copy(fifo.begin(), fifo.end(), fftData.begin());
my_FFT.performRealOnlyForwardTransform(fftData.data());
fifoIndex = 0;
/// complex ----> magnitude ///
int magPlace = 0;
std::fill(magnitudeData.begin(), magnitudeData.end(), 0.0f);
for (int i = 0; i < fftData.size(); i += 2)
{
float magnitude = 0;
magnitude = getMagnitude(fftData[i], fftData[i + 1]);
magnitudeData[magPlace] = magnitude;
magPlace++;
}
/// get fundamental freq ///
max = 0;
idx = 0;
for (int i = 0; i < magnitudeData.size() / 2; i++)
{
float potMaxMagnitude = magnitudeData[i];
if (max < potMaxMagnitude)
{
max = potMaxMagnitude;
idx = i;
}
}
_RPT1(0, "idx %d\n", idx);
fundamentalFreq = (idx * m_sampleRate) / fftData.size(); //// coś jest nie tak że musze dzielić przez dwa
_RPT1(0, "Fundamental_Freq1 %.6f\n", fundamentalFreq);
/// boosting ///
// freq x2,x3,x4,x5...
int count = 2;
for (int i = 0; i < (multiVariables.size() - 1); i++)
{
magnitudeData[idx * count] *= multiVariables[i];
magnitudeData[(magnitudeDataSize - 1) - (idx * count)] *= multiVariables[i];
count++;
}
/// magnitude ----> real,image,real.... ///
int fftIndex = 0;
for (int i = 0; i < magnitudeDataSize; i++)
{
/// phase///
std::complex <float> complexNumber(fftData[fftIndex], fftData[fftIndex + 1]);
float phase = std::arg(complexNumber);
/// real and imag ///
float real = magnitudeData[i] * std::cos(phase);
float imag = magnitudeData[i] * std::sin(phase);
/// fftData changing //
fftData[fftIndex] = real;
fftData[fftIndex + 1] = imag;
fftIndex += 2;
}
//// inverse FFT
my_FFT.performRealOnlyInverseTransform(fftData.data());
}
///float windowAmp = std::sin(float(fifoIndex) * sizeMaxInvPi);
fifo[fifoIndex] = currentSample;///* windowAmp;
++fifoIndex;
/// output ///
channelData_0[s] = fftData[s];
}
}
}
getMaganitude Function:
float FreqBoosterAudioProcessor::getMagnitude(float real, float imag)
{
return std::sqrt(std::pow(real, 2) + std::pow(imag, 2));
}
Thanks in advance!