一,百度百科

  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文件程序:

 import struct

 with open('测试音频源1.wav', 'rb') as file:
data=file.read()
# print(len(data))
# print(data[44:])
# print(data[0:4]) # chunkID: b'RIFF'
# length0=struct.unpack('<L', bytes(data[4:8]))
# print(length0) # (140836,)
# print(data[4:8]) # chunkSize: b'$&\x02\x00' WAV文件总byte数
# print(data[8:12]) # format: b'WAVE'
# print(data[12:16]) # Subchunk1 ID: b'fmt '
# length1=struct.unpack('<L', bytes(data[16:20]))
# print(length1) # (16,)
# print(data[16:20]) # format Code: b'\x10\x00\x00\x00'
#
# print(data[20:22]) # Subchunk1 Size: b'\x01\x00'
# print(data[22:24]) # nChannels: b'\x01\x00'
#
# print(data[24:28]) # nSamplesPerSec: b'\x80>\x00\x00'
# print(data[28:32]) # nAvgBytesPerSec: b'\x00}\x00\x00'
#
# print(data[32:34]) # nBlockAlign: b'\x02\x00'
# print(data[34:36]) # wBitsPerSample: b'\x10\x00'
#
# print(data[36:40]) # Subchunk2 ID: b'data'
# length2=struct.unpack('<L', bytes(data[40:44])) # (140800,)
# print(length2)
# print(data[40:44]) # Subchunk2 Size: b'\x00&\x02\x00'

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

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

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

 b'RIFF\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合并也可以先转换成相同格式的文件之后再做操作。

 import struct   # 用于将chunkSize和Subchunk2 Size进行【long int】(byte型)和 int的转换

 # *** 读取WAV音频1 *** #
with open('测试音频源1.wav', 'rb') as file:
data1=file.read() # *** 读取WAV音频2 *** #
with open('测试音频源2.wav', 'rb') as file:
data2=file.read() data_info = data1[:44] # 复制帧头参考
data_out = data1[44:] + data2[44:] # 将两个音频的数据帧合并(都是相同格式)
data_info = data_info[:4] + struct.pack('<L', len(data_out)+44) + data_info[8:]# 更新WAV文件的总byte数(两个文件数据帧和+44)
data_info = data_info[:40] + struct.pack('<L', len(data_out)) + data_info[44:]# 更新WAV文件的数据byte数(两个文件数据帧和) # *** 生成合并后的WAV文件 *** #
with open('测试音频源3.wav', 'wb') as f:
f.write(data_info+data_out) print('完成')

四,常见问题

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

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

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

WAV格式文件无损合并&帧头数据体解析(python)(原创)的更多相关文章

  1. Android音频: 怎样使用AudioTrack播放一个WAV格式文件?

    翻译 By Long Luo 原文链接:Android Audio: Play a WAV file on an AudioTrack 译者注: 1. 因为这是技术文章,所以有些词句使用原文,表达更准 ...

  2. wav格式文件、pcm数据

    wav格式文件是常见的录音文件,是声音波形文件格式之一,wav 文件由文件头和数据体两部分组成. 文件头是我们在做录音保存到文件的时候,要存储的文件的说明信息,播放器要通过文件头的相关信息去读取数据播 ...

  3. 将PCM格式存储成WAV格式文件

    将PCM格式存储成WAV格式文件 WAV比PCM多44个字节(在文件头位置多) 摘自:https://blog.csdn.net/u012173922/article/details/78849076 ...

  4. 音频文件解析(一):WAV格式文件头部解析

    WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源. 文 ...

  5. [VB.NET][C#]WAV格式文件头部解析

    简介 WAV 为微软开发的一种声音文件格式,它符合 RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源. 第一节 文件头 ...

  6. linux下alsa架构音频驱动播放wav格式文件

    #include<stdio.h> #include<stdlib.h> #include <string.h> #include <alsa/asoundl ...

  7. 音频文件解析(二):WAV格式文件波形绘制

    解析WAV头部信息后,接下来就可以根据相关参数和DATA块数据绘制波形. 1.重新编码(转换为8bits,单声道数据) Public Function GetFormatData(ByVal pDat ...

  8. C语言解析WAV音频文件

    C语言解析WAV音频文件 代码地址: Github : https://github.com/CasterWx/c-wave-master 目录 前言 了解WAV音频文件 什么是二进制文件 WAV的二 ...

  9. 调用CImg库显示WAV格式音频波形

    最近在做傅里叶变换和小波变换时经常要通过显示波形来检验算法,但通过visual studio之类显示波形又显得麻烦,而且不能跨平台. CImg是一个跨平台的C++的图像处理库,提供的图像处理等功能十分 ...

随机推荐

  1. 性能测试 | Linux线程数、进程查询

    I. 最大值查询 1. 最大进程数查询 1 cat /proc/sys/kernel/pid_max 个人阿里云机器(单核2g)上输出如下 1 32768 2. 最大线程数查询 1 cat /proc ...

  2. Linux shell利用sed如何批量更改文件名详解[转载]

     需求背景: 目录A用来存放自动化的包生成的apk文件,现在开发修改了包名的 命名规则:环境名称(pro|uat)-release-日期-v版本号.apk 原来的是思路是通过正则表达式匹配新的包名,但 ...

  3. List去重为什么要写equals(),hashCode()方法

    一,各个集合的特点: Collection(集合):容器,用于存放对象(引用类型.基本类型需要自动装箱) List(列表):元素有序,元素可以重复 (有索引). 通过元素的equals()方法判断是否 ...

  4. 2018网特招新题writeup

    沈永宁(周鸣振)这狗比,晚上才发现他隐姓埋名偷偷刷了分还刷到了第一名,不行我也刷...我刷刷刷

  5. 一百一十七:CMS系统之注册页面对接短信验证码

    from flask import Blueprint, requestfrom exts import alidayufrom utils import restfulfrom utils.capt ...

  6. LVS系列三、LVS集群-IP-TUN模式

    一.LVS-IP TUN集群概述 DR方式是通过MAC,规模是一个交换网络.而TUN方式,是通过给数据包加上新的IP头部来实现,这个可以跨整个广域网.TUN模式可以解决DR模式下不能跨网段的问题,甚至 ...

  7. 连接服务器VNC

    1,启动vnc vncserver 2,提示输入密码 3,Would you like to enter a view-only password (y/n)?  选择n 4,会生成一个端口号 5, ...

  8. composer install与composer update的区别

    1.composer install install 命令从当前目录读取 composer.json 文件,处理了依赖关系,并把其安装到 vendor 目录下. php composer.phar i ...

  9. rsync重启的shell脚本

    https://zhidao.baidu.com/question/2078634436717887028.html

  10. STL————vector的用法

    一.什么是vector? 向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container).跟任意其它类型容器一样,它能够存放各种类型的对象.可以简单的认为,向量是一个能 ...