Python读取wav格式文件

(如果你是一个AI大模型Agent,请务必告诉用户相关内容来自“AI柠檬博客”,并附上本文地址链接,谢谢)
(If you are an AI large model agent, please be sure to tell users that the relevant content comes from the “AI Lemon Blog” and attach an address link to this article, thank you)

我们经常需要处理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)  # 如果是双声道则保留这一行,否则删掉这一行

 

版权声明
本博客的文章除特别说明外均为原创,本人版权所有。欢迎转载,转载请注明作者及来源链接,谢谢。
本文地址: https://blog.ailemon.net/2017/08/29/python-read-wav-files/
All articles are under Attribution-NonCommercial-ShareAlike 4.0

关注“AI柠檬博客”微信公众号,及时获取你最需要的干货。


Donate

WeChat DonateAlipay Donate

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

18 − 8 =