python音频处理用到的操作的示例代码


Posted in Python onOctober 27, 2017

前言

本文主要记录python下音频常用的操作,以.wav格式文件为例。其实网上有很多现成的音频工具包,如果仅仅调用,工具包是更方便的。

更多pyton下的操作可以参考: 用python做科学计算

1、批量读取.wav文件名:

这里用到字符串路径:

1.通常意义字符串(str)
2.原始字符串,以大写R 或 小写r开始,r'',不对特殊字符进行转义
3.Unicode字符串,u'' basestring子类

如:

path = './file/n'

path = r'.\file\n'

path = '.\\file\\n'

三者等价,右划线\为转义字符,引号前加r表示原始字符串,而不转义(r:raw string).

常用获取帮助的方式:

>>> help(str)
>>> dir(str)
>>> help(str.replace)

2、读取.wav文件

wave.open 用法:

wave.open(file,mode)

mode可以是:

‘rb',读取文件;

‘wb',写入文件;

不支持同时读/写操作。

Wave_read.getparams用法:

f = wave.open(file,'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

其中最后一行为常用的音频参数:

  1. nchannels:声道数
  2. sampwidth:量化位数(byte)
  3. framerate:采样频率
  4. nframes:采样点数

单通道

对应code:

import wave

import matplotlib.pyplot as plt

import numpy as np

import os

 

filepath = "./data/" #添加路径

filename= os.listdir(filepath) #得到文件夹下的所有文件名称 

f = wave.open(filepath+filename[1],'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

strData = f.readframes(nframes)#读取音频,字符串格式

waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int

waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化

# plot the wave

time = np.arange(0,nframes)*(1.0 / framerate)

plt.plot(time,waveData)

plt.xlabel("Time(s)")

plt.ylabel("Amplitude")

plt.title("Single channel wavedata")

plt.grid('on')#标尺,on:有,off:无。

结果图:

python音频处理用到的操作的示例代码

多通道

这里通道数为3,主要借助np.reshape一下,其他同单通道处理完全一致,对应code:

# -*- coding: utf-8 -*-

"""

Created on Wed May 3 12:15:34 2017

 

@author: Nobleding

"""

 

import wave

import matplotlib.pyplot as plt

import numpy as np

import os

 

filepath = "./data/" #添加路径

filename= os.listdir(filepath) #得到文件夹下的所有文件名称 

f = wave.open(filepath+filename[0],'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

strData = f.readframes(nframes)#读取音频,字符串格式

waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int

waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化

waveData = np.reshape(waveData,[nframes,nchannels])

f.close()

# plot the wave

time = np.arange(0,nframes)*(1.0 / framerate)

plt.figure()

plt.subplot(5,1,1)

plt.plot(time,waveData[:,0])

plt.xlabel("Time(s)")

plt.ylabel("Amplitude")

plt.title("Ch-1 wavedata")

plt.grid('on')#标尺,on:有,off:无。

plt.subplot(5,1,3)

plt.plot(time,waveData[:,1])

plt.xlabel("Time(s)")

plt.ylabel("Amplitude")

plt.title("Ch-2 wavedata")

plt.grid('on')#标尺,on:有,off:无。

plt.subplot(5,1,5)

plt.plot(time,waveData[:,2])

plt.xlabel("Time(s)")

plt.ylabel("Amplitude")

plt.title("Ch-3 wavedata")

plt.grid('on')#标尺,on:有,off:无。

plt.show()

效果图:

python音频处理用到的操作的示例代码

单通道为多通道的特例,所以多通道的读取方式对任意通道wav文件都适用。需要注意的是,waveData在reshape之后,与之前的数据结构是不同的。即waveData[0]等价于reshape之前的waveData,但不影响绘图分析,只是在分析频谱时才有必要考虑这一点。

3、wav写入

涉及到的主要指令有三个:

参数设置:

nchannels = 1 #单通道为例

sampwidth = 2

fs = 8000

data_size = len(outData)

framerate = int(fs)

nframes = data_size

comptype = "NONE"

compname = "not compressed"

outwave.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))

待写入wav文件的存储路径及文件名:

outfile = filepath+'out1.wav'

outwave = wave.open(outfile, 'wb')#定义存储路径以及文件名

数据的写入:

for v in outData:
outwave.writeframes(struct.pack('h', int(v * 64000 / 2)))#outData:16位,-32767~32767,注意不要溢出

单通道数据写入:

import wave

#import matplotlib.pyplot as plt

import numpy as np

import os

import struct

 

#wav文件读取

filepath = "./data/" #添加路径

filename= os.listdir(filepath) #得到文件夹下的所有文件名称 

f = wave.open(filepath+filename[1],'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

strData = f.readframes(nframes)#读取音频,字符串格式

waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int

waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化

f.close()

#wav文件写入

outData = waveData#待写入wav的数据,这里仍然取waveData数据

outfile = filepath+'out1.wav'

outwave = wave.open(outfile, 'wb')#定义存储路径以及文件名

nchannels = 1

sampwidth = 2

fs = 8000

data_size = len(outData)

framerate = int(fs)

nframes = data_size

comptype = "NONE"

compname = "not compressed"

outwave.setparams((nchannels, sampwidth, framerate, nframes,

  comptype, compname))

 

for v in outData:

    outwave.writeframes(struct.pack('h', int(v * 64000 / 2)))#outData:16位,-32767~32767,注意不要溢出

outwave.close()

多通道数据写入:

多通道的写入与多通道读取类似,多通道读取是将一维数据reshape为二维,多通道的写入是将二维的数据reshape为一维,其实就是一个逆向的过程:

import wave

#import matplotlib.pyplot as plt

import numpy as np

import os

import struct

 

#wav文件读取

filepath = "./data/" #添加路径

filename= os.listdir(filepath) #得到文件夹下的所有文件名称 

f = wave.open(filepath+filename[0],'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

strData = f.readframes(nframes)#读取音频,字符串格式

waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int

waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化

waveData = np.reshape(waveData,[nframes,nchannels])

f.close()

#wav文件写入

outData = waveData#待写入wav的数据,这里仍然取waveData数据

outData = np.reshape(outData,[nframes*nchannels,1])

outfile = filepath+'out2.wav'

outwave = wave.open(outfile, 'wb')#定义存储路径以及文件名

nchannels = 3

sampwidth = 2

fs = 8000

data_size = len(outData)

framerate = int(fs)

nframes = data_size

comptype = "NONE"

compname = "not compressed"

outwave.setparams((nchannels, sampwidth, framerate, nframes,

  comptype, compname))

 

for v in outData:

    outwave.writeframes(struct.pack('h', int(v * 64000 / 2)))#outData:16位,-32767~32767,注意不要溢出

outwave.close()

这里用到struct.pack(.)二进制的转化:

python音频处理用到的操作的示例代码

例如:

python音频处理用到的操作的示例代码

python音频处理用到的操作的示例代码

4、音频播放

wav文件的播放需要用到pyaudio,安装包点击这里。我将它放在\Scripts文件夹下,cmd并切换到对应目录

pip install PyAudio-0.2.9-cp35-none-win_amd64.whl

pyaudio安装完成。

Pyaudio主要用法:

主要列出pyaudio对象的open()方法的参数:

  1. rate:采样率
  2. channels:声道数
  3. format:采样值的量化格式,值可以为paFloat32、paInt32、paInt24、paInt16、paInt8等。下面的例子中,使用get_from_width()将值为2的sampwidth转换为paInt16.
  4. input:输入流标志,Ture表示开始输入流
  5. output:输出流标志

给出对应code:

import wave

import pyaudio 

import os

 

#wav文件读取

filepath = "./data/" #添加路径

filename= os.listdir(filepath) #得到文件夹下的所有文件名称 

f = wave.open(filepath+filename[0],'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

#instantiate PyAudio 

p = pyaudio.PyAudio() 

#define stream chunk  

chunk = 1024 

#打开声音输出流

stream = p.open(format = p.get_format_from_width(sampwidth), 

        channels = nchannels, 

        rate = framerate, 

        output = True) 

 

#写声音输出流到声卡进行播放

data = f.readframes(chunk) 

i=1

while True: 

  data = f.readframes(chunk)

  if data == b'': break

  stream.write(data)  

f.close()

#stop stream 

stream.stop_stream() 

stream.close() 

#close PyAudio 

p.terminate()

因为是python3.5,判断语句if data == b'': break 的b不能缺少。

5、信号加窗

通常对信号截断、分帧需要加窗,因为截断都有频域能量泄露,而窗函数可以减少截断带来的影响。

窗函数在scipy.signal信号处理工具箱中,如hamming窗:

import scipy.signal as signal

pl.plot(signal.hanning(512))

利用上面的函数,绘制hanning窗:

import pylab as pl

import scipy.signal as signal

pl.figure(figsize=(6,2))

pl.plot(signal.hanning(512))

python音频处理用到的操作的示例代码

6、信号分帧

信号分帧的理论依据,其中x是语音信号,w是窗函数:

python音频处理用到的操作的示例代码

加窗截断类似采样,为了保证相邻帧不至于差别过大,通常帧与帧之间有帧移,其实就是插值平滑的作用。

给出示意图:

python音频处理用到的操作的示例代码

这里主要用到numpy工具包,涉及的指令有:

  1. np.repeat:主要是直接重复
  2. np.tile:主要是周期性重复

对比一下:

向量情况:python音频处理用到的操作的示例代码

矩阵情况:

对于数据:python音频处理用到的操作的示例代码

repeat操作:python音频处理用到的操作的示例代码

tile操作:python音频处理用到的操作的示例代码

对应结果:

python音频处理用到的操作的示例代码

python音频处理用到的操作的示例代码

对应分帧的代码实现:

这是没有加窗的示例:

import numpy as np

import wave

import os

#import math

 

def enframe(signal, nw, inc):

  '''将音频信号转化为帧。

  参数含义:

  signal:原始音频型号

  nw:每一帧的长度(这里指采样点的长度,即采样频率乘以时间间隔)

  inc:相邻帧的间隔(同上定义)

  '''

  signal_length=len(signal) #信号总长度

  if signal_length<=nw: #若信号长度小于一个帧的长度,则帧数定义为1

    nf=1

  else: #否则,计算帧的总长度

    nf=int(np.ceil((1.0*signal_length-nw+inc)/inc))

  pad_length=int((nf-1)*inc+nw) #所有帧加起来总的铺平后的长度

  zeros=np.zeros((pad_length-signal_length,)) #不够的长度使用0填补,类似于FFT中的扩充数组操作

  pad_signal=np.concatenate((signal,zeros)) #填补后的信号记为pad_signal

  indices=np.tile(np.arange(0,nw),(nf,1))+np.tile(np.arange(0,nf*inc,inc),(nw,1)).T #相当于对所有帧的时间点进行抽取,得到nf*nw长度的矩阵

  indices=np.array(indices,dtype=np.int32) #将indices转化为矩阵

  frames=pad_signal[indices] #得到帧信号

#  win=np.tile(winfunc(nw),(nf,1)) #window窗函数,这里默认取1

#  return frames*win  #返回帧信号矩阵

  return frames

def wavread(filename):

  f = wave.open(filename,'rb')

  params = f.getparams()

  nchannels, sampwidth, framerate, nframes = params[:4]

  strData = f.readframes(nframes)#读取音频,字符串格式

  waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int

  f.close()

  waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化

  waveData = np.reshape(waveData,[nframes,nchannels]).T

  return waveData

 

filepath = "./data/" #添加路径

dirname= os.listdir(filepath) #得到文件夹下的所有文件名称 

filename = filepath+dirname[0]

data = wavread(filename)

nw = 512

inc = 128

Frame = enframe(data[0], nw, inc)

如果需要加窗,只需要将函数修改为:

def enframe(signal, nw, inc, winfunc):

  '''将音频信号转化为帧。

  参数含义:

  signal:原始音频型号

  nw:每一帧的长度(这里指采样点的长度,即采样频率乘以时间间隔)

  inc:相邻帧的间隔(同上定义)

  '''

  signal_length=len(signal) #信号总长度

  if signal_length<=nw: #若信号长度小于一个帧的长度,则帧数定义为1

    nf=1

  else: #否则,计算帧的总长度

    nf=int(np.ceil((1.0*signal_length-nw+inc)/inc))

  pad_length=int((nf-1)*inc+nw) #所有帧加起来总的铺平后的长度

  zeros=np.zeros((pad_length-signal_length,)) #不够的长度使用0填补,类似于FFT中的扩充数组操作

  pad_signal=np.concatenate((signal,zeros)) #填补后的信号记为pad_signal

  indices=np.tile(np.arange(0,nw),(nf,1))+np.tile(np.arange(0,nf*inc,inc),(nw,1)).T #相当于对所有帧的时间点进行抽取,得到nf*nw长度的矩阵

  indices=np.array(indices,dtype=np.int32) #将indices转化为矩阵

  frames=pad_signal[indices] #得到帧信号

  win=np.tile(winfunc,(nf,1)) #window窗函数,这里默认取1

  return frames*win  #返回帧信号矩阵

其中窗函数,以hamming窗为例:

winfunc = signal.hamming(nw)

Frame = enframe(data[0], nw, inc, winfunc)

调用即可。

7、语谱图

其实得到了分帧信号,频域变换取幅值,就可以得到语谱图,如果仅仅是观察,matplotlib.pyplot有specgram指令:

import wave

import matplotlib.pyplot as plt

import numpy as np

import os

 

filepath = "./data/" #添加路径

filename= os.listdir(filepath) #得到文件夹下的所有文件名称 

f = wave.open(filepath+filename[0],'rb')

params = f.getparams()

nchannels, sampwidth, framerate, nframes = params[:4]

strData = f.readframes(nframes)#读取音频,字符串格式

waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int

waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化

waveData = np.reshape(waveData,[nframes,nchannels]).T

f.close()

# plot the wave

plt.specgram(waveData[0],Fs = framerate, scale_by_freq = True, sides = 'default')

plt.ylabel('Frequency(Hz)')

plt.xlabel('Time(s)')

plt.show()

python音频处理用到的操作的示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python写的一个文本编辑器
Jan 23 Python
python批量生成本地ip地址的方法
Mar 23 Python
Python实现压缩与解压gzip大文件的方法
Sep 18 Python
python购物车程序简单代码
Apr 18 Python
python递归实现快速排序
Aug 18 Python
浅析python参数的知识点
Dec 10 Python
padas 生成excel 增加sheet表的实例
Dec 11 Python
python 检查是否为中文字符串的方法
Dec 28 Python
使用Python实现将list中的每一项的首字母大写
Jun 11 Python
Python创建或生成列表的操作方法
Jun 19 Python
python 将dicom图片转换成jpg图片的实例
Jan 13 Python
Python坐标轴操作及设置代码实例
Jun 04 Python
彻底理解Python list切片原理
Oct 27 #Python
Python在不同目录下导入模块的实现方法
Oct 27 #Python
Django视图之ORM数据库查询操作API的实例
Oct 27 #Python
浅谈python函数之作用域(python3.5)
Oct 27 #Python
python+pyqt实现右下角弹出框
Oct 26 #Python
python中模块的__all__属性详解
Oct 26 #Python
Python内建函数之raw_input()与input()代码解析
Oct 26 #Python
You might like
php多文件上传下载示例分享
2014/02/20 PHP
Win2003+apache+PHP+SqlServer2008 配置生产环境
2014/07/29 PHP
Yii2创建表单(ActiveForm)方法详解
2016/07/23 PHP
Yii框架自定义数据库操作组件示例
2019/11/11 PHP
jquery遍历input取得input的name
2009/04/27 Javascript
extjs 学习笔记(三) 最基本的grid
2009/10/15 Javascript
JavaScript 布尔操作符解析  &amp;&amp; || !
2012/08/10 Javascript
Json字符串转换为JS对象的高效方法实例
2013/05/01 Javascript
javascript动态添加、修改、删除对象的属性与方法详解
2014/01/27 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
在AngularJS中如何使用谷歌地图把当前位置显示出来
2016/01/25 Javascript
学习使用jquery iScroll.js移动端滚动条插件
2020/03/24 Javascript
JS前向后瞻正则表达式定义与用法示例
2016/12/27 Javascript
JS实现数组去重方法总结(六种方法)
2017/07/14 Javascript
Angular中ng-repeat与ul li的多层嵌套重复问题
2017/07/24 Javascript
AngularJs 延时器、计时器实例代码
2017/09/16 Javascript
Angular5集成eventbus的示例代码
2018/07/19 Javascript
微信小程序开发(三):返回上一级页面并刷新操作示例【页面栈】
2020/06/01 Javascript
玩转python爬虫之cookie使用方法
2016/02/17 Python
Python使用smtp和pop简单收发邮件完整实例
2018/01/09 Python
python实现校园网自动登录的示例讲解
2018/04/22 Python
python tkinter GUI绘制,以及点击更新显示图片代码
2020/03/14 Python
Python RabbitMQ实现简单的进程间通信示例
2020/07/02 Python
简单了解Django项目应用创建过程
2020/07/06 Python
奥地利网上书店:Weltbild
2017/07/14 全球购物
美国正宗设计师眼镜在线零售商:EYEZZ
2019/03/23 全球购物
最新奶茶店创业计划书
2014/01/25 职场文书
2014道德模范事迹材料
2014/02/16 职场文书
出生证明公证书
2014/04/09 职场文书
物理教育专业求职信
2014/06/25 职场文书
房屋维修协议书范本
2014/09/25 职场文书
稽核岗位职责
2015/02/10 职场文书
2016年公司中秋节致辞
2015/11/26 职场文书
《开国大典》教学反思
2016/02/16 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python
测量JavaScript函数的性能各种方式对比
2021/04/27 Javascript