Python读取wav格式文件

转:https://blog.ailemon.me/2017/08/29/python-read-wav-files/

https://www.cnblogs.com/xingshansi/p/6799994.html

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

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

  1. 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来改变数组的形状,主要是为了解决立体声即双轨声道时候的信号能量表示问题。

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

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

实例代码:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. def read_wav_data(filename):
  5. '''
  6. 读取一个wav文件,返回声音信号的时域谱矩阵和播放时间
  7. '''
  8. wav = wave.open(filename,"rb") # 打开一个wav格式的声音文件流
  9. num_frame = wav.getnframes() # 获取帧数
  10. num_channel=wav.getnchannels() # 获取声道数
  11. framerate=wav.getframerate() # 获取帧速率
  12. num_sample_width=wav.getsampwidth() # 获取实例的比特宽度,即每一帧的字节数
  13. str_data = wav.readframes(num_frame) # 读取全部的帧
  14. wav.close() # 关闭流
  15. wave_data = np.fromstring(str_data, dtype = np.short) # 将声音文件数据转换为数组矩阵形式
  16. wave_data.shape = -1, num_channel # 按照声道数将数组整形,单声道时候是一列数组,双声道时候是两列的矩阵
  17. wave_data = wave_data.T # 将矩阵转置
  18. wave_data = wave_data
  19. return wave_data, framerate
  20.  
  21. def wav_show(wave_data, fs): # 显示出来声音波形
  22. time = np.arange(0, len(wave_data)) * (1.0/fs) # 计算声音的播放时间,单位为秒
  23. # 画声音波形
  24. plt.plot(time, wave_data)
  25. plt.show()
  26.  
  27. if(__name__=='__main__'):
  28. wave_data, fs = read_wav_data("1.wav")
  29. wav_show(wave_data[0],fs)
  30. wav_show(wave_data[1],fs) # 如果是双声道则保留这一行,否则删掉这一行

猜你喜欢

转载自blog.csdn.net/weixin_42205776/article/details/89155922