spiffyscore

Changes On Branch 1bc01ba9c99ece4e
Login

Changes On Branch 1bc01ba9c99ece4e

Changes In Branch feature/diskin2 Excluding Merge-Ins

This is equivalent to a diff from 072fa6ad30 to 1bc01ba9c9

2011-11-03
18:50
Merged in diskin2 mode for cfg.orc check-in: 0021a3fe22 user: brian tags: develop
18:49
By magic, fixed problem with not all bass notes playing via diskin2 Closed-Leaf check-in: 1bc01ba9c9 user: brian tags: feature/diskin2
18:34
Fixed program to now handle notes with accidentals check-in: b5a8b20242 user: brian tags: feature/diskin2
2011-11-01
19:46
Got diskin2 sample method partially working; it won't play all of the files, though check-in: c9abf46a9f user: brian tags: feature/diskin2
18:54
Imported the todo list from MUS306 check-in: 072fa6ad30 user: brian tags: develop
18:52
Added a sampled double bass, modified the program to respond to an instrument's specified octave check-in: eb81d5f9fd user: brian tags: develop

Modified cfg.orc from [e60884eb39] to [c58361434c].

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
sr=44100
ksmps=20
nchnls=1

gifn ftgen 105, 0, 524288, -1,  "samples/bass/1.05.wav", 0, 0, 1 ; Middle C
gifn ftgen 106, 0, 524288, -1,  "samples/bass/1.06.wav", 0, 0, 1 ; Middle C
gifn ftgen 107, 0, 524288, -1,  "samples/bass/1.07.wav", 0, 0, 1 ; Middle C
gifn ftgen 108, 0, 524288, -1,  "samples/bass/1.08.wav", 0, 0, 1 ; Middle C
gifn ftgen 109, 0, 524288, -1,  "samples/bass/1.09.wav", 0, 0, 1 ; Middle C
gifn ftgen 110, 0, 524288, -1,  "samples/bass/1.10.wav", 0, 0, 1 ; Middle C
gifn ftgen 111, 0, 524288, -1,  "samples/bass/1.11.wav", 0, 0, 1 ; Middle C
gifn ftgen 200, 0, 524288, -1,  "samples/bass/2.01.wav", 0, 0, 1 ; Middle C
gifn ftgen 201, 0, 524288, -1,  "samples/bass/2.02.wav", 0, 0, 1 ; Middle C
gifn ftgen 202, 0, 524288, -1,  "samples/bass/2.03.wav", 0, 0, 1 ; Middle C
gifn ftgen 203, 0, 524288, -1,  "samples/bass/2.04.wav", 0, 0, 1 ; Middle C
gifn ftgen 204, 0, 524288, -1,  "samples/bass/2.05.wav", 0, 0, 1 ; Middle C
gifn ftgen 206, 0, 524288, -1,  "samples/bass/2.06.wav", 0, 0, 1 ; Middle C
gifn ftgen 207, 0, 524288, -1,  "samples/bass/2.07.wav", 0, 0, 1 ; Middle C
gifn ftgen 208, 0, 524288, -1,  "samples/bass/2.08.wav", 0, 0, 1 ; Middle C
gifn ftgen 209, 0, 524288, -1,  "samples/bass/2.09.wav", 0, 0, 1 ; Middle C
gifn ftgen 210, 0, 524288, -1,  "samples/bass/2.10.wav", 0, 0, 1 ; Middle C
gifn ftgen 211, 0, 524288, -1,  "samples/bass/2.11.wav", 0, 0, 1 ; Middle C
gifn ftgen 300, 0, 524288, -1,  "samples/bass/3.00.wav", 0, 0, 1 ; Middle C
gifn ftgen 301, 0, 524288, -1,  "samples/bass/3.01.wav", 0, 0, 1 ; Middle C
gifn ftgen 302, 0, 524288, -1,  "samples/bass/3.02.wav", 0, 0, 1 ; Middle C
gifn ftgen 303, 0, 524288, -1,  "samples/bass/3.03.wav", 0, 0, 1 ; Middle C
gifn ftgen 304, 0, 524288, -1,  "samples/bass/3.04.wav", 0, 0, 1 ; Middle C
gifn ftgen 305, 0, 524288, -1,  "samples/bass/3.05.wav", 0, 0, 1 ; Middle C
gifn ftgen 306, 0, 524288, -1,  "samples/bass/3.06.wav", 0, 0, 1 ; Middle C
gifn ftgen 307, 0, 524288, -1,  "samples/bass/3.07.wav", 0, 0, 1 ; Middle C
gifn ftgen 308, 0, 524288, -1,  "samples/bass/3.08.wav", 0, 0, 1 ; Middle C
gifn ftgen 309, 0, 524288, -1,  "samples/bass/3.09.wav", 0, 0, 1 ; Middle C
gifn ftgen 310, 0, 524288, -1,  "samples/bass/3.10.wav", 0, 0, 1 ; Middle C
gifn ftgen 311, 0, 524288, -1,  "samples/bass/3.11.wav", 0, 0, 1 ; Middle C

