最近公司用的VOX录音文件转换为wav文件的需求。经过一周的收集与研究,总结如下文档与大家分享。也请语音方面大神指点迷津。
前言
本文参考了网络其他大神的文章,语音转换方面资料还是蛮多的,但是绝大部分是C语言(毕竟这方面接近硬件方向)的同一套代码,不过在浏览了大量的文章后,也收获了对wave格式的一个整体理解和认识,最终用JAVA语音完成了录音的格式完美转换。
这里主要讨论了三个方面的问题:
a、文件格式之间如何转换(例如:ADPCM的vox转换为PCM的wav);
b、文件编码之间如何转换(主要涉及到wave格式的调整,存储数据位数的变化等)
c、各个文件的编码算法是什么(这个主要涉及具体如何进行编码实现)
研究主要工具及方法:
工具:
GoldWave:录音编辑工具,方便于录音文件属性查看、调整及编辑等
UltraEdit:强大的编辑器,便于16进制查看、编辑录音文件
UltraCompare:强大的文件比较器,用于二进制对比两个录音文件
Windows 计算器:用来16进制与10进制等其他进制转换。这里主要是分析录音文件使用。
方法:
刚开始对于录音转换完全没有概念,于是从要转换的录音格式VOX(ADPCM)与wav(PCM)入手,先了解两个文件的格式及编码方法等。最后阅读代码并对应相应的算法说明,慢慢的理解了音频文件的编码。在动手编写代码实现时,总是发现转码后的录音文件无法直接被GoldWave识别,总是有部分问题。譬如文件长度不一致,文件内部错误等等情况。最终通过使用UltraEdit、UltraCompare对比和编辑后,发现具体问题所在,经过修改后转换正常。
总结一下,大家可以使用待转换的录音,通过GoldWave工具进行录音格式转换为目标录音格式,最后再对比自己代码生成的文件与GoldWave转换的文件差别。网络上录音转换算法差不多都是正确的,主要是转换出来的录音是否可以自动被播放设备识别的事了。
此外,wave文件格式转换前,可以根据源文件长度、音频格式以及目标文件的音频格式进行理论推导的目标文件的文件长度的。该部分需要在理解wave文件格式以及文件数据组织方式情况下进行,具体可参考本文的wave具体格式等段落。举例如下(可以同后面的各个块的组织格式一起阅读,方便理解具体参数含义)
源文件格式:PCM、16bit、8000Hz、单通道、文件长度为205584字节
目标文件格式:IMA-ADPCM、4bit、8000Hz、单通道
推导:
源文件属性:
采样数据长度 = 205584 -44 //44: PCM格式head长度(字节)
采样数据个数 = (205584 -44) / (16/8) // (16/8) : 16bit 换算为字节数
= (205584 -44) / 2
= 102770
转换后的目标文件属性预测:
单纯采样数据长度 = (205584 -44) / 4 //4: 源文件的16bit[2字节],转换为目标4bit[1/2字节],即压缩比4:1
采样数据个数 = 102770 // 采样个数是不变的
Block块的大小= 256 // 我使用的是256字节一个块(包含4byte的blockHead + 252byte的Data)详解blockHead块组织方式。网络上说可以是其他的大小;
Block块包含采样个数 = Data*2 + 1 // Data*2:1Byte(字节)存储2个4bit(位)的采样个数;+ 1:blockHead包含一个未压缩的16bit的采样数据
=252*2 +1
=505
Block块个数 = 采样数据个数 / Block块包含采样个数 // 该方法应使用向上取整逻辑。即,最后不足505个采样的block块也要导出。
= 102770 / 505
= 203.5049504950495
= 204 // 向上取整,0.5049…的块数据也不能丢失
最后一个块的长度 = (采样数据个数 – 203 * 505 – 1) / 2 + 4 // 203 * 505:前面完整块的采样个数;-1:head中未压缩的采样个数;/ 2:1个采样存储于4bit(1/2字节);+ 4:blockHead的4byte
=(102770 -102515 -1)/2 +4
=254/2 + 4 // 主意,这里除以2同样需要向上取整的(不能丢失每一个采样数据)
=131
采样数据组织为Block块后的长度 = 203 * Block块的大小 + 最后一个块的长度
= 203 * 256 + 131
= 52099
文件长度(字节)= 采样数据组织为Block块后的长度 + 60 // 60 :IMA-ADPCM文件head长度(字节)
= 52099 + 60 // 2: 采样数据大小转换为字节单位,即 4bit 等于 1/2的字节
= 52159
以上推导,是在完全了解wave的PCM、IMA-ADPCM格式的具体格式下进行的。有助于我们排查文件不能正常识别的具体原因。
工具使用举例如下,
在我转换完成的文件GoldWave总报”内部数据大小不正确。该文件可能已损坏”,“文件长度不一致”,“无法确认文件格式”等错误。
我点击是,并强行用ClodWave打开后,再使用“文件”》》“将选择保存为”, 然后现在我需要转换的目标格式(PCM 16bit 单声道)。这样就有了一个与代码生成的文件的可参考的正确的格式文件。
通过使用UltraEdit、UltraCompare将两个文件对比,主要对比两个文件的表头信息和文件DATA部分的长度信息。具体如下(以下截图是用来做步骤说明的,非同一个案例截图,)
UltraEdit示例图如下:
可以很好的定位到具体的16进制对应的ACSII码的具体符合。途中是找到了wave文件表头中data块的data字符串
UltraCompare示例图如下,
左边的是经过GoldWave修改的正确的文件,右边是我自己代码生成的文件。
注意:GoldWave修改后的文件我的fact块跑到文件末尾了。需要使用UltraEdit进行文件编辑调整位置,以方便对比数据。
Wave格式说明
首先我们要了解wave的格式,才好进一步将格式转换。
这块网上资料较详细,我根据自己理解整理使用的地方如下,也请指正:
Wave整体式说明
Wave PCM编码的文件头信息及解释:
wave具体格式总结:
以上灰色底纹部分仅在压缩格式下才会存在。
BlockHead块组织格式:
压缩格式(这里参考IMA-ADPCM)下单Block块的格式如下:
DATA数据存储方式说明
采样的字节存储方式说明:
8 Bit 单声道:
采样1 |
采样2 |