Differences From Artifact [390f3e845041e548]:
- Executable file
spiffyscore.py
- 2011-11-07 01:39:19 - part of checkin [4f872339ff] on branch develop - Altered the sample-based instruments to ine Csound string formatting instead of a billion if clauses to choose what file to play (user: brian) [annotate]
To Artifact [caa7e9ffa774c2cf]:
- Executable file
spiffyscore.py
- 2011-11-15 22:08:44 - part of checkin [befd61cab9] on branch feature/midi - Successfully got the program to output a MIDI file instead of a csound score (user: brian) [annotate]
- 2011-11-15 22:09:21 - part of checkin [0c3fb3e27f] on branch develop - Replaced csound support with midi support (user: brian) [annotate]
3 from __future__ import division 3 from __future__ import division
4 import ipdb 4 import ipdb
5 import os 5 import os
6 import random 6 import random
7 import sys 7 import sys
8 import time 8 import time
9 9
> 10 from midiutil.MidiFile import MIDIFile as midifile
10 import parse 11 import parse
11 import topsort 12 import topsort
12 import yaml 13 import yaml
13 14
14 import tree 15 import tree
15 16
16 random.seed(time.time()) 17 random.seed(time.time())
> 18 mymidi = midifile(15)
17 19
18 def main(): 20 def main():
19 composition = { 21 composition = {
20 "fm_test": { 22 "fm_test": {
21 "intro": { 23 "intro": {
22 "melody": { # Instrument 'melody' 24 "melody": { # Instrument 'melody'
23 "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(no 25 "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(no
................................................................................................................................................................................
101 "u": ["C/4 C/4 C/4 C/4"], 103 "u": ["C/4 C/4 C/4 C/4"],
102 }, 104 },
103 }, 105 },
104 }, 106 },
105 }, 107 },
106 "sync_test": { 108 "sync_test": {
107 "body": { 109 "body": {
108 # "lead_instr": { # Instrument 'melody' | 110 "lead_instr": { # Instrument 'melody'
109 # "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(n | 111 "channel": 6,
110 ## "score_line": "i5 %(time)f %(duration)f 7000 %(octave)d.%( <
111 # "octave": 7, | 112 "octave": 4,
112 # "duration": 30, | 113 "duration": 30,
113 # "grammars": { # Notes for this instrument to use in this p | 114 "grammars": { # Notes for this instrument to use in this pi
114 ## "u": ["A ^A B C ^C D ^D E F ^F G ^G"], | 115 # "u": ["A ^A B C ^C D ^D E F ^F G ^G"],
115 # "u": ["A/2, B/2, C/2 D/2 (u)", "D/2' D/2' D/2' D/2' (v) | 116 "u": ["A/2, B/2, C/2 D/2 (u)", "D/2' D/2' D/2' D/2' (x)"
116 # "v": ["C/2 C/2 C/2 C/2 (w)"], | 117 "v": ["C/2 C/2 C/2 C/2 (w)"],
117 # "w": ["E/2 F/2 E/2 F/2 (u)"], | 118 "w": ["E/2 F/2 E/2 F/2 (u)"],
> 119 "x": ["z4 (v)"],
118 # }, | 120 },
119 # }, | 121 },
120 "follow_instr": { # Instrument 'melody' 122 "follow_instr": { # Instrument 'melody'
121 # "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(n | 123 "channel": 0,
122 "score_line": "i3 %(time)f %(duration)f 7000 %(octave)d.%(no <
123 # "sync": "lead_instr", | 124 "sync": "lead_instr",
124 "octave": 2, 125 "octave": 2,
125 "duration": 30, 126 "duration": 30,
126 "grammars": { # Notes for this instrument to use in this pi 127 "grammars": { # Notes for this instrument to use in this pi
127 # "u": ["A ^A B C ^C D ^D E F ^F G ^G"], 128 # "u": ["A ^A B C ^C D ^D E F ^F G ^G"],
128 "u": ["E F G E (v)"], 129 "u": ["E F G E (v)"],
129 "v": ["G A A A (e)", "G A A A (v)"], 130 "v": ["G A A A (e)", "G A A A (v)"],
130 "e": ["B A G A (u)"], 131 "e": ["B A G A (u)"],
> 132 "x": ["z4 (e)"],
131 }, 133 },
132 }, 134 },
133 # "instr2": { # Instrument 'melody' 135 # "instr2": { # Instrument 'melody'
134 # "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(n 136 # "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(n
135 # "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(n 137 # "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(n
136 # "octave": 5, 138 # "octave": 5,
137 # "duration": 30, 139 # "duration": 30,
................................................................................................................................................................................
169 subsection[instr]["sync"] = None 171 subsection[instr]["sync"] = None
170 unordered_instrs.append([subsection[instr]["sync"], instr]) 172 unordered_instrs.append([subsection[instr]["sync"], instr])
171 ordered_instrs = topsort.topsort(unordered_instrs) 173 ordered_instrs = topsort.topsort(unordered_instrs)
172 ordered_instrs.remove(None) # None used as a placeholder for so 174 ordered_instrs.remove(None) # None used as a placeholder for so
173 175
174 instrs = [] 176 instrs = []
175 syncs = {} 177 syncs = {}
> 178 track = 0
176 for instr in ordered_instrs: 179 for instr in ordered_instrs:
177 print ";Instrument " + instr 180 print ";Instrument " + instr
178 instr = subsection[instr] 181 instr = subsection[instr]
179 max_time = instr["duration"] 182 max_time = instr["duration"]
180 instr_score, syncs = render_instr(instr, syncs, max_time) 183 instr_score, syncs = render_instr(instr, syncs, max_time)
181 instrs.append(instr_score) 184 instrs.append(instr_score)
182 for line in generate_csound_score(instr_score, instr["score_ | 185 generate_csound_score(instr_score, track, instr["channel"],
183 print line <
184 longest_score = max(instrs, key=lambda i: score_len(i)) 186 longest_score = max(instrs, key=lambda i: score_len(i))
185 subsection_start += score_len(longest_score) 187 subsection_start += score_len(longest_score)
186 section_start += score_len(longest_score) 188 section_start += score_len(longest_score)
> 189 track += 1
187 except KeyError: 190 except KeyError:
188 pass 191 pass
> 192 with open("out.mid", "wb") as outfile:
> 193 mymidi.writeFile(outfile)
> 194
189 195
190 196
191 def render_instr(instr, syncs, max_time): 197 def render_instr(instr, syncs, max_time):
192 for g in instr["grammars"]: 198 for g in instr["grammars"]:
193 for i in range(len(instr["grammars"][g])): 199 for i in range(len(instr["grammars"][g])):
194 instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i], defau 200 instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i], defau
195 201
................................................................................................................................................................................
266 total = 0 272 total = 0
267 for n in score: 273 for n in score:
268 if not isinstance(n, tree.Tree): 274 if not isinstance(n, tree.Tree):
269 total += n.duration 275 total += n.duration
270 return total 276 return total
271 277
272 278
> 279 def get_midi_note(octave, note):
> 280 return note + 12 * (octave+1)
> 281
> 282
273 def generate_csound_score(score, score_line, t): | 283 def generate_csound_score(score, track, channel, t):
274 csound_note_values = { <
275 "C": "00", <
276 "C#": "01", "Db": "01", <
277 "D": "02", <
278 "D#": "03", "Eb": "03", | 284 # Assume get_midi_note()
279 "E": "04", | 285 global mymidi
280 "F": "05", <
281 "F#": "06", "Gb": "06", <
282 "G": "07", <
283 "G#": "08", "Ab": "08", <
284 "A": "09", <
285 "A#": "10", "Bb": "10", <
286 "B": "11", <
287 } | 286
288 csound_score = [] <
289 for token in score: 287 for token in score:
290 if isinstance(token, parse.Chord): # Chords 288 if isinstance(token, parse.Chord): # Chords
291 for note in token.chord: 289 for note in token.chord:
292 note = csound_note_values[note] <
293 csound_score.append(score_line % {"time": t, "octave": token.oct <
294 csound_score.append(score_line % {"time": t, "octave": token.oct <
> 290 note = get_midi_note(token.octave, note)
> 291 mymidi.addNote(track=track, channel=channel,pitch=note, time=t,
295 elif isinstance(token, parse.Note): # Individual notes 292 elif isinstance(token, parse.Note): # Individual notes
296 note = csound_note_values[token.value] <
297 csound_score.append(score_line % {"time": t, "octave": token.octave, <
> 293 note = get_midi_note(token.octave, token.value)
> 294 mymidi.addNote(track=track, channel=channel,pitch=note, time=t, dura
298 elif isinstance(token, tree.Tree): 295 elif isinstance(token, tree.Tree):
299 continue 296 continue
300 t += token.duration 297 t += token.duration
> 298
301 return csound_score | 299 return []
302 300
303 301
304 if __name__ == "__main__": main() 302 if __name__ == "__main__": main()