spiffyscore

Check-in [821ac3e4d6]
Login
Overview
SHA1:821ac3e4d67ffce59c4d0b38a5ff31bd6223ea8f
Date: 2011-11-27 02:03:54
User: brian
Comment:Added a volume offset parameter to each instrument. Fixed a bug that kept instruments from always being rendered, and one that broke midi files.
Timelines: family | ancestors | descendants | both | develop
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2011-11-27
02:26
[bf135b5321] Fixed a bug that prevented sharps and flats from working (user: brian, tags: develop)
02:03
[821ac3e4d6] Added a volume offset parameter to each instrument. Fixed a bug that kept instruments from always being rendered, and one that broke midi files. (user: brian, tags: develop)
2011-11-17
19:55
[f8034c7dfb] Removed leftover csound function lines that got printed. Also disabled ipdb so I get concise stacktraces. Also made program crash when your score pointed to a non-existant node. Previously that just generated an invalid MIDI file (somehow...) (user: brian, tags: develop)
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Modified parse.py from [bcac1af73f] to [ce9611a745].

    45     45   
    46     46       t_BASENOTE = r"[A-Ga-g]"
    47     47   #    t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
    48     48       t_ACCIDENTAL = r"\^{1}|_{1}|="
    49     49       t_REST = r"z"
    50     50       t_OCTAVE = r"'+|,+"
    51     51       t_CHORD_TYPE = r"m|7|m7|0|o|\+|mb5|sus|sus4|maj7|mmaj7|7sus4|dim|dim7|7b5|m7b5|6|b6|m6|mb6|46|maj9|9|add9|7b9|m9"
    52         -    t_PAREN = "\(|\)"
           52  +    t_PAREN = "\[|\]"
    53     53       t_SYNCOPATE = "\+|-"
    54     54       t_NODE = r"\([a-zA-Z0-9_-]+\)"
    55     55   
    56     56       def t_NOTE_LENGTH(t):
    57     57           r"/?\d+"
    58     58           multiplier = float(t.value.strip("/"))
    59     59           if t.value.startswith("/"):

Modified spiffyscore.py from [87c5508f41] to [58892e1cd4].

     1      1   #!/usr/bin/env python
     2      2   
     3      3   from __future__ import division
     4         -#import ipdb
            4  +import ipdb
     5      5   import os
     6      6   import random
     7      7   import sys
     8      8   import time
     9      9   
    10     10   from midiutil.MidiFile import MIDIFile as midifile
    11     11   import parse
