目标:接收外部声音并做出即时反馈
例子:玩家通过敲击现实中的鼓来控制游戏中的鼓的敲击
以上述例子为目标,可以将程序逻辑分为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数据来判断是哪种类型的敲击。
比如高频段的能量更强(值更大),则视为一次高音区的敲击。
暂无关于此日志的评论。