5

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

1 回答 1

3

我对与 Python 和 Qt 的交互不是很熟悉,但我确实有使用计时器和线程以及 Qt 的经验。

一般时间限制

Qt 中的时序通常用于图形动画。在Qt Timers文档中,它说计时器精确到大约 15 毫秒,但这取决于平台。在 Windows 中,如果您阅读他们关于计时器和系统时钟的文档,它会说它们精确到大约 11 到 16 毫秒。

线程优先级

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

QObject 连接调用

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

此外,在播放声音后调用 processEvents 或根本不调用。事先这样做会告诉 Qt,您希望在到达下一个呼叫之前处理位于事件队列中的任何其他内容。查看关于qt 事件系统的文档。

MIDI 文件

我知道的大多数游戏中生成的声音都是使用 MIDI 文件完成的。它们很小,并且它们的声音循环的渲染在许多平台上都非常一致。也许你可以从 100 个 midi 文件中选择一个来完成一些事情。也有像ScaleTempo这样的项目,但它似乎有点旧(最后更新于 2008 年)。

希望有帮助。

免责声明:我发布的大多数链接都来自 Qt 5。我主要在 Qt 4.7 中进行编程,但据我所知,定时器和事件系统并未计划为 Qt 5 进行改造(主要是动画后端优化) .

于 2012-06-26T04:54:51.257 回答