AudioClip的频率和音高关系-Unity3D [英] Frequency and pitch relation for 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. 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:
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 EDIT: If you don't care about it being perfect, you can use something below from this nice guy on the internet. 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屋!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 ();
}
}
[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 ();
}
}
audioClip
. This solves every other problems.The down side is that you will have more files.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();
}