unity3D实现录音功能,并将真实录音时长保存至本地(不能用可私信,附可执行文件下载地址)

  1. 项目实现功能:在unity3D中通过Microphone的API实现录音功能,并将真正时长的录音文件以”.wav“格式保存到本地。

  2. 环境:Win10     unity版本:2018.2.15f1             VS版本:2017

  3. 界面展示

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

  5. 根据.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;//麦克风是否连接
    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 = "缺少麦克风设备!";
    19. }
    20. else
    21. {
    22. Infotxt.text = "设备名称为:"+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 = "正在录音中,请勿重复点击Start!";
    46. }
    47. }
    48. else
    49. {
    50. Infotxt.text = "请确认麦克风设备是否已连接!";
    51. }
    52. }
    53. /// <summary>
    54. /// 停止录音
    55. /// </summary>
    56. public void Stop()
    57. {
    58. data = GetRealAudio(ref RecordedClip);
    59. Microphone.End(null);
    60. Infotxt.text = "录音结束!";
    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. /// 创建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. 可执行文件(有个bug目前还没修改,不过不影响使用):

bug:当没有录音的时候,点击save也会出现保存文件的地址,可以在Save()方法中判断一下if(recordedclip!=null)

可执行文件下载地址:https://download.csdn.net/download/qq_40878840/12942233

(0)

相关推荐