0

I'm trying to get the most representative frequency (or first harmonic) from an audio file using the Noise FFT library (https://github.com/paramsen/noise). I have an array with the values of size x and the output array's size is x+2. I'm not familiar with Fourier Transform, so maybe I'm missing something, but from my understanding I should have something that represents the frequencies and stores the magnitude (or in this case a complex number from with to calculate it) of each one.

The thing is: since each position in the array should be a frequency, how can I know the range of the output frequencies, what frequency is each position or something like that?

Edit: This is part of the code I'm using

float[] mono = new float[size];
// I fill the array with the appropiate values

Noise noise = Noise.real(size);
float[] dst = new float[size + 2];
float[] fft = noise.fft(mono, dst);
    
// The result array has the pairs of real+imaginary floats in a one dimensional array; even indices
// are real, odd indices are imaginary. DC bin is located at index 0, 1, nyquist at index n-2, n-1

double greatest = 0;
int greatestIdx = 0;
for(int i = 0; i < fft.length / 2; i++) {
    float real = fft[i * 2];
    float imaginary = fft[i * 2 + 1];
    double magnitude = Math.sqrt(real*real+imaginary*imaginary);
    if (magnitude > greatest) {
        greatest = magnitude;
        greatestIdx = i;
    }
    System.out.printf("index: %d, real: %.5f, imaginary: %.5f\n", i, real, imaginary);
}

I just noticed something I had overlooked. When reading the comment just before the for loop (which is from the sample code provided in GitHub) it says that nyquist is located at the last pair of values of the array. From what I searched, nyquist is 22050Hz, so... To know the frequency corresponding to greatestIdx I should map the range [0,size+2] to the range [0,22050] and calculate the new value? It seems like a pretty unprecise measure.

Taking the prior things into account, maybe I should use another library for more precision? If that is the case, what would be one that let me specify the output frequency range or that gives me approximately the human hearing range by default?

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • Usually, if you're running a FFT on a 2D noise like a texture, you'll get a 2D output. The center of the output is "DC" or zero-frequency noise, and as pixels move away from the center it represents increasing frequency. I think we'd need to see how you've configured the software to tell you how much step each pixel represents. Can you share the code, the input, and the output, the latter two I think would be best as images. – markspace Sep 07 '22 at 01:24
  • I have just edited the question with the code and some new observations I have made. – jose_rullva Sep 07 '22 at 01:50
  • Search the [fft] tag here on StackOverflow - there are lots of answers which over this, e.g. https://stackoverflow.com/a/4678313/253056 – Paul R Sep 07 '22 at 08:21

1 Answers1

1

I believe that the answer to your question is here if I understand it correctly https://stackoverflow.com/a/4371627/9834835

To determine the frequency for each FFT bin you may use the formula

F = i * sample / nFFt

where:
   i = the FFT index
   sample = the sample rate
   nFft = your FFT size