Last active
December 17, 2015 14:29
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
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)
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
Wow this looks interesting
Is it a complete program?