Unity 声音与录音与麦克风实时播放
Unity AudioSource与MicroPhone以及AudioClip之间的关系。
下面是一个声音,长度为7秒钟,声音的实际数据本质是由采样点组成的的列表,一秒钟内的采样点数就是采样频率,下面的采样频率是10,正常实际中是44100,根据需求设置;AudioSource播放声音时,设置其TimeSamples的意思就是从声音的第timeSamples个采样点位置开始播放,因此设置声音的播放的偏移位置的方式是设置timeSamples或者设置time。播放时timeSamples并不是一直固定的,跟随时间逐个指向每个对应的采样点的索引值。
接下来是设置麦克风的,麦克风的原理就是首先定义一个Clip,开始录音之后,就不断的将录音采样点值赋予clip的相对应的采样点,这点和Audiosource的timeSamples相同,区别是两者的操作相反,当前采样点的位置可以用MicroPhone的GetPosition()获得。因此如果想要像KTV那样实时的播放录音,就是让audiosource播放的时候,timeSamples的值刚好等于当前采样点的值,或者延迟不大的一段采样点距离(好吧,我这么干了,可是不知道为什么噪音很严重,有待研究,并且timeSamples的值不能大于当前录音采样点的值,不然没有声音(傻瓜都能想到为什么))。好吧,今日附贴,与公司大佬讨论了一下之后终于明白了,原来噪音出现的原因是我播出来的声音又实时的被录进去了,从而出现类似回音的效果,所以最好戴上耳机录音。
下面是实时播放的代码。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class MicroPhoneTest : MonoBehaviour { public AudioSource aud; bool isHaveMicroPhone; string device; public Text text; //Debug Text public Text clipLength;//记录音频文件的长度 public Text devicePosition;//设备音频的位置 public Text audioTime;//记录音频的时间 public Text audioSampleTime;// // Start is called before the first frame update void Start() { aud = GetComponent<AudioSource>(); string[] devices = Microphone.devices; if (devices.Length > 0) { isHaveMicroPhone = true; device = devices[0]; text.text = devices[0]; } else { isHaveMicroPhone = false; text.text = "没有获取到麦克风"; } } //开始录音按钮 public void OnclickButton() { if (!isHaveMicroPhone) return; aud.clip = Microphone.Start(device, true, 10, 10000); //aud.Play(); //aud.timeSamples = Microphone.GetPosition(device); //aud.timeSamples = 0; Debug.Log("开始录音"); } //开始播放按钮 public void OnPlay() { aud.Play(); aud.timeSamples = Microphone.GetPosition(device);//这里设置了之后就会近乎实时同步 int min; int max; Microphone.GetDeviceCaps(device, out min,out max); //aud.timeSamples = 0; Debug.Log("开始播放"+min+" "+max); } private void Update() { //clipLength.text = " clipLength:" + aud.clip.length; //devicePosition.text = " devicePosition:" + Microphone.GetPosition(device); //audioTime.text = " audioTime:" + aud.time; //audioSampleTime.text = "audioSampleTime:" + aud.timeSamples; //Debug.Log(" clipLength:" + aud.clip.length); //Debug.Log(" devicePosition:" + Microphone.GetPosition(device)); //Debug.Log(" audioTime:" + aud.time); //Debug.Log("audioSampleTime:" + aud.timeSamples); //aud.timeSamples = Microphone.GetPosition(device); } }
注意,实时录音播放后,可能会出现播放的采样点与录音的采样点的值越来越大的问题,因此可能需要在update函数中每隔一段时间进行处理。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用