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