miku39.py - ポケット・ミクにミクミク言わせる。 #大人の科学ポケミク

D
Python 2.7.6 + Pygame 1.9.1 用

u'''miku39.py - ポケット・ミクにミクミク言わせる。

つかいかた: ポケミクさん繋いでスタイラスでツンツンするだけ。
'''
import pygame
import pygame.midi
from pygame.locals import *
LYRIC_MI = 0x65 # み
LYRIC_KU = 0x07 # く
KU_NOTE = 75 # 「く」の音の高さ
KU_TIME = 500 # 「く」の長さ(ms)

WIDTH, HEIGHT = 256, 128  # 画面の大きさ
COLOR = 0, 255, 200  # 文字色
BG_COLOR = 100, 0, 50  # 背景色
FONT_SIZE = HEIGHT
FPS = 60

def set_lyric(output, lyric):
    output.write_sys_ex(
        0, [0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0x00, lyric, 0xF7])
    
def main():
    pygame.init()
    pygame.midi.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption('miku39.py')
    font = pygame.font.SysFont(pygame.font.get_default_font(), FONT_SIZE)
    for i in range(pygame.midi.get_count()):
        interf, name, input, output, opened = pygame.midi.get_device_info(i)
        if output and name == 'NSX-39 ':
            midiout = pygame.midi.Output(i)
        if input and name == 'NSX-39 ':
            midiin = pygame.midi.Input(i)
    clock = pygame.time.Clock()
    clock.tick(FPS)
    set_lyric(midiout, LYRIC_MI)
    note_off_time = None
    text = 'miku'
    while True:
        for e in pygame.event.get():
            if e.type is QUIT:
                return
            elif e.type is KEYDOWN and e.key is K_ESCAPE:
                return
        if midiin.poll():
            for e in midiin.read(1000):
                data, timestamp = e
                if (data[0] & 0xF0) == 0x90: # Note On
                    text = 'Miku'
                    note_off_time = None
                if (data[0] & 0xF0) == 0x80: # Note Off
                    set_lyric(midiout, LYRIC_KU)
                    text = 'miKu'
                    midiout.note_on(KU_NOTE, 56)
                    set_lyric(midiout, LYRIC_MI)
                    note_off_time = pygame.midi.time() + KU_TIME
        if note_off_time and (note_off_time <= pygame.midi.time()):
            midiout.note_off(KU_NOTE)
            text = 'miku'
            note_off_time = None
        screen.fill(BG_COLOR)
        s = font.render(text, True, COLOR)
        screen.blit(font.render(
            text, True, COLOR), ((WIDTH - s.get_width()) // 2, 20))
        clock.tick(FPS)
        pygame.display.flip()

if  __name__ == '__main__':
    try:
        main()
    finally:
        pygame.quit()

# Public Domain. 好きに流用してください。