FingerDrum をつくる(MIDI編)

目次
4x4 のステキなkeypad ができた。
GarageBandに繋いで演奏できるようにする。 MIDI制御の基本は同じ。
## GarageBand のドラムセットのnote
ドレミを押すとなんかドラムセットのどっかの音が鳴る。
その程度の認識だったけど、ちゃんと調べてくれてるひとが! ありがとう。
python
BD=36 # バスドラム
SN=38 # スネア1
RM=40 # リムタムはないので、スネア2
CH=42 # クローズドハイハット
OH=46 # オープンハイハット
HT=50 # ハイタム
LT=45 # ロータム
FT=43 # フロアタム
HC=49 # クラッシュド・シンバル(ハイ)
LC=49 # クラッシュド・シンバル(ロウ)
RC=51 # ライドシンバルキーと音(楽器)の配置
4x4 のどこを押したらどの音がなるべきか?
なんとなくドラムセットの配置と似ればいいのかと思っていた。 が、スパンキーさんの本と動画でなるほどと感心したので、その通りに決定。
python
self.notes_ = [
[ LC, LT, FT, HC ],
[ CH, HT, OH, CH ],
[ RC, SN, RM, RC ],
[ BD, BD, BD, BD ], ]配線
- GP2 ... COL A
- GP3 ... COL B
- GP4 ... COL C
- GP5 ... COL D
- GP6 ... ROW 1
- GP7 ... ROW 2
- GP8 ... ROW 3
- GP9 ... ROW 4
プログラム
CircuitPythonで、簡単。
finger_drum.py · Gistpython
import board
import busio
import digitalio
import time
import usb_midi
import adafruit_midi
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
NROW=4
NCOL=4
# Garageband notes for drum
BD=36 # バスドラム
SN=38 # スネア1
RM=40 # リムタム=スネア2
CH=42 # クローズドハイハット
OH=46 # オープンハイハット
HT=50 # ハイタム
LT=45 # ロータム
FT=43 # フロアタム
HC=49 # クラッシュド・シンバル(ハイ)
LC=49 # クラッシュド・シンバル(ロウ)
RC=51 # ライドシンバル
class MidiDrum:
def __init__(self):
self.was_presses_ = []
self.was_releases_ = []
# keymap
self.notes_ = [
[ LC, LT, FT, HC ],
[ CH, HT, OH, CH ],
[ RC, SN, RM, RC ],
[ BD, BD, BD, BD ],
]
# key press status
self.presses_ = [
[ False, False, False, False ],
[ False, False, False, False ],
[ False, False, False, False ],
[ False, False, False, False ],
]
# COLS(for scan key press & relase)
self.cols_ = []
for pin in (board.GP2, board.GP3, board.GP4, board.GP5):
key = digitalio.DigitalInOut(pin)
key.switch_to_input(pull=digitalio.Pull.UP)
self.cols_.append(key)
# ROWS(for V or GND output)
self.rows_ = []
for pin in (board.GP6, board.GP7, board.GP8, board.GP9):
key = digitalio.DigitalInOut(pin)
key.direction = digitalio.Direction.OUTPUT
self.rows_.append(key)
def scan_keymap(self):
#
# scan row from 0 to (NROW-1)
#
# value=False is PRESS
is_presses = []
is_releases = []
for row_no in range(NROW):
# change HIGH and LOW for scan
for r in range(NROW):
if row_no == r:
self.rows_[r].value = 0 # OFF
else:
self.rows_[r].value = 1 # ON
for col_no in range(NCOL):
# check key press
value = self.cols_[col_no].value # get ON/OFF
if value != self.presses_[row_no][col_no]:
# 変化があった
# print("change ({},{}) {}->{}".format(row_no, col_no, self.presses_[row_no][col_no], value))
self.presses_[row_no][col_no] = value
note = self.notes_[row_no][col_no]
if not value:
# pressed
is_presses.append(note)
else:
# released
is_releases.append(note)
return [ is_presses, is_releases ]
if __name__ == "__main__":
# MIDI
midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)
print("START")
# key press LED
led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT
md = MidiDrum()
next_time = time.monotonic_ns()
while True:
# get current key press or release
now = time.monotonic_ns()
if next_time < now:
[is_presses, is_releases] = md.scan_keymap()
if len(is_presses) > 0:
for note in is_presses:
# print("press note {}".format(note))
midi.send(NoteOn(note, 127))
led.value = True # ON
if len(is_releases) > 0:
for note in is_releases:
# print("release note {}".format(note))
midi.send(NoteOff(note, 0))
led.value = False # OFF
next_time = now + 10_000_000 # 0.01sec
time.sleep(0.001)midi ライブラリの設定は、こっち。
