Index: cfg.py ================================================================== --- cfg.py +++ cfg.py @@ -13,287 +13,34 @@ bps = 60/60 tempo = 1/bps max_duration = 1 composition = { - "intro1": { - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 4, - "grammars": { - "u": ['"I" "ii"/4 "ii"/4 "IV"/2 "V"2 "IV" "ii" x u', '"I" "vii" "III" y u', '"I" "v" "IV" u u'], - "w": ['"i" "VII"2 "VI"/4 "V"/4 "i"/4 "VII"2 "VI" "V" w u'], - "x": ['"III/2" "VI"/2 "III"/2 "vii"2 "i"2 "V" u'], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u x u y x w u", - }, - }, - "intro2": { - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 8, - "grammars": { - "u": ['"I" "ii"/4 "ii"/4 "IV"/2 "V"2 "IV" "ii" x u', '"I" "vii" "III" y u', '"I" "v" "IV" u u'], - "w": ['"i" "VII"2 "VI"/4 "V"/4 "i"/4 "VII"2 "VI" "V" w u'], - "x": ['"III/2" "VI"/2 "III"/2 "vii"2 "i"2 "V" u'], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u x u y x w u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 8, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, "overview": { "melody": { # Instrument 'melody' "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2", "octave": 8, "duration": 40, "grammars": { # Notes for this instrument to use in this piece "u": ["I V/2 V/2 V/2 I VII, IV' I IV I VII IV"], - "w": ['III/4 VI/4 II/4 V/4 VI/4 IV/4 VII2'], - "x": ['I/2 I/2 VI IV/2 V2 z I/2 I/2 VI IV/2 V'], - }, - "score": "u u w w w w w x x", - }, - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 44, - "grammars": { - "u": ['"I" "ii"/4 "ii"/4 "IV"/2 "V"2 "IV" "ii" x u', '"I" "vii" "III" y u', '"I" "v" "IV" u u'], - "w": ['"i" "VII"2 "VI"/4 "V"/4 "i"/4 "VII"2 "VI" "V" w u'], - "x": ['"III/2" "VI"/2 "III"/2 "vii"2 "i"2 "V" u'], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u x u y x w u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 44, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, - "a": { # Movement block 'a' for reuse throughout the piece - "melody": { # Instrument 'melody' - "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2", - "octave": 8, - "duration": 40, - "grammars": { # Notes for this instrument to use in this piece - "u": ["I V/2 V/2 V/2 I VII, IV' x", "I IV w", "I VII IV u"], - "w": ['VII I IV V VI VII I IV V VI VII u'], - "x": ['VI/4 III/4 II/4 I/4 w'], - }, - "score": "u", - }, - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 48, - "grammars": { - "u": ['"I" "ii"/4 "ii"/4 "IV"/2 "V"2 "IV" "ii" x u', '"I" "vii" "III" y u', '"I" "v" "IV" u u'], - "w": ['"i" "VII"2 "VI"/4 "V"/4 "i"/4 "VII"2 "VI" "V" w u'], - "x": ['"III/2" "VI"/2 "III"/2 "vii"2 "i"2 "V" u'], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u x u y x w u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 42, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, - "b": { # Movement block 'a' for reuse throughout the piece - "melody": { # Instrument 'melody' - "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2", - "octave": 8, - "duration": 40, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I VII V III u', "y"], - "w": ['VII I IV V VI u', 'w'], - "x": ['VI/4 III/4 II/4 I/4 w', 'x x'], - "y": ["III/4 VI/4 II/4 V/4 VI/4 IV/4 VII2"], - }, - "score": "w w x x w", - }, - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 44, - "grammars": { - "u": ['"I" "V" "vi" "iii" "IV" "I" "IV" "V" u u', "y"], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u u y y u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 40, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, - "zelda1": { # Movement block 'a' for reuse throughout the piece - "melody": { # Instrument 'melody' - "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2", - "octave": 8, - "duration": 50, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I VI/2 VI/2 IV/2 I VI/2 VI/2 IV/2 I VI/2 VI/2 IV/2 w', "y"], - "w": ['VII/2 I/2 II/2 V/2 u'], - "x": ['VI/4 III/4 II/4 I/4 w'], - "y": ["III/4 VI/4 II/4 V/4 VI/4 IV/4 VII2 x"], - }, - "score": "w", - }, - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 54, - "grammars": { - "u": ['"I"/2 "V"/2 "vi"/2 "iii"/2 "IV"/2 "I"/2 "IV"/2 "V"/2 u u', "y"], - "y": ['"I"/2 "vi" "IV"/2 "V"/2 y y u'], - }, - "score": "u u y y u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 54, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, - "zelda2": { # Movement block 'a' for reuse throughout the piece - "melody": { # Instrument 'melody' - "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2", - "octave": 8, - "duration": 40, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I/2 I/2 VI IV/2 V2 z I/2 I/2 VI IV/2 V u', "w"], - "w": ['III/2 II/2 IV/2 III/2 V/2 IV/2 VI/2 V/2 w', 'u', 'x'], - "x": ['VII3 z2 V/4 IV/4 V/4 IV/4 V/4 VI/4 II/4 II/4 II/4 I/4 II/2 u', 'w'], }, "score": "u", }, "rhythm": { "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", "octave": 7, "duration": 44, "grammars": { - "u": ['"I"/2 "V"/2 "vi"/2 "iii"/2 "IV"/2 "I"/2 "IV"/2 "V"/2 u u', "y"], - "y": ['"I"/2 "vi" "IV"/2 "V"/2 y y u'], - }, - "score": "u u y y u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 44, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, - "timbre_solo": { # Movement block 'a' for reuse throughout the piece - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 30, - "grammars": { - "u": ['"I"/2 "V"/2 "vi"/2 "iii"/2 "IV"/2 "I"/2 "IV"/2 "V"/2 u u', "y"], - "y": ['"I"/2 "vi" "IV"/2 "V"/2 y y u'], - }, - "score": "u u y y u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 30, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I VI/2 VI/2 IV/2 u', "y"], - "w": ['VII/2 I/2 II/2 V/2 u', 'w w', 'u x'], - "x": ['VI/4 III/4 II/4 I/4 w', 'x x', 'x u'], - "y": ["III/4 VI/4 II/4 V/4 VI/4 IV/4 VII2 w", 'y y'], + "u": ['(I) (ii)/4 (ii)/4 (IV)/2 (V)2 (IV) (ii) u', '(I) (vii) (III) u', '(I) (v) (IV) u u'], }, "score": "u", }, }, - "outro1": { # Movement block 'a' for reuse throughout the piece - "melody": { # Instrument 'melody' - "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2", - "octave": 8, - "duration": 20, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I VII V III u', "y"], - "w": ['VII I IV V VI u', 'w w'], - "x": ['VI/4 III/4 II/4 I/4 w', 'x x'], - "y": ["III/4 VI/4 II/4 V/4 VI/4 IV/4 VII2"], - }, - "score": "w w x x w", - }, - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 26, - "grammars": { - "u": ['"I" "V" "vi" "iii" "IV" "I" "IV" "V" u u', "y"], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u u y y u", - }, - "timbre": { - "score_line": "i3 %(time)f %(duration)f 2000 %(octave)d.%(note)s 2 3 5 3", - "octave": 6, - "duration": 26, - "grammars": { # Notes for this instrument to use in this piece - "u": ['I2 VII2 V2 VI2 I2 IV/2 V/2 III2 u', 'I2 IV2 V2 IV I V2 III2 II2 u'] - }, - "score": "u u u u u", - }, - }, - "outro2": { - "rhythm": { - "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6", - "octave": 7, - "duration": 4, - "grammars": { - "u": ['"I" "V" "vi" "iii" "IV" "I" "IV" "V" u u', "y"], - "y": ['"I" "vi"2 "IV" "V" y y u'], - }, - "score": "u u y y u", - }, - }, } max_t = 0 # max time encountered so far. Used for movement timing - progression = "intro1 intro2 overview a timbre_solo zelda1 b zelda2 outro1 outro2" -# progression = "zelda1" + progression = "overview" for comp_name in progression.split(): comp_start_time = max_t for instr_name, instr in composition[comp_name].iteritems(): generated_score = generate_score(instr["score"], instr["grammars"]) # Fill in the scores by generating them based on the grammars # print generated_score Index: parse.py ================================================================== --- parse.py +++ parse.py @@ -17,11 +17,10 @@ self.chord_type = chord_type self.octave = octave def __repr__(self): return "Chord %s %s %s" % (self.value, self.duration, self.chord_type, self.octave) - class Rest(): def __init__(self, duration=.25): self.duration = duration def __repr__(self): return "Rest node %s" % self.duration @@ -34,11 +33,12 @@ "BASENOTE", "ACCIDENTAL", "REST", "OCTAVE", "CHORD_TYPE", - "QUOTE", + "PAREN", + "SYNCOPATE", ) t_ignore = " |" #t_BASENOTE = r"[A-Ga-g]" @@ -45,11 +45,12 @@ t_BASENOTE = r"I+V?|VI*|i+v?|vi*" t_ACCIDENTAL = r"\^{1,2}|_{1,2}|=" 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_QUOTE = '"' + t_PAREN = "\(|\)" + t_SYNCOPATE = "\+|-" def t_NOTE_LENGTH(t): r"/?\d+" multiplier = float(t.value.strip("/")) if t.value.startswith("/"): @@ -59,92 +60,85 @@ def t_error(t): raise TypeError("Unknown text '%s'" % (t.value,)) lex.lex() - - #lex.input("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD") - #s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD" - #s = '''I IV V VI I "I" "ii"/2''' - #s = "GF_G,/2" lex.input(score) - #for tok in iter(lex.token, None): - # print repr(tok.type), repr(tok.value) # Parse (yacc) - - def p_pitch_list(p): + def p_note_list(p): '''score : score note - | score chord - | score rest + | score chord + | score rest ''' p[0] = p[1] + [p[2]] def p_score(p): '''score : note - | chord - | rest + | chord + | rest ''' p[0] = [p[1]] - def p_note(p): - '''note : pitch + def p_chord_length(p): + ''' chord : chord NOTE_LENGTH ''' - p[0] = p[1] + new_note = p[1] + new_note.duration = p[2] + p[0] = new_note def p_note_length(p): ''' note : note NOTE_LENGTH ''' new_note = p[1] new_note.duration = p[2] p[0] = new_note - def p_chord_length(p): - ''' chord : chord NOTE_LENGTH - ''' - new_note = p[1] - new_note.duration = p[2] - p[0] = new_note - def p_chord(p): - '''chord : QUOTE pitch QUOTE - | QUOTE pitch CHORD_TYPE QUOTE + '''chord : PAREN note PAREN + | PAREN note CHORD_TYPE PAREN ''' pitch = p[2].value pitch = pitch.upper() p[0] = Chord(value=pitch, octave=default_octave) if len(p) > 3: p[0].chord_type = p[3] + + def p_note_syncopate(p): + ''' note : note SYNCOPATE + ''' + note.syncopate = p[2] + def p_accidental(p): - '''pitch : ACCIDENTAL pitch + '''note : ACCIDENTAL note ''' p[2].accidental = p[1] p[0] = p[2] - def p_pitch_octave(p): - '''pitch : pitch OCTAVE + def p_octave(p): + '''note : note OCTAVE ''' count = len(p[2]) increment_or_decrement = 1 if p[2].startswith("'") else -1 p[1].octave += (count * increment_or_decrement) p[0] = p[1] - def p_pitch(p): - '''pitch : BASENOTE + def p_note(p): + '''note : BASENOTE ''' p[0] = Note(p[1], octave=default_octave) def p_rest(p): ''' rest : REST - | REST NOTE_LENGTH + | REST NOTE_LENGTH ''' p[0] = Rest() if len(p) > 2: p[0].duration = p[2] @@ -151,7 +145,6 @@ def p_error(p): raise Exception("Syntax error at '%s' of element type %s" % (p.value, p.type)) yacc.yacc() - #print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD") return yacc.parse(score) Index: todo.org ================================================================== --- todo.org +++ todo.org @@ -8,10 +8,12 @@ - [ ] Handle full ABC BNF (yeah, right, that's gonna happen...) - [X] Set instrument octave in score file - [ ] Output score to separate file - [ ] Support parallel voices - ensure e.g. a certain chord progression is always accompanied by a certain melody +- [ ] Syncopation +- [ ] Sustain option for notes (give score notation a sustain symbol, and use it to set how long after the notes's duration to keep holding. With sustain, the next note's start time isn't done by when the current note ends. * Bugs [5/6] - [X] TLD resets clock for each movement - [X] TLD doesn't accept an ordering for the movements - [X] Doesn't handle minor chords