AudioClip 的频率和音调关系 - Unity3D
Frequency and pitch relation for AudioClip - Unity3D
我正在尝试仅使用 6 个音频剪辑来重现吉他的全部音域。
我想有一种方法可以设置音频剪辑的频率,但 audio.frequency 只能 returns 基于压缩格式而不是实际音调的音频频率。
我知道我可以读取 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 ();
}
}
只需更改音频的音高,您尝试做的不会很好地工作。通过改变音调,你会运行陷入其他问题,例如声音结束太快或花费更多时间结束,声音也不会好。
第一个解决方案是在C++中制作一个插件(Synthesizer)读取来自 Unity 的音频文件并更改频率。它还应该执行其他操作来解决速度问题。这非常复杂,除非您是具有出色数学技能的音频工程师。在移动设备上尝试这个是完全不同的故事。 OnAudioFilterRead 是您决定使用此方法时应该使用的功能。
第二个和推荐的解决方案是为每个吉他键制作一个音频文件 然后将它们放入 audioClip
的数组中。这解决了 每个 其他 problems.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();
}
编辑:对于那些对 Mathf.Pow 方程为何被使用和起作用感兴趣的人,请阅读以下内容:https://en.wikipedia.org/wiki/Twelfth_root_of_two
我正在尝试仅使用 6 个音频剪辑来重现吉他的全部音域。
我想有一种方法可以设置音频剪辑的频率,但 audio.frequency 只能 returns 基于压缩格式而不是实际音调的音频频率。
我知道我可以读取 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 ();
}
}
只需更改音频的音高,您尝试做的不会很好地工作。通过改变音调,你会运行陷入其他问题,例如声音结束太快或花费更多时间结束,声音也不会好。
第一个解决方案是在C++中制作一个插件(Synthesizer)读取来自 Unity 的音频文件并更改频率。它还应该执行其他操作来解决速度问题。这非常复杂,除非您是具有出色数学技能的音频工程师。在移动设备上尝试这个是完全不同的故事。 OnAudioFilterRead 是您决定使用此方法时应该使用的功能。
第二个和推荐的解决方案是为每个吉他键制作一个音频文件 然后将它们放入 audioClip
的数组中。这解决了 每个 其他 problems.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();
}
编辑:对于那些对 Mathf.Pow 方程为何被使用和起作用感兴趣的人,请阅读以下内容:https://en.wikipedia.org/wiki/Twelfth_root_of_two