spiffyscore

Check-in [befd61cab9]
Login
Overview
SHA1:befd61cab9abd44e8ac9a8962b3247214bf5d5b2
Date: 2011-11-15 22:08:44
User: brian
Comment:Successfully got the program to output a MIDI file instead of a csound score
Timelines: family | ancestors | feature/midi
Downloads: Tarball | ZIP archive
Other Links: files | file ages | folders | manifest
Tags And Properties
Context
2011-11-15
22:09
[0c3fb3e27f] Replaced csound support with midi support (user: brian, tags: develop)
22:08
[befd61cab9] Closed-Leaf: Successfully got the program to output a MIDI file instead of a csound score (user: brian, tags: feature/midi)
15:47
[daa0ddb3ad] Attempted to make a csound based on midi. Failed. (user: brian, tags: feature/midi)
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Modified parse.py from [a8d0994825] to [bcac1af73f].

   120    120           note.syncopate = p[2]
   121    121   
   122    122   
   123    123       def p_accidental(p):
   124    124           '''note : ACCIDENTAL note
   125    125           '''
   126    126           if p[1] == "^":
   127         -            p[2].value += "#"
          127  +            p[0] = p[2].value + 1
   128    128           else:
   129         -            p[2].value += "b"
   130         -        p[0] = p[2]
          129  +            p[0] = p[2].value - 1
   131    130   
   132    131       def p_octave(p):
   133    132           '''note : note OCTAVE
   134    133           '''
   135    134           count = len(p[2])
   136    135           increment_or_decrement = 1 if p[2].startswith("'") else -1
   137    136           p[1].octave += (count * increment_or_decrement)
   138    137           p[0] = p[1]
   139    138   
   140    139       def p_note(p):
   141    140           '''note : BASENOTE
   142    141           '''
   143         -        p[0] = Note(p[1], octave=default_octave)
          142  +        notes = {
          143  +            "C": 0,
          144  +            "D": 2,
          145  +            "E": 4,
          146  +            "F": 5,
          147  +            "G": 7,
          148  +            "A": 9,
          149  +            "B": 11
          150  +        }
          151  +        n = notes[p[1]]
          152  +        p[0] = Note(n, octave=default_octave)
   144    153   
   145    154       def p_rest(p):
   146    155           ''' rest : REST
   147    156                    | REST NOTE_LENGTH
   148    157           '''
   149    158           p[0] = Rest()
   150    159           if len(p) > 2:

