- Home /
What does 'float[] sample' in GetOutputData represent?
I need to monitor a master sound level while playing the game. AFAIK there is no VU meter of sorts so I think about writing my own meter.
For master channel data I used
float[] samples = new float[1024];
int channel = 0;
AudioListener.GetOutputData(samples,channel);
To get the last 1024 of samples played. But I'm now wondering what does each value in samples represent? Since when I try to sum all 1024 samples I sometimes get negative value.
Only thing I found out is when I play a really loud sound each float value in array will be close to 1. But what is a negative value?
I guess the channel will be 0 for left and 1 for right. Is this true?
Answer by Jessy · Jun 10, 2013 at 01:04 PM
Positive samples (translated to voltage) push your speakers out, and negative ones pull them in. This is not really a Unity question; maybe you are confused, because you're used to seeing half the total bit depth at zero, instead of the number zero?
You can generally count on 0 and 1 mapping to left and right; users can change this, but you don't have any way of knowing about it.
Hm? You means when a sample is at fully negative (-1), it's the loudest possible too? (In addition to 1)
You're close, but you've gotta understand the physics :)
To generate noise requires vibration. That's how speakers work, they oscillate out and in to produce noise. The speed at which they change direction gives you pitch, and the amount that they move between the $$anonymous$$ and max gives you volume.
So in our case, loudest volume would be moving the speaker between 1 and -1 (assu$$anonymous$$g Unity uses normalized values - I haven't looked into it). If the preceding local maximum is only at, say, 0.1, then no, going to -1 won't give you the loudest possible sound.
One more thing: if you're looking for loudest overall sound, it's important to note that human perception of volume varies with pitch.
Oh, and another thing: the time between 2 samples represents one pitch, the time between 4 samples represents another pitch, the time between 8 represents another, etc.
So if you're looking for volume, you want to look at not just sample-to-sample but at every pitch. What you really want is to take the Fourier transform of the clip:
http://en.wikipedia.org/wiki/Fourier_transform
I'm sorry - you wanted a simple solution, but physics isn't simple, and audio when you look closely is just physics :)
Answer by grokbox · Oct 10, 2013 at 10:18 AM
It sounds like what you want is the value of the sound's envelope normalized between 0 and 1. If you want to achieve that, you don't need to mess about with the spectrum data (which incidentally is available via AudioListener.GetSpectrumData() so you don't even need to really worry about Fourier transforming anything yourself). All you really need to do is take a number of samples, normalize them and then find the maximum value out of each set of samples. So for instance:
private AudioListener theSource;
void Update() {
float[] samples = theSource.GetOutputData(1024, 0);
float max = 0;
foreach (float sample in samples) {
sample = (sample + 1f) /2f;
if (sample > max) max = sample;
}
//Use value of max to control your VU meter height for this frame
}
Be aware that the human ear perceives 'loudness' in a logarithmic fashion, so scaling your VU meter's height probably won't give an accurate representation of the perceived loudness of your audio. You'll want to perform a Mathf.Log() on your values to get a better representation of actual perceived loudness.
Your answer
Follow this Question
Related Questions
How to load audio from server url 1 Answer
Intensity of sound. -1 Answers
Audio listeners in multiplayer game 3 Answers