使用python和Qt创建精确的节拍器

时间:2012-06-26 01:45:29

标签: python qt audio pyqt pygame

我正在尝试在我的跨平台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()

1 个答案:

答案 0 :(得分:3)

我对Python和Qt的交互不太熟悉,但我确实有定时器和线程以及Qt的经验。

一般时间限制

Qt中的时间通常用于图形动画。在Qt Timers文档中,它表示定时器精确到大约15毫秒,但这取决于平台。在Windows中,如果您通过他们的documentation计时器和系统时钟阅读它,它们的准确度大约为11到16毫秒。

线程优先级

线程的优先级也会影响节拍器的结果。您应该考虑将线程的优先级设置为时间关键(请参阅QThread::Priority),以便系统为您提供更好的时间,然后告诉您的函数进行休眠(0)或yieldCurrentThread()调用完成播放声音后。

QObject Connect Calls

使用Qt::AutoConnection完成Qt中的连接呼叫,这意味着Qt决定是使用事件队列还是使用直接呼叫连接它。对于时间安排,最好是直接通话。

此外,播放声音后是否调用processEvents或根本不调用。事先做好告诉Qt,您希望在到达下一个呼叫之前处理事件队列中的任何其他内容。查看qt event system上的文档。

MIDI文件

我所知道的游戏中产生的大部分声音都是使用MIDI文件完成的。它们很小,并且它们的声音循环的渲染在许多平台上都非常一致。也许你可以选择100个midi文件中的一个。还有像ScaleTempo那样的项目,但它看起来有点陈旧(2008年最后一次更新)。

希望有所帮助。

免责声明:我发布的大多数链接来自Qt 5.我一直在编写Qt 4.7中的编程,但定时器和事件系统没有安排进行Qt 5的修改(主要是动画后端优化)到目前为止我知道。