日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

unity3D實現(xiàn)錄音功能,并將真實錄音時長保存至本地(不能用可私信,附可執(zhí)行文件下載地址)

 鴻蛟家平 2021-01-31
  1. 項目實現(xiàn)功能:在unity3D中通過Microphone的API實現(xiàn)錄音功能,并將真正時長的錄音文件以”.wav“格式保存到本地。

  2. 環(huán)境:Win10     unity版本:2018.2.15f1             VS版本:2017

  3. 界面展示

  4. 說明:要提前了解.wav文件的格式

  5. 根據(jù).wav文件格式,需要對錄音的聲音流進行重新編碼。

  6. 代碼


    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System;
    4. using System.IO;
    5. public class TestMicro : MonoBehaviour {
    6. private bool micConnected = false;//麥克風(fēng)是否連接
    7. private int minFreq, maxFreq;//最小和最大頻率
    8. public AudioClip RecordedClip;//錄音
    9. public AudioSource audioSource;//播放的音頻
    10. public Text Infotxt;//提示信息
    11. public Text Adress;//音頻保存地址
    12. private string fileName;//保存的文件名
    13. private byte[] data;
    14. private void Start()
    15. {
    16. if (Microphone.devices.Length <= 0)
    17. {
    18. Infotxt.text = "缺少麥克風(fēng)設(shè)備!";
    19. }
    20. else
    21. {
    22. Infotxt.text = "設(shè)備名稱為:"+Microphone.devices[0].ToString()+"請點擊Start開始錄音!";
    23. micConnected = true;
    24. Microphone.GetDeviceCaps(null, out minFreq, out maxFreq);
    25. if (minFreq == 0 && maxFreq == 0)
    26. {
    27. maxFreq = 44100;
    28. }
    29. }
    30. }
    31. /// <summary>
    32. /// 開始錄音
    33. /// </summary>
    34. public void Begin()
    35. {
    36. if (micConnected)
    37. {
    38. if (!Microphone.IsRecording(null))
    39. {
    40. RecordedClip = Microphone.Start(null, false, 60, maxFreq);
    41. Infotxt.text = "開始錄音!";
    42. }
    43. else
    44. {
    45. Infotxt.text = "正在錄音中,請勿重復(fù)點擊Start!";
    46. }
    47. }
    48. else
    49. {
    50. Infotxt.text = "請確認(rèn)麥克風(fēng)設(shè)備是否已連接!";
    51. }
    52. }
    53. /// <summary>
    54. /// 停止錄音
    55. /// </summary>
    56. public void Stop()
    57. {
    58. data = GetRealAudio(ref RecordedClip);
    59. Microphone.End(null);
    60. Infotxt.text = "錄音結(jié)束!";
    61. }
    62. /// <summary>
    63. /// 播放錄音
    64. /// </summary>
    65. public void Player()
    66. {
    67. if (!Microphone.IsRecording(null))
    68. {
    69. audioSource.clip = RecordedClip;
    70. audioSource.Play();
    71. Infotxt.text = "正在播放錄音!";
    72. }
    73. else
    74. {
    75. Infotxt.text = "正在錄音中,請先停止錄音!";
    76. }
    77. }
    78. /// <summary>
    79. /// 保存錄音
    80. /// </summary>
    81. public void Save()
    82. {
    83. if (!Microphone.IsRecording(null))
    84. {
    85. fileName = DateTime.Now.ToString("yyyyMMddHHmmssffff");
    86. if (!fileName.ToLower().EndsWith(".wav"))
    87. {//如果不是“.wav”格式的,加上后綴
    88. fileName += ".wav";
    89. }
    90. string path= Path.Combine(Application.persistentDataPath, fileName);//錄音保存路徑
    91. print(path);//輸出路徑
    92. Adress.text = path;
    93. using (FileStream fs = CreateEmpty(path))
    94. {
    95. fs.Write(data, 0, data.Length);
    96. WriteHeader(fs, RecordedClip); //wav文件頭
    97. }
    98. }
    99. else
    100. {
    101. Infotxt.text = "正在錄音中,請先停止錄音!";
    102. }
    103. }
    104. /// <summary>
    105. /// 獲取真正大小的錄音
    106. /// </summary>
    107. /// <param name="recordedClip"></param>
    108. /// <returns></returns>
    109. public static byte[] GetRealAudio(ref AudioClip recordedClip)
    110. {
    111. int position = Microphone.GetPosition(null);
    112. if (position <= 0 || position > recordedClip.samples)
    113. {
    114. position = recordedClip.samples;
    115. }
    116. float[] soundata = new float[position * recordedClip.channels];
    117. recordedClip.GetData(soundata, 0);
    118. recordedClip = AudioClip.Create(recordedClip.name, position,
    119. recordedClip.channels, recordedClip.frequency, false);
    120. recordedClip.SetData(soundata, 0);
    121. int rescaleFactor = 32767;
    122. byte[] outData = new byte[soundata.Length * 2];
    123. for (int i = 0; i < soundata.Length; i++)
    124. {
    125. short temshort = (short)(soundata[i] * rescaleFactor);
    126. byte[] temdata = BitConverter.GetBytes(temshort);
    127. outData[i * 2] = temdata[0];
    128. outData[i * 2 + 1] = temdata[1];
    129. }
    130. Debug.Log("position=" + position + " outData.leng=" + outData.Length);
    131. return outData;
    132. }
    133. /// <summary>
    134. /// 寫文件頭
    135. /// </summary>
    136. /// <param name="stream"></param>
    137. /// <param name="clip"></param>
    138. public static void WriteHeader(FileStream stream, AudioClip clip)
    139. {
    140. int hz = clip.frequency;
    141. int channels = clip.channels;
    142. int samples = clip.samples;
    143. stream.Seek(0, SeekOrigin.Begin);
    144. Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF");
    145. stream.Write(riff, 0, 4);
    146. Byte[] chunkSize = BitConverter.GetBytes(stream.Length - 8);
    147. stream.Write(chunkSize, 0, 4);
    148. Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE");
    149. stream.Write(wave, 0, 4);
    150. Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt ");
    151. stream.Write(fmt, 0, 4);
    152. Byte[] subChunk1 = BitConverter.GetBytes(16);
    153. stream.Write(subChunk1, 0, 4);
    154. UInt16 one = 1;
    155. Byte[] audioFormat = BitConverter.GetBytes(one);
    156. stream.Write(audioFormat, 0, 2);
    157. Byte[] numChannels = BitConverter.GetBytes(channels);
    158. stream.Write(numChannels, 0, 2);
    159. Byte[] sampleRate = BitConverter.GetBytes(hz);
    160. stream.Write(sampleRate, 0, 4);
    161. Byte[] byteRate = BitConverter.GetBytes(hz * channels * 2);
    162. stream.Write(byteRate, 0, 4);
    163. UInt16 blockAlign = (ushort)(channels * 2);
    164. stream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
    165. UInt16 bps = 16;
    166. Byte[] bitsPerSample = BitConverter.GetBytes(bps);
    167. stream.Write(bitsPerSample, 0, 2);
    168. Byte[] datastring = System.Text.Encoding.UTF8.GetBytes("data");
    169. stream.Write(datastring, 0, 4);
    170. Byte[] subChunk2 = BitConverter.GetBytes(samples * channels * 2);
    171. stream.Write(subChunk2, 0, 4);
    172. }
    173. /// <summary>
    174. /// 創(chuàng)建wav格式文件頭
    175. /// </summary>
    176. /// <param name="filepath"></param>
    177. /// <returns></returns>
    178. private FileStream CreateEmpty(string filepath)
    179. {
    180. FileStream fileStream = new FileStream(filepath, FileMode.Create);
    181. byte emptyByte = new byte();
    182. for (int i = 0; i < 44; i++) //為wav文件頭留出空間
    183. {
    184. fileStream.WriteByte(emptyByte);
    185. }
    186. return fileStream;
    187. }
    188. }
  7. 可執(zhí)行文件(有個bug目前還沒修改,不過不影響使用):

bug:當(dāng)沒有錄音的時候,點擊save也會出現(xiàn)保存文件的地址,可以在Save()方法中判斷一下if(recordedclip!=null)

可執(zhí)行文件下載地址:https://download.csdn.net/download/qq_40878840/12942233

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多