- Home /
Audio Analysis: isolating frequency values
I'm looking for the amplitude of frequencies 570-650. how could i obtain those from GetOutputData?
I'm trying to read certain frequencies from the audio output data, but no idea how many samples this requires or which FFTWindow to use?
Answer by aldonaletto · Oct 10, 2011 at 07:02 PM
You must use GetSpectrumData to analyse a frequency range: allocate a float array with a power-of-two size and pass it to GetSpectrumData. The size (lets call it Q ) defines the frequency resolution: each element shows the relative amplitude (0..1) of the frequency N * 24000/Q Hertz (where N is the element index and 24000 is half the audio sampling rate in a typical PC - read AudioSettings.outputSampleRate for the correct sampling rate). With a 1024 array, for instance, you will have a resolution of 23.4 hertz (each element refers to a frequency 23.4 Hz higher than the previous one). You can use 2048 samples as well, which gives a resolution of 11.7 Hz, but the time taken to get the spectrum may lower your frame rate. Use the BlackmanHarris window - it gives more precise results and isn't so expensive.
The function BandVol below gets the spectrum and returns the average intensity of the range of frequencies specified. You can place this code in your script and attach it to the AudioSource. Play the sound and call BandVol to get the frequency band volume. You can call the function during several Update cycles and average the results, for instance:
private var freqData: float[];
private var nSamples: int = 1024;
private var fMax: float;
function BandVol(fLow:float, fHigh:float): float {
fLow = Mathf.Clamp(fLow, 20, fMax); // limit low...
fHigh = Mathf.Clamp(fHigh, fLow, fMax); // and high frequencies
// get spectrum
audio.GetSpectrumData(freqData, 0, FFTWindow.BlackmanHarris);
var n1: int = Mathf.Floor(fLow * nSamples / fMax);
var n2: int = Mathf.Floor(fHigh * nSamples / fMax);
var sum: float = 0;
// average the volumes of frequencies fLow to fHigh
for (var i=n1; i<=n2; i++){
sum += freqData[i];
}
return sum / (n2 - n1 + 1);
}
function Start() {
freqData = new float[nSamples];
fMax = AudioSettings.outputSampleRate/2;
}
Thank you for this thorough response. I was trying to understand the correlation between samples and frequencies. I knew from visually looking at waveforms that the lower ones were lower Hz. I need to know how they were partitioned. The docs for Unity don't explain that much detail.
I'm still trying to wrap my $$anonymous$$d around FFTs and Laplace transforms. Both for audio and engineering.
The samples you get from GetOutputData is just a subsection of the time series data that makes up the wave form. Looking at the samples directly doesn't help much. All you can immediately see from looking at the samples is the average volume in a certain area.
To actually do frequency analysis you have to apply the discrete fourier transform to a section of your time series data. The resulting values are essentially the frequencies the original signal was made up inside the given subsection.
You could do a discrete fourier transform basically for arbitary frequencies. However this is computationally very expensive. The advantage of the fast fourier transform is that it uses many "shortcuts". This is possible because we only look at n frequencies equally spaced. So in a normal FFT of say 1024 values you get the frequencies from 0Hz up to the sample frequency (which may be 44kHz or 48kHz). So the lowest value usually is 0Hz which is basically a fix offset that never changes. Each "frequency bin" / frequency value represents one particular frequency. That is i * sampleFrequency / numberOfBins
where i is the index. So at 44kHz you get the frequencies: 0Hz, 42.97Hz, 85.94Hz, 128.91Hz, 171.88Hz, ...., 44kHz
The guy in this video actually has a great approach explaining how the FFT works even though he messes up a lot details and numbers in his examples (just see some comments ^^). However i think he actually does a great job at explaining what actually happens. The first 15 $$anonymous$$utes contain the important part. The rest is more about DFT vs FFT, windowing, Eulers formula, overlapping FFTs when you have a lot data / stream and some more examples.
ps: Over here i actually implemented the FFT algorithm in pure C# some time ago.