Example #1
0
    def read_note_list(self, filename, quantize = 0.25):
        reader = midi.FileReader()
        data = reader.read(file(self.filename))


        notes = []
        for track in data:
            track.make_ticks_abs()
            for event in [event for event in track if isinstance(event, midi.events.NoteEvent)]:
                location = event.tick / 96.0
                if isinstance(event, midi.events.NoteOnEvent) and event.velocity > 0:
                    log.info("(%.2f beats) %s. \t(note = %d, velocity = %d)" % (location, miditoname(event.pitch), event.pitch, event.velocity))

                    #------------------------------------------------------------------------
                    # anomaly: sometimes a midi file might have a note on when the previous
                    # note has not finished; end it automatically
                    #------------------------------------------------------------------------
                    for note in reversed(notes):
                        if note.pitch == event.pitch:
                            if not note.duration:
                                log.warn("note-on found without note-off; cancelling previous note")
                                duration = location - note.location
                                note.duration = duration
                                if duration == 0:
                                    log.warn("*** DURATION OF ZERO??")
                            break

                    note = Note(event.pitch, event.velocity, location)
                    notes.append(note)

                #------------------------------------------------------------------------
                # A NoteOn event with velocity == 0 also acts as a NoteOff.
                #------------------------------------------------------------------------
                if isinstance(event, midi.events.NoteOffEvent) or (isinstance(event, midi.events.NoteOnEvent) and event.velocity == 0):
                    log.debug("(%.2f beats) %s off \t(note = %d, velocity = %d)" % (location, miditoname(event.pitch), event.pitch, event.velocity))
                    found = False
                    for note in reversed(notes):
                        if note.pitch == event.pitch:
                            duration = location - note.location
                            # print " -> duration = %.2f beats" % duration
                            note.duration = duration
                            found = True
                            break
                    if not found:
                        log.warn("*** NOTE-OFF FOUND WITHOUT NOTE-ON ***")

        if quantize is not None:
            for note in notes:
                note.location = round(note.location / quantize) * quantize
                note.duration = round(note.duration / quantize) * quantize

        return notes
    def read(self, filename, quantize=0.25):
        reader = midi.FileReader()
        data = reader.read(file(filename))

        class Note:
            def __init__(self, pitch, velocity, location, duration=None):
                # pitch = MIDI 0..127
                self.pitch = pitch
                # velocity = MIDI 0..127
                self.velocity = velocity
                # location in time, beats
                self.location = location
                # duration in time, beats
                self.duration = duration

        notes = []
        for track in data:
            track.make_ticks_abs()
            for event in filter(
                    lambda event: isinstance(event, midi.events.NoteEvent),
                    track):
                location = event.tick / 96.0
                if isinstance(event,
                              midi.events.NoteOnEvent) and event.velocity > 0:
                    print "(%.2f beats) %s. \t(note = %d, velocity = %d)" % (
                        location, miditoname(
                            event.pitch), event.pitch, event.velocity)

                    #----------------------------------------------------------
                    # anomaly: sometimes a midi file might have a note on when the previous
                    # note has not finished; end it automatically
                    #----------------------------------------------------------
                    for note in reversed(notes):
                        if note.pitch == event.pitch:
                            if not note.duration:
                                print "note-on found without note-off; cancelling previous note"
                                duration = location - note.location
                                note.duration = duration
                                if duration == 0:
                                    print "*** DURATION OF ZERO??"
                            break

                    note = Note(event.pitch, event.velocity, location)
                    notes.append(note)

                #--------------------------------------------------------------
                # A NoteOn event with velocity == 0 also acts as a NoteOff.
                #--------------------------------------------------------------
                if isinstance(event, midi.events.NoteOffEvent) or (
                        isinstance(event, midi.events.NoteOnEvent)
                        and event.velocity == 0):
                    print "(%.2f beats) %s off \t(note = %d, velocity = %d)" % (
                        location, miditoname(
                            event.pitch), event.pitch, event.velocity)
                    found = False
                    for note in reversed(notes):
                        if note.pitch == event.pitch:
                            duration = location - note.location
                            # print " -> duration = %.2f beats" % duration
                            note.duration = duration
                            found = True
                            break
                    if not found:
                        print "*** NOTE-OFF FOUND WITHOUT NOTE-ON ***"

        #----------------------------------------------------------------------
        # Construct a sequence which honours chords and relative lengths.
        # First, group all notes by their starting time.
        #----------------------------------------------------------------------
        notes_by_time = {}
        for note in notes:
            print "(%.2f) %d/%d, %s" % (note.location, note.pitch,
                                        note.velocity, note.duration)
            location = note.location
            if quantize is not None:
                location = round(location / quantize) * quantize
            if location in notes_by_time:
                notes_by_time[location].append(note)
            else:
                notes_by_time[location] = [note]

        note_dict = {"note": [], "amp": [], "gate": [], "dur": []}

        #----------------------------------------------------------------------
        # Next, iterate through groups of notes chronologically, figuring out
        # appropriate parameters for duration (eg, inter-note distance) and
        # gate (eg, proportion of distance note extends across).
        #----------------------------------------------------------------------
        times = sorted(notes_by_time.keys())
        for i in range(len(times)):
            time = times[i]
            notes = notes_by_time[time]

            #------------------------------------------------------------------
            # Our duration is always determined by the time of the next note event.
            # If a next note does not exist, this is the last note of the sequence;
            # use the maximal length of note currently playing (assuming a chord)
            #------------------------------------------------------------------
            if i < len(times) - 1:
                next_time = times[i + 1]
            else:
                next_time = time + max([note.duration for note in notes])

            dur = next_time - time
            note_dict["dur"].append(dur)

            if len(notes) > 1:
                note_dict["note"].append(tuple(note.pitch for note in notes))
                note_dict["amp"].append(tuple(note.velocity for note in notes))
                note_dict["gate"].append(
                    tuple(note.duration / dur for note in notes))
            else:
                note = notes[0]
                note_dict["note"].append(note.pitch)
                note_dict["amp"].append(note.velocity)
                note_dict["gate"].append(note.duration / dur)

        return note_dict
Example #3
0
import midi
import pprint
x = midi.FileReader()
p = midi.read('a.mid')
print(p)
input()
midi.write('aa.mid', p)
p = midi.read('aa.mid')
print(p)
input()
#midi.write('aaa.mid', p)
#p = midi.read('aaa.mid')