Differences From Artifact [52bf709d429e7eb3]:
- Executable file
cfg.py
- 2011-10-13 18:15:20 - part of checkin [fde4a012ea] on branch develop - Program now renders instruments according to sync order (user: brian) [annotate]
To Artifact [6468589fdee69e24]:
- Executable file
cfg.py
- 2011-10-20 18:37:19 - part of checkin [4f5bc3936f] on branch refactor - Syncing now works (user: brian) [annotate]
- 2011-10-20 18:38:08 - part of checkin [8c559c112b] on branch develop - Merged the refactor branch into the main develop branch (user: brian) [annotate]
- 2011-10-20 18:44:05 - part of checkin [ba64e400ba] on branch ply - Yay, first alpha release. program supports syncing and basic section/subsection ordering. (user: brian) [annotate]
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 from __future__ import division 3 from __future__ import division
4 import os | 4 import ipdb
5 import pdb | 5 import os
6 import random 6 import random
7 import sys 7 import sys
8 import time 8 import time
9 9
10 import parse 10 import parse
11 import topsort 11 import topsort
12 import yaml 12 import yaml
................................................................................................................................................................................
99 "duration": 30, 99 "duration": 30,
100 "grammars": { # Notes for this instrument to use in this pi 100 "grammars": { # Notes for this instrument to use in this pi
101 "u": ["C/4 C/4 C/4 C/4"], 101 "u": ["C/4 C/4 C/4 C/4"],
102 }, 102 },
103 }, 103 },
104 }, 104 },
105 }, 105 },
> 106 "sync_test": {
> 107 "body": {
> 108 "lead_instr": { # Instrument 'melody'
> 109 "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(no
> 110 "octave": 8,
> 111 "duration": 30,
> 112 "grammars": { # Notes for this instrument to use in this pi
> 113 "u": ["D/4 D/4 D/4 D/4"],
> 114 "v": ["C/4 C/4 C/4 C/4"],
> 115 },
> 116 },
> 117 "follow_instr": { # Instrument 'melody'
> 118 "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(no
> 119 "sync": "lead_instr",
> 120 "octave": 8,
> 121 "duration": 30,
> 122 "grammars": { # Notes for this instrument to use in this pi
> 123 "u": ["D/4 D/4 D/4 D/4"],
> 124 "v": ["C/4 C/4 C/4 C/4"],
> 125 },
> 126 },
> 127 },
> 128 },
106 } 129 }
107 print '''f1 0 512 10 1 130 print '''f1 0 512 10 1
108 f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08 131 f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08
109 f3 0 1025 10 1 132 f3 0 1025 10 1
110 t 0 100 133 t 0 100
111 ''' 134 '''
112 135
113 section_start = 0 136 section_start = 0
114 # for section in ["verse1", "verse2"]: 137 # for section in ["verse1", "verse2"]:
115 for section in ["fm_test"]: | 138 for section in ["sync_test"]:
116 print "; Section " + section 139 print "; Section " + section
117 subsection_start = section_start 140 subsection_start = section_start
118 section = composition[section] 141 section = composition[section]
119 for subsection in ["intro", "body", "outro"]: 142 for subsection in ["intro", "body", "outro"]:
120 try: 143 try:
121 print "; Subsection " + subsection 144 print "; Subsection " + subsection
122 subsection = section[subsection] 145 subsection = section[subsection]
> 146
123 unordered_instrs = [] 147 unordered_instrs = []
124 for instr in subsection: 148 for instr in subsection:
> 149 subsection[instr]["name"] = instr
125 if not "sync" in subsection[instr]: | 150 if not "sync" in subsection[instr].keys():
126 subsection[instr]["sync"] = None 151 subsection[instr]["sync"] = None
127 unordered_instrs.append([subsection[instr]["sync"], instr]) 152 unordered_instrs.append([subsection[instr]["sync"], instr])
128 ordered_instrs = topsort.topsort(unordered_instrs) 153 ordered_instrs = topsort.topsort(unordered_instrs)
129 ordered_instrs.remove(None) | 154 ordered_instrs.remove(None) # None used as a placeholder for so
130 pdb.set_trace() <
> 155
131 instrs = [] 156 instrs = []
> 157 syncs = {}
132 for instr in ordered_instrs: 158 for instr in ordered_instrs:
133 print ";Instrument " + instr 159 print ";Instrument " + instr
134 instr = subsection[instr] 160 instr = subsection[instr]
135 sync = None <
136 max_time = instr["duration"] 161 max_time = instr["duration"]
137 instr_score = render_instr(instr, sync, max_time) | 162 instr_score, syncs = render_instr(instr, syncs, max_time)
138 instrs.append(instr_score) 163 instrs.append(instr_score)
139 for line in generate_csound_score(instr_score, instr["score_ 164 for line in generate_csound_score(instr_score, instr["score_
140 print line 165 print line
141 longest_score = max(instrs, key=lambda i: score_len(i)) 166 longest_score = max(instrs, key=lambda i: score_len(i))
142 subsection_start += score_len(longest_score) 167 subsection_start += score_len(longest_score)
143 section_start += score_len(longest_score) 168 section_start += score_len(longest_score)
144 except KeyError: 169 except KeyError:
145 pass 170 pass
146 | 171
147 | 172
148 | 173 def render_instr(instr, syncs, max_time):
149 def render_instr(instr, sync, max_time): | 174 for g in instr["grammars"]:
150 grammars = instr["grammars"] | 175 for i in range(len(instr["grammars"][g])):
151 for g in instr["grammars"]: | 176 instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i])
152 for i in range(len(grammars[g])): | 177
153 grammars[g][i] = parse.parse(grammars[g][i]) | 178 score= []
154 init_node = random.choice(instr["grammars"].keys()) | 179 try:
155 init_score = random.choice(instr["grammars"][init_node]) | 180 score, syncs = choose_phrase(instr, syncs, 0, max_time)
156 score = init_score | 181
157 while True: | 182 while True:
158 time_remaining = max_time - score_len(score) | 183 score_index_to_replace = None
159 try: | 184 for item in range(len(score)): # Optimize this by caching the index
160 score = choose_node(score, grammars, time_remaining, sync) | 185 if isinstance(score[item], tree.Tree):
161 except ValueError: | 186 score_index_to_replace = item
162 break | 187 if score_index_to_replace is None:
163 return score | 188 raise ValueError("No more nodes to fill in")
164 | 189
165 | 190 time_remaining = max_time - score_len(score)
166 def choose_node(score, grammars, time_remaining, sync): | 191 new_phrase, syncs = choose_phrase(instr, syncs, score_len(score), ti
167 if time_remaining <= 0: | 192 score = score[:node_index-1] + new_phrase + score[node_index+1:]
168 raise ValueError("No time remaining in the score") | 193
169 node = None | 194 except ValueError:
170 node_index = None | 195 return (score, syncs)
171 for item in range(len(score)): | 196
172 if isinstance(score[item], tree.Tree): | 197
173 node = score[item].name | 198 def choose_phrase(instr, syncs, current_time, time_remaining):
174 node_index = item | 199 '''Filters grammars for ones that match the sync option, and phrases that fi
175 if node is None: | 200 time_filtered_grammars = {}
176 raise ValueError("No more nodes to fill in") | 201 for grammar in instr["grammars"]:
177 options = [] | 202 time_filtered_grammars[grammar] = get_phrases_that_fit(instr["grammars"]
178 for g in range(len(grammars[node])): | 203 if len(time_filtered_grammars.keys()) == 0:
179 if score_len(grammars[node][g]) <= time_remaining: | 204 raise ValueError("No available grammars that will fit in the score")
180 options.append(grammars[node][g]) | 205
181 if len(options) == 0: | 206 grammar = None
182 raise ValueError("No available grammars that will fit in the score") | 207 # if instr["name"] == "follow_instr":
183 if sync: | 208 # ipdb.set_trace()
184 pass | 209 if instr["sync"] is not None:
185 else: | 210 guiding_instr = instr["sync"]
186 phrase = random.choice(options) | 211 sync_node = get_sync_node_at_time(syncs[guiding_instr], current_time)
187 score = score[:node_index-1] + phrase + score[node_index+1:] | 212 if sync_node in time_filtered_grammars.keys():
188 return score | 213 grammar = sync_node
> 214 if grammar is None:
> 215 grammar = random.choice(time_filtered_grammars.keys())
> 216 phrases = time_filtered_grammars[grammar]
> 217 if instr["name"] not in syncs.keys():
> 218 syncs[instr["name"]] = []
> 219 syncs[instr["name"]].append({"node": grammar, "time": current_time})
> 220
> 221 return random.choice(phrases), syncs
> 222
> 223
> 224 def get_phrases_that_fit(grammar, time_remaining):
> 225 valid_phrases = []
> 226 for phrase in grammar:
> 227 if score_len(phrase) <= time_remaining:
> 228 valid_phrases.append(phrase)
> 229 return valid_phrases
> 230
> 231
> 232 def get_sync_node_at_time(syncs, t):
> 233 for s in range(len(syncs)):
> 234 if syncs[s]["time"] >= t:
> 235 return syncs[s]["node"]
189 236
190 237
191 def score_len(score): 238 def score_len(score):
192 total = 0 239 total = 0
193 for n in score: 240 for n in score:
194 if not isinstance(n, tree.Tree): 241 if not isinstance(n, tree.Tree):
195 total += n.duration 242 total += n.duration