Skip to content

Instantly share code, notes, and snippets.

@ryansturmer
Last active December 17, 2015 14:29
Show Gist options
  • Save ryansturmer/5625021 to your computer and use it in GitHub Desktop.
Save ryansturmer/5625021 to your computer and use it in GitHub Desktop.
Some functions for dealing with MIDI and music data. Can't say how many times I've re-written these over the years. Bonus demo function written using pygame (poll a midi input device and print events to the console)
NOTES_SHARP = ["C", "C#", "D", "D#", "E", "F", "F#", "G","G#", "A","A#","B"]
NOTES_FLAT = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G","Ab", "A","Bb","B"]
def generate_midi_event_map():
events = ['Note Off',
'Note On',
'Polyphonic Aftertouch',
'Control Mode Change',
'Program Change',
'Channel Aftertouch',
'Pitch Wheel Range']
retval = {}
for i in range(128, 239,16):
for j in range(16):
retval[i+j] = "Ch%d %s" % (j+1, events[(i-128)/16])
retval.update({ 240 : 'System Exclusive',
241 : 'System Common - Undefined',
242 : 'Sys Com Song Position Pntr',
243 : 'Sys Com Song Select(Song #)',
244 : 'System Common - Undefined',
245 : 'System Common - Undefined',
246 : 'Sys Com Tune Request',
247 : 'Sys Com-End of SysEx (EOX)',
248 : 'Sys Real Time Timing Clock',
249 : 'Sys Real Time Undefined',
250 : 'Sys Real Time Start',
251 : 'Sys Real Time Continue',
252 : 'Sys Real Time Stop',
253 : 'Sys Real Time Undefined',
254 : 'Sys Real Time Active Sensing',
255 : 'Sys Real Time Sys Reset'})
return retval
def generate_midi_note_names(notes):
retval = {}
for i in range(24,128):
x = i-24
retval[i] = "%s%d" % (notes[x % 12],(x/12)+1)
return retval
MIDI_EVENT_MAP = generate_midi_event_map()
MIDI_NOTE_MAP_SHARP = generate_midi_note_names(NOTES_SHARP)
MIDI_NOTE_MAP_FLAT = generate_midi_note_names(NOTES_FLAT)
def midi_note_name(x):
flat = MIDI_NOTE_MAP_FLAT.get(x, "??")
sharp = MIDI_NOTE_MAP_SHARP.get(x, "??")
if flat == sharp:
return flat
else:
return "%s (%s)" % (flat, sharp)
def midi_note_frequency(x):
return 440.0*2**((x-69)/12.0)
def demo(device_id):
import pygame.midi
try:
import winsound
except:
pass
pygame.midi.init()
i = pygame.midi.Input(device_id)
try:
while True:
events = i.read(1)
if events:
((evt, d1,d2,d3),timestamp) = events[0]
if evt < 160:
print "%s: %s (%gHz)" % (MIDI_EVENT_MAP[evt], midi_note_name(d1), midi_note_frequency(d1))
if evt == 144:
try:
winsound.Beep(int(midi_note_frequency(d1)), 100)
except:
pass
else:
print "%s: %s" % (MIDI_EVENT_MAP[evt], (d1,d2,d3))
except Exception, e:
pygame.midi.quit()
raise e
if __name__ == "__main__":
demo(1)
@ryansturmer
Copy link
Author

It's mostly functions for dealing with midi data, but the demo() function does take input from a midi device and print events to the console (and play notes on the speaker if you're on windows)

@OzWoz
Copy link

OzWoz commented May 23, 2013

thanx - very cool to have different hobbies that interact, such as music & programming ...!

I just discovered this Gist thing yesterday (not really sure about it - its purpose and usefullness - as it doesn't appear to have a search function, within this Android app version anyway) and was clicking on new posts as they appeared then saw yours,,, kind of like a "lucky dip" - ha ha

So maybe that's how it works ...
click click click then eventually see something inspiring... maybe...
if ya lucky :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment