spiffyscore

Check-in [9bd31df856]
Login
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: 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
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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

     1      1   #!/usr/bin/env python
     2      2   
     3      3   import os
     4      4   import random
     5      5   import sys
     6      6   import time
     7      7   random.seed(time.time())
            8  +import parse
     8      9   
     9     10   def main():
    10     11       key = "A"
    11     12       note_grammars = {
    12     13           "u": ["I V V V I I IV u u", "I IV u u", "I VII IV u u"  , "e"],
    13     14           "e": [""],
    14     15       }
    15     16       chord_grammars = {
    16         -        "u": ["I IV V IV I u u", "I VII IV u u", "I V IV u u", "e"],
           17  +        "u": ['"I" "IV" "V" "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
    17     18           "e": [""]
    18     19       }
    19     20       compose_piece(key, note_grammars)
    20     21       compose_piece(key, chord_grammars, chords=True)
    21     22   
    22     23   def compose_piece(key, grammars, chords=False):
    23     24       score = ""
    24         -    while len(score.split()) < 200:
           25  +    while len(score.split()) < 10:
    25     26           score = "u u u"
    26     27           score = generate_score(score, grammars)
           28  +    score = parse.parse(score)
    27     29       score = transliterate_score(score, key, chords)
    28     30       score = generate_csound_score(score)
    29     31       print "f1  0   256 10  1 0 3   ; sine wave function table"
    30     32       for line in score:
    31     33           print line
    32     34   
    33     35   
................................................................................
    46     48       while 1:
    47     49           found_substitution = False
    48     50           for key,value in grammars.iteritems():
    49     51               if score.find(key) != -1:
    50     52                   found_substitution = True
    51     53                   while score.find(key) != -1:
    52     54                       score = score.replace(key, random.choice(grammars[key]), 1)
           55  +                    if len(score) > 200:
           56  +                        score = score.replace("u", "")
           57  +                        score = score.replace("e", "")
           58  +                        return score
    53     59           if found_substitution is False:
    54     60               break
    55     61       return score
    56     62   
    57     63   def transliterate_score(score, key, chords=False):
    58     64       scale = make_scale(key)
    59     65       scale_conversion = {
................................................................................
    64     70           "V": 5,
    65     71           "VI": 6,
    66     72           "VII": 7,
    67     73           "VIII": 8,
    68     74       }
    69     75       keyed_score = []
    70     76       if chords is False:
    71         -        for token in score.split():
    72         -            keyed_score.append(scale[scale_conversion[token]-1])
           77  +        for i in range(len(score)):
           78  +            score[i].value = scale[scale_conversion[score[i].value]-1]
    73     79       else:
    74         -        for token in score.split():
           80  +        for i in range(len(score)):
    75     81               chord = []
    76         -            root_note_index = scale.index(key) + scale_conversion[token]
           82  +            root_note_index = scale.index(key) + scale_conversion[score[i].value]
    77     83               chord.append(scale[root_note_index])
    78     84               chord.append(scale[(root_note_index+3) % 8])
    79     85               chord.append(scale[(root_note_index+5) % 8])
    80         -            keyed_score.append(chord)
    81         -    return keyed_score
           86  +            score[i].chord = chord
           87  +    return score
    82     88   
    83     89   
    84     90   def generate_csound_score(score):
    85     91       csound_note_values = {
    86     92           "C": "00",
    87     93           "C#": "01",
    88     94           "D": "02",
................................................................................
    95    101           "A": "09",
    96    102           "A#": "10",
    97    103           "B": "11",
    98    104       }
    99    105       t = 0 
   100    106       csound_score = []
   101    107       for token in score:
   102         -        if isinstance(token, list):  # Chords
   103         -            for note in token: 
          108  +        if isinstance(token, parse.Chord):  # Chords
          109  +            for note in token.chord: 
   104    110                   note = csound_note_values[note]
   105    111                   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})
   106    112               t += 1
   107    113           else:  # Individual notes
   108         -            note = csound_note_values[token]
          114  +            note = csound_note_values[token.value]
   109    115               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})
   110    116               t += .25
   111    117       return csound_score
   112    118   
   113    119   
   114    120   if __name__ == "__main__": main() 

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

     1      1   #!/usr/bin/env python
     2      2   
     3      3   from ply import lex, yacc
     4         -
     5         -# Tokenize (lex)
     6         -tokens = (
     7         -    "NOTE_LENGTH",
     8         -    "BASENOTE",
     9         -    "ACCIDENTAL",
    10         -    "REST",
    11         -    "OCTAVE",
    12         -    "CHORD_TYPE",
    13         -    "QUOTE",
    14         -)
    15         -
    16         -t_ignore = " |"
    17         -
    18         -#t_BASENOTE = r"[A-Ga-g]"
    19         -t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
    20         -t_ACCIDENTAL = r"\^{1,2}|_{1,2}|="
    21         -t_REST = r"z"
    22         -t_OCTAVE = r"'+|,+"
    23         -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"
    24         -t_QUOTE = '"'
    25         -
    26         -def t_NOTE_LENGTH(t):
    27         -    r"/?\d+"
    28         -    multiplier = float(t.value.strip("/"))
    29         -    if t.value.startswith("/"):
    30         -        multiplier = 1/multiplier
    31         -    t.value = multiplier
    32         -    return t
    33         -
    34         -def t_error(t):
    35         -    raise TypeError("Unknown text '%s'" % (t.value,))
    36         -
    37         -lex.lex()
    38         -
    39         -#lex.input("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
    40         -#s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD"
    41         -s = '''I IV V VI I "I" "ii"/2'''
    42         -#s = "GF_G,/2"
    43         -lex.input(s)
    44         -for tok in iter(lex.token, None):
    45         -    print repr(tok.type), repr(tok.value)
    46         -
    47         -
    48         -# Parse (yacc)
    49         -
    50      4   class Note():
    51      5       def __init__(self, value, duration=.25, octave=8):
    52      6           self.value = value
    53      7           self.duration = duration
    54      8           self.octave = octave
    55      9           self.accidental = None
    56     10       def __repr__(self):