instr 3
    inum = p5*100
    asig loscil 1, 1, inum, 1 





























































    outs asig
endin

instr 1
    asound pluck   p4, cpspch(p5), cpspch(p6), p7, p8 p9 p10
    out asound
endin




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
sr=44100
ksmps=20
nchnls=1
































instr 3
    if p5=105 then
        asig diskin2 "samples/bass/1.05.wav", 1
    elseif p5=1.06 then
        asig diskin2 "samples/bass/1.06.wav", 1
    elseif p5=1.07 then
        asig diskin2 "samples/bass/1.07.wav", 1
    elseif p5=1.08 then
        asig diskin2 "samples/bass/1.08.wav", 1
    elseif p5=1.08 then
        asig diskin2 "samples/bass/1.09.wav", 1
    elseif p5=1.10 then
        asig diskin2 "samples/bass/1.10.wav", 1
    elseif p5=1.11 then
        asig diskin2 "samples/bass/1.11.wav", 1
    elseif p5=2.00 then
        asig diskin2 "samples/bass/2.00.wav", 1
    elseif p5=2.01 then
        asig diskin2 "samples/bass/2.01.wav", 1
    elseif p5=2.02 then
        asig diskin2 "samples/bass/2.02.wav", 1
    elseif p5=2.03 then
        asig diskin2 "samples/bass/2.03.wav", 1
    elseif p5=2.04 then
        asig diskin2 "samples/bass/2.04.wav", 1
    elseif p5=2.05 then
        asig diskin2 "samples/bass/2.05.wav", 1
    elseif p5=2.06 then
        asig diskin2 "samples/bass/2.06.wav", 1
    elseif p5=2.07 then
        asig diskin2 "samples/bass/2.07.wav", 1
    elseif p5=2.08 then
        asig diskin2 "samples/bass/2.08.wav", 1
    elseif p5=2.09 then
        asig diskin2 "samples/bass/2.09.wav", 1
    elseif p5=2.10 then
        asig diskin2 "samples/bass/2.10.wav", 1
    elseif p5=2.11 then
        asig diskin2 "samples/bass/2.11.wav", 1
    elseif p5=3.00 then
        asig diskin2 "samples/bass/3.00.wav", 1
    elseif p5=3.01 then
        asig diskin2 "samples/bass/3.01.wav", 1
    elseif p5=3.02 then
        asig diskin2 "samples/bass/3.02.wav", 1
    elseif p5=3.03 then
        asig diskin2 "samples/bass/3.03.wav", 1
    elseif p5=3.04 then
        asig diskin2 "samples/bass/3.04.wav", 1
    elseif p5=3.05 then
        asig diskin2 "samples/bass/3.05.wav", 1
    elseif p5=3.06 then
        asig diskin2 "samples/bass/3.06.wav", 1
    elseif p5=3.07 then
        asig diskin2 "samples/bass/3.07.wav", 1
    elseif p5=3.08 then
        asig diskin2 "samples/bass/3.08.wav", 1
    elseif p5=3.09 then
        asig diskin2 "samples/bass/3.09.wav", 1
    elseif p5=3.10 then
        asig diskin2 "samples/bass/3.10.wav", 1
    elseif p5=3.11 then
        asig diskin2 "samples/bass/3.11.wav", 1
    endif
    outs asig
endin

instr 1
    asound pluck   p4, cpspch(p5), cpspch(p6), p7, p8 p9 p10
    out asound
endin

Modified parse.py from [2afbfc4534] to [a8d0994825].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/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
        self.accidental = None
    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










<







1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
#!/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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
        "NODE",
    )

    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 = "\+|-"
    t_NODE = r"\([a-zA-Z0-9_-]+\)"








|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
        "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_-]+\)"

120
121
122
123
124
125
126
127



128
129
130
131
132
133
134
        '''
        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







|
>
>
>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
        '''
        note.syncopate = p[2]


    def p_accidental(p):
        '''note : ACCIDENTAL note
        '''
        if p[1] == "^":
            p[2].value += "#"
        else:
            p[2].value += "b"
        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
151
152
153
154
155
156
157


158
159
160
161
162
163
    def p_node(p):
        '''node : NODE
        '''
        p[0] = tree.Tree(p[1].strip("(").strip(")"))


    def p_error(p):


        print p
        raise Exception("Syntax error at '%s' of element type %s" % (p.value, p.type))
        
    yacc.yacc()

    return yacc.parse(score)







>
>






153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    def p_node(p):
        '''node : NODE
        '''
        p[0] = tree.Tree(p[1].strip("(").strip(")"))


    def p_error(p):
#        import ipdb
#        ipdb.set_trace()
        print p
        raise Exception("Syntax error at '%s' of element type %s" % (p.value, p.type))
        
    yacc.yacc()

    return yacc.parse(score)

