c# – 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是初始音符,设置为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 ();
    }
}

解决方法

只需更改音频的音高,您尝试做的就不会有效.通过改变音高,您将遇到其他问题,例如声音结束太快或花费更多时间完成,声音也不会很好.

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

第二个和推荐的解决方案是为每个吉他键制作一个音频文件,然后将它们放入audioClip数组中.这解决了所有其他问题.不利的一面是你会有更多的文件.

编辑:

如果你不关心它是完美的,你可以在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();
}

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

相关文章

前言 本文记录unity3D开发环境的搭建 unity安装 unity有中文...
前言 有时候我们希望公告牌跟随镜头旋转永远平行面向屏幕,同...
前言 经过一段时间的学习与实际开发,unity3D也勉强算是强行...
前言 在unity中我们常用的获取鼠标点击的方法有: 1、在3D场...
前言 在之前的例子中,我们都没有用到unity的精髓,例如地形...
这篇文章将为大家详细讲解有关Unity3D中如何通过Animator动画...