原创文章:转载请标明出处--博客园 Jason_c
Unity可以很方便的通过 Microphone.Start()方法来调用麦克风,但是有一个弊端是,必须传入时长,这就很尴尬了,因为大多数时间,我们是不知道用户需要何时关闭麦克风的,
这里提供一个解决思路:
1、将microphone设置为循环录制,即:
Microphone.Start(micName, true,2,16000);
2、每隔一定间隔读取录制好的数据,并将它缓存起来。
这里值得一提的是,如果每隔2秒保存一下音频数据(因为我设置的录制时间是2秒),
因为代码运行也需要时间,会导致音频数据损坏,声音会出现明显的断层现象,所以这里将它分段保存就能解决这种问题,
当麦克风录制的位置大于音频的一半的时候,保存上一段音频,当麦克风录制完时,保存后一段音频。
bool isSaveFirstHalf = true;//将音频从中间分生两段,然后分段保存
int micPosition;
while (!isMicRecordFinished)
{
if (isSaveFirstHalf)
{
yield return new WaitUntil(() => { micPosition = Microphone.GetPosition(micName);return micPosition > length * 6 / 10 && micPosition < length; });//保存前半段
micDataTemp = new float[length / 2];
micClip.GetData(micDataTemp, 0);
micDataList.AddRange(micDataTemp);
isSaveFirstHalf = !isSaveFirstHalf;
}
else
{
yield return new WaitUntil(() => { micPosition = Microphone.GetPosition(micName); return micPosition > length / 10 && micPosition < length / 2; });//保存后半段
micDataTemp = new float[length/2];
micClip.GetData(micDataTemp, length / 2);
micDataList.AddRange(micDataTemp);
isSaveFirstHalf = !isSaveFirstHalf;
} }
最后处理一下结束时的音频
micPosition = Microphone.GetPosition(micName);
if (micPosition <= length)//前半段
{
micDataTemp = new float[micPosition/2];
micClip.GetData(micDataTemp, 0);
}
else
{
micDataTemp = new float[micPosition - length/2];
micClip.GetData(micDataTemp, length/2);
}
3、最后通过保存的数据生成新的音频,即:
AudioClip.Create("RecordClip", micDataList.Count, 1, 16000, false); newAudioClip.SetData(micDataList.ToArray(), 0);
完整代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class MicUnlimitedDuration : MonoBehaviour {
public delegate void AudioRecordHandle(AudioClip audioClip);
public AudioSource audioSource; AudioClip micClip; bool isMicRecordFinished= true; List<float> micDataList = new List<float>();
float[] micDataTemp; string micName; public void StartMicrophone() {
StopCoroutine(StartMicrophone(null, PlayAudioRecord));
StartCoroutine(StartMicrophone(null, PlayAudioRecord));
} IEnumerator StartMicrophone(string microphoneName,AudioRecordHandle audioRecordFinishedEvent) {
Debug.Log("Start Mic");
micDataList = new List<float>();
micName = microphoneName;
micClip = Microphone.Start(micName, true,,);
isMicRecordFinished = false;
int length = micClip.channels * micClip.samples;
bool isSaveFirstHalf = true;//将音频从中间分生两段,然后分段保存
int micPosition;
while (!isMicRecordFinished)
{
if (isSaveFirstHalf)
{
yield return new WaitUntil(() => { micPosition = Microphone.GetPosition(micName);return micPosition > length * / && micPosition < length; });//保存前半段
micDataTemp = new float[length / ];
micClip.GetData(micDataTemp, );
micDataList.AddRange(micDataTemp);
isSaveFirstHalf = !isSaveFirstHalf;
}
else
{
yield return new WaitUntil(() => { micPosition = Microphone.GetPosition(micName); return micPosition > length / && micPosition < length / ; });//保存后半段
micDataTemp = new float[length/];
micClip.GetData(micDataTemp, length / );
micDataList.AddRange(micDataTemp);
isSaveFirstHalf = !isSaveFirstHalf;
} }
micPosition = Microphone.GetPosition(micName);
if (micPosition <= length)//前半段
{
micDataTemp = new float[micPosition/];
micClip.GetData(micDataTemp, );
}
else
{
micDataTemp = new float[micPosition - length/];
micClip.GetData(micDataTemp, length/);
}
micDataList.AddRange(micDataTemp);
Microphone.End(micName);
AudioClip newAudioClip = AudioClip.Create("RecordClip", micDataList.Count, , , false);
newAudioClip.SetData(micDataList.ToArray(), );
audioRecordFinishedEvent(newAudioClip);
Debug.Log("RecordEnd");
} public void StopMicrophone()
{
Debug.Log("Stop mic");
isMicRecordFinished = true;
} void PlayAudioRecord(AudioClip newAudioClip)
{
audioSource.clip = newAudioClip;
audioSource.Play();
}
}
如果这篇文章对您有所帮助,打赏一下作者吧,码字也挺辛苦的