使用scikits.samplerate.resample改变音频文件音调后,pygame输出杂音

9 投票
4 回答
12483 浏览
提问于 2025-04-17 08:21

我遇到的问题是关于在Python中改变音频音调的。我现在安装了这些模块:numpy、scipy、pygame,还有scikits的“samplerate”接口。

我的目标是把一个立体声文件以不同的音调播放,并尽量减少步骤。目前,我是先用pygame.sndarray把文件加载到一个数组中,然后用scikits.samplerate.resample进行采样率转换,最后再把输出转换回声音对象,以便用pygame播放。

但问题是,我的扬声器里播放出来的音频很糟糕。肯定是我漏掉了一些步骤(而且我对数学和音频也不太了解)。

import time, numpy, pygame.mixer, pygame.sndarray
from scikits.samplerate import resample

pygame.mixer.init(44100,-16,2,4096)

# choose a file and make a sound object
sound_file = "tone.wav"
sound = pygame.mixer.Sound(sound_file)

# load the sound into an array
snd_array = pygame.sndarray.array(sound)

# resample. args: (target array, ratio, mode), outputs ratio * target array.
# this outputs a bunch of garbage and I don't know why.
snd_resample = resample(snd_array, 1.5, "sinc_fastest")

# take the resampled array, make it an object and stop playing after 2 seconds.
snd_out = pygame.sndarray.make_sound(snd_resample)
snd_out.play()
time.sleep(2)

4 个回答

0

很可能,scikits.samplerate.resample这个工具认为你的音频格式不是16位立体声。你可以查看一下scikits.samplerate的文档,看看在哪里可以选择你数组中正确的音频格式。如果它把16位的音频当成8位的垃圾来处理,那出来的结果就会很糟糕。

3

你最好的选择可能是使用 Python 的 audiere 库。

这里有一个链接,我用它做过类似的事情,真的很简单,只要好好看看所有的文档就行。

http://audiere.sourceforge.net/home.php

11

你的问题是,pygame可以处理 numpy.int16 类型的数组,但你调用 resample 函数时返回的是 numpy.float32 类型的数组:

>>> snd_array.dtype
dtype('int16')
>>> snd_resample.dtype
dtype('float32')

你可以使用 astyperesample 的结果转换成 numpy.int16 类型:

>>> snd_resample = resample(snd_array, 1.5, "sinc_fastest").astype(snd_array.dtype)

通过这个修改,你的Python脚本可以很好地播放 tone.wav 文件,声音会变得更低、更慢。

撰写回答