................................................................................
    17     17   random.seed(time.time())
    18     18   mymidi = midifile(15)
    19     19   
    20     20   def main():
    21     21       composition = {
    22     22           "intro": {
    23     23               "body": {
    24         -                "lead_instr": {  # Instrument 'melody'
           24  +                "pan_flute": {  # Instrument 'melody'
    25     25                       "channel": 8,
    26     26                       "octave": 5,
    27     27                       "duration": 60,
    28     28                       "grammars": {  # Notes for this instrument to use in this piece
    29         -                        "u": ["C2' B2 A3 D3 B C' D C2' z (u)", "C2' C2' C2' C2' (x)"],
    30         -                        "v": ["G2 F2 E2 F2 D5 (u)", "B/4 C/4' B/4 A/4 D2 z"],
    31         -                        "x": ["z4 (v)"],
           29  +                        "u": ["C2' B2 | A3 D3 || B | C' | D | C2' C2' | z | (u)", "C2' C2' | C2' C2' | (x)"],
           30  +                        "v": ["G2 F2 | E2 F2 | D5 (u)", "B/4 C/4' B/4 A/4 | D2 D2 | z | (u)"],
           31  +                        "x": ["z4 | (v)"],
    32     32                       },
    33     33                   },
    34         -                "follow_instr": {  # Instrument 'bass'
           34  +                "bass": {
    35     35                       "channel": 4,
    36         -                    "sync": "lead_instr",
           36  +                    "sync": "pan_flute",
    37     37                       "octave": 2,
    38     38                       "duration": 60,
    39     39                       "grammars": {  # Notes for this instrument to use in this piece
    40     40                           "u": ["C/2 C/2 C/2 z/2 (u)"],
    41     41                       },
    42     42                   },
           43  +                "horn_timbre1": { 
           44  +                    "channel": 13,
           45  +                    "octave": 2,
           46  +                    "duration": 60,
           47  +                    "grammars": {  # Notes for this instrument to use in this piece
           48  +                        "u": ["C4 D4 (u)"],
           49  +                    },
           50  +                },
           51  +                "horn_timbre2": {  
           52  +                    "channel": 13,
           53  +                    "octave": 2,
           54  +                    "duration": 60,
           55  +                    "grammars": {  # Notes for this instrument to use in this piece
           56  +                        "u": ["G4 A4 (u)"],
           57  +                    },
           58  +                },
    43     59               },
    44     60           },
    45     61           "section1": {
    46     62               "body": {
    47         -                "lead_instr": {  # Instrument 'melody'
           63  +                "guitar": {  # Instrument 'melody'
    48     64                       "channel": 6,
    49     65                       "octave": 5,
    50     66                       "duration": 60,
    51     67                       "grammars": {  # Notes for this instrument to use in this piece
    52         -                        "u": ["C E A F G z (u)", "C E A F G z (v)"],
    53         -                        "v": ["A/2 D/2 G/2 C/2 | F/2 B/2 E/2 z/2 | (u)"],
           68  +                        "u": ["C | E | A | F | G | z | (u)", "C | E | A | F | G | z | (v)"],
           69  +                        "v": ["A/2 D/2 | G/2 C/2 | F/2 B/2 | E/2 | z/2 | (u)"],
           70  +                    },
           71  +                },
           72  +                "bass": {  # Instrument 'bass'
           73  +                    "channel": 4,
           74  +                    "sync": "guitar",
           75  +                    "octave": 2,
           76  +                    "duration": 60,
           77  +                    "grammars": {  # Notes for this instrument to use in this piece
           78  +                        "u": ["C/2 C/2 | C/2 z/2 | (u)"],
           79  +                    },
           80  +                },
           81  +                "horn_timbre1": {
           82  +                    "channel": 13,
           83  +                    "octave": 2,
           84  +                    "duration": 60,
           85  +                    "grammars": {  # Notes for this instrument to use in this piece
           86  +                        "u": ["C4 D4 (u)"],
    54     87                       },
    55     88                   },
    56         -                "follow_instr": {  # Instrument 'bass'
    57         -                    "channel": 4,
    58         -                    "sync": "lead_instr",
           89  +                "horn_timbre2": { 
           90  +                    "channel": 13,
    59     91                       "octave": 2,
    60     92                       "duration": 60,
    61     93                       "grammars": {  # Notes for this instrument to use in this piece
    62         -                        "u": ["C/2 C/2 C/2 z/2 (u)"],
           94  +                        "u": ["G4 A4 (u)"],
    63     95                       },
    64     96                   },
    65     97               },
    66     98           },
    67     99       }
    68    100   
    69    101       section_start = 0
    70         -    for section in ["intro", "section1"]:
    71         -        print "Section " + section
          102  +    for section_name in ["intro", "section1"]:
          103  +        print "Section " + section_name
    72    104           subsection_start = section_start
    73         -        section = composition[section]
          105  +        section = composition[section_name]
    74    106           for subsection in ["intro", "body", "outro"]:
    75         -            try:
    76         -                print "Subsection " + subsection
    77         -                subsection = section[subsection]
    78         -
    79         -                unordered_instrs = []
    80         -                for instr in subsection:
    81         -                    subsection[instr]["name"] = instr
    82         -                    if not "sync" in subsection[instr].keys():
    83         -                        subsection[instr]["sync"] = None
    84         -                    unordered_instrs.append([subsection[instr]["sync"], instr])
    85         -                ordered_instrs = topsort.topsort(unordered_instrs)
    86         -                ordered_instrs.remove(None)  # None used as a placeholder for sort order for instruments with no sync setting
    87         -
    88         -                instrs = []
    89         -                syncs = {}
    90         -                track = 0
    91         -                for instr in ordered_instrs:
    92         -                    print "Instrument " + instr
    93         -                    instr = subsection[instr]
    94         -                    max_time = instr["duration"]
    95         -                    instr_score, syncs = render_instr(instr, syncs, max_time)
    96         -                    instrs.append(instr_score)
    97         -                    midify_instr_score(instr_score, track, instr["channel"], subsection_start)
    98         -                longest_score = max(instrs, key=lambda i: score_len(i))
    99         -                subsection_start += score_len(longest_score)
   100         -                section_start += score_len(longest_score)
   101         -                track += 1
   102         -            except KeyError:
   103         -                pass
          107  +            if not section.has_key(subsection):
          108  +                continue
          109  +            print "\tSubsection " + subsection
          110  +            subsection = section[subsection]
          111  +
          112  +            unordered_instrs = []
          113  +            for instr in subsection:
          114  +                subsection[instr]["name"] = instr
          115  +                if not "sync" in subsection[instr].keys():
          116  +                    subsection[instr]["sync"] = None
          117  +                unordered_instrs.append([subsection[instr]["sync"], instr])
          118  +            ordered_instrs = topsort.topsort(unordered_instrs)
          119  +            ordered_instrs.remove(None)  # None used as a placeholder for sort order for instruments with no sync setting
          120  +            for sync_instr in ordered_instrs:
          121  +                if sync_instr not in subsection.keys():
          122  +                    raise KeyError("The sync instrument '%s' does not exist in this subsection" % sync_instr)
          123  +
          124  +            instrs = []
          125  +            syncs = {}
          126  +            track = 0
          127  +            for instr in ordered_instrs:
          128  +                print "\t\tInstrument " + instr
          129  +#                if instr == "guitar":
          130  +#                    ipdb.set_trace()
          131  +                instr = subsection[instr]
          132  +                max_time = instr["duration"]
          133  +                instr_score, syncs = render_instr(instr, syncs, max_time)
          134  +                instrs.append(instr_score)
          135  +
          136  +                volume = 100
          137  +                if instr.has_key("vol_offset"):
          138  +                    volume += instr["vol_offset"]
          139  +                    print "\t\t\tvolume offset = %d, nev volume = %d" % (instr["vol_offset"], volume)
          140  +                midify_instr_score(instr_score, track, instr["channel"], subsection_start, volume=volume)
          141  +            longest_score = max(instrs, key=lambda i: score_len(i))
          142  +            subsection_start += score_len(longest_score)
          143  +            section_start += score_len(longest_score)
          144  +            track += 1
   104    145       with open("out.mid", "wb") as outfile:
   105    146           mymidi.writeFile(outfile)
   106    147   
   107    148   
   108    149   
   109    150   def render_instr(instr, syncs, max_time):
   110    151       for g in instr["grammars"]:
................................................................................
   151    192               grammar = random.choice(time_filtered_grammars.keys())
   152    193       if score is None:
   153    194           grammar = random.choice(time_filtered_grammars.keys())
   154    195       elif instr["sync"] is None:
   155    196           grammar = get_next_node(score);
   156    197           if grammar not in instr["grammars"].keys():
   157    198               raise Exception("You tried to direct a grammar to a node that doesn't exist")
          199  +
          200  +    if grammar not in time_filtered_grammars.keys():
          201  +        return [], syncs
          202  +
   158    203       phrases = time_filtered_grammars[grammar]
   159    204       if instr["name"] not in syncs.keys():
   160    205           syncs[instr["name"]] = []
   161    206       syncs[instr["name"]].append({"node": grammar, "time": current_time})
   162    207   
   163    208       return random.choice(phrases), syncs
   164    209   
................................................................................
   190    235       return total
   191    236   
   192    237   
   193    238   def get_midi_note(octave, note):
   194    239       return note + 12 * (octave+1)
   195    240   
   196    241   
   197         -def midify_instr_score(score, track, channel, t):
          242  +def midify_instr_score(score, track, channel, t, volume):
   198    243       # Assume get_midi_note()
   199    244       global mymidi
   200    245   
   201    246       for token in score:
   202    247           if isinstance(token, parse.Chord):  # Chords
   203    248               for note in token.chord: 
   204    249                   note = get_midi_note(token.octave, note)
   205         -                mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=100)
          250  +                mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume)
   206    251           elif isinstance(token, parse.Note):  # Individual notes
   207    252               note = get_midi_note(token.octave, token.value)
   208         -            mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=100)
          253  +            mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume)
   209    254           elif isinstance(token, tree.Tree):
   210    255               continue
   211    256           t += token.duration
   212    257   
   213    258       return []
   214    259   
   215    260   
   216    261   if __name__ == "__main__": main()