spiffyscore

Check-in [42c3ba150c]
Login
Overview
SHA1:42c3ba150c20ddef15dd5b3574414b096cc66d7b
Date: 2011-10-18 20:19:17
User: brian
Edited Comment: 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.
Original Comment: Broke the score generator by not initialing a first phrase in an empty score. Checkpointing so I can refactor and clean things of to make more progress.
Timelines: family | ancestors | descendants | both | refactor
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2011-10-20
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)
2011-10-13
18:15
[fde4a012ea] Program now renders instruments according to sync order (user: brian, tags: develop)
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Modified cfg.py from [52bf709d42] to [368187a13f].

     1      1   #!/usr/bin/env python
     2      2   
     3      3   from __future__ import division
     4      4   import os
     5         -import pdb
            5  +import ipdb
     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
................................................................................
    99     99                       "duration": 30,
   100    100                       "grammars": {  # Notes for this instrument to use in this piece
   101    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.%(note)s %(octave)d.%(note)s 0 6",
          110  +                    "octave": 8,
          111  +                    "duration": 30,
          112  +                    "grammars": {  # Notes for this instrument to use in this piece
          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.%(note)s 1",
          119  +                    "sync": "lead_instr",
          120  +                    "octave": 8,
          121  +                    "duration": 30,
          122  +                    "grammars": {  # Notes for this instrument to use in this piece
          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    130       print '''f1 0 512 10 1
   108    131   f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08
   109    132   f3 0 1025 10 1
   110    133   t 0 100
   111    134       '''
   112    135   
   113    136       section_start = 0
   114    137   #    for section in ["verse1", "verse2"]:
   115         -    for section in ["fm_test"]:
          138  +    for section in ["sync_test"]:
   116    139           print "; Section " + section
   117    140           subsection_start = section_start
   118    141           section = composition[section]
   119    142           for subsection in ["intro", "body", "outro"]:
   120    143               try:
   121    144                   print "; Subsection " + subsection
   122    145                   subsection = section[subsection]
          146  +
   123    147                   unordered_instrs = []
   124    148                   for instr in subsection:
   125         -                    if not "sync" in subsection[instr]:
          149  +                    if not "sync" in subsection[instr].keys():
   126    150                           subsection[instr]["sync"] = None
   127    151                       unordered_instrs.append([subsection[instr]["sync"], instr])
   128    152                   ordered_instrs = topsort.topsort(unordered_instrs)
   129         -                ordered_instrs.remove(None)
   130         -                pdb.set_trace()
          153  +                ordered_instrs.remove(None)  # None used as a placeholder for sort order for instruments with no sync setting
          154  +
   131    155                   instrs = []
          156  +                syncs = {}
   132    157                   for instr in ordered_instrs:
   133    158                       print ";Instrument " + instr
   134    159                       instr = subsection[instr]
   135         -                    sync = None
          160  +#                    ipdb.set_trace()
   136    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    163                       instrs.append(instr_score)
   139    164                       for line in generate_csound_score(instr_score, instr["score_line"], subsection_start):
   140    165                           print line
   141    166                   longest_score = max(instrs, key=lambda i: score_len(i))
   142    167                   subsection_start += score_len(longest_score)
   143    168                   section_start += score_len(longest_score)
   144    169               except KeyError:
   145    170                   pass
   146         -        
   147    171   
   148    172   
   149         -def render_instr(instr, sync, max_time):
   150         -    grammars = instr["grammars"]
          173  +def render_instr(instr, syncs, max_time):
   151    174       for g in instr["grammars"]:
   152         -        for i in range(len(grammars[g])):
   153         -            grammars[g][i] = parse.parse(grammars[g][i])
   154         -    init_node = random.choice(instr["grammars"].keys())
   155         -    init_score = random.choice(instr["grammars"][init_node])
   156         -    score = init_score
          175  +        for i in range(len(instr["grammars"][g])):
          176  +            instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i])
          177  +    score = []
   157    178       while True:
          179  +#        ipdb.set_trace()
   158    180           time_remaining = max_time - score_len(score)
   159    181           try:
   160         -            score = choose_node(score, grammars, time_remaining, sync)
          182  +            score, syncs = choose_node(score, instr, time_remaining, syncs)
   161    183           except ValueError:
   162    184               break
   163         -    return score
          185  +    return (score, syncs)
   164    186   
   165    187   
   166         -def choose_node(score, grammars, time_remaining, sync):
          188  +def choose_node(score, instr, time_remaining, syncs):
          189  +#    ipdb.set_trace()
          190  +    grammars = instr["grammars"]
   167    191       if time_remaining <= 0:
   168    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])
          198  +
          199  +    # Find the next node in the score that needs choosing
   169    200       node = None
   170    201       node_index = None
   171    202       for item in range(len(score)):
   172    203           if isinstance(score[item], tree.Tree):
   173    204               node = score[item].name
   174    205               node_index = item
   175    206       if node is None:
   176    207           raise ValueError("No more nodes to fill in")
   177         -    options = []
   178         -    for g in range(len(grammars[node])):
   179         -        if score_len(grammars[node][g]) <= time_remaining:
   180         -            options.append(grammars[node][g])
   181         -    if len(options) == 0:
   182         -        raise ValueError("No available grammars that will fit in the score")
   183         -    if sync:
   184         -        pass
   185         -    else:
   186         -        phrase = random.choice(options)
          208  +
          209  +    options = get_node_choices(instr, syncs, score_len(score))
          210  +    node = random.choice(options)
          211  +    phrase = random.choice(instr["grammars"][node])
   187    212       score = score[:node_index-1] + phrase + score[node_index+1:]
   188    213       return score
   189    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 = []
          221  +    if instr["sync"] is not None:
          222  +        guiding_instr = instr["sync"]
          223  +        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
          237  +
          238  +
          239  +def get_sync_node_at_time(syncs, t):
          240  +    for s in len(syncs):
          241  +        if syncs[s]["time"] > t:
          242  +            return syncs[s]["node"]
          243  +
   190    244   
   191    245   def score_len(score):
   192    246       total = 0
   193    247       for n in score:
   194    248           if not isinstance(n, tree.Tree):
   195    249               total += n.duration
   196    250       return total