Frequency and pitch relation for AudioClip - Unity3D

末鹿安然 提交于 2019-12-10 04:30:53

问题


I am trying to recreate the full range of a guitar only using 6 audio clips.

I was thinking there would be a way to set frequency of an audio clip but audio.frequency only returns the frequency of the audio based on compression format and not the actual tone.

I know I can read GetSpectrumData, but that solution is fairly complex and would require some Fourier Transform analysis or something of the kind.

Affecting the pitch, it is easy to alter the tone so I can go up and down but is there a way to figure out what are the steps to use.

void Update () 
{
    CheckAudio(KeyCode.Q, 1.0f);
    CheckAudio(KeyCode.W, 1.1f);
    CheckAudio(KeyCode.E, 1.2f);
    CheckAudio(KeyCode.R, 1.3f);
    CheckAudio(KeyCode.T, 1.4f);
}

void CheckAudio(KeyCode key, float pitch)
{
    if (Input.GetKeyDown (key)) 
    {
        audio.pitch = pitch;
        audio.Play ();
    }
}

I can hear it does not sound right.

Knowing the initial tone E4 329.63Hz with pitch at 1 is there any equation that affecting the pitch, I would get the next key F4 349.23Hz (or close enough)?

It has to be considered also that Unity AudioSource limits the pitch within -3/3 range (which I think is more than needed).

EDIT: Adding some personal research. It seems pitch 1 is initial note and setting to 2 give the same key one octave higher.

Since a chromatic scale (all black and white notes on the piano) is 12 keys, I assume that using 1/12 for each step should do it.

It sounds close but I fell it is not quite right. Here is the new code:

[SerializeField] private AudioSource audio;
float step = 1f/12f;
KeyCode[]keys = new KeyCode[]{
    KeyCode.Q, KeyCode.W,KeyCode.E,KeyCode.R,KeyCode.T,
    KeyCode.Y, KeyCode.U, KeyCode.I, KeyCode.O, KeyCode.P,
    KeyCode.A, KeyCode.S, KeyCode.D
};

void Update () 
{
    float f = 0.0f;
    foreach (KeyCode key in keys) 
    {
        CheckAudio(key, f);
        f += 1f;
    }
}

void CheckAudio(KeyCode key, float pitch)
{
    if (Input.GetKeyDown (key)) 
    {
        audio.pitch = 1f + pitch * step;
        audio.Play ();
    }
}

回答1:


What you are trying to do will not work well by simply changing the pitch of the audio. By changing the pitch, you will run into other problems such as sound finishing too fast or taking more time to finish and the sound will not be good either.

The first solution is to make a plugin(Synthesizer) in C++ that reads the audio file from Unity and change the frequency. It should also perform other actions to fix speed issues. This is very complicated unless you are an audio engineer with some great math skills. And trying this on a mobile device is whole different story. OnAudioFilterRead is a function you should use if you decide to go with this method.

The second and the recommended solution is to make an audio file for each guitar key then put them into array of audioClip. This solves every other problems.The down side is that you will have more files.

EDIT:

If you don't care about it being perfect, you can use something below from this nice guy on the internet.

void playSound(){
     float transpose = -4; 
     float note = -1; 
     if (Input.GetKeyDown("a")) note = 0;  // C
     if (Input.GetKeyDown("s")) note = 2;  // D
     if (Input.GetKeyDown("d")) note = 4;  // E
     if (Input.GetKeyDown("f")) note = 5;  // F
     if (Input.GetKeyDown("g")) note = 7;  // G
     if (Input.GetKeyDown("h")) note = 9;  // A
     if (Input.GetKeyDown("j")) note = 11; // B
     if (Input.GetKeyDown("k")) note = 12; // C
     if (Input.GetKeyDown("l")) note = 14; // D

     if (note>=0){ // if some key pressed...
         audio.pitch =  Mathf.Pow(2, (note+transpose)/12.0);
         audio.Play();
}

EDIT: For those of you interested in why the Mathf.Pow equation is used and working, read the following: https://en.wikipedia.org/wiki/Twelfth_root_of_two



来源:https://stackoverflow.com/questions/36793628/frequency-and-pitch-relation-for-audioclip-unity3d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!