AudioClip的频率和音高关系-Unity3D [英] Frequency and pitch relation for AudioClip - Unity3D

查看:739
本文介绍了AudioClip的频率和音高关系-Unity3D的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图仅使用6个音频片段来重新创建吉他的全部音域.

我当时在想可以设置音频片段的频率,但是audio.frequency只根据压缩格式而不是实际音调返回音频的频率.

我知道我可以阅读GetSpectrumData,但是该解决方案相当复杂,需要进行傅立叶变换分析或类似的分析.

影响音高,很容易改变音调,因此我可以上下移动,但是有一种方法可以弄清楚要使用的步骤.

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 ();
    }
}

我听到声音听起来不正确.

知道初始音调为E4 329.63Hz且音高为1时,是否有任何影响音高的方程式,我会得到下一个键F4 349.23Hz(或足够接近)吗?

还必须考虑到Unity AudioSource将音高限制在-3/3范围内(我认为这超出了需要).

添加一些个人研究.音高1似乎是初始音符,将音高1设置为2可使同一个音调高八度.

由于半音阶(钢琴上的所有黑白音符)是12个琴键,因此我假设对每一步使用1/12即可.

听起来很近,但我倒是不太对.这是新代码:

[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 ();
    }
}

解决方案

您尝试做的事情仅通过更改音频的 pitch 就不会很有效.通过更改音调,您会遇到其他问题,例如声音音调过快或需要花费更多的时间来完成,声音也不佳.

第一个解决方案是在 C ++ 中制作一个插件(合成器),该插件可从Unity读取音频文件并更改频率.它还应执行其他操作来解决速度问题.除非您是一位具有出色数学技能的音频工程师,否则这将非常复杂.而在移动设备上进行尝试则完全不同. OnAudioFilterRead 是您决定使用此方法时应该使用的功能./p>

second 推荐解决方案是为每个吉他琴键制作音频文件,然后将其放入audioClip数组.这样可以解决个其他问题.缺点是,您将有更多文件.

如果您不希望它完美,可以在

对于那些对为什么使用Mathf.Pow方程感兴趣的人,请阅读以下内容: https://en.wikipedia.org/wiki/Twelfth_root_of_two

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 ();
    }
}

解决方案

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

这篇关于AudioClip的频率和音高关系-Unity3D的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