Sign in to follow this  
johnboy007

Get the Hertz outa here

Recommended Posts

I want to be able to get the frequency out of some audio do detect gender. I am using C# and the Unity engine.

[code]

void Update ()
{

if(listener.enabled)
{
AudioListener.GetSpectrumData(number, 0,FFTWindow.BlackmanHarris);

for(int i=0; i < numSamples; i++)
{
int newHertz = Mathf.RoundToInt (Mathf.Clamp (number[i] * 2, 0, AudioSettings.outputSampleRate) / (AudioSettings.outputSampleRate / numSamples));

if(newHertz >=100 && newHertz <= 150)
bMan = true;
else if(newHertz >= 170 && newHertz <= 220)
bWoman = true;
else
bGender = false;

if(newHertz > peakData.Hertz)
peakData.Hertz = newHertz;
}
}
}

[/code]

I thought this would work but it does not, can anyone point me i0n the right direction?

Share this post


Link to post
Share on other sites
[quote name='johnboy007' timestamp='1313423805' post='4849432']
[code]
void Update ()
{

if(listener.enabled)

{

AudioListener.GetOutputData(number, 0);

for(int i=0; i < numSamples; i++)

{

int newHertz = Mathf.RoundToInt (Mathf.Clamp (number[i] * 2, 0, AudioSettings.outputSampleRate) / (AudioSettings.outputSampleRate / numSamples));

if(newhertz >=100 && newHertz <= 150)

bMan = true;

else if(newHertz >= 170 && newHertz <= 220)

bWoman = true;

else

bGender = false;

}

}

}

[/code]
[/quote]

I don't know if it would work and if it did it is not doing what you think it is. It will only store the last time newHertz was checked. I would try it like this:

[code]
int newHertz = 0;

for (numsamples with i)
{
//NOTE THE += and not =
newHertz += do calculation
}
newHertz /= numsamples;
if (newHerz ....)
male
else if (newHerz ....
female
else
none

[/code]

Share this post


Link to post
Share on other sites
Hi jp,

Extracting frequency info from the raw amplitudes is, I'm afraid, not a trivial problem. You need to do a Fourier analysis (FFT) on the data.

For you though it IS trivial, because you're using Unity -- happy day!

You just need to check out AudioListener.GetSpectrumData(), which gives you an array of amplitudes of different frequency bands.

Ideas for procedurally-generated-from music race games....

HTH.

Share this post


Link to post
Share on other sites
[quote name='johnboy007' timestamp='1313423805' post='4849432']
I want to be able to get the frequency out of some audio do detect gender. I am using C# and the Unity engine.
[/quote]

There is no unique frequency you can get out of a audio file/stream. You can try to Fourier transform the input and then analyze the "spectrum".

I don't get at all what you are trying to do in your code? You are trying to calculate the gender inside the loop for every audio sample? The audio samples are an amplitude so to speak. So you can't get a frequency from a single sample. Also the whole upper bound of the clamp "AudioSettings.outputSampleRate) / (AudioSettings.outputSampleRate / numSamples)" is just a fancy way to write "numSamples" + some integer rounding error?

Edit: after the ninja edit it makes more sense. I still don't get why you are clamping the result. Basically what you want to do is search for the max amplitude.

[code]
void Update ()
{

if(listener.enabled)
{
AudioListener.GetSpectrumData(number, 0,FFTWindow.BlackmanHarris);

double max = 0;
int maxpos = 0;
for(int i=0; i < numSamples; i++)
{
if(Mathf.Abs(number[i])>max)
{
max = Mathf.Abs(number[i]);
maxpos = i;
}
}
double frequency = maxpos*AudioSettings.outputSampleRate/numSamples;
//...

}
}

[/code]

Share this post


Link to post
Share on other sites
Ah, gotcha now after the edit!

OK, the numbers[] array you're getting back IS the frequency data. Each cell in that array corresponds to the amplitude of the frequencies in that particular bin. A bin in this case is a little sub-band of audio frequencies.

So, assuming each bin is 1Hz wide (is that the case? Not sure..), you could check the value of numbers[170] to get the amplitude of the 170Hz component, and compare that to other components.

For your example use case, you could check all array cells between 100 and 150 and find an average amplitude; then do the same for cells 170 to 220, and compare the two averages amplitudes.

Whether this will actually WORK to discriminate male and female voices is a different matter :cool:

Share this post


Link to post
Share on other sites
[quote name='japro' timestamp='1313425174' post='4849444']
[quote name='johnboy007' timestamp='1313423805' post='4849432']
I want to be able to get the frequency out of some audio do detect gender. I am using C# and the Unity engine.
[/quote]

There is no unique frequency you can get out of a audio file/stream. You can try to Fourier transform the input and then analyze the "spectrum".

I don't get at all what you are trying to do in your code? You are trying to calculate the gender inside the loop for every audio sample? The audio samples are an amplitude so to speak. So you can't get a frequency from a single sample. Also the whole upper bound of the clamp "AudioSettings.outputSampleRate) / (AudioSettings.outputSampleRate / numSamples)" is just a fancy way to write "numSamples" + some integer rounding error?

Edit: after the ninja edit it makes more sense. I still don't get why you are clamping the result. Basically what you want to do is search for the max amplitude.

[code]
void Update ()
{

if(listener.enabled)
{
AudioListener.GetSpectrumData(number, 0,FFTWindow.BlackmanHarris);

double max = 0;
int maxpos = 0;
for(int i=0; i < numSamples; i++)
{
if(Mathf.Abs(number[i])>max)
{
max = Mathf.Abs(number[i]);
maxpos = i;
}
}
double frequency = maxpos*AudioSettings.outputSampleRate/numSamples;
//...

}
}

[/code]
[/quote]
Thank you for your reply:
I have now added this to get my frequency, and i have 2 test wav files, man and woman and the womans is higher but both output value are alot higher than i expected, i like 22500 hertz, going to see if i can find a wav file that outputs just 500 hertz and see if it is calibrated right?

Share this post


Link to post
Share on other sites
Well, I don't have experience with unity and just assumed the spectrum data would return a fourier transform that's why I put that scaling factor there. What happens when you just write "frequency = maxpos"?

Share this post


Link to post
Share on other sites
[quote name='japro' timestamp='1313486234' post='4849769']
Well, I don't have experience with unity and just assumed the spectrum data would return a fourier transform that's why I put that scaling factor there. What happens when you just write "frequency = maxpos"?
[/quote]


I have downloaded and tested it with a wav file that outputs 500hz

If i do fequency = maxpos with numsample that = 256 the frequency is showing as 5

Then i thought well i really need to up the numsamples to test so i put that to 512 and my freq is 10 not 500? Has anyone got any ideas why?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this