spiffyscore

Diff
Login

Differences From Artifact [08a2f25157]:

To Artifact [3046d9915b]:


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
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
152
153
154
155
156
157
158
159


160
161
162
163
164
165
166
167












-
+
-





-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+



+
+
+
+
-
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+

-
+
-
-
+

-
+


-
+

+
-
-
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
+
+
+
+

-
+


+
-
-
+
+
-

-
-
+
+

-
+





-
+

-
+


+
-
+


-
+


-

-

-
+
+
+
+
+
+




+
+
+
+





-
-
+







#!/usr/bin/env python

from __future__ import division
import os
import random
import sys
import time
random.seed(time.time())
import parse

def main():
    key = "A"
    bps = 80/60
    bps = 60/60
    print bps
    tempo = 1/bps
    max_duration = 1

    composition = {
        "a": {  # Movement block 'a' for reuse throughout the piece
            "melody": {  # Instrument 'melody'
                "csound_parameters": {
                    "instrument": 1,
                },
#            "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 u", "I IV w w", "I VII IV u u"],
#                    "w": ['VII I IV V VI u', 'w w'],
#                    "x": ['VI/4 III/4 II/4 I/4 w', 'x x'],
#                },
#                "score": "u",
#            },
#            "rhythm": {
#                "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
#                "octave": 7,
#                "duration": 50,
#                "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 5000 %(octave)d.%(note)s 2 3 5 3",
                "octave": 5,
                "duration": 40,
                "grammars": {  # Notes for this instrument to use in this piece
                    "u": ["I V V V I I IV u u", "I IV u u", "I VII IV u u"  , "e"],
                    "e": [""],
                    "u": ['I2 I2 V VI I/2 IV/2 "V"2 "I"2']
                },
                "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",
            "rhythm": {
                "csound_parameters": {
                    "instrument": 1,
                "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": 24,
                "grammars": {
                    "u": ['"I" "ii"/4 "ii"/4 "IV"/2 "V"2 "IV" "I" u u', '"I" "vii" "IV" u u', '"I" "v" "IV" u u', "e"],
                    "u": ['"I" "V" "vi" "iii" "IV" "I" "IV" "V" u u', "y"],
#                    "u": ['"i" "I" "ii" "II" "v" "V" u', "e"],
                    "e": [""]
                    "y": ['"I" "vi"2 "IV" "V" y y u'],
                },
                "score": "u u u",
                "score": "u u y y u",
            },
        },
        "b": {
        "c": {  # Movement block 'a' for reuse throughout the piece
            "melody": {  # Instrument 'melody'
                "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2",
                "csound_parameters": {
                    "instrument": 1,
                "octave": 8,
                "duration": 20,
                "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'],
                    "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": 20,
                "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",
            },
        },
        "d": {  # 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 V I I/2 IV/2 u u", "I2 IV u u", "I IV IV VI V u u" , "e"],
#                    "u": ["I IV I V u u u", "e"],
                    "e": [""],
                    "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": "u u u",
                "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",
                "csound_parameters": {
                    "instrument": 1,
                "octave": 7,
                "duration": 24,
                },
                "grammars": {
                    "u": ['"I" "IV"/2 "V"2 "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
                    "e": [""]
                    "u": ['"I" "V" "vi" "iii" "IV" "I" "IV" "V" u u', "y"],
                    "y": ['"I" "vi"2 "IV" "V" y y u'],
                },
                "score": "u u u",
                "score": "u u y y u",
            },
        },
    }

    max_t = 0  # max time encountered so far. Used for movement timing
    progression = "a b"
    progression = "a b c d"
    for comp_name in progression.split():
        instr_start_time = max_t
        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)  # Return Node/Chord objects
            score = parse.parse(generated_score, default_octave=instr["octave"])  # Return Node/Chord objects

            # Generate timestamps for the notes 
            t = instr_start_time
            t = comp_start_time
            for note in range(len(score)):
                score[note].time = t
#                print "Original duration:", score[note].duration
                score[note].duration *= tempo
#                print "New duration:", score[note].duration
                t += score[note].duration
#                print "t:", t
#                print "time difference =", t-comp_start_time
#                print "instrument duration =",composition[comp_name][instr_name]["duration"]
                if (t-comp_start_time) > float(composition[comp_name][instr_name]["duration"]):
#                    print "here"
                    score = score[:note]
                    break
                max_t = t if t > max_t else max_t
            composition[comp_name][instr_name]["score"] = score

    # Must be done after all note times keyed in, else you can't coordinate melodies with the rhythm chords
    print '''f1  0  512  10  1
            f2 0 8192 10 .24 .64 .88 .76 .06 .5 .34 .08
            f3 0 1025 10 1
    '''
    for comp_name in progression.split():
        for instr_name, instr in composition[comp_name].iteritems():
            composition[comp_name][instr_name]["score"] = transliterate_score(composition[comp_name][instr_name]["score"], key)
#            print "\nMovement %s instrument %s" % (comp_name, instr_name)
#            print composition[comp_name][instr_name]["score"] 
            print "f1  0   256 10  1 0 3   ; sine wave function table"
            final_score = generate_csound_score(composition[comp_name][instr_name]["score"])
            final_score = generate_csound_score(composition[comp_name][instr_name]["score"], composition[comp_name][instr_name]["score_line"])
            for line in final_score:
                print line
            

def make_scale(key):
    notes = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
    scale = [key]
111
112
113
114
115
116
117

118
119



120
121
122
123
124
125
126
127
177
178
179
180
181
182
183
184


185
186
187

188
189
190
191
192
193
194







+
-
-
+
+
+
-







    while 1:
        found_substitution = False
        for key,value in grammars.iteritems():
            if score.find(key) != -1:
                found_substitution = True
                while score.find(key) != -1:
                    score = score.replace(key, random.choice(grammars[key]), 1)
#                    print scoe
                    if len(score.split()) > 200:
                        score = score.replace("u", "")
                    if len(score.split()) > 2000:
                        for k in grammars.keys():
                            score = score.replace(k, "")
                        score = score.replace("e", "")
                        return score
        if found_substitution is False:
            break
    return score

def transliterate_score(score, key):
    scale = make_scale(key)
139
140
141
142
143
144
145

146
147


148
149
150

151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

178
179
180

181
182
183
184
206
207
208
209
210
211
212
213


214
215
216


217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

244
245
246

247
248
249
250
251







+
-
-
+
+

-
-
+






-
+



















-
+


-
+




    for i in range(len(score)):
        if isinstance(score[i], parse.Note):
            score[i].value = scale[scale_conversion[score[i].value]-1]
        elif isinstance(score[i], parse.Chord):
            chord = []
            root_note_index = scale.index(key) + scale_conversion[score[i].value]
            chord.append(scale[root_note_index])
            chord.append(scale[(root_note_index+3) % 8])
            if score[i].chord_type == "m":  # Minor chords, flat the 3rd
                chord.append(scale[(root_note_index+2) % 8])
            if score[i].chord_type == "m":  # Minor chords, flat the 5th
                chord.append(scale[(root_note_index+4) % 8])
            else:
                chord.append(scale[(root_note_index+3) % 8])
            chord.append(scale[(root_note_index+5) % 8])
                chord.append(scale[(root_note_index+5) % 8])
            score[i].chord = chord
        elif isinstance(score[i], parse.Rest):
            pass
    return score


def generate_csound_score(score):
def generate_csound_score(score, score_line):
    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("i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6" % {"time": token.time, "octave": random.choice([7,8]), "note": note, "duration": token.duration})
                csound_score.append(score_line % {"time": token.time, "octave": token.octave, "note": note, "duration": token.duration})
        elif isinstance(token, parse.Note):  # Individual notes
            note = csound_note_values[token.value]
            csound_score.append("i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6" % {"time": token.time, "octave": random.choice([8,9]), "note": note, "duration": token.duration})
            csound_score.append(score_line % {"time": token.time, "octave": token.octave, "note": note, "duration": token.duration})
    return csound_score


if __name__ == "__main__": main()