Python读取wav格式文件

点击量:2412

我们经常需要处理wav格式的文件,读取其中的声音信号和相关参数,来做一些事情。如果我们使用C++来做,那么需要对文件的底层存储格式有一个透彻的了解才行,而且考虑不周还有可能出Bug;如果使用MatLab来做,虽然只有一行代码就可以读取文件,但是MatLab语言自身的局限性使得写出的代码难以在实际中投入使用。因此,兼顾简介易用和实用性,用Python来做就显得比较好了。

首先,自然地,我们需要导入Python包:

import wave

这个Pyhton包提供了一个方便的WAV格式文件读写的接口。

它支持单声道与立体声,但是不支持压缩和解压缩。

 

wave类的方法函数:

open(file, [mode])
打开一个wave文件流对象,返回该对象。

参数:
file: 如果file是一个字符串,那么就打开文件,否则就把它当做一个类文件对象。
mode: 可缺省,如果输入的参数是一个类文件对象,那么file.mode将会作为mode的值。

mode可选参数如下:
只读模式:  ‘r’, ‘rb’
只写模式:  ‘w’, ‘wb’

注意:不能同时完成读/写操作

close()
关闭该流,使得该实例不可用,它会自动调用对象收集机制。

getnchannels()
返回音频的声道数(1是单声道,2是立体声)。

getsampwidth()
返回该实例每一帧的字节宽度。

getframerate()
返回实例的频率(单位:Hz)。

getnframes()
返回音频的帧数。

getcomtype()
返回压缩类型(仅支持’NONE’)。

getcompname()
是getcomtype()的人类可读的版本,通常用’not compressed’表示’NONE’。

getparams()
返回一个元组tuple (nchannels, sampwidth, framerate, nframes, comptype, compname),包含了以上的方法取得的几个值。

readframes(n)
从流的当前指针位置一次读出音频的n个帧,并且指针后移n个帧,返回一个字节数组。

rewind()
倒带,将该文件指针指向音频流的最开始位置。

 

其次,我们需要使用numpy中的shape来改变数组的形状,主要是为了解决立体声即双轨声道时候的信号能量表示问题。

import numpy as np
arr = np.array([[1,2,3],[4,5,6]])
arr.shape = 3,2

可以将原为2*3的数组(矩阵)转为3*2数组(矩阵)。当某数轴的参数为-1时,可根据元素个数,自动计算另一轴的最大长度。

实例代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def read_wav_data(filename):
  '''
  读取一个wav文件,返回声音信号的时域谱矩阵和播放时间
  '''
  wav = wave.open(filename,"rb") # 打开一个wav格式的声音文件流
  num_frame = wav.getnframes() # 获取帧数
  num_channel=wav.getnchannels() # 获取声道数
  framerate=wav.getframerate() # 获取帧速率
  num_sample_width=wav.getsampwidth() # 获取实例的比特宽度,即每一帧的字节数
  str_data = wav.readframes(num_frame) # 读取全部的帧
  wav.close() # 关闭流
  wave_data = np.fromstring(str_data, dtype = np.short) # 将声音文件数据转换为数组矩阵形式
  wave_data.shape = -1, num_channel # 按照声道数将数组整形,单声道时候是一列数组,双声道时候是两列的矩阵
  wave_data = wave_data.T # 将矩阵转置
  wave_data = wave_data 
  return wave_data, framerate  

def wav_show(wave_data, fs): # 显示出来声音波形
  time = np.arange(0, len(wave_data)) * (1.0/fs)  # 计算声音的播放时间,单位为秒
  # 画声音波形
  plt.plot(time, wave_data)  
  plt.show()  

if(__name__=='__main__'):
  wave_data, fs = read_wav_data("1.wav")  
  wav_show(wave_data[0],fs)
  wav_show(wave_data[1],fs)  # 如果是双声道则保留这一行,否则删掉这一行

 

打赏作者
很喜欢这篇文章,赞赏一下作者,以激励其创作出更多好文!

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

分享到社交网络:

发表评论

电子邮件地址不会被公开。 必填项已用*标注