• Unity Microphone 无限时长录制


    原创文章:转载请标明出处--博客园 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,2,16000);
            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 * 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);
            }
            micDataList.AddRange(micDataTemp);
            Microphone.End(micName);
            AudioClip newAudioClip = AudioClip.Create("RecordClip", micDataList.Count, 1, 16000, false);
            newAudioClip.SetData(micDataList.ToArray(), 0);
            audioRecordFinishedEvent(newAudioClip);
            Debug.Log("RecordEnd");
        }
    
    
    
        public void StopMicrophone()
        {
            Debug.Log("Stop mic");
            isMicRecordFinished = true;
        }
    
        void PlayAudioRecord(AudioClip newAudioClip)
        {
            audioSource.clip = newAudioClip;
            audioSource.Play();
        }
    }

    如果这篇文章对您有所帮助,打赏一下作者吧,码字也挺辛苦的

                                   

  • 相关阅读:
    各种插件
    如何在C#中选择正确的集合 转
    转载 hashtable和dictionary的区别
    堆和栈的区别 转载
    数据结构王道错题集2019版(上>一>四章)
    mongoDB连接数据库
    linuix没有网络
    rand函数
    mongodb学习(入门。。。。。)
    先随便写
  • 原文地址:https://www.cnblogs.com/Jason-c/p/10216075.html
Copyright © 2020-2023  润新知