In this article, we are going to learn techniques to match audio pitch to animation speed. This is very crucial while editing videos and creating animated contents.
(For more resources related to this topic, see here.)
Many artifacts sound higher in pitch when accelerated and lower when slowed down. Car engines, fan coolers, Vinyl, a record player the list goes on. If you want to simulate this kind of sound effect in an animated object that can have its speed changed dynamically, follow this article.
For this, you'll need an animated 3D object and an audio clip. Please use the files animatedRocket.fbx and engineSound.wav, available in the 1362_09_01 folder, that you can find in code bundle of the book Unity 5.x Cookbook at https://www.packtpub.com/game-development/unity-5x-cookbook.
To change the pitch of an audio clip according to the speed of an animated object, please follow these steps:
The reason why we didn't need to check Loop Pose option is because our animation already loops in a seamless fashion. If it didn't, we could have checked that option to automatically create a seamless transition from the last to the first frame of the animation.
using UnityEngine;
public class ChangePitch : MonoBehaviour{
public float accel = 0.05f;
public float minSpeed = 0.0f;
public float maxSpeed = 2.0f;
public float animationSoundRatio = 1.0f;
private float speed = 0.0f;
private Animator animator;
private AudioSource audioSource;
void Start(){
animator = GetComponent<Animator>();
audioSource = GetComponent<AudioSource>();
speed = animator.speed;
AccelRocket (0f);
}
void Update(){
if (Input.GetKey (KeyCode.Alpha1))
AccelRocket(accel);
if (Input.GetKey (KeyCode.Alpha2))
AccelRocket(-accel);
}
public void AccelRocket(float accel){
speed += accel;
speed = Mathf.Clamp(speed,minSpeed,maxSpeed);
animator.speed = speed;
float soundPitch = animator.speed * animationSoundRatio;
audioSource.pitch = Mathf.Abs(soundPitch);
}
}
At the Start() method, besides storing the Animator and Audio oururcecuSource components in variables, we'll get the initial speed from the Animator and, we'll call the AccelRocket() function by passing 0 as an argument, only for that function to calculate the resulting pitch for the Audio Source. During Update() function, the lines of the if(Input.GetKey (KeyCode.Alpha1)) and if(Input.GetKey (KeyCode.Alpha2)) code detect whenever the 1 or 2 keys are being pressed on the alphanumeric keyboard to call the AccelRocket() function, passing a accel float variable as an argument. The AccelRocket() function, in its turn, increments speed with the received argument (the accel float variable). However, it uses the Mathf.Clamp()command to limit the new speed value between the minimum and maximum speed as set by the user. Then, it changes the Animator speed and Audio Source pitch according to the new speed absolute value (the reason for making it an absolute value is keeping the pitch a positive number, even when the animation is reversed by a negative speed value). Also, please note that setting the animation speed and therefore, the sound pitch to 0 will cause the sound to stop, making it clear that stopping the object's animation also prevents the engine sound from playing.
Here is some information on how to fine-tune and customize this recipe.
If you want the audio clip pitch to be more or less affected by the animation speed, change the value of the Animation/Sound Ratio parameter.
The AccelRocket()function was made public so that it can be accessed from other scripts. As an example, we have included the ExtChangePitch.cs script in 1362_09_01 folder. Try attaching this script to the Main Camera object and use it to control the speed by clicking on the left and right mouse buttons.
In this article we learned, how to match audio pitch to the animation speed, how to change Animation/Sound Ratio.
To learn more please refer to the following books:
Further resources on this subject: