コード例 #1
0
def noteStateMatrixToMidi(state_matrix, name="example", span=span):
    state_matrix = np.array(state_matrix)
    if not len(state_matrix.shape) == 3:
        state_matrix = np.dstack((state_matrix[:, :span], state_matrix[:,
                                                                       span:]))
    state_matrix = np.asarray(state_matrix)
    pattern = MidiFile()

    pattern.add_track()
    track = pattern.tracks[0]

    span = upperBound - lowerBound
    tickscale = 55

    lastcmdtime = 0
    prevstate = [[0, 0] for x in range(span)]
    for time, state in enumerate(state_matrix + [prevstate[:]]):
        offNotes = []
        onNotes = []
        for i in range(span):
            n = state[i]
            p = prevstate[i]
            if p[0] == 1:
                if n[0] == 0:
                    offNotes.append(i)
                elif n[1] == 1:
                    offNotes.append(i)
                    onNotes.append(i)
            elif n[0] == 1:
                onNotes.append(i)
        for note in offNotes:
            track.append(
                Message(type='note_off',
                        time=(time - lastcmdtime) * tickscale,
                        note=note + lowerBound))
            lastcmdtime = time
        for note in onNotes:
            track.append(
                Message(type='note_on',
                        time=(time - lastcmdtime) * tickscale,
                        velocity=40,
                        note=note + lowerBound))
            lastcmdtime = time

        prevstate = state

    eot = MetaMessage('end_of_track')
    track.append(eot)

    pattern.save(f'{name}.mid')
コード例 #2
0
def save_musical_file(path: str, out: str = None):
    if out is None:
        out = path
    f = MidiFile()
    ap = f.add_track('Main').append
    last_bpm = tempo2bpm(DEFAULT_TEMPO)
    ap(MetaMessage("set_tempo", tempo=DEFAULT_TEMPO))
    notes_on = []
    i = 0
    for bpm, duration, notes in musical_extract_midi(path):
        i += 1
        if notes_on:
            ap(Message(type='note_off', note=notes_on[0],
                       time=int(duration * f.ticks_per_beat * 0.95)))
            for n in notes_on[1:]:
                ap(Message(type='note_off', note=n, time=0))
        notes_on = notes
        ap(Message(type='note_on', note=notes_on[0],
                   time=int(duration * f.ticks_per_beat * 0.05)))
        for n in notes_on:
            ap(Message(type='note_on', note=n, time=0))
        if bpm != last_bpm:
            last_bpm = bpm
            ap(MetaMessage("set_tempo", tempo=bpm2tempo(bpm)))
    if notes_on:  # Last note; just make it 1 beat long
        ap(Message(type='note_off', note=notes_on[0], time=f.ticks_per_beat))
        for n in notes_on[1:]:
            ap(Message(type='note_off', note=n, time=0))
    f.save(out)
    print(f"{i} hits wrote to {out}")
コード例 #3
0
def save_processed_file(path: str, out: str = None, resolution=1 / 16):
    if out is None:
        out = path
    f = MidiFile(ticks_per_beat=1)
    ap = f.add_track('Main').append
    ap(MetaMessage("set_tempo", tempo=100000))

    def on(note: int, time: int):
        ap(Message(type='note_on', note=note, time=time))

    def off(note: int, time: int):
        ap(Message(type='note_off', note=note, time=time))

    def note(time: int, *notes):
        if notes:
            for n in notes:
                on(n, 0)
            off(notes[0], time)
            for n in notes[1:]:
                off(n, 0)

    i = 0
    for fwd, notes in readAndProcessMidi(path, resolution):
        note(fwd, *notes)
        i += 1
    f.save(out)
    print(f"{i} hits wrote to {out}")
コード例 #4
0
def readTempo():
    readingMido = MidiFile("music/forDrums.mid")
    actualMidi = MidiFile()
    for i,track in enumerate(readingMido.tracks):
        actualTrack = MidiTrack()
        actualMidi.add_track(actualTrack)

        if i % 2 == 0:

            for msg in track:
               if msg.type == "note_on" or msg.type == "note_off":
                    if msg.channel == 9:
                         actualTrack.append(Message('program_change', program="10", time="0"))
                         break

    for msg in track:
      actualTrack.append(msg)
コード例 #5
0
    def write(self):
        mid = MidiFile()
        track = mid.add_track(self.track.name)

        for i in self.track:
            track.append(i[0])
            track.append(i[1])

        mid.save(self.filename)
コード例 #6
0
    def write(track_list, filename):
        mid = MidiFile()
        for track in track_list:
            t = mid.add_track(track.name)

            for message in track.track:
                t.append(message[0])
                t.append(message[1])

        new_mid = MidiFile()

        for track in mid.tracks:
            new_track = MidiTrack()
            new_mid.tracks.append(new_track)
            for msg in track:
                if msg.type == 'set_tempo':
                    msg.tempo = 250000

                new_track.append(msg)
        new_mid.save(filename)
コード例 #7
0
def make_midi_file(tempo: int, queue: List[List[MidiNote]]) -> MidiFile:
    """
    Takes the queue of notes, returns them in timestamp order.
    :param tempo:
    :param queue:
    :return:
    """
    tpb = mido.midifiles.midifiles.DEFAULT_TICKS_PER_BEAT
    file = MidiFile()
    for (i, track_data) in enumerate(queue):
        track = file.add_track('Track ' + str(i))

        last_delta = 0
        for n in track_data:
            track += note_to_message(tpb, i, n, last_delta)
            # we ignore last_delta changes for now...

    tempo_msg = mido.MetaMessage('set_tempo', tempo=mido.bpm2tempo(tempo))
    for track in file.tracks:
        track.insert(0, tempo_msg)
    return file
