用Python实现音频卷积,并制作一个简单的HRTF效果

用Python实现音频卷积,并制作一个简单的HRTF效果

作为一个刚刚入门Python的小白用户,写出这篇文章还是废了我很大的力气,不过幸运的是,在网上到处东拼西凑,我还是把它给做出来了。
废话不多说,直接开始(入门向):

音频卷积

我的Python版本是2.7.13,先安装必需的库:

pip install scipy

导入库:

from scipy.io import wavfile
from scipy.signal import fftconvolve

正经操作开始了:

file_path1 = '你的音频文件路径'
file_path2 = '你的第二个音频文件路径'
fs1, wav_data1 = wavfile.read(file_path1)
fs2, wav_data2 = wavfile.read(file_path2)  #fs里保存的是头信息,wav_data保存的就是数据,它是以数组形式存在的
temp = fftconvolve(wav_data1,wav_data2)  #将两个音频数据进行卷积
wavfile.write('temp要写入的文件路径'44100,temp) 

ps:如果遇到警告信息:WavFileWarning: Chunk (non-data) not understood, skipping it. 可以清除wav文件的元数据再试

制作HRTF效果

这个东西的简介我就不发了,直接度娘就好了
核心要求就是如下:
1,确定你要卷积的hrir方位点
2,最好是把双声道的文件分割成左右声道两个文件在进行卷积

我用的HRIR数据是CIPIC的,它是把数据以三维数组的形式保存在一个.mat文件里的。
直接上源码:

#coding=utf-8
#__Version__  1.0
#Python 2.7.13
'''
Filename: fast_convolution.py
Project: hrtf制作
Author: o花间留步面馆o
FileCreated:Sunday, 22nd March 2020 14:32
Last Modified:Sunday, 23nd March 2020 1857
'''
import wave
import numpy as np
from scipy.io import wavfile
from scipy.io import loadmat
from scipy.signal import fftconvolve  #所有操作需要的库

global filename_l
global filename_r
global filename_over_l
global filename_over_r      #不想删了,怕又删出问题了。。。

print ("输入所有文件的同一个上级父目录:\n")
file_path = input()

print ("选择你的操作系统:\n 1,Mac/linux   2,windows")
tmp = input()

def ououou():
	global filename_l
	global filename_r
	global filename_over_l
	global filename_over_r
	global hrir_l
	global hrir_r
	filename = file_path + '\\hrtf\\hrir_final.mat'
	hrtfdata = loadmat(filename)  #导入hrir数据
	hrir_l = hrtfdata['hrir_l']
	hrir_r = hrtfdata['hrir_r']
	filename_l = file_path + '\\left.wav'
	filename_r = file_path + '\\right.wav'
	filename_over_l = file_path + '\\zuo.wav'
	filename_over_r = file_path + '\\you.wav'

def lalala():
	global filename_l
	global filename_r
	global filename_over_l
	global filename_over_r
	global hrir_l
	global hrir_r
	filename = file_path + '/hrtf/hrir_final.mat'
	hrtfdata = loadmat(filename)  #导入hrir数据
	hrir_l = hrtfdata['hrir_l']
	hrir_r = hrtfdata['hrir_r']
	filename_l = file_path + '/left.wav'
	filename_r = file_path + '/right.wav'
	filename_over_l = file_path + '/zuo.wav'
	filename_over_r = file_path + '/you.wav'

if tmp == 1:
	lalala()

if tmp == 2:
	ououou()

def project_1(n,c):
	file_l = wave.open(filename_l,'rb')
	file_r = wave.open(filename_r,'rb')
	params_l = file_l.getparams()
	params_r = file_r.getparams()
	nchannels_l, sampwidth_l, framerate_l, nframes_l = params_l[:4]
	nchannels_r, sampwidth_r, framerate_r, nframes_r = params_r[:4]
	str_data_l = file_l.readframes(nframes_l)  #读取byte数组
	str_data_r = file_r.readframes(nframes_r)
	file_l.close()
	file_r.close()
	wavdatal = np.fromstring(str_data_l, dtype = np.float32)
	wavdatar = np.fromstring(str_data_r, dtype = np.float32)  #byte数组转十进制数组
	hrir_a = hrir_l[n,c,:]
	hrir_b = hrir_r[n,c,:]  #取方位点的数据
	overl = fftconvolve(hrir_a,wavdatal)
	overr = fftconvolve(hrir_b,wavdatar)  #最重要的操作,卷积
	wavfile.write(filename_over_l,44100,overl)
	wavfile.write(filename_over_r,44100,overr)  #写出文件



