greyhh

记录学习中的点点滴滴
posts - 37, comments - 1, trackbacks - 0, articles - 0

导航

Unity中使用Microphone录音保存以及回放

Posted on 2017-05-24 13:09  greyhh  阅读(...)  评论(...编辑  收藏

录音类

MicrophoneManager包含开始录音,停止录音,播放录音以及录音的保存等。

public partial class MicrophoneManager : MonoBehaviour
{   
    private static MicrophoneManager m_instance;

    private static string[] micArray = null; //录音设备列表
    private AudioClip audioClip;
    private DateTime beginTime;

    public float sensitivity=100;  
    public float loudness=0; 
    
    const int HEADER_SIZE = 44;  
    const int RECORD_TIME = 10;  
    const int RECORD_RATE = 44100; //录音采样率

    //void Awake()
    //{
    //    m_instance = this;
    //}
    public static MicrophoneManager GetInstance()  
    {  
        if (m_instance == null)   
        {  
            micArray = Microphone.devices;  
            if (micArray.Length == 0)  
            {
                Debug.LogError("no mic device");
            }  
            foreach (string deviceStr in Microphone.devices)  
            {  
                Debug.Log("device name = " + deviceStr);  
            }  
            GameObject micManager=new GameObject("MicManager");  
            m_instance= micManager.AddComponent<MicrophoneManager>();  
        }  
        return m_instance;  
    }  
   
    /// <summary>
    /// 开始录音
    /// </summary>
    public void StartRecord()  
    {  
        if (micArray.Length == 0)  
        {  
            Debug.Log("No Record Device!");  
            return;  
        }
        Microphone.End(null);//录音时先停掉录音,录音参数为null时采用默认的录音驱动
        beginTime = DateTime.Now;
        audioClip = Microphone.Start(null, false, RECORD_TIME, RECORD_RATE);
        while (!(Microphone.GetPosition(null)>0)) {  
        }
        Debug.Log("StartRecord");
    }  
  
    /// <summary>
    /// 停止录音
    /// </summary>
    public void StopRecord()  
    {  
        if (micArray.Length == 0)  
        {  
            Debug.Log("No Record Device!");  
            return;  
        }  
        if (!Microphone.IsRecording(null))  
        {  
            return;  
        }  
        Microphone.End (null);
        Debug.Log("StopRecord");  
    }

    /// <summary>
    ///播放录音 
    /// </summary>
    public void PlayRecord()
    {
        PlayRecord(audioClip);
    }
    public void PlayRecord(AudioClip clip)
    {
        PlayRecord(clip,Vector3.zero);
    }

    public void PlayRecord(AudioClip clip, Vector3 pos)
    {
        if (clip == null)
        {
            Debug.Log("audioClip is null");
            return;
        }
        AudioSource.PlayClipAtPoint(clip, pos);
        Debug.Log("PlayRecord");
    }


    public byte[] Save()
    {
        if (audioClip == null) return null;
        return WavUtility.FromAudioClip(audioClip);
    }

    public void Save(string path,string filename)
    {
        Save(audioClip,path,filename);
    }

    public void Save(AudioClip clip, string path, string filename)
    {
        if (clip == null)
        {
            Debug.Log("clip is null,can't be saved");
            return;
        }
        WavUtility.FromAudioClip(clip, path, filename, true);
    }

    public AudioClip Read(string path)
    {
       return WavUtility.ToAudioClip(path);
    }

    public AudioClip Read(byte[] data)
    {
       return WavUtility.ToAudioClip(data);
    }

    public JObject SaveAudioClip()
    {
        JObject jd = new JObject();
        jd["time"] = beginTime.ToString("yyMMdd-HHmmss-fff");
        //jd["time"] = beginTime.ToFileTime();
        //使用Unicode编码,其他编码格式会有问题
        jd["audioclip"] = Encoding.Unicode.GetString(Save());
        return jd;
    }
}

录音的保存

WavUtility是对录音数据的保存和读取,可以保存为本地文件.wav或者byte数组进行传输。这个东东是我从github上发现的,由于代码太长就不贴了,网址放上:https://github.com/deadlyfingers/UnityWav

重要的方法

/// - Use "ToAudioClip" method for loading wav file / bytes.
/// Loads .wav (PCM uncompressed) files at 8,16,24 and 32 bits and converts data to Unity's AudioClip.
/// - Use "FromAudioClip" method for saving wav file / bytes.
/// Converts an AudioClip's float data into wav byte array at 16 bit.

public static AudioClip ToAudioClip (string filePath)

public static AudioClip ToAudioClip (byte[] fileBytes, int offsetSamples = 0, string name = "wav")

public static byte[] FromAudioClip (AudioClip audioClip)

public static byte[] FromAudioClip (AudioClip audioClip,string filepath,string filename, bool saveAsFile = true)

录音的回放

为了方便回放,又不额外引入其他文件来记录回放时间与录音的对应信息,将录音时间作为文件名(ex:170515-114114-676),并在开始的时候录一个空录音作为起始时间,回放代码如下:

 IEnumerator PlayAudioClip()
    {
        string[] files = Directory.GetFiles(savePath);
        if (files.Length > 0)
        {
            List<string> temp = new List<string>();
            for (int i = 0; i < files.Length; i++)
            {
                if (!files[i].Contains(".meta"))
                    temp.Add(files[i]);
            }
            string[] audioFiles = temp.ToArray();
            Array.Sort(audioFiles);
            float interval = 0f;
            for (int i = 0; i < audioFiles.Length - 1; i++)
            {
                AudioClip clip = MicrophoneManager.GetInstance().Read(audioFiles[i]);
                MicrophoneManager.GetInstance().PlayRecord(clip);
                interval = (float)(GetTime(audioFiles[i + 1]) - GetTime(audioFiles[i])).TotalSeconds;
                Debug.Log(interval);
                yield return new WaitForSeconds(interval);
            }
            MicrophoneManager.GetInstance().PlayRecord
            (
               MicrophoneManager.GetInstance().Read(audioFiles[audioFiles.Length - 1])
            );
        }     
    }