2016-04-22 92 views
6

我想重新创建只有6个音频剪辑的吉他的全部范围。音频剪辑的频率和音调关系 - Unity3D

我在想会有一种方法来设置音频剪辑的频率,但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(); 
    } 
} 

我可以听到它听起来不对。

知道音高为1的E4 329.63Hz的初始音调是否有任何影响音调的方程式,我会得到下一个键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(); 
    } 
} 

回答

5

你正在尝试通过简单地改变声音的音高做会工作做好。通过改变音调,你会遇到其他问题如声音完成太快或需要更多的时间来完成,声音也不会很好。

第一解决方案是使在C++一个插件(合成),其读取从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

+0

是的我想到了第二种方案,但被扫描是否会有一个更编程方法来避免你提到的缺点。现在你把它带出去了,事实上声音比较短的时候可能会想要上场。想想吉他,当你上指板时,弦线更短,并且谐振时间更短。由于这是一个个人研究项目,我想我会选择一个不完全完美的解决方案。不管怎么说,还是要谢谢你。 – Everts

+0

@Everts如果你不在乎它有多完美,你可以试试刚刚编辑的代码。它不是来自我,而是我把它从哪里来的链接。我认为这是你可能正在寻找的等式。 – Programmer

+0

好的编辑实际上已经足够接近了。我正在和一些在线钢琴进行比较,它很好。为此非常感谢。 – Everts