예제 #1
0
 def parse_midi(path):
     midifile = smf.SMF(path)
     notes_on = []
     for event in midifile.events:
         # if it is as "Note On" event, append the time and the pitch
         if event.midi_buffer[0] == 144:
             notes_on.append((event.time_pulses, event.midi_buffer[1]))
     notes_on = [(t, max(map(itemgetter(1), notes)))
                 for t, notes in groupby(notes_on, itemgetter(0))]
     ticks = list(map(itemgetter(0), notes_on))
     pitches = bytes(map(itemgetter(1), notes_on))
     return pitches, ticks, event.time_pulses
예제 #2
0
def process_file(infile, outfile, patch):
    """
    Process a MIDI file, using pysmf.
    """
    import smf

    # create dummy engine with no inputs or outputs
    _setup._config_impl(backend='dummy')
    engine = Engine()
    engine.setup({_util.offset(0): patch}, None, None, None)

    # open input file
    smf_in = smf.SMF(infile)

    # create SMF object with same ppqn and number of tracks as input file
    smf_out = smf.SMF()
    smf_out.ppqn = smf_in.ppqn
    for n in range(len(smf_in.tracks)):
        smf_out.add_track()

    for smf_ev in smf_in.events:
        if smf_ev.midi_buffer[0] == 0xff:
            # event is metadata. copy to output unmodified
            smf_out.add_event(smf.Event(smf_ev.midi_buffer),
                              smf_ev.track_number,
                              pulses=smf_ev.time_pulses)
        else:
            ev = _mididings.buffer_to_midi_event(smf_ev.midi_buffer,
                                                 smf_ev.track_number,
                                                 smf_ev.time_pulses)

            # use base class version of process_event() to bypass calling
            # ev._finalize(), which would fail since ev is of type
            # _mididings.MidiEvent.
            for out_ev in _mididings.Engine.process_event(engine, ev):
                buf, track, pulses = _mididings.midi_event_to_buffer(out_ev)
                smf_out.add_event(smf.Event(buf), track, pulses=pulses)

    smf_out.save(outfile)
예제 #3
0
def peek_midi_file(context, filepath, use_some_setting):
    print(filepath)
    prefs = context.user_preferences.addons["sound_drivers"].preferences
    import sys
    sys.path.append(prefs.smf_dir)
    import smf
    pin_id = getattr(context.space_data, "pin_id", None)
    sp = pin_id if pin_id is not None else context.object.data
    sound = sp.sound

    f = smf.SMF(filepath)
    midi = {}
    tracks = {}
    for t in f.tracks:
        track = {}
        for e in t.events:
            #print(e.decode(), e.time_seconds)
            s = e.decode()
            #print(s.startswith("Note"))

            if s.startswith("Instrument"):
                #print("INSTRUMENT", s)
                track["name"] = "Track %d" % (t.track_number)
                track["index"] = t.track_number

                track["instrument"] = s.title()

            elif s.startswith("Time Signature"):
                track["time_sig"] = s

            elif s.startswith("Tempo"):
                track["tempo"] = s

            elif s.startswith("Key Signature"):
                print("KEYSIG", s)
                track["keysig"] = s
            elif s.startswith("Program Change"):
                #print("PROGCHA", s)
                # this could be instrument too
                idx = int(s.split(" ")[-1])
                s = midi_instruments[idx]
                track["name"] = "Track %d" % (t.track_number)
                track["instrument"] = s.title()
                track["index"] = t.track_number
            elif s.startswith("Controller"):
                continue
                print("CONTROLLER", s)
            elif s.startswith("Pitch Wheel"):
                # do nothing for now
                continue
            elif s.startswith("Note"):
                continue
            elif s.startswith("End Of Track"):
                break
            else:
                #continue
                print("XXX", s)
        if t.track_number == 0:
            midi = track

        if track.get("name", False):
            tracks.setdefault(track["name"], track)

    sound.midifile.filepath = filepath
    sound.midifile.tracks.clear()

    for k, track in tracks.items():
        t = sound.midifile.tracks.add()
        t.name = track["name"]

        t.data_dic = json.dumps(track)
        print("-" * 77)
        print(k, tracks[k])

    return