Modified spiffyscore.py from [791db3d131] to [d189f30210].

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
                        "u": ["C/4 C/4 C/4 C/4"],
                    },
                },
            },
        },
        "sync_test": {
            "body": {
                "lead_instr": {  # Instrument 'melody'
                    "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
                    "octave": 8,
                    "duration": 30,
                    "grammars": {  # Notes for this instrument to use in this piece
                        "u": ["A/4, B/4, C/4 D/4 (u)", "D/4' D/4' D/4' D/4' (v)"],
                        "v": ["C/4 C/4 C/4 C/4 (w)"],
                        "w": ["E/4 F/4 E/4 F/4 (u)"],
                    },
                },
                "follow_instr": {  # Instrument 'melody'
                    "score_line": "i3 %(time)f %(duration)f 7000 %(octave)d.%(note)s",
#                    "sync": "lead_instr",
                    "octave": 2,
                    "duration": 30,
                    "grammars": {  # Notes for this instrument to use in this piece

                        "u": ["E F G E (u)"],
                        "v": ["G A A A (e)"],
                        "e": ["B' A' G' A' (v)"],
                    },
                },
            },
        },
    }
    print '''f1 0 512 10 1
f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08







|
|
|
|
|
|
|
|
|
|






>
|
|
|







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
                        "u": ["C/4 C/4 C/4 C/4"],
                    },
                },
            },
        },
        "sync_test": {
            "body": {
#                "lead_instr": {  # Instrument 'melody'
#                    "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
#                    "octave": 8,
#                    "duration": 30,
#                    "grammars": {  # Notes for this instrument to use in this piece
#                        "u": ["A/4, B/4, C/4 D/4 (u)", "D/4' D/4' D/4' D/4' (v)"],
#                        "v": ["C/4 C/4 C/4 C/4 (w)"],
#                        "w": ["E/4 F/4 E/4 F/4 (u)"],
#                    },
#                },
                "follow_instr": {  # Instrument 'melody'
                    "score_line": "i3 %(time)f %(duration)f 7000 %(octave)d.%(note)s",
#                    "sync": "lead_instr",
                    "octave": 2,
                    "duration": 30,
                    "grammars": {  # Notes for this instrument to use in this piece
                        "u": ["A ^A B C ^C D ^D E F ^F G ^G"],
#                        "u": ["E F G E (v)"],
#                        "v": ["G A A A (e)", "G A A A (v)"],
#                        "e": ["B A G A (v)"],
                    },
                },
            },
        },
    }
    print '''f1 0 512 10 1
f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284
285
286
287
            total += n.duration
    return total


def generate_csound_score(score, score_line, t):
    csound_note_values = {
        "C": "00",
        "C#": "01",
        "D": "02",
        "D#": "03",
        "E": "04",
        "F": "05",
        "F#": "06",
        "G": "07",
        "G#": "08",
        "A": "09",
        "A#": "10",
        "B": "11",
    }
    csound_score = []
    for token in score:
        if isinstance(token, parse.Chord):  # Chords
            for note in token.chord: 
                note = csound_note_values[note]

                csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
        elif isinstance(token, parse.Note):  # Individual notes
            note = csound_note_values[token.value]
            csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
        elif isinstance(token, tree.Tree):
            continue
        t += token.duration
    return csound_score


if __name__ == "__main__": main() 







|

|


|

|

|







>











254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
            total += n.duration
    return total


def generate_csound_score(score, score_line, t):
    csound_note_values = {
        "C": "00",
        "C#": "01", "Db": "01",
        "D": "02",
        "D#": "03", "Eb": "03",
        "E": "04",
        "F": "05",
        "F#": "06", "Gb": "06",
        "G": "07",
        "G#": "08", "Ab": "08",
        "A": "09",
        "A#": "10", "Bb": "10",
        "B": "11",
    }
    csound_score = []
    for token in score:
        if isinstance(token, parse.Chord):  # Chords
            for note in token.chord: 
                note = csound_note_values[note]
                csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
                csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
        elif isinstance(token, parse.Note):  # Individual notes
            note = csound_note_values[token.value]
            csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
        elif isinstance(token, tree.Tree):
            continue
        t += token.duration
    return csound_score


if __name__ == "__main__": main() 

Deleted todo.org version [510751b73f].

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
* 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
- [ ] Whole notes not held for proper duration

* Structure [1/7]    
- [ ] Chords should be composed of Notes, not ordinary arrays
- [ ] There should be a Musical_Phrase object that holds phrases (and sets of
  phrases), and allows them to nest
- [ ] Does each instrument need a score parameter if the grammars are non-terminating?
- [ ] Duration should be in beats, not seconds. This ensures movements don't
  end in the middle of a phrase.
- [ ] Generate score with proper generation tools, not this string-replace nonsense
- [X] Store csound score lines with instruments
- [ ] Upgrade from simple string substitution for the score to something
  list-based (maybe). Idea is to keep musical phrases intact in the event of a
  truncation of the score. Also, if done right, no need for retroactive length
  parsing- a measure is has a specific length, which is known at
  generation-time, thus solving the length limit problem.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<