【问题标题】:Pygame keyboard event too slowPygame键盘事件太慢
【发布时间】:2020-07-17 23:18:47
【问题描述】:

我一直在尝试使用我的树莓派 4 创建一个 MIDI 键盘,并且我正在尝试将我的键盘事件与 MIDI 消息链接起来。问题是代码在树莓派上运行非常缓慢,并且在可以听到声音时存在输入延迟。这不是合成器问题,而是 Pygame 的延迟,因为我尝试在没有 Pygame 的情况下运行它。任何人都可以发现以下代码的任何主要问题吗?

import pygame as pg
from pygame.locals import *
from sonic_pi_api import SynthStream
from keyboard import Keyboard
import sys

class Main_Menu(object):
    def __init__(self):
        pg.init()
        pg.display.set_caption('OP1 interface test')
        self.screen = pg.display.set_mode((500, 500), 32)
        self.font = pg.font.SysFont(None, 20)
        self.mainClock = pg.time.Clock()
        self.stream = SynthStream(stream_num=0)
        self.keyboard = Keyboard(self.stream)
        self.instrum_index = 0
        self.key_set = self.make_key_mapping()
        self.on_notes = set()

        self.loop()

    def draw_interface(self):
        self.screen.fill((0, 0, 255))
        self.draw_text('main menu', self.font, (255, 255, 255), self.screen, 20, 20)

        mx, my = pg.mouse.get_pos()

        button_1 = pg.Rect(50, 100, 200, 50)
        pg.draw.rect(self.screen, (255, 0, 0), button_1)

    def get_events(self):
        e = pg.event.wait()
        if e.type == pg.QUIT:
            sys.exit()
        elif e.type == pg.KEYDOWN:
            try:
                note = self.key_set[e.key]
            except KeyError:
                pass
            else:
                if note not in self.on_notes:
                    self.keyboard.key_down(note)
                    self.on_notes.add(note)
        elif e.type == pg.KEYUP:
            try:
                note = self.key_set[e.key]
            except KeyError:
                pass
            else:
                if note in self.on_notes:
                    self.keyboard.key_up(note)
                    self.on_notes.remove(note)


        # if keys[pg.K_UP]:
        #     self.keyboard.next_prog(0,pressed=True)
        # elif not keys[pg.K_UP]:
        #     self.keyboard.next_prog(0,pressed=False)
        # if keys[pg.K_DOWN]:
        #     self.keyboard.prev_prog(1, pressed=True)
        # elif not keys[pg.K_DOWN]:
        #     self.keyboard.prev_prog(1, pressed=False)

    def make_key_mapping(self):
        key_list = [
            pg.K_z,
            pg.K_s,
            pg.K_x,
            pg.K_d,
            pg.K_c,
            pg.K_v,
            pg.K_g,
            pg.K_b,
            pg.K_h,
            pg.K_n,
            pg.K_j,
            pg.K_m,
            pg.K_COMMA,
        ]
        mapping = {}
        for i in range(len(key_list)):
            mapping[key_list[i]] = (i)
        return mapping



    def loop(self):
        while True:
            self.draw_interface()
            self.get_events()
            pg.display.update()
            self.mainClock.tick(120)

    def draw_text(self, text, font, color, surface, x, y):
        textobj = font.render(text, 1, color)
        textrect = textobj.get_rect()
        textrect.topleft = (x, y)
        surface.blit(textobj, textrect)

整个项目可以在https://github.com/Riddy21/Portable_Synthesizer找到

【问题讨论】:

    标签: python pygame keyboard fluidsynth


    【解决方案1】:

    您接收事件的方式只允许它每帧处理一个事件。 这是因为您使用函数 pygame.event.wait() 等待任何事件发生并返回给定事件。 如果你想处理每一个事件,每一帧都有一个事件,而不是每帧一个事件,你可以使用函数 pygame.event.get() 来返回每个尚未处理的事件的元组。

    所以你可以从这里改变你的代码:

    def get_events(self):
        e = pg.event.wait()
        if e.type == pg.QUIT:
            sys.exit()
        elif e.type == pg.KEYDOWN:
            try:
                note = self.key_set[e.key]
            except KeyError:
                pass
            else:
                if note not in self.on_notes:
                    self.keyboard.key_down(note)
                    self.on_notes.add(note)
        elif e.type == pg.KEYUP:
            try:
                note = self.key_set[e.key]
            except KeyError:
                pass
            else:
                if note in self.on_notes:
                    self.keyboard.key_up(note)
                    self.on_notes.remove(note)
    

    到这里:

    def get_events(self):
    for e in pg.event.get():
        if e.type == pg.QUIT:
            sys.exit()
        elif e.type == pg.KEYDOWN:
            try:
                note = self.key_set[e.key]
            except KeyError:
                pass
            else:
                if note not in self.on_notes:
                    self.keyboard.key_down(note)
                    self.on_notes.add(note)
        elif e.type == pg.KEYUP:
            try:
                note = self.key_set[e.key]
            except KeyError:
                pass
            else:
                if note in self.on_notes:
                    self.keyboard.key_up(note)
                    self.on_notes.remove(note)
    

    【讨论】:

    • 哦,谢谢!那行得通!那么在什么情况下你会使用 event.wait() 呢?
    • 没问题。如果您暂停程序,函数 event.wait() 会很有用。您可以在循环中检查事件类型,当您收到事件时,您会跳出循环。这比在 while 循环中使用 for 循环比不断检查 wantet 事件更有效。
    猜你喜欢
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多