예제 #4
0
def read_midi_file(context, filepath, use_some_setting):
    print(filepath)
    prefs = context.user_preferences.addons["sound_drivers"].preferences
    import sys
    sys.path.append(prefs.smf_dir)
    import smf
    pin_id = context.space_data.pin_id
    sp = pin_id if pin_id is not None else context.object.data

    channels = [
        c for sp in context.scene.objects if sp.type == 'SPEAKER'
        for c in sp.data.channels
    ]
    midichannels = []
    f = smf.SMF(filepath)
    tracks = []
    for t in f.tracks:
        print("TRACK : %s" % t.track_number)
        a = {}
        #a = bpy.data.actions.new("MidiAction")

        print(channels)
        channel_name = unique_name(channels, 'AA')
        channels.append(channel_name)
        a["name"] = "%s Unknown (trk %d)" % (channel_name, t.track_number)
        a['wavfile'] = sp.sound.name
        a['start'] = 0
        a['end'] = len(midi_notes)
        a['row_height'] = 0.4
        a["Channels"] = 0
        a["channel_name"] = channel_name
        a['MIDI'] = filepath
        #sp.animation_data.action = a
        a["keyframe_points"] = {}  # list of tups (dp, frame, value)
        '''
        for i, n in enumerate(midi_notes):
            channel = "%s%d" % (channel_name, i)
            sp[channel] = 0
            sp.keyframe_insert('["%s"]' % channel, frame = 0)
            #sp.keyframe_insert('["%s"]' % channel, frame = 0)
            #sp.keyframe_insert('["%s"]' % channel, frame = 0)
        '''
        for e in t.events:
            s = e.decode()
            print("XXXXXXXX", s, e.time_seconds)
            #print(s.startswith("Note"))

            if s.startswith("Instrument"):
                print("INSTRUMENT", s)
                a["name"] = "%s:%s (trk %d)" % (channel_name, s.title(),
                                                t.track_number)
            elif s.startswith("Key Signature"):
                print("KEYSIG", s)
            elif s.startswith("Program Change"):
                #print("PROGCHA", s)
                # this could be instrument too
                idx = int(s.split(" ")[-1])
                #print(midi_instruments[idx])
                a["name"] = "%s:%s (trk %d)" % (channel_name,
                                                midi_instruments[idx].title(),
                                                t.track_number)
            elif s.startswith("Controller"):
                continue
                print("CONTROLLER", s)
            elif s.startswith("Pitch Wheel"):
                print("PITCHWEEL", s)
                # do nothing for now
                continue
            elif s.startswith("Note"):
                v = 0
                s = s.replace("Note ", "")
                #print("StartsWithNote", s)
                c = s.split(",")
                #print("CC", c[0])
                v = int(c[3].replace(" velocity ", ""))
                if c[0] == "On":
                    note = c[2].replace(" note ", "")
                    print("ON key[%s] = %d @ %fs" % (note, v, e.time_seconds))
                elif c[0] == "Off":
                    v = 0
                    note = c[2].replace(" note ", "")
                    print("OFF key[%s] = %d @ %fs" % (note, v, e.time_seconds))
                if note not in midi_notes:
                    print("WARNING: unable to use note %s %d" %
                          notesplit(note))
                    continue
                channel = "%s%i" % (channel_name, midi_notes.index(note))
                fcurve = a["keyframe_points"].setdefault(channel, [])
                fcurve.append((e.time_seconds * context.scene.render.fps, v))
                #sp[channel] = v
                #a["keyframe_points"].append(('["%s"]' % channel, e.time_seconds * context.scene.render.fps, v))
            else:
                #continue
                print("XXX", s)

        if len(a["keyframe_points"].keys()):
            midichannels.append(channel_name)
            midifile["TRACK : %s" % t.track_number] = a

    print(midichannels)

    keys = [
        "name", "wavfile", "start", "end", "row_height", "Channels",
        "channel_name", "MIDI"
    ]
    actions = []
    channels = []
    action = bpy.data.actions.new("MidiAction")
    sp.animation_data.action = action
    for k, a in midifile.items():
        print("-" * 77)
        print(midifile[k]["name"])

        tracks = a["keyframe_points"]

        #action = bpy.data.actions.new("MidiAction")
        #sp.animation_data.action = action
        for key in keys:
            action[key] = a[key]
        channel = a["channel_name"]
        channels.append(channel)
        for t in tracks.keys():
            kfps = tracks[t]
            print(t)
            #fc = action.fcurves.new('["%s"]' % t)
            # make the fcurves
            sp[t] = 0
            sp.keyframe_insert('["%s"]' % t, frame=1, group=a["name"])
            for kfp in kfps:
                f, v = kfp
                sp[t] = v
                sp.keyframe_insert('["%s"]' % t, frame=f, group=a["name"])
            print("KFPS", t, len(tracks[t]))

    actions.append(action)

    # would normally load the data here

    vals = []
    sp_rna = {}
    for a in actions:

        if len(a.fcurves) <= 1:
            print("NO FCURVES IN ", a.name)
            try:
                del (a["wavfile"])
                a.user_clear()
                actions.remove(a)
                #bpy.data.actions.remove(a)
                #print("REMOVED")
            except:
                print("XCPT")
                continue
            print("WTF")
            continue

        a["Channels"] = len(a.fcurves)
        a["channels"] = channels
        channel_name = a["channel_name"]

        for fc in a.fcurves:

            for kp in fc.keyframe_points:
                kp.interpolation = 'CONSTANT'
            fc_range, points = fc.minmax
            cn = fc.data_path.replace('["', '').replace('"]', '')
            print(channel_name, cn)
            n = int(cn[2:])
            f = pow(2, (n - 69) / 12.0) * 440
            high = low = f
            vals.extend(list(fc_range))
            rna = sp['_RNA_UI']
            set_channel_idprop_rna(cn,
                                   rna,
                                   low,
                                   high,
                                   fc_range,
                                   fc_range,
                                   is_music=True)
            '''
            vcns = ["%s%d" % (channel_name, i) for i in
                    range(len(midi_notes))]

            '''
        sp_rna = {k: sp['_RNA_UI'][k].to_dict() for k in sp['_RNA_UI'].keys()}
        # if k in vcns}

        a['rna'] = str(sp_rna)
        a['min'] = min(vals)
        a['max'] = max(vals)

        nla_drop(sp, action, 1, "%s %s" % (channel_name, channel_name))

    return {'FINISHED'}
