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.849 |
| 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()
|