spiffyscore

Check-in [8f28834102]
Login
Overview
SHA1:8f28834102b41a640931e718c456c3dace788a11
Date: 2011-11-27 02:56:34
User: brian
Comment:Fixed chord support
Timelines: family | ancestors | descendants | both | develop
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2011-12-04
20:52
[3023a967c2] Leaf: Made room for arbitrary-note chording whenever I figure out the CFY to represent iTSYntax to use for it (user: brian, tags: develop)
2011-11-27
02:56
[8f28834102] Fixed chord support (user: brian, tags: develop)
02:26
[bf135b5321] Fixed a bug that prevented sharps and flats from working (user: brian, tags: develop)
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Modified parse.py from [4cca2f3d0c] to [0884d30f89].

     1      1   #!/usr/bin/env python
     2      2   
     3      3   import tree
     4      4   
     5      5   from ply import lex, yacc
     6      6   class Note():
     7      7       def __init__(self, value, duration=1, octave=8):
     8         -        self.value = value
     9      8           self.duration = duration
            9  +        if value > 12:
           10  +            self.duration += 1
           11  +            value = value % 12
           12  +        self.value = value
    10     13           self.octave = octave
    11     14       def __repr__(self):
    12     15           return "Note %s %s %s" % (self.value, self.duration, self.octave)
    13     16   
    14     17   class Chord():
    15         -    def __init__(self, value, duration=1, chord_type="major", octave=5):
    16         -        self.value = value
           18  +    def __init__(self, notes, duration=1):
           19  +        self.notes = notes
    17     20           self.duration = duration
    18         -        self.chord_type = chord_type
    19         -        self.octave = octave
    20     21       def __repr__(self):
    21         -        return "Chord %s %s %s" % (self.value, self.duration, self.chord_type, self.octave)
           22  +        return "Chord %s" % (self.notes)
    22     23   
    23     24   class Rest():
    24     25       def __init__(self, duration=1):
    25     26           self.duration = duration
    26     27       def __repr__(self):
    27     28           return "Rest node %s" % self.duration
    28     29   
................................................................................
    32     33       tokens = (
    33     34           "NOTE_LENGTH",
    34     35           "BASENOTE",
    35     36           "ACCIDENTAL",
    36     37           "REST",
    37     38           "OCTAVE",
    38     39           "CHORD_TYPE",
    39         -        "PAREN",
           40  +        "BRACKET",
    40     41           "SYNCOPATE",
    41     42           "NODE",
    42     43       )
    43     44   
    44     45       t_ignore = " |"
    45     46   
    46     47       t_BASENOTE = r"[A-Ga-g]"
    47     48   #    t_BASENOTE = r"I+V?|VI*|i+v?|vi*"
    48     49       t_ACCIDENTAL = r"\^{1}|_{1}|="
    49     50       t_REST = r"z"
    50     51       t_OCTAVE = r"'+|,+"
    51     52       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"
    52         -    t_PAREN = "\[|\]"
           53  +    t_BRACKET = r"\[|\]"
    53     54       t_SYNCOPATE = "\+|-"
    54     55       t_NODE = r"\([a-zA-Z0-9_-]+\)"
    55     56   
    56     57       def t_NOTE_LENGTH(t):
    57     58           r"/?\d+"
    58     59           multiplier = float(t.value.strip("/"))
    59     60           if t.value.startswith("/"):
................................................................................
   100    101           '''
   101    102           new_note = p[1]
   102    103           new_note.duration = p[2]
   103    104           p[0] = new_note
   104    105   
   105    106   
   106    107       def p_chord(p):
   107         -        '''chord : PAREN note PAREN
   108         -                 | PAREN note CHORD_TYPE PAREN
          108  +        '''chord : BRACKET note BRACKET
          109  +                 | BRACKET note CHORD_TYPE BRACKET
   109    110           '''
   110         -        pitch = p[2].value
   111         -        pitch = pitch.upper()
   112         -        p[0] = Chord(value=pitch, octave=default_octave)
   113         -        if len(p) > 3:
   114         -            p[0].chord_type = p[3]
          111  +        root_note = p[2].value
          112  +        chorded_notes = []
          113  +
          114  +        for offset in [0, 4, 7]:
          115  +            chorded_notes.append(Note(root_note+offset, octave=p[2].octave))
          116  +
          117  +        p[0] = Chord(notes=chorded_notes)
   115    118   
   116    119   
   117    120       def p_note_syncopate(p):
   118    121           ''' note : note SYNCOPATE
   119    122           '''
   120    123           note.syncopate = p[2]
   121    124   

