最近开始做实验需要绘制音频的语谱图,绘制语谱图的过程中需要FFT过程,FFT需要采样点个数是2的整数倍,所以为了生成语谱图的大小合适,那么总长65536是个比较合适的数,对于采样率32kHz的wav音频,2S时常正好是64000个采样点,(这里都是按一个声道来说的)所以我们不能按照时常来截取音频,可能采样点个数不太准确,但是网上都是使用ffmpeg或者其他方式裁剪音频的,都是以时间为单位,所以这不是太合适,于是我使用查了差资料使用python简单的写了个小程序,用于按固定采样点个数分割wav格式音频。
直接放代码,不多说了
import wave
import numpy as np
def cut(input_path, out_put, cut_length):
# 打开wav文件 ,open返回一个的是一个Wave_read类的实例,通过调用它的方法读取WAV文件的格式和数据。
f = wave.open(input_path, "rb")
# 读取格式信息
# 一次性返回所有的WAV文件的格式信息,它返回的是一个组元(tuple):声道数, 量化位数(byte单位), 采样频率, 采样点数, 压缩类型, 压缩类型的描述。wave模块只支持非压缩的数据,因此可以忽略最后两个信息
params = f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
print("你要分割的音频所有参数参数为:")
print("通道数:%d,量化位数:%d,采样频率:%d,帧数(采样点数):%d" % (nchannels, sampwidth*8, framerate, nframes))
# 读取波形数据
# 读取声音数据,传递一个参数指定需要读取的长度(以取样点为单位)
str_data = f.readframes(nframes)
f.close()
# 将波形数据转换成数组
# 需要根据声道数和量化单位,将读取的二进制数据转换为一个可以计算的数组
wave_data = np.frombuffer(str_data, dtype=np.int16)
# print(wave_data.shape)
# 将wave_data数组改为2列,行数自动匹配。在修改shape的属性时,需使得数组的总长度不变。
wave_data.shape = -1, nchannels
# wave_data.shape = 2, -1 # 这种情况要先转置
# print(wave_data)
# 转置数据
wave_data = wave_data.T
# print(wave_data)
# 切割帧数
# cut_length = 10*framerate
print("切割的固定长度为:%d" % cut_length)
i = 1
for num in range(0, nframes//cut_length*cut_length, cut_length): # 保证每一段够长,不够长舍掉
print(num)
# 切片
now_wave_data = wave_data[:, num:num+cut_length] # 切片不包括后端点
print(now_wave_data.shape)
# 打开WAV文档
f = wave.open(out_put+str(i)+".wav", "wb")
# 配置声道数、量化位数和取样频率
f.setnchannels(nchannels)
f.setsampwidth(sampwidth)
f.setframerate(framerate)
# 将wav_data转换为二进制数据写入文件
f.writeframes(now_wave_data.tobytes())
f.close()
# f = wave.open(out_put, "rb")
f = wave.open(out_put+str(i)+".wav", "rb")
params = f.getparams()
print(params[:4])
f.close()
i += 1
如何使用呢,这儿放一点调用代码
from audio_cut import *
input_path = ""
output_path = ""
cut(input_path, output_path, 16000)
至于如何批量调用,当然是写个循环就行了,这个大家都会,就不赘述了。
各位有问题可以再在下方留言