spiffyscore

Check-in [4f5bc3936f]
Login
Overview
SHA1:4f5bc3936f3fe8c21b65e90aaf431418ce7ded7e
Date: 2011-10-20 18:37:19
User: brian
Comment:Syncing now works
Timelines: family | ancestors | refactor
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2011-10-20
18:38
[8c559c112b] Merged the refactor branch into the main develop branch (user: brian, tags: develop)
18:37
[4f5bc3936f] Closed-Leaf: Syncing now works (user: brian, tags: refactor)
2011-10-18
20:19
[42c3ba150c] Broke the score generator by not initialing a first phrase in an empty score. Checkpointing so I can refactor and clean things up to make more progress. (user: brian, tags: refactor)
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Modified cfg.py from [368187a13f] to [6468589fde].

     1      1   #!/usr/bin/env python
     2      2   
     3      3   from __future__ import division
     4         -import os
     5      4   import ipdb
            5  +import os
     6      6   import random
     7      7   import sys
     8      8   import time
     9      9   
    10     10   import parse
    11     11   import topsort
    12     12   import yaml
................................................................................
   142    142           for subsection in ["intro", "body", "outro"]:
   143    143               try:
   144    144                   print "; Subsection " + subsection
   145    145                   subsection = section[subsection]
   146    146   
   147    147                   unordered_instrs = []
   148    148                   for instr in subsection:
          149  +                    subsection[instr]["name"] = instr
   149    150                       if not "sync" in subsection[instr].keys():
   150    151                           subsection[instr]["sync"] = None
   151    152                       unordered_instrs.append([subsection[instr]["sync"], instr])
   152    153                   ordered_instrs = topsort.topsort(unordered_instrs)
   153    154                   ordered_instrs.remove(None)  # None used as a placeholder for sort order for instruments with no sync setting
   154    155   
   155    156                   instrs = []
   156    157                   syncs = {}
   157    158                   for instr in ordered_instrs:
   158    159                       print ";Instrument " + instr
   159    160                       instr = subsection[instr]
   160         -#                    ipdb.set_trace()
   161    161                       max_time = instr["duration"]
   162    162                       instr_score, syncs = render_instr(instr, syncs, max_time)
   163    163                       instrs.append(instr_score)
   164    164                       for line in generate_csound_score(instr_score, instr["score_line"], subsection_start):
   165    165                           print line
   166    166                   longest_score = max(instrs, key=lambda i: score_len(i))
   167    167                   subsection_start += score_len(longest_score)
................................................................................
   170    170                   pass
   171    171   
   172    172   
   173    173   def render_instr(instr, syncs, max_time):
   174    174       for g in instr["grammars"]:
   175    175           for i in range(len(instr["grammars"][g])):
   176    176               instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i])
   177         -    score = []
   178         -    while True:
   179         -#        ipdb.set_trace()
   180         -        time_remaining = max_time - score_len(score)
   181         -        try:
   182         -            score, syncs = choose_node(score, instr, time_remaining, syncs)
   183         -        except ValueError:
   184         -            break
   185         -    return (score, syncs)
   186         -
   187         -
   188         -def choose_node(score, instr, time_remaining, syncs):
   189         -#    ipdb.set_trace()
   190         -    grammars = instr["grammars"]
   191         -    if time_remaining <= 0:
   192         -        raise ValueError("No time remaining in the score")
   193         -
   194         -    if len(score) == 0:
   195         -        options = get_node_choices(instr, syncs, score_len(score))
   196         -        node = random.choice(options)
   197         -        phrase = random.choice(instr["grammars"][node])
          177  +
          178  +    score= []
          179  +    try:
          180  +        score, syncs = choose_phrase(instr, syncs, 0, max_time)
          181  +
          182  +        while True:
          183  +            score_index_to_replace = None
          184  +            for item in range(len(score)):  # Optimize this by caching the index of the last node I replaced and startng there
          185  +                if isinstance(score[item], tree.Tree):
          186  +                    score_index_to_replace = item
          187  +            if score_index_to_replace is None:
          188  +                raise ValueError("No more nodes to fill in")
          189  +
          190  +            time_remaining = max_time - score_len(score)
          191  +            new_phrase, syncs = choose_phrase(instr, syncs, score_len(score), time_remaining)
          192  +            score = score[:node_index-1] + new_phrase + score[node_index+1:]
          193  +
          194  +    except ValueError:
          195  +        return (score, syncs)
          196  +
          197  +
          198  +def choose_phrase(instr, syncs, current_time, time_remaining):
          199  +    '''Filters grammars for ones that match the sync option, and phrases that fit the time remaining in the score'''
          200  +    time_filtered_grammars = {}
          201  +    for grammar in instr["grammars"]:
          202  +        time_filtered_grammars[grammar] = get_phrases_that_fit(instr["grammars"][grammar], time_remaining)
          203  +    if len(time_filtered_grammars.keys()) == 0:
          204  +        raise ValueError("No available grammars that will fit in the score")
   198    205   
   199         -    # Find the next node in the score that needs choosing
   200         -    node = None
   201         -    node_index = None
   202         -    for item in range(len(score)):
   203         -        if isinstance(score[item], tree.Tree):
   204         -            node = score[item].name
   205         -            node_index = item
   206         -    if node is None:
   207         -        raise ValueError("No more nodes to fill in")
   208         -
   209         -    options = get_node_choices(instr, syncs, score_len(score))
   210         -    node = random.choice(options)
   211         -    phrase = random.choice(instr["grammars"][node])
   212         -    score = score[:node_index-1] + phrase + score[node_index+1:]
   213         -    return score
   214         -
   215         -
   216         -def get_node_choices(instr, syncs, current_time):
   217         -    # If this instrument should follow another, choose a grammar node from the correct instrument
   218         -#    ipdb.set_trace()
   219         -    grammars = instr["grammars"]
   220         -    options = []
          206  +    grammar = None
          207  +#    if instr["name"] == "follow_instr":
          208  +#        ipdb.set_trace()
   221    209       if instr["sync"] is not None:
   222    210           guiding_instr = instr["sync"]
   223    211           sync_node = get_sync_node_at_time(syncs[guiding_instr], current_time)
   224         -        if sync_node in instr["grammars"].keys():
   225         -            options.append(sync_node)
   226         -        else:
   227         -            for g in range(len(grammars[node])):
   228         -                if score_len(grammars[node][g]) <= time_remaining:
   229         -                    options.append(grammars[node][g])
   230         -    else:
   231         -        for g in range(len(grammars[node])):
   232         -            if score_len(grammars[node][g]) <= time_remaining:
   233         -                options.append(grammars[node][g])
   234         -    if len(options) == 0:
   235         -        raise ValueError("No available grammars that will fit in the score")
   236         -    return options
          212  +        if sync_node in time_filtered_grammars.keys():
          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
   237    230   
   238    231   
   239    232   def get_sync_node_at_time(syncs, t):
   240         -    for s in len(syncs):
   241         -        if syncs[s]["time"] > t:
          233  +    for s in range(len(syncs)):
          234  +        if syncs[s]["time"] >= t:
   242    235               return syncs[s]["node"]
   243    236   
   244    237   
   245    238   def score_len(score):
   246    239       total = 0
   247    240       for n in score:
   248    241           if not isinstance(n, tree.Tree):