Modified spiffyscore.py from [390f3e8450] to [caa7e9ffa7].

     3      3   from __future__ import division
     4      4   import ipdb
     5      5   import os
     6      6   import random
     7      7   import sys
     8      8   import time
     9      9   
           10  +from midiutil.MidiFile import MIDIFile as midifile
    10     11   import parse
    11     12   import topsort
    12     13   import yaml
    13     14   
    14     15   import tree
    15     16   
    16     17   random.seed(time.time())
           18  +mymidi = midifile(15)
    17     19   
    18     20   def main():
    19     21       composition = {
    20     22           "fm_test": {
    21     23               "intro": {
    22     24                   "melody": {  # Instrument 'melody'
    23     25                       "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 2 6 5 1",
................................................................................
   101    103                           "u": ["C/4 C/4 C/4 C/4"],
   102    104                       },
   103    105                   },
   104    106               },
   105    107           },
   106    108           "sync_test": {
   107    109               "body": {
   108         -#                "lead_instr": {  # Instrument 'melody'
   109         -#                    "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
   110         -##                    "score_line": "i5 %(time)f %(duration)f 7000 %(octave)d.%(note)s",
   111         -#                    "octave": 7,
   112         -#                    "duration": 30,
   113         -#                    "grammars": {  # Notes for this instrument to use in this piece
   114         -##                        "u": ["A ^A B C ^C D ^D E F ^F G ^G"],
   115         -#                        "u": ["A/2, B/2, C/2 D/2 (u)", "D/2' D/2' D/2' D/2' (v)"],
   116         -#                        "v": ["C/2 C/2 C/2 C/2 (w)"],
   117         -#                        "w": ["E/2 F/2 E/2 F/2 (u)"],
   118         -#                    },
   119         -#                },
          110  +                "lead_instr": {  # Instrument 'melody'
          111  +                    "channel": 6,
          112  +                    "octave": 4,
          113  +                    "duration": 30,
          114  +                    "grammars": {  # Notes for this instrument to use in this piece
          115  +#                        "u": ["A ^A B C ^C D ^D E F ^F G ^G"],
          116  +                        "u": ["A/2, B/2, C/2 D/2 (u)", "D/2' D/2' D/2' D/2' (x)"],
          117  +                        "v": ["C/2 C/2 C/2 C/2 (w)"],
          118  +                        "w": ["E/2 F/2 E/2 F/2 (u)"],
          119  +                        "x": ["z4 (v)"],
          120  +                    },
          121  +                },
   120    122                   "follow_instr": {  # Instrument 'melody'
   121         -#                    "score_line": "i2 %(time)f %(duration)f 7000 %(octave)d.%(note)s 1",
   122         -                    "score_line": "i3 %(time)f %(duration)f 7000 %(octave)d.%(note)s",
   123         -#                    "sync": "lead_instr",
          123  +                    "channel": 0,
          124  +                    "sync": "lead_instr",
   124    125                       "octave": 2,
   125    126                       "duration": 30,
   126    127                       "grammars": {  # Notes for this instrument to use in this piece
   127    128   #                        "u": ["A ^A B C ^C D ^D E F ^F G ^G"],
   128    129                           "u": ["E F G E (v)"],
   129    130                           "v": ["G A A A (e)", "G A A A (v)"],
   130    131                           "e": ["B A G A (u)"],
          132  +                        "x": ["z4 (e)"],
   131    133                       },
   132    134                   },
   133    135   #                "instr2": {  # Instrument 'melody'
   134    136   #                    "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s 0 6",
   135    137   #                    "score_line": "i1 %(time)f %(duration)f 7000 %(octave)d.%(note)s %(octave)d.%(note)s",
   136    138   #                    "octave": 5,
   137    139   #                    "duration": 30,
................................................................................
   169    171                           subsection[instr]["sync"] = None
   170    172                       unordered_instrs.append([subsection[instr]["sync"], instr])
   171    173                   ordered_instrs = topsort.topsort(unordered_instrs)
   172    174                   ordered_instrs.remove(None)  # None used as a placeholder for sort order for instruments with no sync setting
   173    175   
   174    176                   instrs = []
   175    177                   syncs = {}
          178  +                track = 0
   176    179                   for instr in ordered_instrs:
   177    180                       print ";Instrument " + instr
   178    181                       instr = subsection[instr]
   179    182                       max_time = instr["duration"]
   180    183                       instr_score, syncs = render_instr(instr, syncs, max_time)
   181    184                       instrs.append(instr_score)
   182         -                    for line in generate_csound_score(instr_score, instr["score_line"], subsection_start):
   183         -                        print line
          185  +                    generate_csound_score(instr_score, track, instr["channel"], subsection_start)
   184    186                   longest_score = max(instrs, key=lambda i: score_len(i))
   185    187                   subsection_start += score_len(longest_score)
   186    188                   section_start += score_len(longest_score)
          189  +                track += 1
   187    190               except KeyError:
   188    191                   pass
          192  +    with open("out.mid", "wb") as outfile:
          193  +        mymidi.writeFile(outfile)
          194  +
   189    195   
   190    196   
   191    197   def render_instr(instr, syncs, max_time):
   192    198       for g in instr["grammars"]:
   193    199           for i in range(len(instr["grammars"][g])):
   194    200               instr["grammars"][g][i] = parse.parse(instr["grammars"][g][i], default_octave=instr["octave"])
   195    201   
................................................................................
   266    272       total = 0
   267    273       for n in score:
   268    274           if not isinstance(n, tree.Tree):
   269    275               total += n.duration
   270    276       return total
   271    277   
   272    278   
   273         -def generate_csound_score(score, score_line, t):
   274         -    csound_note_values = {
   275         -        "C": "00",
   276         -        "C#": "01", "Db": "01",
   277         -        "D": "02",
   278         -        "D#": "03", "Eb": "03",
   279         -        "E": "04",
   280         -        "F": "05",
   281         -        "F#": "06", "Gb": "06",
   282         -        "G": "07",
   283         -        "G#": "08", "Ab": "08",
   284         -        "A": "09",
   285         -        "A#": "10", "Bb": "10",
   286         -        "B": "11",
   287         -    }
   288         -    csound_score = []
          279  +def get_midi_note(octave, note):
          280  +    return note + 12 * (octave+1)
          281  +
          282  +
          283  +def generate_csound_score(score, track, channel, t):
          284  +    # Assume get_midi_note()
          285  +    global mymidi
          286  +
   289    287       for token in score:
   290    288           if isinstance(token, parse.Chord):  # Chords
   291    289               for note in token.chord: 
   292         -                note = csound_note_values[note]
   293         -                csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
   294         -                csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
          290  +                note = get_midi_note(token.octave, note)
          291  +                mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=100)
   295    292           elif isinstance(token, parse.Note):  # Individual notes
   296         -            note = csound_note_values[token.value]
   297         -            csound_score.append(score_line % {"time": t, "octave": token.octave, "note": note, "duration": token.duration})
          293  +            note = get_midi_note(token.octave, token.value)
          294  +            mymidi.addNote(track=track, channel=channel,pitch=note, time=t, duration=token.duration, volume=100)
   298    295           elif isinstance(token, tree.Tree):
   299    296               continue
   300    297           t += token.duration
   301         -    return csound_score
          298  +
          299  +    return []
   302    300   
   303    301   
   304    302   if __name__ == "__main__": main()