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 | #!/usr/bin/env python import tree from ply import lex, yacc class Note(): def __init__(self, value, duration=1, octave=8): | > | | > > | | < < | | | | 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 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 | #!/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 def parse(score, default_octave=8): # Tokenize (lex) 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("/"): |
︙ | ︙ | |||
100 101 102 103 104 105 106 | ''' new_note = p[1] new_note.duration = p[2] p[0] = new_note def p_chord(p): | | | | > | > | | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | ''' 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 | mymidi = midifile(15) def main(): composition = { "intro": { "body": { "percusion": { | | > > | | | | | 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 | 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": { |
︙ | ︙ | |||
140 141 142 143 144 145 146 | 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"] | < | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | 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) |
︙ | ︙ | |||
248 249 250 251 252 253 254 | def midify_instr_score(score, track, channel, t, volume): # Assume get_midi_note() global mymidi for token in score: | | | | | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | 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() |