首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从wav文件中获取wav样本?

如何从wav文件中获取wav样本?
EN

Stack Overflow用户
提问于 2010-06-17 13:26:20
回答 4查看 11.9K关注 0票数 5

我想知道为了执行两个.wav文件的窗口连接,如何从.wav文件中获取样本。

有谁能告诉我怎么做吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-06-17 13:38:42

标准库的wave模块是关键:当然,在代码顶部的import wave之后,wave.open('the.wav', 'r')返回一个"wave read“对象,您可以使用.readframes方法从该对象读取帧,该方法返回一个字节字符串,该字符串是示例...无论wave文件采用哪种格式(可以使用.getnchannels方法确定通道数,使用.getsampwidth方法确定每个采样的字节数,确定与将帧分解为采样相关的两个参数)。

将字节字符串转换为数值序列的最佳方法是使用array模块,并(分别)为每个样本使用1、2、4字节的'B''H''L'类型(在32位版本的Python上;您可以使用数组对象的itemsize值来仔细检查)。如果您的样本宽度不同于array所能提供的宽度,则需要对字节字符串进行分片(用值为0的字节适当地填充每个小分片),并改用struct模块(但这会更笨重、更慢,所以如果可以,请改用array )。

票数 13
EN

Stack Overflow用户

发布于 2010-06-17 13:33:34

您可以使用wave模块。首先,您应该读取元数据,例如我们的样本大小或通道数。使用readframes()方法,您可以读取样本,但只能将其作为字节字符串。根据示例格式,您必须使用struct.unpack()将它们转换为示例。

或者,如果您希望样本作为浮点数的数组,您可以使用SciPy的io.wavfile模块。

票数 2
EN

Stack Overflow用户

发布于 2015-10-30 07:20:07

这是一个从wave文件中读取样本的函数(用单声道和立体声测试):

代码语言:javascript
复制
def read_samples(wave_file, nb_frames):
    frame_data = wave_file.readframes(nb_frames)
    if frame_data:
        sample_width = wave_file.getsampwidth()
        nb_samples = len(frame_data) // sample_width
        format = {1:"%db", 2:"<%dh", 4:"<%dl"}[sample_width] % nb_samples
        return struct.unpack(format, frame_data)
    else:
        return ()

下面是对多个.wav文件进行窗口混合或连接的完整脚本。所有输入文件需要具有相同的参数(通道数和采样宽度)。

代码语言:javascript
复制
import argparse
import itertools
import struct
import sys
import wave

def _struct_format(sample_width, nb_samples):
    return {1:"%db", 2:"<%dh", 4:"<%dl"}[sample_width] % nb_samples

def _mix_samples(samples):
    return sum(samples)//len(samples)

def read_samples(wave_file, nb_frames):
    frame_data = wave_file.readframes(nb_frames)
    if frame_data:
        sample_width = wave_file.getsampwidth()
        nb_samples = len(frame_data) // sample_width
        format = _struct_format(sample_width, nb_samples)
        return struct.unpack(format, frame_data)
    else:
        return ()

def write_samples(wave_file, samples, sample_width):
    format = _struct_format(sample_width, len(samples))
    frame_data = struct.pack(format, *samples)
    wave_file.writeframes(frame_data)

def compatible_input_wave_files(input_wave_files):
    nchannels, sampwidth, framerate, nframes, comptype, compname = input_wave_files[0].getparams()
    for input_wave_file in input_wave_files[1:]:
        nc,sw,fr,nf,ct,cn = input_wave_file.getparams()
        if (nc,sw,fr,ct,cn) != (nchannels, sampwidth, framerate, comptype, compname):
            return False
    return True

def mix_wave_files(output_wave_file, input_wave_files, buffer_size):
    output_wave_file.setparams(input_wave_files[0].getparams())
    sampwidth = input_wave_files[0].getsampwidth()
    max_nb_frames = max([input_wave_file.getnframes() for input_wave_file in input_wave_files])
    for frame_window in xrange(max_nb_frames // buffer_size + 1):
        all_samples = [read_samples(wave_file, buffer_size) for wave_file in input_wave_files]
        mixed_samples = [_mix_samples(samples) for samples in itertools.izip_longest(*all_samples, fillvalue=0)]
        write_samples(output_wave_file, mixed_samples, sampwidth)

def concatenate_wave_files(output_wave_file, input_wave_files, buffer_size):
    output_wave_file.setparams(input_wave_files[0].getparams())
    sampwidth = input_wave_files[0].getsampwidth()
    for input_wave_file in input_wave_files:
        nb_frames = input_wave_file.getnframes()
        for frame_window in xrange(nb_frames // buffer_size + 1):
            samples = read_samples(input_wave_file, buffer_size)
            if samples:
                write_samples(output_wave_file, samples, sampwidth)

def argument_parser():
    parser = argparse.ArgumentParser(description='Mix or concatenate multiple .wav files')
    parser.add_argument('command', choices = ("mix", "concat"), help='command')
    parser.add_argument('output_file', help='ouput .wav file')
    parser.add_argument('input_files', metavar="input_file", help='input .wav files', nargs="+")
    parser.add_argument('--buffer_size', type=int, help='nb of frames to read per iteration', default=1000)
    return parser

if __name__ == '__main__':
    args = argument_parser().parse_args()

    input_wave_files = [wave.open(name,"rb") for name in args.input_files]
    if not compatible_input_wave_files(input_wave_files):
        print "ERROR: mixed wave files must have the same params."
        sys.exit(2)

    output_wave_file = wave.open(args.output_file, "wb")
    if args.command == "mix":
        mix_wave_files(output_wave_file, input_wave_files, args.buffer_size)
    elif args.command == "concat":
        concatenate_wave_files(output_wave_file, input_wave_files, args.buffer_size)

    output_wave_file.close()
    for input_wave_file in input_wave_files:
        input_wave_file.close()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3059089

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档