Unity 录音压缩保存读取方法

发表于2017-08-24
评论2 3.9k浏览
  想要为玩家开发语音功能,就必须要掌握录音压缩保存读取的方法,可能有些开发者还不会,下面就给大家介绍下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数据。同样的找出一个平均值来代表当前的音量。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论