コード例 #8
0
def write_midi_seq(score, quantization, ticks_per_beat, write_path, tempo=80, metadata=None):
	# score is a list = [(pc(12), octave(11), intensity(128), instru_integer, repeat_flag(1))]
	#
	# First convert score into a dictionnary:
	# {'Instrument': list_events}

	_, instru_mapping_reverse = get_instru_mapping()

	dict_tracks = {'Piano': []}
	for instru_name in instru_mapping_reverse.values():
		dict_tracks[instru_name] = []

	for event in score:
		time, notes = event
		
		if len(notes) == 0:
			# Silence !!
			for instru_name in instru_mapping_reverse.values():
				if len(dict_tracks[instru_name])!=0:
					dict_tracks[instru_name].append((time, set()))

		new_events = {'Piano': set()}
		for instru_name in instru_mapping_reverse.values():
			new_events[instru_name] = set()

		for note in notes:
			instrument_index = note[3]
			if instrument_index == -1:
				instru_name = 'Piano'
			else:
				instru_name = instru_mapping_reverse[instrument_index]
			# Remove instrument info
			new_events[instru_name].add(note)
		
		for instru_name in instru_mapping_reverse.values():
			if len(new_events[instru_name])!=0:
				dict_tracks[instru_name].append((time, new_events[instru_name]))
		if len(new_events["Piano"])!=0:
			dict_tracks["Piano"].append((time, new_events["Piano"]))

	# Tempo
	microseconds_per_beat = mido.bpm2tempo(tempo)
	# Write a pianoroll in a midi file
	mid = MidiFile()
	mid.ticks_per_beat = ticks_per_beat

	# Create a metaTrack
	# Add a new track with the instrument name to the midi file
	track = mid.add_track("metatrack")
	# Not advised, tends to f**k up everyting
	if metadata:
		if "time_signature" in metadata.keys():
			track.append(mido.MetaMessage('time_signature', numerator=metadata["time_signature"][0], denominator=metadata["time_signature"][1], 
				clocks_per_click=metadata["time_signature"][2], notated_32nd_notes_per_beat=metadata["time_signature"][3], time=0))
		if "key_signature" in metadata.keys():
			track.append(mido.MetaMessage('key_signature', key=metadata["key_signature"], time=0))
	# Tempo
	track.append(mido.MetaMessage('set_tempo', tempo=microseconds_per_beat))

	for instrument_name, track_list in dict_tracks.items():

		if len(track_list) == 0:
			continue

		# Add a new track with the instrument name to the midi file
		track = mid.add_track(instrument_name)
		
		# Not advised, tends to f**k up everyting
		if metadata:
			if "time_signature" in metadata.keys():
				track.append(mido.MetaMessage('time_signature', numerator=metadata["time_signature"][0], denominator=metadata["time_signature"][1], 
					clocks_per_click=metadata["time_signature"][2], notated_32nd_notes_per_beat=metadata["time_signature"][3], time=0))
			if "key_signature" in metadata.keys():
				track.append(mido.MetaMessage('key_signature', key=metadata["key_signature"], time=0))

		# Tempo
		track.append(mido.MetaMessage('set_tempo', tempo=microseconds_per_beat))
		
		# Add the program_change (for playback, GeneralMidi norm)
		program = program_change_mapping[instrument_name]-1
		track.append(mido.Message('program_change', program=program))
		# Each instrument is a track

		# Safety: sort by time
		sorted_track_list = sorted(track_list, key=lambda tup: tup[0])

		# Keep track of note on to know which one to shut down
		notes_previous = set()
		time_previous = 0
		repeated_note_previous = 0

		# print("# " + instrument_name)

		# Write events in the midi file
		for time_now, notes in sorted_track_list:

			notes_played = set()

			time = int( (time_now - time_previous) * (ticks_per_beat/quantization) ) - repeated_note_previous

			message_written = False
			repeated_note_previous = 0

			for note in notes:
				pc, octave, velocity, _, repeat = note
				
				pitch = from_pc_octave_to_pitch(pc, octave)
				
				if (pitch in notes_previous):
					# Note repeat or sustained ? If sustained do nothing
					if repeat == 1:
						track.append(mido.Message('note_off', note=pitch, velocity=0, time=time))
						# print(mido.Message('note_off', note=pitch, velocity=0, time=time))
						time = 1
						track.append(mido.Message('note_on', note=pitch, velocity=velocity, time=time))
						# print(mido.Message('note_on', note=pitch, velocity=velocity, time=time))
						time = 0
						message_written = True
						repeated_note_previous += 1
					notes_played.add(pitch)
				else:
					track.append(mido.Message('note_on', note=pitch, velocity=velocity, time=time))
					# print(mido.Message('note_on', note=pitch, velocity=velocity, time=time))
					notes_played.add(pitch)
					time = 0
					message_written = True
			
			# Clean removed note
			notes_to_remove = notes_previous - notes_played
			for pitch in notes_to_remove:
				track.append(mido.Message('note_off', note=pitch, velocity=0, time=time))
				# print(mido.Message('note_off', note=pitch, velocity=0, time=time))
				notes_previous.remove(pitch)
				time = 0
				message_written = True
			notes_previous = notes_previous | notes_played

			# Increment time
			if message_written:
				time_previous = time_now

		# Finish with a not off
		last_time = int(4*ticks_per_beat)
		track.append(mido.MetaMessage('end_of_track', time=last_time))


	mid.save(write_path)
	return
コード例 #9
0
importFolder = os.path.join(dir, "interchange", sessionName, "midifiles")
exportFolder = os.path.join(dir, "export")
vprint(importFolder, exportFolder)

# Iterate through the MIDI tracks in Ardour (called "Routes" in the XML file)
# Gets Ardour track id's and saves track names
mid = MidiFile(type=1, ticks_per_beat=19200)
trackRef = {}  #ardour-track-id : midi-track-id
i = 0
for route in dom.getElementsByTagName("Route"):
    if route.getAttribute("default-type") == "midi":
        rname = route.getAttribute("name")
        if args.omitparens:
            p = re.compile("(.*)(\(.*\))(.*)")
            rname = p.sub(r"\1\3", rname).strip()
        mid.add_track(name=rname)
        mid.tracks[i].append(MetaMessage("instrument_name", name=rname))
        programNumber = getGeneralMidiNumber(rname)
        if programNumber == -10:
            mid.tracks[i].append(
                MetaMessage("channel_prefix", channel=10, time=0))
            if args.musescore:
                mid.tracks[i].append(
                    Message("program_change", program=56, time=0)
                )  #avoids the double staff for program=0 in MuseScore
        else:
            mid.tracks[i].append(
                Message("program_change", program=programNumber, time=0))
        beatsPerMinute = int(
            dom.getElementsByTagName("Tempo")[0].getAttribute(
                "beats-per-minute"))
