1

我一直在尝试使用我的树莓派 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找到

4

1 回答 1

0

您接收事件的方式仅允许它每帧处理一个事件。这是因为您使用函数 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)
于 2020-07-17T15:18:47.163 回答