Unity 录音压缩保存读取方法
发表于2017-08-24
想要为玩家开发语音功能,就必须要掌握录音压缩保存读取的方法,可能有些开发者还不会,下面就给大家介绍下Unity中录音压缩保存读取,一起来看看吧。
unity 录音功能主要通过,Microphone这个类来完成。使用这个类自然可以跨平台,不用调用平台本地代码处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private static AudioClip clip; private static int maxRecordTime = 10; private static int samplingRate = 12000; public static bool TryStartRecording() { try { Microphone.End( null ); clip = Microphone.Start( null , false , maxRecordTime, samplingRate); } catch (Exception e) { return false ; } return true ; } |
Start开始录音,name默认不写就是寻找默认设备。samplingRate是采样率长度,越长音质越好,录音文件越大。Start之前调用End是为了结束可能正在进行的录音。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void EndRecording( out int length, out AudioClip outClip) { int lastPos = Microphone.GetPosition( null ); if (Microphone.IsRecording( null )) { length = lastPos / samplingRate; } else { length = maxRecordTime; } Microphone.End( null ); if (length < 1.0f) { outClip = null ; return ; } outClip = clip; } |
结束的时候,计算音频数据的长度,返回长度和clip对象,做进一步处理。拿到,clip文件就可以利用AudioSource播放了。如果,我们需要保存和读取这个音频文件我们就需要使用clip的SetData和GetData文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public static byte [] GetData( this AudioClip clip) { var data = new float [clip.samples * clip.channels]; clip.GetData(data, 0); byte [] bytes = new byte [data.Length * 4]; Buffer.BlockCopy(data, 0, bytes, 0, bytes.Length); return SVZip.ConvertBytesZlib(bytes, Ionic.Zlib.CompressionMode.Compress); } public static void SetData( this AudioClip clip, byte [] bytes) { bytes = SVZip.ConvertBytesZlib(bytes, Ionic.Zlib.CompressionMode.Decompress); float [] data = new float [bytes.Length / 4]; Buffer.BlockCopy(bytes, 0, data, 0, data.Length); clip.SetData(data, 0); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static byte [] ConvertBytesZlib( byte [] data, CompressionMode compressionMode) { CompressionMode mode = compressionMode; if (mode != CompressionMode.Compress) { if (mode != CompressionMode.Decompress) { throw new NotImplementedException(); } return ZlibStream.UncompressBuffer(data); } return ZlibStream.CompressBuffer(data); } |
GetData会获得一个float数组,里面是采样音频数据。我们需要把它转换byte数据保存文件,利用BlockCopy内存拷贝,并且使用了Zlib压缩算法对最终的byte数据压缩。GetData的时候,先解压在逆向把byte数据转换为flaot数据,返回给clip,就拿到了可以播放的clip对象了。
使用SetData的clip需要我们调用AudioClip.Create方法创建出来,所以录音的时候,我们需要拿到原始clip的frequency和LengthSamples属性,传入给create方法。
当clip的数据可以转换成byte数据的时候,我们就可以使用读写文件的方法保存和读取了。另外,既然我们有了音频数据,我们可以做一些操作修改音调添加魔音处理等这样的功能。
还有一个功能需求,就是在录音的过程中。如何显示录的声音的大小,同时显示一个音量大小的动画呢。其,核心的思路是,音频数据是float的0-1范围内的数据。就是音量大小的比例。我们可以把0-1的范围,分为若干个区间,来表示音量的大小。那么,我们有两个方案,来录音的时候实时获取这个sample数据。
第一,就是使用协程,不断的检测Microphone.IsRecording是否在录音中,然后利用Microphone.GetPosition获得当前的进度,往前计算一段sample数据,找出一个平均值来代表这段时间的音量大小。
第二,就是使用clip的回调接口PCMReaderCallback,在录到数据的时候会回调这个函数,参数中可以拿到当前的一段的sample数据。同样的找出一个平均值来代表当前的音量。