To my surprise this worked out-the-box, nothing to install. I made sure my Raspbian OS was up to date before I started but that was it. I have never done anything with Midi before but I knew it was a simple serial protocol and so assumed I'd be able to open some kind of tty device. In fact the ALSA driver on the OS detects it correctly as a USB-Midi input/ouput device. You can see this by running the amidi command:
pi@raspberrypi ~ $ amidi -l Dir Device Name IO hw:1,0,0 USB2.0-MIDI MIDI 1 O hw:1,0,1 USB2.0-MIDI MIDI 2
There are probably loads of proper Midi tools you can use since it has been discovered correctly by I just wanted to look at the raw bytes coming in. The device node that's been created in the file system can be found in /dev/snd:
pi@raspberrypi ~ $ ls /dev/snd by-id by-path controlC0 controlC1 midiC1D0 pcmC0D0p seq timer
So all my program has to do is read bytes from /dev/snd/midiC1D0. To get this to work I didn't need to understand or decode much of the protocol - I'm basically just looking for a sequence when an "instrument" is hit. In this case it is a sequence (in hex) of 99 XX where XX is the instrument code, 26 for snare drum, 24 for kick drum etc. There's a lot more going on but I can ignore the rest apart from a useful continual pulse of FE. This is known as "Active sense" and you get this once every 300ms. I'm using this to switch the GPIO off again as you'll see in the code later. In order to ring the bell you need a quick on/off motion. You can read more about the solenoid bell in my previous post: Raspberry Pi solenoid alarm bell.
Anyway, here's a rather shakey video (sorry) and the code. Enjoy!
import RPi.GPIO as GPIO inst = { '\x26':'snare', '\x28':'snare rim', '\x30':'tom1', '\x32':'tom1 rim', '\x2d':'tom2', '\x2f':'tom2 rim', '\x2b':'tom3', '\x3a':'tom3 rim', '\x24':'kick', '\x1a':'hi-hat rim', '\x2e':'hi-hat head', '\x2c':'hi-hat close', '\x31':'crash head', '\x37':'crash rim', '\x33':'ride head', '\x3b':'ride rim', '\x35':'ride bell', } f=open('/dev/snd/midiC1D0') note=False GPIO_NUM = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(GPIO_NUM, GPIO.OUT) while True: b = f.read(1) if b == '\xfe': GPIO.output(GPIO_NUM, False) else: # if b == '\x40': # print hex(ord(b)) # else: # print hex(ord(b)), if b == '\x99': note=True elif note: if b in inst: print inst[b] if b == '\x26': GPIO.output(GPIO_NUM, True) else: print hex(ord(b)) note=False
No comments:
Post a Comment