spiffyscore

Check-in [9bd31df856]
Login

Check-in [9bd31df856]

Overview
Comment:Now prints csound code, both notes and chords, replicating the functionality of the original Minimaly Functional Version
Timelines: family | ancestors | descendants | both | ply
Files: files | file ages | folders
SHA1: 9bd31df856f40277a57e58faef14e0b9a5449a11
User & Date: spiffytech@gmail.com on 2010-11-16 18:37:14
Other Links: branch diff | manifest | tags
Context
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
16:36
Now parses chord length check-in: 4aeb057ae0 user: spiffytech@gmail.com tags: ply
Changes

Modified cfg.py from [df0a6863be] to [8e359b2146].

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







+








-
+







-
+


+







#!/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"],
        "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)
    compose_piece(key, chord_grammars, chords=True)

def compose_piece(key, grammars, chords=False):
    score = ""
    while len(score.split()) < 200:
    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


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







+
+
+
+


















-
-
+
+

-
+

-
+



-
-
+
+




















-
-
+
+




-
+






    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:
                        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):
    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 token in score.split():
            keyed_score.append(scale[scale_conversion[token]-1])
        for i in range(len(score)):
            score[i].value = scale[scale_conversion[score[i].value]-1]
    else:
        for token in score.split():
        for i in range(len(score)):
            chord = []
            root_note_index = scale.index(key) + scale_conversion[token]
            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])
            chord.append(scale[(root_note_index+5) % 8])
            keyed_score.append(chord)
    return keyed_score
            score[i].chord = chord
    return score


def generate_csound_score(score):
    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",
    }
    t = 0 
    csound_score = []
    for token in score:
        if isinstance(token, list):  # Chords
            for note in token: 
        if isinstance(token, parse.Chord):  # Chords
            for note in token.chord: 
                note = csound_note_values[note]
                csound_score.append("i2 %(time)f 1 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6" % {"time": t, "octave": random.choice([7,8]), "note": note})
            t += 1
        else:  # Individual notes
            note = csound_note_values[token]
            note = csound_note_values[token.value]
            csound_score.append("i2 %(time)f 1 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6" % {"time": t, "octave": random.choice([8,9]), "note": note})
            t += .25
    return csound_score


if __name__ == "__main__": main() 

Modified parse.py from [8130e10658] to [503badc6f2].

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


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



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-


















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

-
-
-
-
-
+
+
+
+
+


-
-
-
-
+
+
+
+


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

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


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


-
-
-
-
-
+
+
+
+
+

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

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
+
+
#!/usr/bin/env python

from ply import lex, yacc

# Tokenize (lex)
tokens = (
    "NOTE_LENGTH",
    "BASENOTE",
    "ACCIDENTAL",
    "REST",
    "OCTAVE",
    "CHORD_TYPE",
    "QUOTE",
)

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_QUOTE = '"'

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("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
#s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD"
s = '''I IV V VI I "I" "ii"/2'''
#s = "GF_G,/2"
lex.input(s)
for tok in iter(lex.token, None):
    print repr(tok.type), repr(tok.value)


# Parse (yacc)

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


def parse(score):
    # Tokenize (lex)
    tokens = (
        "NOTE_LENGTH",
        "BASENOTE",
        "ACCIDENTAL",
        "REST",
        "OCTAVE",
        "CHORD_TYPE",
        "QUOTE",
    )

    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_QUOTE = '"'

    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("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
    #s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD"
    #s = '''I IV V VI I "I" "ii"/2'''
    #s = "GF_G,/2"
    lex.input(score)
    #for tok in iter(lex.token, None):
    #    print repr(tok.type), repr(tok.value)


    # Parse (yacc)


def p_pitch_list(p):
    '''score : score note
        score : score chord
    '''
    p[0] = p[1] + [p[2]]
    def p_pitch_list(p):
        '''score : score note
            score : score chord
        '''
        p[0] = p[1] + [p[2]]

def p_score(p):
    '''score : note
        score : chord
    '''
    p[0] = [p[1]]
    def p_score(p):
        '''score : note
            score : chord
        '''
        p[0] = [p[1]]


def p_note(p):
    '''note : pitch
    '''
    p[0] = p[1]
    def p_note(p):
        '''note : pitch
        '''
        p[0] = p[1]


def p_note_length(p):
    ''' note : note 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_length(p):
    ''' chord : chord NOTE_LENGTH
    '''
    new_note = p[1]
    new_note.duration = p[2]
    p[0] = new_note
    def p_chord_length(p):
        ''' chord : chord NOTE_LENGTH
        '''
        new_note = p[1]
        new_note.duration = p[2]
        p[0] = new_note


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


def p_accidental(p):
    '''pitch : ACCIDENTAL pitch
    '''
    p[2].accidental = p[1]
    p[0] = p[2]
    def p_accidental(p):
        '''pitch : ACCIDENTAL pitch
        '''
        p[2].accidental = p[1]
        p[0] = p[2]

def p_octave(p):
    '''pitch : pitch OCTAVE
    '''
    count = len(p[2])
    increment_or_decrement = 1 if p[2][0] == "," else -1
    octave = 8 + (count * increment_or_decrement)
    p[1].octave = octave
    p[0] = p[1]
    def p_octave(p):
        '''pitch : pitch OCTAVE
        '''
        count = len(p[2])
        increment_or_decrement = 1 if p[2][0] == "," else -1
        octave = 8 + (count * increment_or_decrement)
        p[1].octave = octave
        p[0] = p[1]

def p_pitch(p):
    '''pitch : BASENOTE
    '''
    p[0] = Note(p[1])
    def p_pitch(p):
        '''pitch : BASENOTE
        '''
        p[0] = Note(p[1])

def p_error(p):
    print "Syntax error at '%s' of element type %s" % (p.value, p.type)
    
yacc.yacc()
    def p_error(p):
        print "Syntax error at '%s' of element type %s" % (p.value, p.type)
        
    yacc.yacc()

#print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
print yacc.parse(s)
    #print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
    return yacc.parse(score)