spiffyscore

Changes On Branch f02f66468f3954b3
Login

Changes In Branch tld Through [f02f66468f] Excluding Merge-Ins

This is equivalent to a diff from 3d4ddcbab5 to f02f66468f

2010-11-17
06:27
TLD now accepts ordering of movements. Also, fixed bug that caused all movements and instruments to play simultaneously. check-in: db1df2f460 user: spiffytech@gmail.com tags: tld
05:32
Now supports minor chords check-in: f02f66468f user: spiffytech@gmail.com tags: tld
00:07
Added support for top-down composition check-in: 7c7ce6adb8 user: spiffytech@gmail.com tags: tld
2010-11-16
19:15
Added todo list Leaf check-in: 3d4ddcbab5 user: spiffytech@gmail.com tags: ply
18:37
Now prints csound code, both notes and chords, replicating the functionality of the original Minimaly Functional Version check-in: 9bd31df856 user: spiffytech@gmail.com tags: ply

Modified cfg.py from [8e359b2146] to [79cec58b40].

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
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











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




















-
+







-
+












-
-
+
+

-
+
-



+
+
+
-
+







#!/usr/bin/env python

import os
import random
import sys
import time
random.seed(time.time())
import parse

def main():
    key = "A"
    note_grammars = {
        "u": ["I V V V I I IV u u", "I IV u u", "I VII IV u u"  , "e"],
        "e": [""],
    }
    chord_grammars = {
        "u": ['"I" "IV" "V" "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
        "e": [""]
    }
    compose_piece(key, note_grammars)

    composition = {
        "a": {  # Movement block 'a' for reuse throughout the piece
#            "melody": {  # Instrument 'melody'
#                "csound_parameters": {
#                    "instrument": 1,
#                },
#                "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": [""],
#                },
#                "score": "u u u",
#            },
            "rhythm": {
                "csound_parameters": {
                    "instrument": 1,
                },
                "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" "I" "ii" "II" "v" "V" u', "e"],
                    "e": [""]
                },
                "score": "u u u",
            },
        },
#        "b": {
#            "melody": {  # Instrument 'melody'
#                "csound_parameters": {
#                    "instrument": 1,
#                },
#                "grammars": {  # Notes for this instrument to use in this piece
    compose_piece(key, chord_grammars, chords=True)

def compose_piece(key, grammars, chords=False):
    score = ""
    while len(score.split()) < 10:
        score = "u u u"
        score = generate_score(score, grammars)
    score = parse.parse(score)
    score = transliterate_score(score, key, chords)
    score = generate_csound_score(score)
    print "f1  0   256 10  1 0 3   ; sine wave function table"
    for line in score:
        print line

#                    "u": ["I V I I/2 IV/2 u u", "I4 IV u u", "I IV IV VI V u u"  , "e"],
#                    "e": [""],
#                },
#                "score": "u u u",
#            },
#            "rhythm": {
#                "csound_parameters": {
#                    "instrument": 1,
#                },
#                "grammars": {
#                    "u": ['"I" "IV"/2 "V"2 "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
#                    "e": [""]
#                },
#                "score": "u u u",
#            },
#        },
    }

    for comp_name, comp in composition.iteritems():
        for instr_name, instr in comp.iteritems():
            generated_score = generate_score(instr["score"], instr["grammars"])  # Fill in the scores by generating them based on the grammars
#                composition[comp_name][instr_name][grammar]["score"] = parse.parse(generate_score)  # Return Node/Chord objects
            score = parse.parse(generated_score)  # Return Node/Chord objects

            # Generate timestamps for the notes 
            t = 0
            for note in range(len(score)):
                score[note].time = t
                t += score[note].duration
            composition[comp_name][instr_name]["score"] = score

    # Must be done after all note times keyed in, else you c,an't coordinate melodies with the rhythm chords
    for comp_name, comp in composition.iteritems():
        for instr_name, instr in comp.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"])
            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]
    pos = notes.index(key)
    progression = [2,2,1,2,2,2,1]
    for p in progression:
        pos = (pos + p) % 12
        scale.append(notes[pos])
    return scale


def generate_score(score, grammars):
    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)
                    if len(score) > 200:
                    if len(score.split()) > 200:
                        score = score.replace("u", "")
                        score = score.replace("e", "")
                        return score
        if found_substitution is False:
            break
    return score

def transliterate_score(score, key, chords=False):
def transliterate_score(score, key):
    scale = make_scale(key)
    scale_conversion = {
        "I": 1,
        "II": 2,
        "III": 3,
        "IV": 4,
        "V": 5,
        "VI": 6,
        "VII": 7,
        "VIII": 8,
    }
    keyed_score = []
    if chords is False:
        for i in range(len(score)):
    for i in range(len(score)):
        if isinstance(score[i], parse.Note):
            score[i].value = scale[scale_conversion[score[i].value]-1]
    else:
        else:
        for i in range(len(score)):
            chord = []
            root_note_index = scale.index(key) + scale_conversion[score[i].value]
            chord.append(scale[root_note_index])
            if score[i].chord_type == "m":  # Minor chords, flat the 3rd
                chord.append(scale[(root_note_index+2) % 8])
            else:
            chord.append(scale[(root_note_index+3) % 8])
                chord.append(scale[(root_note_index+3) % 8])
            chord.append(scale[(root_note_index+5) % 8])
            score[i].chord = chord
    return score


