# HG changeset patch # User Daniel O'Connor # Date 1457177384 -37800 # Node ID 0773354c742882563d90c041a8a388a36f3422ef Initial commit, WIP. diff -r 000000000000 -r 0773354c7428 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sat Mar 05 21:59:44 2016 +1030 @@ -0,0 +1,24 @@ +.SUFFIXES: .mup .ps .midi + +MUP= mup +RM= rm -f +MOPTS= +MVOPTS= +MPOPTS= -DPIANO -DNOVOICE + +all: test.midi test.ps +#all: test.ps test-piano.ps test.midi + +test-piano.ps: test.mup + $(MUP) $(MOPTS) $(MPOPTS) $> > $@ + +clean: + $(RM) test.ps test-piano.ps + +# Generic rules +.mup.midi: + $(MUP) -m $@ $> + +.mup.ps: + $(MUP) $(MOPTS) $(MVOPTS) $> > $@ + diff -r 000000000000 -r 0773354c7428 README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Sat Mar 05 21:59:44 2016 +1030 @@ -0,0 +1,1 @@ +https://github.com/vishnubob/python-midi.git diff -r 000000000000 -r 0773354c7428 musiccutter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/musiccutter.py Sat Mar 05 21:59:44 2016 +1030 @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +import exceptions +import mido +import svgwrite +import sys + +def test(): + # http://www.orgues-de-barbarie.com/wp-content/uploads/2014/09/format-cartons.pdf + conf = { 'notefile' : 'notes', 'pitch' : 5.5 } + midi2note, note2midi = genmidi2note() + note2slot = loadnote2slot(conf['notefile'], note2midi) + midi2svg('test.midi', 'test%d.svg', conf['pitch'], midi2note, note2midi, note2slot) + +# http://www.electronics.dit.ie/staff/tscarff/Music_technology/midi/midi_note_numbers_for_octaves.htm +def genmidi2note(): + '''Create forward & reverse tables for midi number to note name (assuming 69 == A440)''' + names = ['C%d', 'C%d#', 'D%d', 'D%d#', 'E%d', 'F%d', 'F%d#', 'G%d', 'G%d#', 'A%d', 'A%d#', 'B%d'] + midi2note = {} + note2midi = {} + for midi in range(128): + octave = midi / len(names) + index = midi % len(names) + name = names[index] % (octave) + midi2note[midi] = name + note2midi[name] = midi + + return midi2note, note2midi + +def loadnote2slot(fname, note2midi): + svg = svgwrite.Drawing(fname) + + note2slot = {} + index = 0 + + for note in file(fname): + note = note.strip() + if note[0] == '#': + continue + if note not in note2midi: + raise exceptions.ValueError('Note \'%s\' not valid' % note) + note2slot[note] = index + index += 1 + + return note2slot + +def emitnote(svg, slot, start, notelen): + # Let us say 185 ticks for a quaver and that is 5mm long + tickscale = 185.0 / 5.0 + pitch = 5.5 + offset = 6 + x = start / tickscale + y = offset + slot * pitch + w = notelen / tickscale + h = pitch + print x, y, w, h + svg.add(svgwrite.shapes.Rect(insert = ('%.3fcm' % (x / 10, '%.3fcm' % (y / 10)), size = (w, h), stroke = 'red', stroke_width = '1px', fill = 'red')) + +def midi2svg(inf, outpat, pitch, midi2note, note2midi, note2slot): + midi = mido.MidiFile(inf) + svg = svgwrite.Drawing(outpat % (0)) + tnum = 0 + for t in midi.tracks: + print "Track", tnum + tnum += 1 + channels = [] + for i in range(16): + channels.append({}) + ctime = 0 + for ev in t: + ctime += ev.time + if ev.type == 'note_on' and ev.velocity > 0: + if ev.note in channels[ev.channel]: + print "Duplicate channel on message" + else: + channels[ev.channel][ev.note] = ctime + elif ev.type == 'note_off' or (ev.type == 'note_on' and ev.velocity == 0): + if ev.note not in channels[ev.channel]: + print 'Note_off with no corresponding note_on for track %d channel %d note %d' % (tnum, ev.channel, ev.note) + else: + note = midi2note[ev.note] + if note not in note2slot: + print 'Skipping unplayable note %s' % (note) + else: + notelen = ctime - channels[ev.channel][ev.note] + slot = note2slot[note] + print 'Note %s (%d) at %d length %d' % (note, slot, ctime, notelen) + emitnote(svg, slot, ctime, notelen) + del channels[ev.channel][ev.note] + svg.save() + +if __name__ == '__main__': + main() diff -r 000000000000 -r 0773354c7428 notes --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/notes Sat Mar 05 21:59:44 2016 +1030 @@ -0,0 +1,30 @@ +# List of notes the organ plays in order +# Any line beginning with a # is a comment +# http://www.orgues-de-barbarie.com/wp-content/uploads/2014/09/gammes.pdf +C3 +D3 +F3 +G3 +C4 +D4 +E4 +F4 +F4# +G4 +A4 +A4# +B4 +C5 +C5# +D5 +D5# +E5 +F5 +F5# +G5 +G5# +A5 +A5# +B5 +C6 +D6 diff -r 000000000000 -r 0773354c7428 test.mup --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test.mup Sat Mar 05 21:59:44 2016 +1030 @@ -0,0 +1,31 @@ +header + title(22) "Test" + +score + scale = 0.75 + packfact = 0.5 + units = cm +// pageheight = 29.7 +// pagewidth = 21 + topmargin = 1 + botmargin = 1 + leftmargin = 1 + rightmargin = 1 + measnum = y + staffs = 1 + +music + +// Put each voice on a different channel +// using a different instrument sound. +// The program numbers correspond to the +// General MIDI sounds as noted. +midi 1 1: 0 "channel=1"; 0 "program=1"; 0 "parameter=10,0"; + +// Bar 1 +1 1: 4a; 4b; 2d; +endbar + +// Bar 2 +1 1: 4c+#; 4r; 2e; +endbar \ No newline at end of file