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')
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}")
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}")
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)
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)
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)
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
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
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"))
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:
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
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
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)