音频剪辑的频率和音高关系 - Unity3D

本文关键字:关系 Unity3D 高关系 频率 音频 | 更新日期: 2024-11-06 05:21:34

我正在尝试仅使用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 ();
    }
}

我听得出来听起来不对劲。

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

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

编辑:添加一些个人研究。似乎音高 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 ();
    }
}

音频剪辑的频率和音高关系 - Unity3D

您尝试执行的操作无法通过简单地更改音频的音高来正常工作。通过改变音高,您会遇到其他问题,例如声音完成太快或需要更多时间才能完成并且声音也不会很好。

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

第二个也是推荐的解决方案是为每个吉他键制作一个音频文件,然后将它们放入audioClip数组中。这解决了所有其他问题。缺点是您将拥有更多文件

编辑:

如果你不在乎它是否完美,你可以在互联网上使用这个好人下面的东西。

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

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