在Python中播放时改变audio的音调和速度

我正在开发一个播放音乐的Python程序。 一个function将是一个滑块,用户可以上下拖动以改变音乐播放的音调。

例如,如果音高设置为2,那么音乐听起来会高一个八度,播放速度会快一倍,而且会持续一半。 所有我真正改变的是播放速度,但我需要实时交互。

在flash中实现的这个function的一个很好的例子可以在这里find。 (加载需要一点点,要耐心等待)

我已经看过很多pythonaudio包,但我还没有find可以改变当前正在播放的声音的音调。 我有多个版本的Python,所以不需要包支持哪个版本。 我正在Windows 7上开发这个。

有什么build议么?

这听起来好像你想要即时重新采样音频。

也许你可以尝试使用scikits.samplerate模块。 它使用秘密兔子代码库 。

在Craig McQueen的帮助下,我创建了一个概念验证程序。

该程序播放一个名为“music.wav”的单声道 wav文件(与程序位于同一文件夹中),并显示一个短而宽的窗口。 当您在窗口中单击并拖动时,音乐的音调会改变。 窗户的左侧是两个八度音阶,右侧是两个八度音阶。

这里有一些奇怪的行为,我不知道如何解决。 如果音高目前很低,那么在音高改变之前大约有2秒延迟。 但是,高音调的音高实时变化。 (音高越低,延迟越平稳)。 如果soundOutput.getLeft() < 0.2我只会将更多的声音添加到缓冲区。 也就是说,如果缓冲区剩余的声音量小于0.2秒。 因此不应该有任何延误。 对于故障排除,我包含了将soundOutput.getLeft()写入文件代码。 它往往一直停留在或非常接近0。

减少读取到waveRead.readframes(100)的帧减少了延迟,但也使声音波涛汹涌。 增加读取帧显着增加了延迟。

import os,sys,wave,pygame,numpy,pymedia.audio.sound,scikits.samplerate class Window: def __init__(self,width,height,minOctave,maxOctave): """ width,height: the width and height of the screen. minOctave,maxOctave: the highest and lowest pitch changes. 0 is no change. """ self.minOctave = minOctave self.maxOctave = maxOctave self.width = width self.mouseDown = False self.ratio = 1.0 # The resampling ratio waveRead = wave.open(os.path.join(sys.path[0],"music.wav"),'rb') sampleRate = waveRead.getframerate() channels = waveRead.getnchannels() soundFormat = pymedia.audio.sound.AFMT_S16_LE soundOutput = pymedia.audio.sound.Output(sampleRate,channels,soundFormat) pygame.init() screen = pygame.display.set_mode((width,height),0) screen.fill((255,255,255)) pygame.display.flip() fout = open(os.path.join(sys.path[0],"musicdata.txt"),'w') # For troubleshooting byteString = waveRead.readframes(1000) # Read at most 1000 samples from the file. while len(byteString) != 0: self.handleEvent(pygame.event.poll()) # This does not wait for an event. fout.write(str(soundOutput.getLeft()) + "n") # For troubleshooting if soundOutput.getLeft() < 0.2: # If there is less than 0.2 seconds left in the sound buffer. array = numpy.fromstring(byteString,dtype=numpy.int16) byteString = scikits.samplerate.resample(array,self.ratio,"sinc_fastest").astype(numpy.int16).tostring() soundOutput.play(byteString) byteString = waveRead.readframes(500) # Read at most 500 samples from the file. waveRead.close() return def handleEvent(self,event): if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE): sys.exit() if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: self.mouseDown = True self.setRatio(event.pos) if event.type == pygame.MOUSEBUTTONUP and event.button == 1: self.mouseDown = False if event.type == pygame.MOUSEMOTION and self.mouseDown: self.setRatio(event.pos) return None def setRatio(self,point): self.ratio = 2 ** -(self.minOctave + point[0] * (self.maxOctave - self.minOctave) / float(self.width)) print(self.ratio) def main(): Window(768,100,-2.0,2.0) if __name__ == '__main__': main()

试图让所有我使用的软件包一起工作,这是一件很痛苦的事情。 我使用的是Python 2.6.6 , PyGame 1.9.1 for python 2.6 , NumPy 1.3.0 for python 2.6 , PyMedia 1.3.7.3 for python 2.6以及scikits.samplerate 0.3.1 for python 2.6 。 请注意,scikits.samplerate与NumPy 1.4或更高版本冲突,其中一个包(我忘记了哪一个)需要setuptools

你可能想看看使用wxPython来创建一个媒体播放器 ,并调查SetPlaybackRate()函数。 wxWidget文档在这里

这个SetPlaybackRate()函数在所有平台上都不被支持,而我自己也没有试过,看看它是否正是你想要的,以及它的工作与否。

设置工具是scikits.samplerate 0.3.1所必需的

如果你不这样做,你会不断得到一个错误ImportError:没有名为pkg_resources的模块

相关文章

可以认为OpenFeign是Feign的增强版,不同的是OpenFeign支持S...
为进一步规范小程序交易生态、提升用户购物体验、满足用户在...
云原生之使用Docker部署Dashdot服务器仪表盘
本文主要描述TensorFlow之回归模型的基本原理
1.漏洞描述Apache Druid 是一个集时间序列数据库、数据仓库和...
内部类(当作类中的一个普通成员变量,只不过此成员变量是cl...