コード例 #10
0
now_on = []
now_on_msg = []
sky = mido.Message('note_on', note=0, velocity=0, time=0)
tick = 0

#mido.merge_tracks(mid_in.tracks)

#set file
mid_out.ticks_per_beat = mid_in.ticks_per_beat
mid_out.type = mid_in.type
mid_out.charset = mid_in.charset

#skyline for every tracks
for i, track in enumerate(mid_in.tracks):
    #create same number of track of mid_in for mid_out
    mid_out.add_track()
    mid_out.tracks[i].name = track.name

    for message in track:
        #meta message
        if message.type != 'note_on' and message.type != 'note_off':
            message.time += tick
            tick = 0
            mid_out.tracks[i].append(message)
            #tick += message.time
            #print(1)

        #note on event
        elif message.type == 'note_on' and message.velocity != 0:
            if message.note >= sky.note:
                if sky.note > 0 and message.note != sky.note:
コード例 #11
0
def write_midi(pr, ticks_per_beat, write_path, tempo=80):
    def pr_to_list(pr):
        # List event = (pitch, velocity, time)
        T, N = pr.shape
        t_last = 0
        pr_tm1 = np.zeros(N)
        list_event = []
        for t in range(T):
            pr_t = pr[t]
            mask = (pr_t != pr_tm1)
            if (mask).any():
                for n in range(N):
                    if mask[n]:
                        pitch = n
                        velocity = int(pr_t[n])
                        # Time is incremented since last event
                        t_event = t - t_last
                        t_last = t
                        list_event.append((pitch, velocity, t_event))
            pr_tm1 = pr_t
        return list_event

    # Tempo
    microseconds_per_beat = mido.bpm2tempo(tempo)
    # Write a pianoroll in a midi file
    mid = MidiFile()
    mid.ticks_per_beat = ticks_per_beat

    # Each instrument is a track
    for instrument_name, matrix in pr.items():
        # Add a new track with the instrument name to the midi file
        track = mid.add_track(instrument_name)
        # transform the matrix in a list of (pitch, velocity, time)
        events = pr_to_list(matrix)
        # Tempo
        track.append(mido.MetaMessage('set_tempo',
                                      tempo=microseconds_per_beat))
        # Add the program_change
        try:
            program = program_change_mapping[instrument_name]
        except:
            # Defaul is piano
            # print instrument_name + " not in the program_change mapping"
            # print "Default value is 1 (piano)"
            # print "Check acidano/data_processing/utils/program_change_mapping.py"
            program = 1
        track.append(mido.Message('program_change', program=program))

        # This list is required to shut down
        # notes that are on, intensity modified, then off only 1 time
        # Example :
        # (60,20,0)
        # (60,40,10)
        # (60,0,15)
        notes_on_list = []
        # Write events in the midi file
        for event in events:
            pitch, velocity, time = event
            if velocity == 0:
                # Get the channel
                track.append(
                    mido.Message('note_off', note=pitch, velocity=0,
                                 time=time))
                notes_on_list.remove(pitch)
            else:
                if pitch in notes_on_list:
                    track.append(
                        mido.Message('note_off',
                                     note=pitch,
                                     velocity=0,
                                     time=time))
                    notes_on_list.remove(pitch)
                    time = 0
                track.append(
                    mido.Message('note_on',
                                 note=pitch,
                                 velocity=velocity,
                                 time=time))
                notes_on_list.append(pitch)
    mid.save(write_path)
    return
