spiffyscore

Check-in [7c7ce6adb8]
Login
Overview
Comment:Added support for top-down composition
Timelines: family | ancestors | descendants | both | tld
Files: files | file ages | folders
SHA1: 7c7ce6adb86ec3329d3ccac1a6d7ae84667fffac
User & Date: spiffytech@gmail.com on 2010-11-17 00:07:43
Other Links: branch diff | manifest | tags
Context
2010-11-17
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
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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

     5      5   import sys
     6      6   import time
     7      7   random.seed(time.time())
     8      8   import parse
     9      9   
    10     10   def main():
    11     11       key = "A"
    12         -    note_grammars = {
    13         -        "u": ["I V V V I I IV u u", "I IV u u", "I VII IV u u"  , "e"],
    14         -        "e": [""],
    15         -    }
    16         -    chord_grammars = {
    17         -        "u": ['"I" "IV" "V" "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
    18         -        "e": [""]
           12  +
           13  +    composition = {
           14  +        "a": {  # Movement block 'a' for reuse throughout the piece
           15  +            "melody": {  # Instrument 'melody'
           16  +                "csound_parameters": {
           17  +                    "instrument": 1,
           18  +                },
           19  +                "grammars": {  # Notes for this instrument to use in this piece
           20  +                    "u": ["I V V V I I IV u u", "I IV u u", "I VII IV u u"  , "e"],
           21  +                    "e": [""],
           22  +                },
           23  +                "score": "u u u",
           24  +            },
           25  +            "rhythm": {
           26  +                "csound_parameters": {
           27  +                    "instrument": 1,
           28  +                },
           29  +                "grammars": {
           30  +                    "u": ['"I" "IV"/2 "V"2 "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
           31  +                    "e": [""]
           32  +                },
           33  +                "score": "u u u",
           34  +            },
           35  +        },
           36  +        "b": {
           37  +            "melody": {  # Instrument 'melody'
           38  +                "csound_parameters": {
           39  +                    "instrument": 1,
           40  +                },
           41  +                "grammars": {  # Notes for this instrument to use in this piece
           42  +                    "u": ["I V I I/2 IV/2 u u", "I4 IV u u", "I IV IV VI V u u"  , "e"],
           43  +                    "e": [""],
           44  +                },
           45  +                "score": "u u u",
           46  +            },
           47  +            "rhythm": {
           48  +                "csound_parameters": {
           49  +                    "instrument": 1,
           50  +                },
           51  +                "grammars": {
           52  +                    "u": ['"I" "IV"/2 "V"2 "IV" "I" u u', '"I" "VII" "IV" u u', '"I" "V" "IV" u u', "e"],
           53  +                    "e": [""]
           54  +                },
           55  +                "score": "u u u",
           56  +            },
           57  +        },
    19     58       }
    20         -    compose_piece(key, note_grammars)
    21         -    compose_piece(key, chord_grammars, chords=True)
           59  +
           60  +    for comp_name, comp in composition.iteritems():
           61  +        for instr_name, instr in comp.iteritems():
           62  +            generated_score = generate_score(instr["score"], instr["grammars"])  # Fill in the scores by generating them based on the grammars
           63  +#                composition[comp_name][instr_name][grammar]["score"] = parse.parse(generate_score)  # Return Node/Chord objects
           64  +            score = parse.parse(generated_score)  # Return Node/Chord objects
    22     65   
    23         -def compose_piece(key, grammars, chords=False):
    24         -    score = ""
    25         -    while len(score.split()) < 10:
    26         -        score = "u u u"
    27         -        score = generate_score(score, grammars)
    28         -    score = parse.parse(score)
    29         -    score = transliterate_score(score, key, chords)
    30         -    score = generate_csound_score(score)
    31         -    print "f1  0   256 10  1 0 3   ; sine wave function table"
    32         -    for line in score:
    33         -        print line
           66  +            # Generate timestamps for the notes 
           67  +            t = 0
           68  +            for note in range(len(score)):
           69  +                score[note].time = t
           70  +                t += score[note].duration
           71  +            composition[comp_name][instr_name]["score"] = score
    34     72   
           73  +    # Must be done after all note times keyed in, else you c,an't coordinate melodies with the rhythm chords
           74  +    for comp_name, comp in composition.iteritems():
           75  +        for instr_name, instr in comp.iteritems():
           76  +            composition[comp_name][instr_name]["score"] = transliterate_score(composition[comp_name][instr_name]["score"], key)
           77  +#            print "\nMovement %s instrument %s" % (comp_name, instr_name)
           78  +#            print composition[comp_name][instr_name]["score"] 
           79  +            print "f1  0   256 10  1 0 3   ; sine wave function table"
           80  +            final_score = generate_csound_score(composition[comp_name][instr_name]["score"])
           81  +            for line in final_score:
           82  +                print line
           83  +            
    35     84   
    36     85   def make_scale(key):
    37     86       notes = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
    38     87       scale = [key]
    39     88       pos = notes.index(key)
    40     89       progression = [2,2,1,2,2,2,1]
    41     90       for p in progression:
................................................................................
    48     97       while 1:
    49     98           found_substitution = False
    50     99           for key,value in grammars.iteritems():
    51    100               if score.find(key) != -1:
    52    101                   found_substitution = True
    53    102                   while score.find(key) != -1:
    54    103                       score = score.replace(key, random.choice(grammars[key]), 1)
    55         -                    if len(score) > 200:
          104  +                    if len(score.split()) > 200:
    56    105                           score = score.replace("u", "")
    57    106                           score = score.replace("e", "")
    58    107                           return score
    59    108           if found_substitution is False:
    60    109               break
    61    110       return score
    62    111   
    63         -def transliterate_score(score, key, chords=False):
          112  +def transliterate_score(score, key):
    64    113       scale = make_scale(key)
    65    114       scale_conversion = {
    66    115           "I": 1,
    67    116           "II": 2,
    68    117           "III": 3,
    69    118           "IV": 4,
    70    119           "V": 5,
    71    120           "VI": 6,
    72    121           "VII": 7,
    73    122           "VIII": 8,
    74    123       }
    75    124       keyed_score = []
    76         -    if chords is False:
    77         -        for i in range(len(score)):
          125  +    for i in range(len(score)):
          126  +        if isinstance(score[i], parse.Note):
    78    127               score[i].value = scale[scale_conversion[score[i].value]-1]
    79         -    else:
    80         -        for i in range(len(score)):
          128  +        else:
    81    129               chord = []
    82    130               root_note_index = scale.index(key) + scale_conversion[score[i].value]
    83    131               chord.append(scale[root_note_index])
    84    132               chord.append(scale[(root_note_index+3) % 8])
    85    133               chord.append(scale[(root_note_index+5) % 8])
    86    134               score[i].chord = chord
    87    135       return score

Modified todo.org from [9c9ed49773] to [9bec386f24].

     1      1   * Features [0/5]
     2      2   - [ ] Top-down composition
     3      3   - [ ] Transition the melody between chords appropriately
     4      4   - [ ] Set maximum song length
     5      5   
     6      6   * Bugs [0/1]
     7      7   - [ ] Doesn't handle minor chords
            8  +- [ ] Duration syntax is absolute, not relative to BPM