def generate_csound_score(score):
    csound_note_values = {

Modified parse.py from [503badc6f2] to [b7fd05b171].

100
101
102
103
104
105
106


107

108
109
110
111
112
113
114
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116







+
+
-
+







        p[0] = new_note


    def p_chord(p):
        '''chord : QUOTE pitch QUOTE
                | QUOTE pitch CHORD_TYPE QUOTE
        '''
        pitch = p[2].value
        pitch = pitch.upper()
        p[0] = Chord(value=p[2].value)
        p[0] = Chord(value=pitch)
        if len(p) > 3:
            p[0].chord_type = p[3]


    def p_accidental(p):
        '''pitch : ACCIDENTAL pitch
        '''

Modified test.sco from [da39a3ee5e] to [7126d43817].
























































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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
f1  0   256 10  1 0 3   ; sine wave function table
i2 0.000000 1 7000 7.11 7.11 0 6
i2 0.000000 1 7000 7.04 7.04 0 6
i2 0.000000 1 7000 8.08 8.08 0 6
i2 1.000000 1 7000 8.11 8.11 0 6
i2 1.000000 1 7000 8.04 8.04 0 6
i2 1.000000 1 7000 8.08 8.08 0 6
i2 2.000000 1 7000 8.01 8.01 0 6
i2 2.000000 1 7000 8.06 8.06 0 6
i2 2.000000 1 7000 8.09 8.09 0 6
i2 3.000000 1 7000 7.01 7.01 0 6
i2 3.000000 1 7000 7.06 7.06 0 6
i2 3.000000 1 7000 8.09 8.09 0 6
i2 4.000000 1 7000 7.06 7.06 0 6
i2 4.000000 1 7000 7.09 7.09 0 6
i2 4.000000 1 7000 7.01 7.01 0 6
i2 5.000000 1 7000 8.06 8.06 0 6
i2 5.000000 1 7000 7.09 7.09 0 6
i2 5.000000 1 7000 7.01 7.01 0 6
i2 6.000000 1 7000 7.11 7.11 0 6
i2 6.000000 1 7000 7.04 7.04 0 6
i2 6.000000 1 7000 8.08 8.08 0 6
i2 7.000000 1 7000 8.11 8.11 0 6
i2 7.000000 1 7000 7.04 7.04 0 6
i2 7.000000 1 7000 7.08 7.08 0 6
i2 8.000000 1 7000 8.01 8.01 0 6
i2 8.000000 1 7000 8.06 8.06 0 6
i2 8.000000 1 7000 7.09 7.09 0 6
i2 9.000000 1 7000 8.01 8.01 0 6
i2 9.000000 1 7000 7.06 7.06 0 6
i2 9.000000 1 7000 8.09 8.09 0 6
i2 10.000000 1 7000 8.06 8.06 0 6
i2 10.000000 1 7000 7.09 7.09 0 6
i2 10.000000 1 7000 8.01 8.01 0 6
i2 11.000000 1 7000 8.06 8.06 0 6
i2 11.000000 1 7000 8.09 8.09 0 6
i2 11.000000 1 7000 8.01 8.01 0 6
i2 12.000000 1 7000 7.11 7.11 0 6
i2 12.000000 1 7000 7.04 7.04 0 6
i2 12.000000 1 7000 8.08 8.08 0 6
i2 13.000000 1 7000 7.11 7.11 0 6
i2 13.000000 1 7000 8.04 8.04 0 6
i2 13.000000 1 7000 7.08 7.08 0 6
i2 14.000000 1 7000 7.01 7.01 0 6
i2 14.000000 1 7000 7.06 7.06 0 6
i2 14.000000 1 7000 7.09 7.09 0 6
i2 15.000000 1 7000 8.01 8.01 0 6
i2 15.000000 1 7000 8.06 8.06 0 6
i2 15.000000 1 7000 7.09 7.09 0 6
i2 16.000000 1 7000 8.06 8.06 0 6
i2 16.000000 1 7000 8.09 8.09 0 6
i2 16.000000 1 7000 7.01 7.01 0 6
i2 17.000000 1 7000 7.06 7.06 0 6
i2 17.000000 1 7000 7.09 7.09 0 6
i2 17.000000 1 7000 7.01 7.01 0 6

Modified todo.org from [9c9ed49773] to [0747c315e6].

1
2


3
4

5
6
7













1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
-
-
+
+


+

-
-
+
+
+
+
+
+
+
+
+
+
+
* Features [0/5]
- [ ] Top-down composition
* Features [1/4]
- [X] Top-down composition
- [ ] Transition the melody between chords appropriately
- [ ] Set maximum song length
- [ ] Need to support all chord types

* Bugs [0/1]
- [ ] Doesn't handle minor chords
* Bugs [1/5]
- [ ] TLD resets clock for each movement
- [ ] TLD doesn't accept an ordering for the movements
- [X] Doesn't handle minor chords
- [ ] Duration syntax is absolute, not relative to BPM
- [ ] Chords don't respect octaves


* Structure [0/2]
- [ ] Chords should be composed of Notes, not ordinary arrays
- [ ] Generate score with proper generation tools