예제 #5
0
import smf

# create a new SMF object
f = smf.SMF()

# add a track
f.add_track()

# add a single note (middle C with a duration of one second)
f.add_event(smf.Event([0x90, 60, 127]), 0, seconds=0.0)
f.add_event(smf.Event([0x80, 60, 0]), 0, seconds=1.0)

# save as a new standard MIDI file
f.save('test.mid')
예제 #6
0
parser.add_argument('inputfile',
                    metavar='inputfile.mid',
                    nargs='?',
                    help='input midi file name')
parser.add_argument('--blofeld',
                    action='store_true',
                    help='ignore all sysex except waldorf blofeld patches')
parser.add_argument('--verbose', action='store_true', help='verbose output')

args = parser.parse_args()

midfile = args.inputfile
syxfile = midfile.split('.')[0] + ".syx"

print("opening input file '%s'..." % midfile)
f = smf.SMF(midfile)
t = f.tracks[0]

print("opening output file '%s'" % syxfile)
outfile = open(syxfile, 'wb')

patchno = 0

for e in t.events:
    if e.midi_buffer[0] == 0xf0:
        patchno += 1
        buflen = len(e.midi_buffer)
        bufhex = map(hex, e.midi_buffer)

        if args.blofeld:
            if buflen != 392:
예제 #7
0
import smf
import sys

filename = sys.argv[1]
tracknum = int(sys.argv[2])

print("opening file '%s'..." % filename)
f = smf.SMF(filename)

t = f.tracks[tracknum]

print("---\nlisting binary data for track %d:\n---" % tracknum)
for e in t.events:
    print(e.midi_buffer)

print("---\nlisting decoded events for track %d:\n---" % tracknum)
for e in t.events:
    print(e.decode())