首页 > 编程语言 > 详细

WAV格式文件合并&帧头数据体解析(python)(原创)

时间:2019-05-16 23:43:05      阅读:346      评论:0      收藏:0      [点我收藏+]

一,百度百科

 

  WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几! WAV打开工具是WINDOWS的媒体播放器

 

  通常使用三个参数来表示声音,量化位数,取样频率和采样点振幅。量化位数分为8位,16位,24位三种,声道有单声道和立体声之分,单声道振幅数据为n*1矩阵点,立体声为n*2矩阵点,取样频率一般有11025Hz(11kHz) ,22050Hz(22kHz)和44100Hz(44kHz) 三种,不过尽管音质出色,但在压缩后的文件体积过大!相对其他音频格式而言是一个缺点,其文件大小的计算方式为:WAV格式文件所占容量(B) = (取样频率 X量化位数X 声道) X 时间 / 8 (字节= 8bit) 每一分钟WAV格式的音频文件的大小为10MB,其大小不随音量大小及清晰度的变化而变化。

 

  WAV是最接近无损的音乐格式,所以文件大小相对也比较大。
 
二,文件帧头
 

 

技术分享图片

图1 WAV文件帧头data[0:44]数据格式

技术分享图片

图2.WAV文件帧头图解

 

读取WAV文件程序:

 1 import struct
 2 
 3 with open(测试音频源1.wav, rb) as file:
 4     data=file.read()
 5     # print(len(data))
 6     # print(data[44:])
 7     # print(data[0:4])            # chunkID:          b‘RIFF‘
 8     # length0=struct.unpack(‘<L‘, bytes(data[4:8]))
 9     # print(length0)              # (140836,)
10     # print(data[4:8])            # chunkSize:        b‘$&\x02\x00‘   WAV文件总byte数
11     # print(data[8:12])           # format:           b‘WAVE‘
12     # print(data[12:16])          # Subchunk1 ID:     b‘fmt ‘
13     # length1=struct.unpack(‘<L‘, bytes(data[16:20]))
14     # print(length1)              # (16,)
15     # print(data[16:20])    # format Code:      b‘\x10\x00\x00\x00‘
16     #
17     # print(data[20:22])          # Subchunk1 Size:   b‘\x01\x00‘
18     # print(data[22:24])    # nChannels:        b‘\x01\x00‘
19     #
20     # print(data[24:28])          # nSamplesPerSec:   b‘\x80>\x00\x00‘
21     # print(data[28:32])    # nAvgBytesPerSec:  b‘\x00}\x00\x00‘
22     #
23     # print(data[32:34])          # nBlockAlign:      b‘\x02\x00‘
24     # print(data[34:36])    # wBitsPerSample:   b‘\x10\x00‘
25     #
26     # print(data[36:40])          # Subchunk2 ID:     b‘data‘
27     # length2=struct.unpack(‘<L‘, bytes(data[40:44]))    # (140800,)
28     # print(length2)
29     # print(data[40:44])    # Subchunk2 Size:   b‘\x00&\x02\x00‘

通过将data值输出,可知其是一个byte文件

 

帧头数据为data[0:44],例如:

其中又划分出3大子块,每个子块又分为若干功能块。有标志位、数据长度、通道数、采样率等等相关参数。

1 bRIFF\xac\xdc9\x00WAVEfmt\x10\x00\x00\x00\x01\x00\x01\x00\x80>\x00\x00\x00}\x00\x00\x02\x00\x10\x00data\x80\xdc9\x00

数据帧为data[44:],剩余的数据即为音频采样数据。

 

 三,WAV文件无损合并

我这种方法只针对通道数、采样率等等(除了文件数据帧长度不同)都相同的多个WAV文件合并,当然如果想要将不同格式的WAV合并也可以先转换成相同格式的文件之后再做操作。

 1 import struct   # 用于将chunkSize和Subchunk2 Size进行【long int】(byte型)和 int的转换
 2 
 3 # *** 读取WAV音频1 *** #
 4 with open(测试音频源1.wav, rb) as file:
 5     data1=file.read()
 6 
 7 # *** 读取WAV音频2 *** #
 8 with open(测试音频源2.wav, rb) as file:
 9     data2=file.read()
10 
11 data_info = data1[:44]  # 复制帧头参考
12 data_out = data1[44:] + data2[44:]  # 将两个音频的数据帧合并(都是相同格式)
13 data_info = data_info[:4] + struct.pack(<L, len(data_out)+44) + data_info[8:]# 更新WAV文件的总byte数(两个文件数据帧和+44)
14 data_info = data_info[:40] + struct.pack(<L, len(data_out)) + data_info[44:]# 更新WAV文件的数据byte数(两个文件数据帧和)
15 
16 # *** 生成合并后的WAV文件 *** #
17 with open(测试音频源3.wav, wb) as f:
18     f.write(data_info+data_out)
19 
20 print(完成)

 

四,常见问题

  我之前遇到的问题,直接将两个文件的byte值相加写入新文件,帧头没有更改;这样写的结果就是数据的大小满足两个源文件的和,但是使用播放器播放的时候音频无法正常全部播放

  尤其是我使用阿里云-语音合成api合成的WAV格式音频,它们的格式有一定的问题,每个生成的chunkSize和Subchunk2 Size数值都比实际音频数据长度要大一些,导致我直接将多个音频合并的时候,音频长度超过一定长度,后面的语音就无法播放,但是较少的几段音频合并又可以正常播放,这个地方我一直都没有弄明白,同时我又不想使用第三方的库(主要是觉得要先将音频存起来-之后又读取很麻烦),所以才细心的参看WAV格式文件的相关资料,通过对多个音频的比对发现了这个问题的由来。

  备注:如果想要直接使用byte文件进行WAV文件合并一定要在合并后更新相关的数据,与此同时也要注意文件的通道数、采样频率等格式是否相同,一定要转换到相同格式合并才有效

 

WAV格式文件合并&帧头数据体解析(python)(原创)

原文:https://www.cnblogs.com/Mufasa/p/10878777.html

(0)
(1)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!