Overview
Comment: | Added lexical support for parens instead of quotes for chords, cleaned up the yacc parser, added lex tokens for syncopation |
---|---|
Timelines: | family | ancestors | descendants | both | master |
Files: | files | file ages | folders |
SHA1: |
702d933446257117bbc81a7603231aef |
User & Date: | brian@linux-85dd.site on 2011-02-10 22:34:39 |
Other Links: | branch diff | manifest | tags |
Context
2011-02-10
| ||
23:50 | Program generates a render order for the instruments based on their sync order check-in: 689adc054e user: brian@linux-85dd.site tags: master | |
22:34 | Added lexical support for parens instead of quotes for chords, cleaned up the yacc parser, added lex tokens for syncopation check-in: 702d933446 user: brian@linux-85dd.site tags: master | |
2010-11-30
| ||
17:33 | This is what I submitted as my final piece for MUS 306 check-in: 843dabad43 user: spiffytech@gmail.com tags: master | |
Changes
Modified cfg.py from [019c552e42] to [82bf7ad059].
︙ | ︙ | |||
11 12 13 14 15 16 17 | def main(): key = "A" bps = 60/60 tempo = 1/bps max_duration = 1 composition = { | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 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 | def main(): key = "A" bps = 60/60 tempo = 1/bps max_duration = 1 composition = { "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"], }, "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) (ii)/4 (ii)/4 (IV)/2 (V)2 (IV) (ii) u', '(I) (vii) (III) u', '(I) (v) (IV) u u'], }, "score": "u", }, }, } max_t = 0 # max time encountered so far. Used for movement timing 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 score = parse.parse(generated_score, default_octave=instr["octave"]) # Return Node/Chord objects |
︙ | ︙ |
Modified parse.py from [9c47a4ff24] to [3ec57c3fbe].
︙ | ︙ | |||
15 16 17 18 19 20 21 | self.value = value self.duration = duration 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) | < > | > | < < < < < < < < | | | | | | | > > | < < < < < < < | | > > > > > > | | | | | | < | 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 | self.value = value self.duration = duration 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 def parse(score, default_octave=8): # Tokenize (lex) tokens = ( "NOTE_LENGTH", "BASENOTE", "ACCIDENTAL", "REST", "OCTAVE", "CHORD_TYPE", "PAREN", "SYNCOPATE", ) t_ignore = " |" #t_BASENOTE = r"[A-Ga-g]" 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_PAREN = "\(|\)" t_SYNCOPATE = "\+|-" def t_NOTE_LENGTH(t): r"/?\d+" multiplier = float(t.value.strip("/")) if t.value.startswith("/"): multiplier = 1/multiplier t.value = multiplier return t def t_error(t): raise TypeError("Unknown text '%s'" % (t.value,)) lex.lex() lex.input(score) # Parse (yacc) def p_note_list(p): '''score : score note | score chord | score rest ''' p[0] = p[1] + [p[2]] def p_score(p): '''score : note | chord | rest ''' p[0] = [p[1]] def p_chord_length(p): ''' chord : chord NOTE_LENGTH ''' 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(p): '''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): '''note : ACCIDENTAL note ''' p[2].accidental = p[1] p[0] = p[2] 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_note(p): '''note : BASENOTE ''' p[0] = Note(p[1], octave=default_octave) def p_rest(p): ''' rest : REST | REST NOTE_LENGTH ''' p[0] = Rest() if len(p) > 2: p[0].duration = p[2] def p_error(p): raise Exception("Syntax error at '%s' of element type %s" % (p.value, p.type)) yacc.yacc() return yacc.parse(score) |
Modified todo.org from [bc98f41fc3] to [510751b73f].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | * Features [4/10] - [X] Top-down composition - [ ] Coordinate the melody and rhythm - [X] Set maximum song length of movement per instrument - [ ] Set minimum song length of movement per instrument - [ ] Need to support all chord types - [X] Doesn't handle rest notes - [ ] 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 * 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 - [X] Calculated duration is absolute, not relative to BPM - [X] Chords don't respect octaves | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | * Features [4/10] - [X] Top-down composition - [ ] Coordinate the melody and rhythm - [X] Set maximum song length of movement per instrument - [ ] Set minimum song length of movement per instrument - [ ] Need to support all chord types - [X] Doesn't handle rest notes - [ ] 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 - [X] Calculated duration is absolute, not relative to BPM - [X] Chords don't respect octaves |
︙ | ︙ |