def project_3(n,c):
	fs1, wavdatal = wavfile.read(filename_l)
	fs2, wavdatar = wavfile.read(filename_r)  
	hrir_a = hrir_l[n,c, :]
	hrir_b = hrir_r[n,c, :]
	overl = fftconvolve(hrir_a,wavdatal)
	overr = fftconvolve(hrir_b,wavdatar)
	wavfile.write(filename_over_l,44100,overl)
	wavfile.write(filename_over_r,44100,overr)


def project_2(n,c):
	file_l = wave.open(filename_l,'rb')
	file_r = wave.open(filename_r,'rb')
	params_l = file_l.getparams()
	params_r = file_r.getparams()
	nchannels_l, sampwidth_l, framerate_l, nframes_l = params_l[:4]
	nchannels_r, sampwidth_r, framerate_r, nframes_r = params_r[:4]
	str_data_l = file_l.readframes(nframes_l)
	str_data_r = file_r.readframes(nframes_r)
	file_l.close()
	file_r.close()
	wavdatal = np.fromstring(str_data_l, dtype = np.short)
	wavdatar = np.fromstring(str_data_r, dtype = np.short)
	hrir_a = hrir_l[n,c,:]
	hrir_b = hrir_r[n,c,:]
	overl = fftconvolve(hrir_a,wavdatal)
	overr = fftconvolve(hrir_b,wavdatar)
	wavfile.write(filename_over_l,44100,overl)
	wavfile.write(filename_over_r,44100,overr)


def project_4(n,a):
	fs1, wavdatal = wavfile.read(filename_l)
	fs2, wavdatar = wavfile.read(filename_r)
	hrir_a = hrir_l[0,0,:]
	hrir_b = hrir_r[0,0,:]
	overl = fftconvolve(hrir_a,wavdatal)
	overr = fftconvolve(hrir_b,wavdatar)
	for n in range(1,20,a):
		hrir_a = hrir_l[n,n,:]
		hrir_b = hrir_r[n,n,:]
		overl = fftconvolve(hrir_a,overl)
		overr = fftconvolve(hrir_b,overr)
	wavfile.write(filename_over_l,44100,overl)
	wavfile.write(filename_over_r,44100,overr)

print("选择处理音频的方案:\n 1(成败参半,32位)		2(成败参半,16位)       	3(稳定性ok)	  4(实验性)")
o = 0
while o <= 3:
	print("输入代表方案的数字:\n")
	x = input()
	if x <= 4:
	    break
	o = o + 1
if x == 1:
	n = int(raw_input("输入一个方位点:(0-24)").strip())
	c = int(raw_input("再输一个:(0-24)").strip())
	project_1(n,c)
if x == 2:
	n = int(raw_input("输入一个方位点:(0-24)").strip())
	c = int(raw_input("再输一个:(0-24)").strip())
	project_2(n,c)
if x == 3:
	n = int(raw_input("输入一个方位点:(0-24)").strip())
	c = int(raw_input("再输一个:(0-24)").strip())
	project_3(n,c)
if x == 4:
	n = int(raw_input("输入一个方位点:(0-24)").strip())
	a = int(raw_input("输每个方位点之间的间隔:(0-20)").strip())
	project_4(n,a)

'''
注意事项:

1、要使用这个脚本,你需要将你的音频文件拆分成左,右两个单声道文件,并分别命名为left.wav和right.wav放在桌面上
2、在桌面上新建两个空文件,分别命名为zuo.wav和you.wav
3、你需要使用cipic的hrir数据,它的格式为.mat,将它放在桌面的\hrtf文件夹里并命名为hrir_final.mat
4、要运行这个脚本你还需要安装scipy库和numpy库,如果只使用方案3,4则只需要scipy库
	python 2.x版本可以用 pip install scipy
	python 3.x版本则是 pip3 install scipy   #python3.x 我还没有测试
5、最后输出的数据需要限幅,我测试的结果它的输出最高到了792db
6、输入父目录时要按照如下格式:
	windows: 'C:\\Adminmaster\\Desktop' #手里没有windows电脑,这样写也是网上看的,两个反斜杠转义成一个
	Mac&linux: '/usr/share'
7、文件的所有输出都是44100hz,请尽量使用44100hz采样的音源
8、cipic的数据需要FQ下载,用wavfile读取的音频直接就以数组形式储存在name中
8、暂时就只想到这么多了,以后想到会补充的
'''
初学Python我也就只能写出这个水平的,肯定还有很多地方需要优化,还请大佬们不吝赐教
  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值