spiffyscore

Check-in [8f28834102]
Login
Overview
SHA1:8f28834102b41a640931e718c456c3dace788a11
Date: 2011-11-27 02:56:34
User: brian
Comment:Fixed chord support
Timelines: family | ancestors | descendants | both | develop
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2011-12-04
20:52
[3023a967c2] Leaf: Made room for arbitrary-note chording whenever I figure out the CFY to represent iTSYntax to use for it (user: brian, tags: develop)
2011-11-27
02:56
[8f28834102] Fixed chord support (user: brian, tags: develop)
02:26
[bf135b5321] Fixed a bug that prevented sharps and flats from working (user: brian, tags: develop)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified parse.py from [4cca2f3d0c] to [0884d30f89].

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
..
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
...
100
101
102
103
104
105
106
107
108
109
110
111
112

113
114


115
116
117
118
119
120
121
#!/usr/bin/env python

import tree

from ply import lex, yacc
class Note():
    def __init__(self, value, duration=1, octave=8):

        self.value = value
        self.duration = duration


        self.octave = octave
    def __repr__(self):
        return "Note %s %s %s" % (self.value, self.duration, self.octave)

class Chord():
    def __init__(self, value, duration=1, chord_type="major", octave=5):
        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=1):
        self.duration = duration
    def __repr__(self):
        return "Rest node %s" % self.duration

................................................................................
    tokens = (
        "NOTE_LENGTH",
        "BASENOTE",
        "ACCIDENTAL",
        "REST",
        "OCTAVE",
        "CHORD_TYPE",
        "PAREN",
        "SYNCOPATE",
        "NODE",
    )

    t_ignore = " |"

    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("/"):
................................................................................
        '''
        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]








>
|
|
>
>





|
|

<
<

<
>







 







|












|







 







|
|

|
|
<
>
|
|
>
>







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
..
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
...
101
102
103
104
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python

import tree

from ply import lex, yacc
class Note():
    def __init__(self, value, duration=1, octave=8):
        self.duration = duration
        if value > 12:
            self.duration += 1
            value = value % 12
        self.value = value
        self.octave = octave
    def __repr__(self):
        return "Note %s %s %s" % (self.value, self.duration, self.octave)

class Chord():
    def __init__(self, notes, duration=1):
        self.notes = notes
        self.duration = duration


    def __repr__(self):

        return "Chord %s" % (self.notes)

class Rest():
    def __init__(self, duration=1):
        self.duration = duration
    def __repr__(self):
        return "Rest node %s" % self.duration

................................................................................
    tokens = (
        "NOTE_LENGTH",
        "BASENOTE",
        "ACCIDENTAL",
        "REST",
        "OCTAVE",
        "CHORD_TYPE",
        "BRACKET",
        "SYNCOPATE",
        "NODE",
    )

    t_ignore = " |"

    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_BRACKET = r"\[|\]"
    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("/"):
................................................................................
        '''
        new_note = p[1]
        new_note.duration = p[2]
        p[0] = new_note


    def p_chord(p):
        '''chord : BRACKET note BRACKET
                 | BRACKET note CHORD_TYPE BRACKET
        '''
        root_note = p[2].value
        chorded_notes = []


        for offset in [0, 4, 7]:
            chorded_notes.append(Note(root_note+offset, octave=p[2].octave))

        p[0] = Chord(notes=chorded_notes)


    def p_note_syncopate(p):
        ''' note : note SYNCOPATE
        '''
        note.syncopate = p[2]

Modified spiffyscore.py from [8b19298d3a] to [11e8d97d43].

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
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
mymidi = midifile(15)

def main():
    composition = {
        "intro": {
            "body": {
                "percusion": {
                    "channel": 14,
                    "octave": 4,
                    "duration": 60,
                    "grammars": {
                        "u": ["A ^A (u)"]
                    }
                },
                "pan_flute": {
                    "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": {  
................................................................................
                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 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() 







|










>

>
|
|
|












|







 







<







 







|
|
|












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
...
142
143
144
145
146
147
148

149
150
151
152
153
154
155
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
mymidi = midifile(15)

def main():
    composition = {
        "intro": {
            "body": {
                "percusion": {
                    "channel": 14,  # Orchestra kit
                    "octave": 4,
                    "duration": 60,
                    "grammars": {
                        "u": ["A ^A (u)"]
                    }
                },
                "pan_flute": {
                    "channel": 8,
                    "octave": 5,
                    "duration": 60,
                    "vol_offset": -15,
                    "grammars": {  # Notes for this instrument to use in this piece
                        "u": ["[C2'] C2' | [A3] A3 (u)"],
#                        "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,  # 'Atmosphere'
                    "octave": 2,
                    "duration": 60,
                    "grammars": {  # Notes for this instrument to use in this piece
                        "u": ["C4 D4 (u)"],
                    },
                },
                "horn_timbre2": {  
................................................................................
                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"]

                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 midify_instr_score(score, track, channel, t, volume):
    # Assume get_midi_note()
    global mymidi

    for token in score:
        if isinstance(token, parse.Chord):
            for note in token.notes: 
                note = get_midi_note(note.octave, note.value)
                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()