コード例 #12
0
ファイル: write_midi.py プロジェクト: aciditeam/acidano
def write_midi(pr, quantization, write_path, tempo=80):
    def pr_to_list(pr):
        # List event = (pitch, velocity, time)
        T, N = pr.shape
        t_last = 0
        pr_tm1 = np.zeros(N)
        list_event = []
        for t in range(T):
            pr_t = pr[t]
            mask = (pr_t != pr_tm1)
            if (mask).any():
                for n in range(N):
                    if mask[n]:
                        pitch = n
                        velocity = int(pr_t[n])
                        # Time is incremented since last event
                        t_event = t - t_last
                        t_last = t
                        list_event.append((pitch, velocity, t_event))
            pr_tm1 = pr_t
        return list_event
    # Tempo
    microseconds_per_beat = mido.bpm2tempo(tempo)
    # Write a pianoroll in a midi file
    mid = MidiFile()
    # ticks_per_beat can be the quantization, this simplify the writing process
    mid.ticks_per_beat = quantization

    # Each instrument is a track
    for instrument_name, matrix in pr.iteritems():
        # A bit shity : if the pr is a binary pr, multiply by 127
        if np.max(matrix) == 1:
            matrix = matrix * 127
        # Add a new track with the instrument name to the midi file
        track = mid.add_track(instrument_name)
        # transform the matrix in a list of (pitch, velocity, time)
        events = pr_to_list(matrix)
        # Tempo
        track.append(mido.MetaMessage('set_tempo', tempo=microseconds_per_beat))
        # Add the program_change
        try:
            program = program_change_mapping[instrument_name]
        except:
            # Defaul is piano
            print instrument_name + " not in the program_change mapping"
            print "Default value is 1 (piano)"
            print "Check acidano/data_processing/utils/program_change_mapping.py"
            program = 1
        track.append(mido.Message('program_change', program=program))

        # This list is required to shut down
        # notes that are on, intensity modified, then off only 1 time
        # Example :
        # (60,20,0)
        # (60,40,10)
        # (60,0,15)
        notes_on_list = []
        # Write events in the midi file
        for event in events:
            pitch, velocity, time = event
            if velocity == 0:
                # Get the channel
                track.append(mido.Message('note_off', note=pitch, velocity=0, time=time))
                notes_on_list.remove(pitch)
            else:
                if pitch in notes_on_list:
                    track.append(mido.Message('note_off', note=pitch, velocity=0, time=time))
                    notes_on_list.remove(pitch)
                    time = 0
                track.append(mido.Message('note_on', note=pitch, velocity=velocity, time=time))
                notes_on_list.append(pitch)
    mid.save(write_path)
    return
コード例 #13
0
ファイル: midi_file.py プロジェクト: fbxiang/ugly-midi
    def write(self, midi_file):
        mid = MidiFile(ticks_per_beat=self.resolution)

        # default time signature
        if not self.time_signatures:
            self.time_signatures = [TimeSignature(4, 4, 0)]

        # default tempo
        if not self.tempo_changes:
            self.tempo_changes = [TempoChange(120, 0)]

        track = mid.add_track()

        events = []
        for ks in self.key_signatures:
            events.append(
                MetaMessage('key_signature', key=ks.key, time=ks.time))
        for ts in self.time_signatures:
            events.append(
                MetaMessage('time_signature',
                            numerator=ts.numerator,
                            denominator=ts.denominator,
                            time=ts.time))
        for tc in self.tempo_changes:
            events.append(
                MetaMessage('set_tempo', tempo=bpm2tempo(tc.bpm),
                            time=tc.time))
        events = sorted(events, key=lambda msg: msg.time)
        now = 0
        for msg in events:
            msg.time -= now
            track.append(msg)
            now += msg.time

        if len([instr
                for instr in self.instruments if not instr.is_drum]) > 15:
            warnings.warn(
                "Synthesizing with more than 15 instruments is not supported",
                RuntimeWarning)

        current_channel = 0
        for instr in self.instruments:
            track = mid.add_track()
            channel = 9 if instr.is_drum else current_channel

            track.append(
                Message('program_change',
                        channel=channel,
                        program=instr.program,
                        time=0))

            note_msgs = []
            for n in instr.notes:
                note_msgs.append(
                    Message('note_on',
                            channel=channel,
                            note=n.pitch,
                            velocity=n.velocity,
                            time=n.start))
                note_msgs.append(
                    Message('note_off',
                            channel=channel,
                            note=n.pitch,
                            velocity=0,
                            time=n.end))

            note_msgs = sorted(note_msgs, key=lambda msg: msg.time)
            now = 0
            for msg in note_msgs:
                track.append(msg.copy(time=msg.time - now))
                now = msg.time

            if not instr.is_drum:
                current_channel += 1
                if current_channel > 15:
                    break

        mid.save(midi_file)