python按固定采样点个数分割wav格式音频

2020年11月29日 214 次阅读 0 条评论 0 人点赞

最近开始做实验需要绘制音频的语谱图,绘制语谱图的过程中需要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)

至于如何批量调用,当然是写个循环就行了,这个大家都会,就不赘述了。

各位有问题可以再在下方留言

文章评论(0)