我正在尝试编写一个节拍器脚本,它可以为我提供音频反馈并将 MIDI 消息发送到合成器。我用Python 2.7.5+
and Pygame 1.9.1.release
在 Linux Mint 16 上。我对 MIDI 部分很满意。令我烦恼的是时机。
首先,这基本上是我所做的:
import time
import pygame.mixer
pygame.mixer.init()
sound = pygame.mixer.Sound('click.wav')
interval = 0.5 #should be equivalent to 120 bpm
t0 = time.time()
while True: #infinite loop, use keyboard interrupt Ctrl-C
if time.time() - t0 >= interval:
sound.play()
t0 = time.time()
然而,这是相当不稳定的并且不可能演奏乐器。
我也调查过time.clock()
:
import time
import pygame.mixer
pygame.mixer.init()
sound = pygame.mixer.Sound('click.wav')
interval = 0.5 #should be equivalent to 120 bpm
t0 = time.clock()
while True:
if time.clock() - t0 >= interval:
sound.play()
t0 = time.clock()
...也pygame.time.Clock()
, 具体来说pygame.time.Clock.tick_busy_loop()
,据说它通过消耗更多的处理器来提供更好的精度:
import pygame.time
import pygame.mixer
pygame.mixer.init()
#pygame.time has no init function
sound = pygame.mixer.Sound('click.wav')
clock = pygame.time.Clock()
interval = 0.5 #should be equivalent to 120 bpm
time_passed = 0
clock.tick_busy_loop()
while True: #infinite loop, use keyboard interrupt Ctrl-C
time_passed += clock.tick_busy_loop()
if time_passed >= interval:
sound.play()
time_passed = 0
所有这些都产生了相同的问题。虽然,我不得不承认,当我尝试这些最小的例子时,pygame.time
溶液非常稳定。这里的问题是,在我的实际脚本中,我在while
循环似乎会影响循环所需的时间,并且点击开始结巴和绊倒。
我在看这个答案,但我不太了解 MIDI 文件的概念。这会有帮助吗?一些解释会是最有帮助的。
此外,我试图把
import os
os.nice(-19)
一开始,为了获得更高的进程优先级,但没有明显的改善。
我想知道如何才能像 Cubase、Ableton 和 Logic 等常见 DAW 那样实现稳定的节拍器。我读到了生成或预先录制相关节奏的音频样本并链接这些样本以实现更高精度的方法,但我真的很想避免这种方法,因为它看起来非常费力。
有什么聪明的方法我可以使用马厩pygame.time
变体并在其他地方进行处理?
如果有任何用处:这是实际的while
我正在运行的循环:
bpm = 80.0
beats_in_one_second = bpm/60.0
midi_send_interval = beats_in_one_second/24.0 #MIDI convention
playing = True
player.write_short(250) #start
frame_count = 0
quarter_count = 0
time_0 = time.time()
while playing:
if time.time() - time_0 >= midi_send_interval:
player.write_short(248) #clock tick
time_0 = time.time()
frame_count += 1
if frame_count == 24:
sound.play()
quarter_count += 1
frame_count = 0
if quarter_count == 16:
playing = False
player.write_short(252) #stop
问题是 MIDI 标准要求每个四分音符有 24 个消息,这显着增加了对精度的要求。