................................................................................
    61     15           self.value = value
    62     16           self.duration = duration
    63     17           self.chord_type = chord_type
    64     18       def __repr__(self):
    65     19           return "Chord %s %s %s" % (self.value, self.duration, self.chord_type)
    66     20   
    67     21   
    68         -def p_pitch_list(p):
    69         -    '''score : score note
    70         -        score : score chord
    71         -    '''
    72         -    p[0] = p[1] + [p[2]]
           22  +def parse(score):
           23  +    # Tokenize (lex)
           24  +    tokens = (
           25  +        "NOTE_LENGTH",
           26  +        "BASENOTE",
           27  +        "ACCIDENTAL",
           28  +        "REST",
           29  +        "OCTAVE",
           30  +        "CHORD_TYPE",
           31  +        "QUOTE",
           32  +    )
           33  +
           34  +    t_ignore = " |"
           35  +
           36  +    #t_BASENOTE = r"[A-Ga-g]"
           37  +    t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
           38  +    t_ACCIDENTAL = r"\^{1,2}|_{1,2}|="
           39  +    t_REST = r"z"
           40  +    t_OCTAVE = r"'+|,+"
           41  +    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"
           42  +    t_QUOTE = '"'
           43  +
           44  +    def t_NOTE_LENGTH(t):
           45  +        r"/?\d+"
           46  +        multiplier = float(t.value.strip("/"))
           47  +        if t.value.startswith("/"):
           48  +            multiplier = 1/multiplier
           49  +        t.value = multiplier
           50  +        return t
           51  +
           52  +    def t_error(t):
           53  +        raise TypeError("Unknown text '%s'" % (t.value,))
           54  +
           55  +    lex.lex()
           56  +
           57  +    #lex.input("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
           58  +    #s = "GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD"
           59  +    #s = '''I IV V VI I "I" "ii"/2'''
           60  +    #s = "GF_G,/2"
           61  +    lex.input(score)
           62  +    #for tok in iter(lex.token, None):
           63  +    #    print repr(tok.type), repr(tok.value)
           64  +
           65  +
           66  +    # Parse (yacc)
           67  +
           68  +
           69  +    def p_pitch_list(p):
           70  +        '''score : score note
           71  +            score : score chord
           72  +        '''
           73  +        p[0] = p[1] + [p[2]]
           74  +
           75  +    def p_score(p):
           76  +        '''score : note
           77  +            score : chord
           78  +        '''
           79  +        p[0] = [p[1]]
           80  +
           81  +
           82  +    def p_note(p):
           83  +        '''note : pitch
           84  +        '''
           85  +        p[0] = p[1]
           86  +
           87  +
           88  +    def p_note_length(p):
           89  +        ''' note : note NOTE_LENGTH
           90  +        '''
           91  +        new_note = p[1]
           92  +        new_note.duration = p[2]
           93  +        p[0] = new_note
           94  +
           95  +    def p_chord_length(p):
           96  +        ''' chord : chord NOTE_LENGTH
           97  +        '''
           98  +        new_note = p[1]
           99  +        new_note.duration = p[2]
          100  +        p[0] = new_note
          101  +
          102  +
          103  +    def p_chord(p):
          104  +        '''chord : QUOTE pitch QUOTE
          105  +                | QUOTE pitch CHORD_TYPE QUOTE
          106  +        '''
          107  +        p[0] = Chord(value=p[2].value)
          108  +        if len(p) > 3:
          109  +            p[0].chord_type = p[3]
          110  +
    73    111   
    74         -def p_score(p):
    75         -    '''score : note
    76         -        score : chord
    77         -    '''
    78         -    p[0] = [p[1]]
          112  +    def p_accidental(p):
          113  +        '''pitch : ACCIDENTAL pitch
          114  +        '''
          115  +        p[2].accidental = p[1]
          116  +        p[0] = p[2]
    79    117   
          118  +    def p_octave(p):
          119  +        '''pitch : pitch OCTAVE
          120  +        '''
          121  +        count = len(p[2])
          122  +        increment_or_decrement = 1 if p[2][0] == "," else -1
          123  +        octave = 8 + (count * increment_or_decrement)
          124  +        p[1].octave = octave
          125  +        p[0] = p[1]
    80    126   
    81         -def p_note(p):
    82         -    '''note : pitch
    83         -    '''
    84         -    p[0] = p[1]
    85         -
    86         -
    87         -def p_note_length(p):
    88         -    ''' note : note NOTE_LENGTH
    89         -    '''
    90         -    new_note = p[1]
    91         -    new_note.duration = p[2]
    92         -    p[0] = new_note
          127  +    def p_pitch(p):
          128  +        '''pitch : BASENOTE
          129  +        '''
          130  +        p[0] = Note(p[1])
    93    131   
    94         -def p_chord_length(p):
    95         -    ''' chord : chord NOTE_LENGTH
    96         -    '''
    97         -    new_note = p[1]
    98         -    new_note.duration = p[2]
    99         -    p[0] = new_note
   100         -
   101         -
   102         -def p_chord(p):
   103         -    '''chord : QUOTE pitch QUOTE
   104         -            | QUOTE pitch CHORD_TYPE QUOTE
   105         -    '''
   106         -    p[0] = Chord(value=p[2].value)
   107         -    if len(p) > 3:
   108         -        p[0].chord_type = p[3]
          132  +    def p_error(p):
          133  +        print "Syntax error at '%s' of element type %s" % (p.value, p.type)
          134  +        
          135  +    yacc.yacc()
   109    136   
   110         -
   111         -def p_accidental(p):
   112         -    '''pitch : ACCIDENTAL pitch
   113         -    '''
   114         -    p[2].accidental = p[1]
   115         -    p[0] = p[2]
   116         -
   117         -def p_octave(p):
   118         -    '''pitch : pitch OCTAVE
   119         -    '''
   120         -    count = len(p[2])
   121         -    increment_or_decrement = 1 if p[2][0] == "," else -1
   122         -    octave = 8 + (count * increment_or_decrement)
   123         -    p[1].octave = octave
   124         -    p[0] = p[1]
   125         -
   126         -def p_pitch(p):
   127         -    '''pitch : BASENOTE
   128         -    '''
   129         -    p[0] = Note(p[1])
   130         -
   131         -def p_error(p):
   132         -    print "Syntax error at '%s' of element type %s" % (p.value, p.type)
   133         -    
   134         -yacc.yacc()
   135         -
   136         -#print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
   137         -print yacc.parse(s)
          137  +    #print yacc.parse("GFG B'AB,, | g/2fg gab | GFG BAB | d2A AFD")
          138  +    return yacc.parse(score)