This script uses audio.GetSpectrumData to analyze the audio data and to calculate the instantaneous volume of a given range of frequencies. In order to use GetSpectrumData, we must supply a power-of-two sized float array as the first argument, which the function fills with the spectrum of the sound currently playing. Each element in this array contains the instantaneous volume (0…1) of its corresponding frequency, calculated as N * 24000Hz / arraySize
where N is the element index.
The function BandVol(fLow, fHigh) below calculates the averaged volume of all frequencies between fLow and fHigh. In this case, where voice sounds must be analyzed, we can set the range to 200Hz - 800Hz - it will produce good results, although other ranges can be tested as well (voice sounds range from 150Hz to 3KHz). If bass sounds were to be used, for instance, we should use a lower range like 50Hz to 250Hz.
In order to test it, I used a simple object (defined in mouth) which have this Y position elevated proportionally to the output of BandVol. A variable called volume is used to set how much the mouth raises. You can change this and use the value returned by BandVol to control the mouth vertical scale, for instance.
This script must be added to the object which contains the Audio Source, and another object must be defined in the mouth variable. It plays the audio clip defined in Audio Source and moves the mouth up and down following the sound played. In order to reproduce several different sounds, you can use PlayOneShot(audioClip) instead of Play().
EDITED: PlayOneShot doesn’t affect GetSpectrumData, like @FutureRobot observed in his answer below. In order to play different sounds, declare an AudioClip array and populate it with the clips in the Inspector. To play one of these clips, assign it to audio.clip and use the old and good Play() (array and function PlaySoundN included below):
var sounds: AudioClip[]; // set the array size and the sounds in the Inspector
private var freqData: float[];
private var nSamples: int = 256;
private var fMax = 24000;
private var audio: AudioSource; // AudioSource attached to this object
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: freqData[n] = vol of frequency n * fMax / nSamples
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*;*
- }*
- return sum / (n2 - n1 + 1);*
}
var mouth: GameObject;
var volume = 40;
var frqLow = 200;
var frqHigh = 800;
private var y0: float;
function Start() {
audio = GetComponent.(); // get AudioSource component
- y0 = mouth.transform.position.y;*
- freqData = new float[nSamples];*
- audio.Play();*
}
function Update() {
_ mouth.transform.position.y = y0 + BandVol(frqLow,frqHigh) * volume;_
}
// A function to play sound N:
function PlaySoundN(N: int){
audio.clip = sounds[N];
audio.Play();
}