drum39.py - ポケット・ミクでドラム #大人の科学ポケミク
「inst39.py - ポケット・ミクで楽器音を鳴らす。 #大人の科学ポケミク - つちのこ、のこのこ。(はてな番外地)」のドラム版。
u'''drum39.py - ポケット・ミクでドラム スタイラスでツンツンすると打楽器鳴るよ。 「A I U E」ボタンで楽器の割り当て。 「O」はシンバル、「SHIFT」はスネア、「VIBRATO」はバスドラで固定。 ''' import pygame import pygame.midi from pygame.locals import * WIDTH = 600 # 画面の大きさ HEIGHT = WIDTH // 4 COLOR = 0, 255, 200 # 文字色 BG_COLOR = 100, 0, 50 # 背景色 FONT_SIZE = HEIGHT // 2 FPS = 60 VELOCITY = 64 # ペロシティの基準 BUTTON_O_NOTE = 49 # Crash Cymbal 1 BUTTON_VIBRATO_NOTE = 35 # Bass Drum M BUTTOU_SHIFT_NOTE = 38 # Snare M # ボタンで設定される音域 BUTTON_A_NOTE_SHIFT = 24 BUTTON_I_NOTE_SHIFT = BUTTON_A_NOTE_SHIFT - 24 BUTTON_U_NOTE_SHIFT = BUTTON_I_NOTE_SHIFT - 24 BUTTON_E_NOTE_SHIFT = BUTTON_U_NOTE_SHIFT - 24 # ポケミクのボタン BUTTON_A = 0x01 BUTTON_I = 0x02 BUTTON_U = 0x04 BUTTON_E = 0x08 BUTTON_O = 0x10 BUTTON_VIBRATO = 0x20 BUTTOU_SHIFT = 0x40 POKEMIKU_NOTE = 78 # ポケミクから送出されるMIDIノートナンバー PORT_SHIFT = -16 # タポルタメント値との差分(data3 / 4 の値に対して) GM_DRUM = { # XG相当 13: 'Surdo Mute', 14: 'Surdo Open', 15: 'Hi Q', 16: 'Whip Slap', 17: 'Scratch Push', 18: 'Scratch Pull', 19: 'Finger Snap', 20: 'Click Noise', 21: 'Metronome Click', 22: 'Metronome Bell', 23: 'Seq Click L', 24: 'Seq Click H', 25: 'Brush Tap', 26: 'Brush Swirl L', 27: 'Brush Slap', 28: 'Brush Swirl H', 29: 'Snare Roll', 30: 'Castanet', 31: 'Snare L', 32: 'Sticks', 33: 'Bass Drum L', 34: 'Open Rim Shot', 35: 'Bass Drum M', 36: 'Bass Drum H', 37: 'Side Stick', 38: 'Snare M', 39: 'Hand Clap', 40: 'Snare H', 41: 'Floor Tom L', 42: 'Hi-Hat Closed', 43: 'Floor Tom H', 44: 'Hi-Hat Pedal', 45: 'Low Tom', 46: 'Hi-Hat Open', 47: 'Mid Tom L', 48: 'Mid Tom H', 49: 'Crash Cymbal 1', 50: 'High Tom', 51: 'Ride Cymbal 1', 52: 'Chinese Cymbal', 53: 'Ride Cymbal Cup', 54: 'Tambourine', 55: 'Splash Cymbal', 56: 'Cowbell', 57: 'Crash Cymbal 2', 58: 'Vibraslap', 59: 'Ride Cymbal 2', 60: 'Bongo H', 61: 'Bongo L', 62: 'Conga H Mute', 63: 'Conga H Open', 64: 'Conga L', 65: 'Timbale H', 66: 'Timbale L', 67: 'Agogo H', 68: 'Agogo L', 69: 'Cabasa', 70: 'Maracas', 71: 'Samba Whistle H', 72: 'Samba Whistle L', 73: 'Guiro Short', 74: 'Guiro Long', 75: 'Claves', 76: 'Wood Block H', 77: 'Wood Block L', 78: 'Cuica Mute', 79: 'Cuica Open', 80: 'Triangle Mute', 81: 'Triangle Open', 82: 'Shaker', 83: 'Jingle Bell', 84: 'Bell Tree' } def put_text(surface, font, text, dest, color=COLOR): x, y = dest for t in text.split('\n'): s = font.render(t, True, color) surface.blit(s, (x, y)) y += font.get_linesize() def main(): pygame.init() pygame.midi.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('drum39.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) midiout.write_short(0xB0, 7, 0) # ミクさんの音量を0に base_note_shift = BUTTON_U_NOTE_SHIFT # 中心になる音域(ミクとの差分 moduration = 0 # モジュレーション ON/OFF note_no = 0 button_o = False # 各ボタン押下状態 button_shift = False button_vibrato = False while True: sysex = False for e in pygame.event.get(): if (e.type is QUIT) or (e.type is KEYDOWN and e.key is K_ESCAPE): if last_note is not None: midiout.note_off(last_note, 64, 1) midiout.write_short(0xB0, 7, 64) # ミクさんの音量を64に return if midiin.poll(): for e in midiin.read(1000): (status,data1,data2,data3), timestamp = e if sysex and status == 0x11 and data1 == 0x20: if not (data3 & BUTTON_O): button_o = False if not (data3 & BUTTOU_SHIFT): button_shift = False if not (data3 & BUTTON_VIBRATO): button_vibrato = False if data3 & BUTTON_A: base_note_shift = BUTTON_A_NOTE_SHIFT if data3 & BUTTON_I: base_note_shift = BUTTON_I_NOTE_SHIFT if data3 & BUTTON_U: base_note_shift = BUTTON_U_NOTE_SHIFT if data3 & BUTTON_E: base_note_shift = BUTTON_E_NOTE_SHIFT if data3 & BUTTON_O: if not button_o: midiout.note_on(BUTTON_O_NOTE, VELOCITY, 9) button_o = True if data3 & BUTTOU_SHIFT: if not button_shift: midiout.note_on(BUTTOU_SHIFT_NOTE, VELOCITY, 9) button_shift = True if data3 & BUTTON_VIBRATO: if not button_vibrato: midiout.note_on(BUTTON_VIBRATO_NOTE, VELOCITY, 9) button_vibrato = True if status == 0xF0: # SysEx start sysex = True if status == 0xF7: # SysEx end sysex = False if (status & 0xF0) == 0x90: # Note On note_no = now_note_shift + data1 + base_note_shift midiout.note_on(note_no, VELOCITY, 9) last_note = note_no if (status & 0xF0) == 0x80: # Note Off if last_note is not None: midiout.note_off(last_note, VELOCITY, 9) last_note = None if (status & 0xF0) == 0xE0: # ピッチベンド midiout.write_short(0xE1, data1, data2) now_note_shift = PORT_SHIFT + data2 / 4 screen.fill(BG_COLOR) try: note_name = GM_DRUM[note_no] if last_note is not None: note_name = note_name.upper() except KeyError: note_name = None x = y = 10 put_text(screen, font, '%3d: %s' % (note_no, note_name), (x, 10)) y = HEIGHT // 2 x += FONT_SIZE put_text(screen, font, 'vV'[button_vibrato], (x, y)) put_text(screen, font, 'sS'[button_shift], (x + FONT_SIZE, y)) put_text(screen, font, 'oO'[button_o], (x + FONT_SIZE * 2, y)) clock.tick(FPS) pygame.display.flip() if __name__ == '__main__': try: main() finally: pygame.quit() # Public Domain. 好きに流用してください。
歌うキーボード ポケット・ミク (大人の科学マガジンシリーズ)
- 作者: 大人の科学マガジン編集部
- 出版社/メーカー: 学研プラス
- 発売日: 2014/04/03
- メディア: ムック
- この商品を含むブログ (24件) を見る