Overview
Comment: | Fixed chord support |
---|---|
Timelines: | family | ancestors | descendants | both | develop |
Files: | files | file ages | folders |
SHA1: |
8f28834102b41a640931e718c456c3da |
User & Date: | brian on 2011-11-27 02:56:34 |
Other Links: | branch diff | manifest | tags |
Context
2011-12-04
| ||
20:52 | Made room for arbitrary-note chording whenever I figure out the CFY to represent iTSYntax to use for it Leaf check-in: 3023a967c2 user: brian tags: develop | |
2011-11-27
| ||
02:56 | Fixed chord support check-in: 8f28834102 user: brian tags: develop | |
02:26 | Fixed a bug that prevented sharps and flats from working check-in: bf135b5321 user: brian tags: develop | |
Changes
Modified parse.py from [4cca2f3d0c] to [0884d30f89].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 .. 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 ... 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
#!/usr/bin/env python import tree from ply import lex, yacc class Note(): def __init__(self, value, duration=1, octave=8): self.value = value self.duration = duration self.octave = octave def __repr__(self): return "Note %s %s %s" % (self.value, self.duration, self.octave) class Chord(): def __init__(self, value, duration=1, chord_type="major", octave=5): self.value = value self.duration = duration self.chord_type = chord_type self.octave = octave def __repr__(self): return "Chord %s %s %s" % (self.value, self.duration, self.chord_type, self.octave) class Rest(): def __init__(self, duration=1): self.duration = duration def __repr__(self): return "Rest node %s" % self.duration ................................................................................ tokens = ( "NOTE_LENGTH", "BASENOTE", "ACCIDENTAL", "REST", "OCTAVE", "CHORD_TYPE", "PAREN", "SYNCOPATE", "NODE", ) t_ignore = " |" t_BASENOTE = r"[A-Ga-g]" # t_BASENOTE = r"I+V?|VI*|i+v?|vi*" t_ACCIDENTAL = r"\^{1}|_{1}|=" t_REST = r"z" t_OCTAVE = r"'+|,+" t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7b5|6|b6|m6|mb6|46|maj9|9|add9|7b9|m9" t_PAREN = "\[|\]" t_SYNCOPATE = "\+|-" t_NODE = r"\([a-zA-Z0-9_-]+\)" def t_NOTE_LENGTH(t): r"/?\d+" multiplier = float(t.value.strip("/")) if t.value.startswith("/"): ................................................................................ ''' new_note = p[1] new_note.duration = p[2] p[0] = new_note def p_chord(p): '''chord : PAREN note PAREN | PAREN note CHORD_TYPE PAREN ''' pitch = p[2].value pitch = pitch.upper() p[0] = Chord(value=pitch, octave=default_octave) if len(p) > 3: p[0].chord_type = p[3] def p_note_syncopate(p): ''' note : note SYNCOPATE ''' note.syncopate = p[2] |
> | | > > | | < < < > | | | | | | < > | | > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 .. 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 ... 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
#!/usr/bin/env python import tree from ply import lex, yacc class Note(): def __init__(self, value, duration=1, octave=8): self.duration = duration if value > 12: self.duration += 1 value = value % 12 self.value = value self.octave = octave def __repr__(self): return "Note %s %s %s" % (self.value, self.duration, self.octave) class Chord(): def __init__(self, notes, duration=1): self.notes = notes self.duration = duration def __repr__(self): return "Chord %s" % (self.notes) class Rest(): def __init__(self, duration=1): self.duration = duration def __repr__(self): return "Rest node %s" % self.duration ................................................................................ tokens = ( "NOTE_LENGTH", "BASENOTE", "ACCIDENTAL", "REST", "OCTAVE", "CHORD_TYPE", "BRACKET", "SYNCOPATE", "NODE", ) t_ignore = " |" t_BASENOTE = r"[A-Ga-g]" # t_BASENOTE = r"I+V?|VI*|i+v?|vi*" t_ACCIDENTAL = r"\^{1}|_{1}|=" t_REST = r"z" t_OCTAVE = r"'+|,+" t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7b5|6|b6|m6|mb6|46|maj9|9|add9|7b9|m9" t_BRACKET = r"\[|\]" t_SYNCOPATE = "\+|-" t_NODE = r"\([a-zA-Z0-9_-]+\)" def t_NOTE_LENGTH(t): r"/?\d+" multiplier = float(t.value.strip("/")) if t.value.startswith("/"): ................................................................................ ''' new_note = p[1] new_note.duration = p[2] p[0] = new_note def p_chord(p): '''chord : BRACKET note BRACKET | BRACKET note CHORD_TYPE BRACKET ''' root_note = p[2].value chorded_notes = [] for offset in [0, 4, 7]: chorded_notes.append(Note(root_note+offset, octave=p[2].octave)) p[0] = Chord(notes=chorded_notes) def p_note_syncopate(p): ''' note : note SYNCOPATE ''' note.syncopate = p[2] |
Modified spiffyscore.py from [8b19298d3a] to [11e8d97d43].
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 ... 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 ... 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
mymidi = midifile(15) def main(): composition = { "intro": { "body": { "percusion": { "channel": 14, "octave": 4, "duration": 60, "grammars": { "u": ["A ^A (u)"] } }, "pan_flute": { "channel": 8, "octave": 5, "duration": 60, "grammars": { # Notes for this instrument to use in this piece "u": ["C2' B2 | A3 D3 || B | C' | D | C2' C2' | z | (u)", "C2' C2' | C2' C2' | (x)"], "v": ["G2 F2 | E2 F2 | D5 (u)", "B/4 C/4' B/4 A/4 | D2 D2 | z | (u)"], "x": ["z4 | (v)"], }, }, "bass": { "channel": 4, "sync": "pan_flute", "octave": 2, "duration": 60, "grammars": { # Notes for this instrument to use in this piece "u": ["C/2 C/2 C/2 z/2 (u)"], }, }, "horn_timbre1": { "channel": 13, "octave": 2, "duration": 60, "grammars": { # Notes for this instrument to use in this piece "u": ["C4 D4 (u)"], }, }, "horn_timbre2": { ................................................................................ max_time = instr["duration"] instr_score, syncs = render_instr(instr, syncs, max_time) instrs.append(instr_score) volume = 100 if instr.has_key("vol_offset"): volume += instr["vol_offset"] print "\t\t\tvolume offset = %d, nev volume = %d" % (instr["vol_offset"], volume) midify_instr_score(instr_score, track, instr["channel"], subsection_start, volume=volume) longest_score = max(instrs, key=lambda i: score_len(i)) subsection_start += score_len(longest_score) section_start += score_len(longest_score) track += 1 with open("out.mid", "wb") as outfile: mymidi.writeFile(outfile) ................................................................................ def midify_instr_score(score, track, channel, t, volume): # Assume get_midi_note() global mymidi for token in score: if isinstance(token, parse.Chord): # Chords for note in token.chord: note = get_midi_note(token.octave, note) mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume) elif isinstance(token, parse.Note): # Individual notes note = get_midi_note(token.octave, token.value) mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume) elif isinstance(token, tree.Tree): continue t += token.duration return [] if __name__ == "__main__": main() |
| > > | | | | < | | | |
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 ... 142 143 144 145 146 147 148 149 150 151 152 153 154 155 ... 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
mymidi = midifile(15) def main(): composition = { "intro": { "body": { "percusion": { "channel": 14, # Orchestra kit "octave": 4, "duration": 60, "grammars": { "u": ["A ^A (u)"] } }, "pan_flute": { "channel": 8, "octave": 5, "duration": 60, "vol_offset": -15, "grammars": { # Notes for this instrument to use in this piece "u": ["[C2'] C2' | [A3] A3 (u)"], # "u": ["[C2'] [B2] | [A3] D3 || B | C' | D | C2' C2' | z | (u)", "C2' C2' | C2' C2' | (x)"], # "v": ["G2 F2 | E2 F2 | D5 (u)", "B/4 C/4' B/4 A/4 | D2 D2 | z | (u)"], # "x": ["z4 | (v)"], }, }, "bass": { "channel": 4, "sync": "pan_flute", "octave": 2, "duration": 60, "grammars": { # Notes for this instrument to use in this piece "u": ["C/2 C/2 C/2 z/2 (u)"], }, }, "horn_timbre1": { "channel": 13, # 'Atmosphere' "octave": 2, "duration": 60, "grammars": { # Notes for this instrument to use in this piece "u": ["C4 D4 (u)"], }, }, "horn_timbre2": { ................................................................................ max_time = instr["duration"] instr_score, syncs = render_instr(instr, syncs, max_time) instrs.append(instr_score) volume = 100 if instr.has_key("vol_offset"): volume += instr["vol_offset"] midify_instr_score(instr_score, track, instr["channel"], subsection_start, volume=volume) longest_score = max(instrs, key=lambda i: score_len(i)) subsection_start += score_len(longest_score) section_start += score_len(longest_score) track += 1 with open("out.mid", "wb") as outfile: mymidi.writeFile(outfile) ................................................................................ def midify_instr_score(score, track, channel, t, volume): # Assume get_midi_note() global mymidi for token in score: if isinstance(token, parse.Chord): for note in token.notes: note = get_midi_note(note.octave, note.value) mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume) elif isinstance(token, parse.Note): # Individual notes note = get_midi_note(token.octave, token.value) mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume) elif isinstance(token, tree.Tree): continue t += token.duration return [] if __name__ == "__main__": main() |