spiffyscore
File Annotation
Not logged in
6bfc2449ff 2010-11-04 spiffytech@gm: #!/usr/bin/env python
6bfc2449ff 2010-11-04 spiffytech@gm: 
5a35ffdd27 2010-11-17 spiffytech@gm: from __future__ import division
42c3ba150c 2011-10-18         brian: import ipdb
4f5bc3936f 2011-10-20         brian: import os
6bfc2449ff 2010-11-04 spiffytech@gm: import random
6bfc2449ff 2010-11-04 spiffytech@gm: import sys
6bfc2449ff 2010-11-04 spiffytech@gm: import time
689adc054e 2011-02-10 brian@linux-8: 
9bd31df856 2010-11-16 spiffytech@gm: import parse
689adc054e 2011-02-10 brian@linux-8: import topsort
689adc054e 2011-02-10 brian@linux-8: import yaml
689adc054e 2011-02-10 brian@linux-8: 
192b8b1639 2011-10-11         brian: import tree
192b8b1639 2011-10-11         brian: 
192b8b1639 2011-10-11         brian: random.seed(time.time())
192b8b1639 2011-10-11         brian: 
6a17d4d36a 2010-11-12 spiffytech@gm: def main():
192b8b1639 2011-10-11         brian:     composition = {
192b8b1639 2011-10-11         brian:         "fm_test": {
192b8b1639 2011-10-11         brian:             "intro": {
192b8b1639 2011-10-11         brian:                 "melody": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2 6 5 1",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 10,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["G/2 G/2 | G/4 G/4 A/4 A/4 | A/2 A/2 | G | G | A | A | A3 (w)"],
192b8b1639 2011-10-11         brian:                         "w": ["E | E | F | F | G/2 G/2 | G3 (u)"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:             },
192b8b1639 2011-10-11         brian:         },
192b8b1639 2011-10-11         brian:         "verse1": {
192b8b1639 2011-10-11         brian:             "intro": {
192b8b1639 2011-10-11         brian:                 "melody": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 1",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 10,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["G/2 G/2 | G/4 G/4 A/4 A/4 | A/2 A/2 | G | G | A | A | A3 (w)"],
192b8b1639 2011-10-11         brian:                         "w": ["E | E | F | F | G/2 G/2 | G3 (u)"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:             },
192b8b1639 2011-10-11         brian:             "body": {
192b8b1639 2011-10-11         brian:                 "melody": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 1",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 10,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["C | G/2 G/2 | G/2 G/2 | C | B, | F' | C | F | C | B | F | (w)"],
192b8b1639 2011-10-11         brian:                         "w": ["E/4 A/4 D/4 G/4 | F/4 F/4 B2 | (u)"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:             },
192b8b1639 2011-10-11         brian:             "outro": {
192b8b1639 2011-10-11         brian:                 "melody": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 1",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 10,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["C/4 C/4 C/4 C/4 | z2"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:             },
192b8b1639 2011-10-11         brian:         },
192b8b1639 2011-10-11         brian:         "verse2": {
192b8b1639 2011-10-11         brian:             "body": {
192b8b1639 2011-10-11         brian:                 "melody": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 1",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 30,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["C | C | C | C | F/2 F/2 | F/2 F/2 | (u)", "D | D | G/2 A/2 | D | D | (u)"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:                 "harmony": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i3 %(time)f %(duration)f 4000 %(octave)d.%(note)s 2 3 5 3",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 30,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["C | C | z | C | C | z/2 F/4 F/2 F/2 | F/2 F/2 | z (u)", "D | D | G/2 A/2 | D | D | z (u)"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:                 "percussion": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 30,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["C/4 C/4 C/4 C/4 | F/2 F/2 | F/2 F/2 | (u)", "D/4 D/4 G/4 A/4 | D | D | (v)"],
192b8b1639 2011-10-11         brian:                         "v": ["C | D | E | F | E | D | C | (u)",],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:             },
192b8b1639 2011-10-11         brian:             "outro": {
192b8b1639 2011-10-11         brian:                 "percussion": {  # Instrument 'melody'
192b8b1639 2011-10-11         brian:                     "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
192b8b1639 2011-10-11         brian:                     "octave": 8,
192b8b1639 2011-10-11         brian:                     "duration": 30,
192b8b1639 2011-10-11         brian:                     "grammars": {  # Notes for this instrument to use in this piece
192b8b1639 2011-10-11         brian:                         "u": ["C/4 C/4 C/4 C/4"],
192b8b1639 2011-10-11         brian:                     },
192b8b1639 2011-10-11         brian:                 },
192b8b1639 2011-10-11         brian:             },
192b8b1639 2011-10-11         brian:         },
42c3ba150c 2011-10-18         brian:         "sync_test": {
42c3ba150c 2011-10-18         brian:             "body": {
42c3ba150c 2011-10-18         brian:                 "lead_instr": {  # Instrument 'melody'
42c3ba150c 2011-10-18         brian:                     "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
42c3ba150c 2011-10-18         brian:                     "octave": 8,
42c3ba150c 2011-10-18         brian:                     "duration": 30,
42c3ba150c 2011-10-18         brian:                     "grammars": {  # Notes for this instrument to use in this piece
42c3ba150c 2011-10-18         brian:                         "u": ["D/4 D/4 D/4 D/4"],
42c3ba150c 2011-10-18         brian:                         "v": ["C/4 C/4 C/4 C/4"],
42c3ba150c 2011-10-18         brian:                     },
42c3ba150c 2011-10-18         brian:                 },
42c3ba150c 2011-10-18         brian:                 "follow_instr": {  # Instrument 'melody'
42c3ba150c 2011-10-18         brian:                     "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 1",
42c3ba150c 2011-10-18         brian:                     "sync": "lead_instr",
42c3ba150c 2011-10-18         brian:                     "octave": 8,
42c3ba150c 2011-10-18         brian:                     "duration": 30,
42c3ba150c 2011-10-18         brian:                     "grammars": {  # Notes for this instrument to use in this piece
42c3ba150c 2011-10-18         brian:                         "u": ["D/4 D/4 D/4 D/4"],
42c3ba150c 2011-10-18         brian:                         "v": ["C/4 C/4 C/4 C/4"],
42c3ba150c 2011-10-18         brian:                     },
42c3ba150c 2011-10-18         brian:                 },
42c3ba150c 2011-10-18         brian:             },
42c3ba150c 2011-10-18         brian:         },
6a17d4d36a 2010-11-12 spiffytech@gm:     }
192b8b1639 2011-10-11         brian:     print '''f1 0 512 10 1
192b8b1639 2011-10-11         brian: f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08
192b8b1639 2011-10-11         brian: f3 0 1025 10 1
192b8b1639 2011-10-11         brian: t 0 100
192b8b1639 2011-10-11         brian:     '''
192b8b1639 2011-10-11         brian: 
192b8b1639 2011-10-11         brian:     section_start = 0
192b8b1639 2011-10-11         brian: #    for section in ["verse1", "verse2"]:
42c3ba150c 2011-10-18         brian:     for section in ["sync_test"]:
192b8b1639 2011-10-11         brian:         print "; Section " + section
192b8b1639 2011-10-11         brian:         subsection_start = section_start
192b8b1639 2011-10-11         brian:         section = composition[section]
192b8b1639 2011-10-11         brian:         for subsection in ["intro", "body", "outro"]:
192b8b1639 2011-10-11         brian:             try:
192b8b1639 2011-10-11         brian:                 print "; Subsection " + subsection
192b8b1639 2011-10-11         brian:                 subsection = section[subsection]
42c3ba150c 2011-10-18         brian: 
fde4a012ea 2011-10-13         brian:                 unordered_instrs = []
192b8b1639 2011-10-11         brian:                 for instr in subsection:
4f5bc3936f 2011-10-20         brian:                     subsection[instr]["name"] = instr
42c3ba150c 2011-10-18         brian:                     if not "sync" in subsection[instr].keys():
fde4a012ea 2011-10-13         brian:                         subsection[instr]["sync"] = None
fde4a012ea 2011-10-13         brian:                     unordered_instrs.append([subsection[instr]["sync"], instr])
fde4a012ea 2011-10-13         brian:                 ordered_instrs = topsort.topsort(unordered_instrs)
42c3ba150c 2011-10-18         brian:                 ordered_instrs.remove(None)  # None used as a placeholder for sort order for instruments with no sync setting
42c3ba150c 2011-10-18         brian: 
fde4a012ea 2011-10-13         brian:                 instrs = []
42c3ba150c 2011-10-18         brian:                 syncs = {}
fde4a012ea 2011-10-13         brian:                 for instr in ordered_instrs:
192b8b1639 2011-10-11         brian:                     print ";Instrument " + instr
192b8b1639 2011-10-11         brian:                     instr = subsection[instr]
192b8b1639 2011-10-11         brian:                     max_time = instr["duration"]
42c3ba150c 2011-10-18         brian:                     instr_score, syncs = render_instr(instr, syncs, max_time)
192b8b1639 2011-10-11         brian:                     instrs.append(instr_score)
192b8b1639 2011-10-11         brian:                     for line in generate_csound_score(instr_score, instr["score_line"], subsection_start):
192b8b1639 2011-10-11         brian:                         print line
192b8b1639 2011-10-11         brian:                 longest_score = max(instrs, key=lambda i: score_len(i))
192b8b1639 2011-10-11         brian:                 subsection_start += score_len(longest_score)
192b8b1639 2011-10-11         brian:                 section_start += score_len(longest_score)
192b8b1639 2011-10-11         brian:             except KeyError:
192b8b1639 2011-10-11         brian:                 pass
192b8b1639 2011-10-11         brian: 
192b8b1639 2011-10-11         brian: 
42c3ba150c 2011-10-18         brian: def render_instr(instr, syncs, max_time):
192b8b1639 2011-10-11         brian:     for g in instr["grammars"]:
42c3ba150c 2011-10-18         brian:         for i in range(len(instr["grammars"][g])):
42c3ba150c 2011-10-18         brian:             instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i])
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian:     score= []
4f5bc3936f 2011-10-20         brian:     try:
4f5bc3936f 2011-10-20         brian:         score, syncs = choose_phrase(instr, syncs, 0, max_time)
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian:         while True:
4f5bc3936f 2011-10-20         brian:             score_index_to_replace = None
4f5bc3936f 2011-10-20         brian:             for item in range(len(score)):  # Optimize this by caching the index of the last node I replaced and startng there
4f5bc3936f 2011-10-20         brian:                 if isinstance(score[item], tree.Tree):
4f5bc3936f 2011-10-20         brian:                     score_index_to_replace = item
4f5bc3936f 2011-10-20         brian:             if score_index_to_replace is None:
4f5bc3936f 2011-10-20         brian:                 raise ValueError("No more nodes to fill in")
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian:             time_remaining = max_time - score_len(score)
4f5bc3936f 2011-10-20         brian:             new_phrase, syncs = choose_phrase(instr, syncs, score_len(score), time_remaining)
4f5bc3936f 2011-10-20         brian:             score = score[:node_index-1] + new_phrase + score[node_index+1:]
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian:     except ValueError:
4f5bc3936f 2011-10-20         brian:         return (score, syncs)
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian: def choose_phrase(instr, syncs, current_time, time_remaining):
4f5bc3936f 2011-10-20         brian:     '''Filters grammars for ones that match the sync option, and phrases that fit the time remaining in the score'''
4f5bc3936f 2011-10-20         brian:     time_filtered_grammars = {}
4f5bc3936f 2011-10-20         brian:     for grammar in instr["grammars"]:
4f5bc3936f 2011-10-20         brian:         time_filtered_grammars[grammar] = get_phrases_that_fit(instr["grammars"][grammar], time_remaining)
4f5bc3936f 2011-10-20         brian:     if len(time_filtered_grammars.keys()) == 0:
4f5bc3936f 2011-10-20         brian:         raise ValueError("No available grammars that will fit in the score")
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian:     grammar = None
4f5bc3936f 2011-10-20         brian: #    if instr["name"] == "follow_instr":
4f5bc3936f 2011-10-20         brian: #        ipdb.set_trace()
42c3ba150c 2011-10-18         brian:     if instr["sync"] is not None:
42c3ba150c 2011-10-18         brian:         guiding_instr = instr["sync"]
42c3ba150c 2011-10-18         brian:         sync_node = get_sync_node_at_time(syncs[guiding_instr], current_time)
4f5bc3936f 2011-10-20         brian:         if sync_node in time_filtered_grammars.keys():
4f5bc3936f 2011-10-20         brian:             grammar = sync_node
4f5bc3936f 2011-10-20         brian:     if grammar is None:
4f5bc3936f 2011-10-20         brian:         grammar = random.choice(time_filtered_grammars.keys())
4f5bc3936f 2011-10-20         brian:     phrases = time_filtered_grammars[grammar]
4f5bc3936f 2011-10-20         brian:     if instr["name"] not in syncs.keys():
4f5bc3936f 2011-10-20         brian:         syncs[instr["name"]] = []
4f5bc3936f 2011-10-20         brian:     syncs[instr["name"]].append({"node": grammar, "time": current_time})
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian:     return random.choice(phrases), syncs
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian: 
4f5bc3936f 2011-10-20         brian: def get_phrases_that_fit(grammar, time_remaining):
4f5bc3936f 2011-10-20         brian:     valid_phrases = []
4f5bc3936f 2011-10-20         brian:     for phrase in grammar:
4f5bc3936f 2011-10-20         brian:         if score_len(phrase) <= time_remaining:
4f5bc3936f 2011-10-20         brian:             valid_phrases.append(phrase)
4f5bc3936f 2011-10-20         brian:     return valid_phrases
42c3ba150c 2011-10-18         brian: 
42c3ba150c 2011-10-18         brian: 
42c3ba150c 2011-10-18         brian: def get_sync_node_at_time(syncs, t):
4f5bc3936f 2011-10-20         brian:     for s in range(len(syncs)):
4f5bc3936f 2011-10-20         brian:         if syncs[s]["time"] >= t:
42c3ba150c 2011-10-18         brian:             return syncs[s]["node"]
192b8b1639 2011-10-11         brian: 
192b8b1639 2011-10-11         brian: 
192b8b1639 2011-10-11         brian: def score_len(score):
192b8b1639 2011-10-11         brian:     total = 0
192b8b1639 2011-10-11         brian:     for n in score:
192b8b1639 2011-10-11         brian:         if not isinstance(n, tree.Tree):
192b8b1639 2011-10-11         brian:             total += n.duration
192b8b1639 2011-10-11         brian:     return total
702d933446 2011-02-10 brian@linux-8: 
6bfc2449ff 2010-11-04 spiffytech@gm: 
192b8b1639 2011-10-11         brian: def generate_csound_score(score, score_line, t):
6a17d4d36a 2010-11-12 spiffytech@gm:     csound_note_values = {
6a17d4d36a 2010-11-12 spiffytech@gm:         "C": "00",
6a17d4d36a 2010-11-12 spiffytech@gm:         "C#": "01",
6a17d4d36a 2010-11-12 spiffytech@gm:         "D": "02",
6a17d4d36a 2010-11-12 spiffytech@gm:         "D#": "03",
6a17d4d36a 2010-11-12 spiffytech@gm:         "E": "04",
6a17d4d36a 2010-11-12 spiffytech@gm:         "F": "05",
6a17d4d36a 2010-11-12 spiffytech@gm:         "F#": "06",
6a17d4d36a 2010-11-12 spiffytech@gm:         "G": "07",
3cd7a5dcd0 2010-11-12 spiffytech@gm:         "G#": "08",
6a17d4d36a 2010-11-12 spiffytech@gm:         "A": "09",
6a17d4d36a 2010-11-12 spiffytech@gm:         "A#": "10",
6a17d4d36a 2010-11-12 spiffytech@gm:         "B": "11",
6a17d4d36a 2010-11-12 spiffytech@gm:     }
6a17d4d36a 2010-11-12 spiffytech@gm:     csound_score = []
6a17d4d36a 2010-11-12 spiffytech@gm:     for token in score:
9bd31df856 2010-11-16 spiffytech@gm:         if isinstance(token, parse.Chord):  # Chords
9bd31df856 2010-11-16 spiffytech@gm:             for note in token.chord:
5aa14570f1 2010-11-13 spiffytech@gm:                 note = csound_note_values[note]
192b8b1639 2011-10-11         brian:                 csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
aa88358397 2010-11-17 spiffytech@gm:         elif isinstance(token, parse.Note):  # Individual notes
9bd31df856 2010-11-16 spiffytech@gm:             note = csound_note_values[token.value]
192b8b1639 2011-10-11         brian:             csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
192b8b1639 2011-10-11         brian:         elif isinstance(token, tree.Tree):
192b8b1639 2011-10-11         brian:             continue
192b8b1639 2011-10-11         brian:         t += token.duration
6a17d4d36a 2010-11-12 spiffytech@gm:     return csound_score
338933c1a8 2010-11-12 spiffytech@gm: 
6bfc2449ff 2010-11-04 spiffytech@gm: 
6a17d4d36a 2010-11-12 spiffytech@gm: if __name__ == "__main__": main()