目标:接收外部声音并做出即时反馈
例子:玩家通过敲击现实中的鼓来控制游戏中的鼓的敲击
以上述例子为目标,可以将程序逻辑分为3步
- 接收外部声音并分析
- 根据分析结果判断玩家是否进行了一次敲击
- 判断玩家此次的敲击类型(敲击高音区/低音区)
1、接收外部声音并分析
Unity无法直接对外部的声音输入进行分析,只能分析AudioSource当前正在播放的音频。
因此需要对外部音频输入进行录制,并实时通过AudioSource播放并分析录制的音频(可以通过AudioMixer静音来避免玩家听到播放的录音)。
protected IEnumerator DoRecordAndPlay()
{
// 将录音存入AudioSource中
audioSource.clip = Microphone.Start(deviceName, true, 999, 8000);
// 等待麦克风开始录制之后再播放录制的音频
yield return new WaitUntil(() => (Microphone.GetPosition(deviceName) - 1) >= 0);
audioSource.Play();
// 让AudioSource较录制的音频有一点延迟(为了等待录音完成)
audioSource.timeSamples = Microphone.GetPosition(deviceName) - 1;
} 2、判断玩家是否进行了一次敲击
判断逻辑:若当前“总音量”大于上一次的“总音量”,则视为发生了敲击。
float[] spectrumDatas = new float[4096]; // 声音的采样数
bool IsNewHit()
{
// 获得AudioSource播放音频的当前频谱数据
audioSource.GetSpectrumData(spectrumDatas, 0, FFTWindow.Rectangular);
// 记录各频段的“音量和”
CurrTotalVolume = 0;
for (int i = 0; i < spectrumDatas.Length; i++){
CurrTotalVolume += spectrumDatas[i];
}
// 当前“音量和”大于上一次的“音量和”则视为一次敲击
if (CurrTotalVolume > LastTotalVolume)
{
LastTotalVolume = CurrTotalVolume; // 记录本次敲击的“总音量”
return true;
}
else
{
LastTotalVolume = CurrTotalVolume;
return false;
}
}3、判断敲击的类型
可通过IsNewHit()中收集的spectrumDatas数据来判断是哪种类型的敲击。
比如高频段的能量更强(值更大),则视为一次高音区的敲击。


暂无关于此日志的评论。