zoukankan      html  css  js  c++  java
  • WAV格式文件无损合并&帧头数据体解析(python)(原创)

    一,百度百科

      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'$&x02x00'   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'x10x00x00x00'
    16     #
    17     # print(data[20:22])          # Subchunk1 Size:   b'x01x00'
    18     # print(data[22:24])    # nChannels:        b'x01x00'
    19     #
    20     # print(data[24:28])          # nSamplesPerSec:   b'x80>x00x00'
    21     # print(data[28:32])    # nAvgBytesPerSec:  b'x00}x00x00'
    22     #
    23     # print(data[32:34])          # nBlockAlign:      b'x02x00'
    24     # print(data[34:36])    # wBitsPerSample:   b'x10x00'
    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&x02x00'

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

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

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

    1 b'RIFFxacxdc9x00WAVEfmtx10x00x00x00x01x00x01x00x80>x00x00x00}x00x00x02x00x10x00datax80xdc9x00'

    数据帧为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文件合并一定要在合并后更新相关的数据,与此同时也要注意文件的通道数、采样频率等格式是否相同,一定要转换到相同格式合并才有效

  • 相关阅读:
    就南通大学教务管理系统微信公众号的个人看法
    设计一款给爸爸妈妈用的手机
    .NET中DLL“没有可放置在工具箱的组件”—FreeTextBox
    如何查看.Net源代码vs版本号以及C#项目中各文件的含义
    .NET在后置代码中输入JS提示语句(背景不会变白)
    Docker技术学习
    学习linux基本命令
    性能相关英文单词学习
    常见Http状态码的含义
    学习siege实战
  • 原文地址:https://www.cnblogs.com/Mufasa/p/10878777.html
Copyright © 2011-2022 走看看