gpt4 book ai didi

python - 在 Python 中播放期间更改音频的音高(和速度)

转载 作者:可可西里 更新时间:2023-11-01 09:22:09 25 4
gpt4 key购买 nike

我正在开发一个播放音乐的 Python 程序。其中一项功能是一个 slider ,用户可以向上或向下拖动它来改变音乐播放时的音调。

例如,如果将音高设置为 2,则音乐听起来高一个 Octave ,播放速度加倍,持续时间减半。我真正要改变的只是播放速度,但我需要以交互方式实时进行。

可以找到在 Flash 中实现此功能的一个很好的例子 here . (加载需要一点时间,请耐心等待。)

我研究了很多 python 音频包,但我还没有找到可以改变当前正在播放的声音的音高的包。我有多个版本的Python,所以没有要求包支持什么版本。我正在 Windows 7 上开发它。

有什么建议吗?

最佳答案

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

此程序播放名为“music.wav”的单声道 wav 文件(与程序位于同一文件夹中)并显示一个短而宽的窗口。当您在窗口中单击并拖动时,音乐的音调会发生变化。窗口左侧低两个 Octave ,右侧高两个 Octave 。

这里有一些奇怪的行为,我不确定如何修复。如果当前音调较低,则在音调改变之前会有大约 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

关于python - 在 Python 中播放期间更改音频的音高(和速度),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3982007/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com