Modified spiffyscore.py from [8b19298d3a] to [11e8d97d43].

    18     18   mymidi = midifile(15)
    19     19   
    20     20   def main():
    21     21       composition = {
    22     22           "intro": {
    23     23               "body": {
    24     24                   "percusion": {
    25         -                    "channel": 14,
           25  +                    "channel": 14,  # Orchestra kit
    26     26                       "octave": 4,
    27     27                       "duration": 60,
    28     28                       "grammars": {
    29     29                           "u": ["A ^A (u)"]
    30     30                       }
    31     31                   },
    32     32                   "pan_flute": {
    33     33                       "channel": 8,
    34     34                       "octave": 5,
    35     35                       "duration": 60,
           36  +                    "vol_offset": -15,
    36     37                       "grammars": {  # Notes for this instrument to use in this piece
    37         -                        "u": ["C2' B2 | A3 D3 || B | C' | D | C2' C2' | z | (u)", "C2' C2' | C2' C2' | (x)"],
    38         -                        "v": ["G2 F2 | E2 F2 | D5 (u)", "B/4 C/4' B/4 A/4 | D2 D2 | z | (u)"],
    39         -                        "x": ["z4 | (v)"],
           38  +                        "u": ["[C2'] C2' | [A3] A3 (u)"],
           39  +#                        "u": ["[C2'] [B2] | [A3] D3 || B | C' | D | C2' C2' | z | (u)", "C2' C2' | C2' C2' | (x)"],
           40  +#                        "v": ["G2 F2 | E2 F2 | D5 (u)", "B/4 C/4' B/4 A/4 | D2 D2 | z | (u)"],
           41  +#                        "x": ["z4 | (v)"],
    40     42                       },
    41     43                   },
    42     44                   "bass": {
    43     45                       "channel": 4,
    44     46                       "sync": "pan_flute",
    45     47                       "octave": 2,
    46     48                       "duration": 60,
    47     49                       "grammars": {  # Notes for this instrument to use in this piece
    48     50                           "u": ["C/2 C/2 C/2 z/2 (u)"],
    49     51                       },
    50     52                   },
    51     53                   "horn_timbre1": { 
    52         -                    "channel": 13,
           54  +                    "channel": 13,  # 'Atmosphere'
    53     55                       "octave": 2,
    54     56                       "duration": 60,
    55     57                       "grammars": {  # Notes for this instrument to use in this piece
    56     58                           "u": ["C4 D4 (u)"],
    57     59                       },
    58     60                   },
    59     61                   "horn_timbre2": {  
................................................................................
   140    142                   max_time = instr["duration"]
   141    143                   instr_score, syncs = render_instr(instr, syncs, max_time)
   142    144                   instrs.append(instr_score)
   143    145   
   144    146                   volume = 100
   145    147                   if instr.has_key("vol_offset"):
   146    148                       volume += instr["vol_offset"]
   147         -                    print "\t\t\tvolume offset = %d, nev volume = %d" % (instr["vol_offset"], volume)
   148    149                   midify_instr_score(instr_score, track, instr["channel"], subsection_start, volume=volume)
   149    150               longest_score = max(instrs, key=lambda i: score_len(i))
   150    151               subsection_start += score_len(longest_score)
   151    152               section_start += score_len(longest_score)
   152    153               track += 1
   153    154       with open("out.mid", "wb") as outfile:
   154    155           mymidi.writeFile(outfile)
................................................................................
   248    249   
   249    250   
   250    251   def midify_instr_score(score, track, channel, t, volume):
   251    252       # Assume get_midi_note()
   252    253       global mymidi
   253    254   
   254    255       for token in score:
   255         -        if isinstance(token, parse.Chord):  # Chords
   256         -            for note in token.chord: 
   257         -                note = get_midi_note(token.octave, note)
          256  +        if isinstance(token, parse.Chord):
          257  +            for note in token.notes: 
          258  +                note = get_midi_note(note.octave, note.value)
   258    259                   mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume)
   259    260           elif isinstance(token, parse.Note):  # Individual notes
   260    261               note = get_midi_note(token.octave, token.value)
   261    262               mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=volume)
   262    263           elif isinstance(token, tree.Tree):
   263    264               continue
   264    265           t += token.duration
   265    266   
   266    267       return []
   267    268   
   268    269   
   269    270   if __name__ == "__main__": main()