我正在尝试在我的跨平台pyQt程序中添加一个简单的节拍器,但要获得准确的计时有很多困难。使用PyGame的音响系统播放声音似乎效果最佳。我试过Phonon,但它根本不一致,QSound在我的系统上根本不起作用。我已经尝试使用python的时间库和使用QTimers来处理时序,但QTimeLine似乎工作得最好。
节奏较低的时机也不算太差......在这里和那里仍然是打嗝。然而,更高的节奏并不准确。
非常感谢任何想法/建议!
以下是一些代码:
class Metronome(object):
def init_metronome(self):
self.metronome_timer = QtCore.QTimeLine(100000)
self.metronome_timer.valueChanged.connect(self.tick)
self.metronome_timer.setCurveShape(3) #linear curve
self.ui.pushButton_metronome.toggled.connect(self.toggle_metronome)
self.ui.spinBox_metronome_bpm.valueChanged.connect(self.set_metronome_bpm)
pygame.mixer.init()
self.sound = pygame.mixer.Sound("./sounds/tick.wav")
def toggle_metronome(self):
if self.ui.pushButton_metronome.isChecked() == True:
self.set_metronome_bpm()
self.metronome_timer.start()
else:
self.metronome_timer.stop()
def set_metronome_bpm(self):
bpm = self.ui.spinBox_metronome_bpm.value()
self.metronome_timer.setUpdateInterval(60./bpm * 1000)
def tick(self):
QtCore.QCoreApplication.processEvents()
self.sound.play()
答案 0 :(得分:3)
我对Python和Qt的交互不太熟悉,但我确实有定时器和线程以及Qt的经验。
Qt中的时间通常用于图形动画。在Qt Timers文档中,它表示定时器精确到大约15毫秒,但这取决于平台。在Windows中,如果您通过他们的documentation计时器和系统时钟阅读它,它们的准确度大约为11到16毫秒。
线程的优先级也会影响节拍器的结果。您应该考虑将线程的优先级设置为时间关键(请参阅QThread::Priority
),以便系统为您提供更好的时间,然后告诉您的函数进行休眠(0)或yieldCurrentThread()
调用完成播放声音后。
使用Qt::AutoConnection
完成Qt中的连接呼叫,这意味着Qt决定是使用事件队列还是使用直接呼叫连接它。对于时间安排,最好是直接通话。
此外,播放声音后是否调用processEvents或根本不调用。事先做好告诉Qt,您希望在到达下一个呼叫之前处理事件队列中的任何其他内容。查看qt event system上的文档。
我所知道的游戏中产生的大部分声音都是使用MIDI文件完成的。它们很小,并且它们的声音循环的渲染在许多平台上都非常一致。也许你可以选择100个midi文件中的一个。还有像ScaleTempo那样的项目,但它看起来有点陈旧(2008年最后一次更新)。
希望有所帮助。
免责声明:我发布的大多数链接来自Qt 5.我一直在编写Qt 4.7中的编程,但定时器和事件系统没有安排进行Qt 5的修改(主要是动画后端优化)到目前为止我知道。