def create_inst_label(path, noteLength, shortestLen): info = pm.PrettyMIDI(path, initial_tempo=120) guit = [] trump = [] if len(info.instruments) == 1: if ("Guitar" in pm.program_to_instrument_name(info.instruments[0].program)): for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: guit.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) trump.append([0]*128 + [1]) i += 1 elif ("Trumpet" in pm.program_to_instrument_name(info.instruments[0].program)): for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: guit.append([0]*128 + [1]) trump.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 elif (len(info.instruments) == 2): guitar = info.instruments[0].notes trumpet = info.instruments[1].notes for note in trumpet: i = 0 while i*shortestLen < noteLength: trump.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 for note in guitar: i = 0 while i*shortestLen < noteLength: guit.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 return guit, trump
def unpack_sample(name='', concat=False): if name == '': pathlist = list(pathlib.Path('Samples').glob('**/*.npy')) name = str(pathlist[-1]) if not os.path.exists(name): os.mkdir(name) savename = name + '/' + name.split('/')[-1] if not '.npy' in name: name = name + '.npy' samples = np.load(name) > 0 program_nums = [0, 24, 40, 56, 64, 72] is_drum = [False] * CHANNEL_NUM if concat: sample = np.concatenate([i for i in samples], axis=-1) write_piano_rolls_to_midi(sample, program_nums=program_nums, is_drum=is_drum, filename=savename + '.mid') tqdm.write(name + '.mid') for i, piano_roll in enumerate(sample): fig = plt.figure(figsize=(12, 4)) librosa.display.specshow(piano_roll, x_axis='time', y_axis='cqt_note', hop_length=1, sr=96, fmin=pm.note_number_to_hz(12)) plt.title(savename + '_' + pm.program_to_instrument_name(program_nums[i])) fig.savefig(savename + '_' + str(i) + '.png') plt.close(fig) return for id, sample in enumerate(samples): write_piano_rolls_to_midi(sample, program_nums=program_nums, is_drum=is_drum, filename=savename + '_' + str(id) + '.mid') tqdm.write(savename + '_' + str(id) + '.mid') for i, piano_roll in enumerate(sample): fig = plt.figure(figsize=(12, 4)) librosa.display.specshow(piano_roll, x_axis='time', y_axis='cqt_note', hop_length=1, sr=96, fmin=pm.note_number_to_hz(12)) plt.title(savename + '_' + pm.program_to_instrument_name(program_nums[i])) fig.savefig(savename + '_' + str(id) + '_' + str(i) + '.png') plt.close(fig)
def main(path, grouped_instruments, p1, p2, p3): print('Main Instruments: ', pm.program_to_instrument_name(p1), pm.program_to_instrument_name(p2), pm.program_to_instrument_name(p3)) converted_data = [] for filename in os.listdir(path): if filename.lower().endswith('.mid'): try: pm_file = pm.PrettyMIDI(os.path.join(path, filename)) print(filename) converted_data.append( convert_file(pm_file, [p1, p2, p3, grouped_instruments])) except OSError: print(filename, 'could not be loaded as MIDI file - skipped.') except KeySignatureError: print(filename, 'has bad key values - skipped.') converted_array = np.asarray(converted_data) num_data_points = converted_array.shape[0] test_set_index = int(num_data_points / 5) valid_set_index = int(test_set_index * 4) np.savez(os.path.join(path, 'TrainData.npz'), test=converted_array[0:test_set_index], train=converted_array[test_set_index:valid_set_index], valid=converted_array[valid_set_index:num_data_points]) nonzero = np.sum(np.count_nonzero(file) for file in converted_data) tot = np.sum(file.size for file in converted_data) print('ratio of non-zero pitch values', nonzero / tot) return converted_array
def prettyMidiSingle(filename): pm = pretty_midi.PrettyMIDI(filename) notes = [] for i in range(0, len(pm.instruments)): pm.instruments[i].remove_invalid_notes() print(pretty_midi.program_to_instrument_name( pm.instruments[i].program)) print(len(pm.instruments[i].notes)) print(pm.instruments[i].notes) notes.append(pm.instruments[i].notes) print("Pitch Bends", len(pm.instruments[0].pitch_bends)) print("Control changes", len(pm.instruments[0].control_changes)) print(len(notes)) sample_Output = pretty_midi.PrettyMIDI() AcousticPiano = pretty_midi.instrument_name_to_program( 'Acoustic Grand Piano') piano1 = pretty_midi.Instrument(program=AcousticPiano) piano2 = pretty_midi.Instrument(program=AcousticPiano) for note in notes[0]: piano1.notes.append(note) for note in notes[1]: piano2.notes.append(note) sample_Output.instruments.append(piano1) sample_Output.instruments.append(piano2) sample_Output.write("test_output_pretty_midi.mid") print("--------------------------------------------------")
def save(self, path): """Saves mididata in an array shaped (timesteps,pitch,tracks)) into a .mid file""" src = self.array * np.float16(127) # (timesteps,pitch,tracks) src = np.swapaxes(src.astype(np.uint8), 1, 2) # (timesteps,tracks,pitch) src = np.swapaxes(src, 0, 1) # (tracks,timesteps,pitch) mul = mullib.Multitrack(resolution=self.res) mul.tracks = mul.tracks[1:] if len(self.tracks_map) != len(src): raise ValueError( "track_map do not have the same number of tracks of the array") l = len(self.tracks_map) for i in range(l): program = self.tracks_map[i]["program"] is_drum = self.tracks_map[i]["is_drum"] pianoroll = src[i] name = self.tracks_map[i].get("name") if name is None: if is_drum: name = "Drums" else: name = prelib.program_to_instrument_name(program) t = mullib.StandardTrack(name=name, program=program, is_drum=is_drum, pianoroll=pianoroll) mul.tracks += [t] mul.write(path) # adds one track
def get_track_label(track_label, track=None): """Return corresponding track labels.""" if track_label == "name": return track.name if track_label == "program": return pretty_midi.program_to_instrument_name(track.program) if track_label == "family": return pretty_midi.program_to_instrument_class(track.program) return track_label
def chiptunes_synthesize(midi, fs=44100): ''' Synthesize a pretty_midi.PrettyMIDI object chiptunes style. Parameters ---------- midi : pretty_midi.PrettyMIDI PrettyMIDI object to synthesize fs : int Sampling rate of the synthesized audio signal, default 44100 Returns ------- synthesized : np.ndarray Waveform of the MIDI data, synthesized at fs ''' # If there are no instruments, return an empty array if len(midi.instruments) == 0: return np.array([]) # Get synthesized waveform for each instrument waveforms = [] for inst in midi.instruments: # Synthesize as drum if inst.is_drum: waveforms.append(synthesize_drum_instrument(inst, fs=fs)) else: # Call it a bass instrument when no notes are over 48 (130hz) # or the program's name has the word "bass" in it is_bass = ( np.max([n.pitch for i in midi.instruments for n in i.notes]) < 48 or 'Bass' in pretty_midi.program_to_instrument_name(inst.program)) if is_bass: # Synthesize as a sine wave (should be triangle!) audio = inst.synthesize(fs=fs, wave=np.sin) # Quantize to 5-bit audio = np.digitize(audio, np.linspace(-audio.min(), audio.max(), 32)) waveforms.append(audio) else: # Otherwise, it's a harmony/lead instrument, so arpeggiate it # Arpeggio time of 30ms seems to work well inst_arpeggiated = arpeggiate_instrument(inst, .03) # These instruments sound louder because they're square, # so scale down waveforms.append(.5 * inst_arpeggiated.synthesize( fs=fs, wave=scipy.signal.square)) # Allocate output waveform, with #sample = max length of all waveforms synthesized = np.zeros(np.max([w.shape[0] for w in waveforms])) # Sum all waveforms in for waveform in waveforms: synthesized[:waveform.shape[0]] += waveform # Normalize synthesized /= np.abs(synthesized).max() return synthesized
def chiptunes_synthesize(midi, fs=44100): ''' Synthesize a pretty_midi.PrettyMIDI object chiptunes style. Parameters ---------- midi : pretty_midi.PrettyMIDI PrettyMIDI object to synthesize fs : int Sampling rate of the synthesized audio signal, default 44100 Returns ------- synthesized : np.ndarray Waveform of the MIDI data, synthesized at fs ''' # If there are no instruments, return an empty array if len(midi.instruments) == 0: return np.array([]) # Get synthesized waveform for each instrument waveforms = [] for inst in midi.instruments: # Synthesize as drum if inst.is_drum: waveforms.append(synthesize_drum_instrument(inst, fs=fs)) else: # Call it a bass instrument when no notes are over 48 (130hz) # or the program's name has the word "bass" in it is_bass = ( np.max([n.pitch for i in midi.instruments for n in i.notes]) < 48 or 'Bass' in pretty_midi.program_to_instrument_name(inst.program)) if is_bass: # Synthesize as a sine wave (should be triangle!) audio = inst.synthesize(fs=fs, wave=np.sin) # Quantize to 5-bit audio = np.digitize( audio, np.linspace(-audio.min(), audio.max(), 32)) waveforms.append(audio) else: # Otherwise, it's a harmony/lead instrument, so arpeggiate it # Arpeggio time of 30ms seems to work well inst_arpeggiated = arpeggiate_instrument(inst, .03) # These instruments sound louder because they're square, # so scale down waveforms.append(.5*inst_arpeggiated.synthesize( fs=fs, wave=scipy.signal.square)) # Allocate output waveform, with #sample = max length of all waveforms synthesized = np.zeros(np.max([w.shape[0] for w in waveforms])) # Sum all waveforms in for waveform in waveforms: synthesized[:waveform.shape[0]] += waveform # Normalize synthesized /= np.abs(synthesized).max() return synthesized
def get_track_label(track_label, track=None): """Convenient function to get track labels""" if track_label == 'name': return track.name if track.name != "" else pretty_midi.program_to_instrument_class( track.program) elif track_label == 'program': return pretty_midi.program_to_instrument_name(track.program) elif track_label == 'family': return pretty_midi.program_to_instrument_class(track.program) elif track is None: return track_label
def test_5(): print("[%s:%d] test_5()" % \ (os.path.basename(libs.thisfile()), libs.linenum() ), file=sys.stderr) for i in range(128): name_Inst = pretty_midi.program_to_instrument_name(i) print("num = %d / %s" % (i, name_Inst))
def get_instrument_info(instrument): """Given a pretty_midi.Instrument class instance, return the infomation dictionary of the instrument.""" return { 'program_num': instrument.program, 'program_name': pretty_midi.program_to_instrument_name(instrument.program), 'name': instrument.name.strip(), 'is_drum': instrument.is_drum, 'family_num': int(instrument.program) // 8, 'family_name': pretty_midi.program_to_instrument_class(instrument.program) }
def split_midi(self, file_name: str): """ Split MIDI files to ones corresponding to each instrument found throughout. Function creates multiple files for each instrument track and stores them in a separate directory. Inclusion of drum tracks is optional. For each track a unique dictionary key is created that has assigned a music21.instrument object that can be later referenced in the process of creating learning streams. :param file_name: Name of the file found in input path. :return: """ # input file is loaded and its initial tempo is extracted pretty_mf = pm.PrettyMIDI(self.__input_path + file_name) init_tempo = round(pretty_mf.get_tempo_changes()[1][0]) part_tag = 0 for instrument in pretty_mf.instruments: if self.uniform_tempo: # temporary MIDI for a single instrument is created and has copied values from the input MIDI temp_pretty = pm.PrettyMIDI(initial_tempo=init_tempo) temp_pretty.time_signature_changes = pretty_mf.time_signature_changes # a single instrument is appended onto ints instrument list, with it all its notes temp_pretty.instruments.append(instrument) else: # deep copy should preserve all exact tempo changes throughout the song temp_pretty = deepcopy(pretty_mf) # all existing instruments are cleared and only one from the original file is appended temp_pretty.instruments.clear() temp_pretty.instruments.append(instrument) # assigning comments for music21.instrument edit = mu.editorial.Editorial() edit.true_program = str(instrument.program) edit.is_drum = str(instrument.is_drum) insert_instrument = mu.instrument.Instrument() insert_instrument.editorial.comments.append(edit) # assigning file / dictionary key name if not instrument.is_drum: out_name = file_name + "_part_" + str(part_tag) + "_" + \ pm.program_to_instrument_name(instrument.program) + ".mid" else: out_name = file_name + "_part_" + str( part_tag) + "_Percussion" + ".mid" # placing commented instrument into dictionary for later usage with music21 module self.instruments_dict[out_name] = insert_instrument part_tag += 1 temp_pretty.write(self.__split_path + out_name)
def main(directory, cumulative_instrument_counts): file_names = os.listdir(directory) songs = {} unique_instruments = set() instr_presences = {} total_song_durations = 0 for fname in file_names: try: with open(directory + '/' + fname, 'rb') as f: midi = pretty_midi.PrettyMIDI(f) total_song_durations += midi.get_end_time() instruments = midi.instruments songs[fname] = {'instruments': []} for instr in instruments: instr_type = pretty_midi.program_to_instrument_name( instr.program ) # Program number says what instrument, see doc above if instr_type not in instr_presences: instr_presences[instr_type] = set() if instr_type not in cumulative_instrument_counts: cumulative_instrument_counts[instr_type] = set() instr_presences[instr_type].add(fname) cumulative_instrument_counts[instr_type].add(fname) songs[fname]['instruments'].append( [instr_type, int(instr.program), instr.name] ) # type and program store == info, name is used to map instruments in garadge band unique_instruments.add(instr_type) except Exception as err: print(f"Issue with {fname} : {err}") continue print(f'***UNIQUE INSTRUMENTS***\n{directory}') print(f'Not Bad Songs: {len(songs)}') print(unique_instruments) print(len(unique_instruments)) directory = directory[directory.rfind('/') + 1:] with open(f'music_analysis_scripts/{directory}DATA.json', 'w') as f: f.write(json.dumps(songs)) data = sorted(list( map(lambda x: (x[0], len(x[1])), instr_presences.items())), key=lambda x: x[1]) for instr, presence in data: print(instr, presence / len(songs)) print() return total_song_durations, len(songs)
def instrument_to_column(instrument, array_length, song_row): if instrument: if song_row == '(drums)': print('Instrument: ', song_row, instrument.program) else: print('Instrument: ', song_row, pm.program_to_instrument_name(instrument.program)) sampling_per_second = 100 # using times gave artifacts, padding with zeros instead data = instrument.get_piano_roll(fs=sampling_per_second, times=None) lowestloudest = np.zeros(array_length) for i in np.arange(data.shape[1]): row = data[:, i] # select the loudest (most important) values, if multiple, take lowest note (most of the time base note) lowestloudest[i] = min(np.argwhere(row == np.amax(row))) return lowestloudest
def load_song(filename): velocity = [] pitch = [] offset = [] duration = [] songlengths = [] notes = [] notesVar = [] pm = pretty_midi.PrettyMIDI(filename) for i in range(0, len(pm.instruments)): pm.instruments[i].remove_invalid_notes() if pm.instruments[i].program != 0: print( pretty_midi.program_to_instrument_name( pm.instruments[i].program)) print(len(pm.instruments[i].notes)) notes.append(pm.instruments[i].notes) if len(pm.instruments[i].pitch_bends) > 0: print("Pitch Bends", len(pm.instruments[i].pitch_bends)) if len(pm.instruments[i].control_changes) > 0: print("Control changes", len(pm.instruments[i].control_changes)) for list in notes: length = 0 for note in list: notesVar.append( (note.start, note.get_duration(), note.pitch, note.velocity)) length += 1 notesVar = sorted(notesVar) prevOffset = 0 songlengths.append(length) for note in notesVar: offset.append(round(note[0] - prevOffset, 1)) duration.append(round(note[1], 1)) pitch.append(note[2]) velocity.append(note[3]) prevOffset = note[0] notesVar = [] return pitch, velocity, offset, duration, songlengths
def orchestrate(self, i_to_t={(0, False): 0}, t_to_i=[{ 'program': 1, "is_drum": False }]): """Reorchestrate using a mapping from a tuple i1=(program,is_drum) to a track t1 (i_to_t[i1]=t1) and associating a tuple i2=(program,is_drum) to each one of the final tracks t2 (t_to_i[t2]=i2). Not mapped combinations will not be included in the final result.""" self.dims mul = self.to(mullib.Multitrack) new_mul = mul.copy() new_mul.tracks = [] for t in range(len(t_to_i)): program = t_to_i[t]["program"] is_drum = t_to_i[t]["is_drum"] name = prelib.program_to_instrument_name(program) if is_drum: name = "Drums" tmp_mul = mul.copy() tmp_mul.tracks = [] for i in mul.tracks: if i_to_t.get((i.program, i.is_drum), i_to_t.get((128, i.is_drum), None)) == t: tmp_mul.tracks += [i] if tmp_mul.tracks: pianoroll = tmp_mul.blend() track = mullib.StandardTrack(pianoroll=pianoroll, program=program, is_drum=is_drum, name=name) new_mul.tracks += [track] self._state = new_mul return self._state
def multitrack_load(path, res): pretty = prelib.PrettyMIDI(path, resolution=res) mul = mullib.from_pretty_midi(pretty, resolution=res) for t in mul.tracks: if t.name == "": if t.is_drum: t.name = "Drums" else: t.name = prelib.program_to_instrument_name(t.program) for i in range(len(mul.tracks)): if not isinstance(mul.tracks[i], mullib.StandardTrack) and not isinstance(mul.tracks[i], mullib.BinaryTrack): mul.tracks[i] = mullib.StandardTrack( pianoroll=mul.tracks[i].pianoroll, name=mul.tracks[i].name, program=mul.tracks[i].program, is_drum=mul.tracks[i].is_drum ) return mul
def save_all_timbre(): for i in range(128): c_chord = pretty_midi.PrettyMIDI() instr = pretty_midi.Instrument(program=i) for j, note_name in enumerate(['C5', 'E5', 'G5']): note_number = pretty_midi.note_name_to_number(note_name) note = pretty_midi.Note(velocity=100, pitch=note_number, start=2, end=2.5) instr.notes.append(note) note = pretty_midi.Note(velocity=100, pitch=note_number, start=j * 0.5, end=(j + 1) * .5) instr.notes.append(note) c_chord.instruments.append(instr) instr_name = pretty_midi.program_to_instrument_name(i) midi_path = f'data/timbre/midi/{i}_{instr_name}.mid' c_chord.write(midi_path) audio_path = f'data/timbre/audio/{i}_{instr_name}.wav' sf2.midi_to_audio(midi_path, audio_path)
import glob import pretty_midi for file in glob.glob("type0/*.mid"): pm = pretty_midi.PrettyMIDI(file) #takes a midi file and converts to pretty_midi instr = pm.instruments #splits into list of instruments for instrument in instr: name = pretty_midi.program_to_instrument_name(instrument.program) #print(name) if name == "Acoustic Grand Piano": #only take the piano track piano_roll = instrument.get_piano_roll() #get the piano roll, which is a np.ndarray print(piano_roll)
def main(): args = parse_args() args.verbose = True # prime file validation if args.prime_file and not os.path.exists(args.prime_file): utils.log( 'Error: prime file {} does not exist. Exiting.'.format( args.prime_file), True) exit(1) else: if not os.path.isdir(args.data_dir): utils.log( 'Error: data dir {} does not exist. Exiting.'.format( args.prime_file), True) exit(1) midi_files = [ args.prime_file ] if args.prime_file else \ [ os.path.join(args.data_dir, f) for f in os.listdir(args.data_dir) \ if '.mid' in f or '.midi' in f ] experiment_dir = get_experiment_dir(args.experiment_dir) utils.log('Using {} as --experiment_dir'.format(experiment_dir), args.verbose) if not args.save_dir: args.save_dir = os.path.join(experiment_dir, 'generated') if not os.path.isdir(args.save_dir): os.makedirs(args.save_dir) utils.log('Created directory {}'.format(args.save_dir), args.verbose) model, epoch = train.get_model(args, experiment_dir=experiment_dir) utils.log( 'Model loaded from {}'.format( os.path.join(experiment_dir, 'model.json')), args.verbose) window_size = model.layers[0].get_input_shape_at(0)[1] seed_generator = utils.get_data_generator(midi_files, window_size=window_size, batch_size=32, num_threads=1, max_files_in_ram=10) # validate midi instrument name try: # try and parse the instrument name as an int instrument_num = int(args.midi_instrument) if not (instrument_num >= 0 and instrument_num <= 127): utils.log('Error: {} is not a supported instrument. Number values must be ' \ 'be 0-127. Exiting'.format(args.midi_instrument), True) exit(1) args.midi_instrument = pretty_midi.program_to_instrument_name( instrument_num) except ValueError as err: # if the instrument name is a string try: # validate that it can be converted to a program number _ = pretty_midi.instrument_name_to_program(args.midi_instrument) except ValueError as er: utils.log('Error: {} is not a valid General MIDI instrument. Exiting.'\ .format(args.midi_instrument), True) exit(1) # generate 10 tracks using random seeds utils.log('Loading seed files...', args.verbose) X, y = next(seed_generator) generated = utils.generate(model, X, window_size, args.file_length, args.num_files, args.midi_instrument) for i, midi in enumerate(generated): file = os.path.join(args.save_dir, '{}.mid'.format(i + 1)) midi.write(file.format(i + 1)) utils.log('wrote midi file to {}'.format(file), True)
def create_sole_inst_label(path, noteLength, shortestLen, label_instrument): info = pm.PrettyMIDI(path) inst = [] if len(info.instruments) == 1: if ("Guitar" in pm.program_to_instrument_name(info.instruments[0].program)): if label_instrument != 'Guitar': for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: inst.append([0]*128 + [1]) i += 1 else: for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: inst.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 elif ("Trumpet" in pm.program_to_instrument_name(info.instruments[0].program)): if label_instrument != 'Trumpet': for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: inst.append([0]*128 + [1]) i += 1 else: for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: inst.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 elif ("Piano" in pm.program_to_instrument_name(info.instruments[0].program)): if label_instrument != 'Piano': for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: inst.append([0]*128 + [1]) i += 1 else: for note in info.instruments[0].notes: i=0 while i*shortestLen < noteLength: inst.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 elif (len(info.instruments) == 2): if label_instrument == 'Guitar': guitar = info.instruments[0].notes i = 0 for note in guitar: i=0 while i*shortestLen < noteLength: inst.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 if label_instrument == 'Trumpet': trumpet = info.instruments[1].notes i = 0 for note in trumpet: i=0 while i*shortestLen < noteLength: inst.append([0]*(note.pitch) + [1] + [0]*(127-note.pitch) + [0]) i += 1 return inst
midi_files_test = [] train_data = [] test_data = [] for file in os.listdir("./../data/beeth_train"): if file.endswith(".mid"): midi_files_train.append(os.path.join("./../data/beeth_train", file)) for item in midi_files_train: midi_data = pretty_midi.PrettyMIDI(item) time = midi_data.get_end_time() midi_data.time_to_tick(time) instrument = midi_data.instruments instrument_notes = [] for instrument in midi_data.instruments: print("Instrument: " + pretty_midi.program_to_instrument_name(instrument.program) + " " + str( instrument.get_piano_roll().shape)) if pretty_midi.program_to_instrument_name(instrument.program) == "Acoustic Grand Piano": train_data.append(instrument.get_piano_roll()) for item in train_data: item = item.transpose() for file in os.listdir("./../data/beeth_test"): if file.endswith(".mid"): midi_files_test.append(os.path.join("./../data/beeth_test", file)) for item in midi_files_test: midi_data = pretty_midi.PrettyMIDI(item) time = midi_data.get_end_time() midi_data.time_to_tick(time)
# plt.title('Audio CQT'); filename = 'chromagrams/test_midi_chromagram_playaround' + '{0:05}'.format( i) + '.png' # fig.savefig(filename,format='png',dpi=1200,bbox_inches='tight',pad_inches=0) # plt.close(fig) #without this line, the code crashed after 62 iterations...with it, closed after 89 print(filename + ' saved') end = time.time() print(str(end - start) + ' seconds to save chromagram') # Retrieve piano roll of one of the instruments piano_roll = pm.instruments[2].get_piano_roll() piano_roll = piano_roll[12:96] fig = plt.figure(figsize=(10, 3)) librosa.display.specshow(piano_roll, y_axis='cqt_note', cmap=plt.cm.hot) # Get the text name of this instrument's program number program_name = pretty_midi.program_to_instrument_name( pm.instruments[2].program) plt.title('Instrument 4 ({}) piano roll'.format(program_name)) #fig.savefig('Instrument_Note_Piano_Roll.png',format='png',dpi=1200) # pretty_midi also provides direct access to the pitch and start/end time of each note intervals = np.array([[note.start, note.end] for note in pm.instruments[2].notes]) notes = np.array([note.pitch for note in pm.instruments[2].notes]) fig = plt.figure(figsize=(10, 3)) mir_eval.display.piano_roll(intervals, midi=notes, facecolor='orange') plt.title('Instrument 4 ({}) piano roll'.format(program_name)) plt.xlabel('Time') plt.ylabel('MIDI note number') #fig.savefig('Instrument_Midi_Piano_Roll.png') ''' Downbeats code. Doesn't work as requires access to audio. ''' '''
def prettyMidiMultiple(): velocity = [] pitch = [] offset = [] duration = [] songlengths = [] BadFiles = 0 GoodFiles = 0 for file in glob.glob("Yuge_Data_Anime2/*.mid"): print("--------------------------------------") print("Parsing %s" % file) print("--------------------------------------") notes = [] notesVar = [] try: pm = pretty_midi.PrettyMIDI(file) GoodFiles += 1 except: print("This file did not work: ", file) BadFiles += 1 continue for i in range(0, len(pm.instruments)): pm.instruments[i].remove_invalid_notes() if pm.instruments[i].program != 0: print( pretty_midi.program_to_instrument_name( pm.instruments[i].program)) print(len(pm.instruments[i].notes)) notes.append(pm.instruments[i].notes) # if len(pm.instruments[i].pitch_bends) > 0: print("Pitch Bends", len(pm.instruments[i].pitch_bends)) # if len(pm.instruments[i].control_changes) > 0: print("Control changes", len(pm.instruments[i].control_changes)) for list in notes: length = 0 for note in list: notesVar.append((note.start, note.get_duration(), note.pitch, note.velocity)) length += 1 notesVar = sorted(notesVar) prevOffset = 0 songlengths.append(length) for note in notesVar: offset.append(round(note[0] - prevOffset, 1)) duration.append(round(note[1], 1)) pitch.append(note[2]) velocity.append(note[3]) prevOffset = note[0] notesVar = [] print("Offset") print(len(offset)) print("Unique Offset", len(set(offset))) print(sorted(set(offset))) print("Duration") print(len(duration)) print("Unique Duration", len(set(duration))) print(sorted(set(duration))) print("Notes") print(len(pitch)) print("Unique Pitches", len(set(pitch))) print("Notes") print(len(velocity)) print("Unique Velocity", len(set(velocity))) print("This many files did work", GoodFiles) print("This many files did not work", BadFiles) print(len(songlengths)) print(songlengths)
def main(): args = parse_args() args.verbose = True # prime file validation if args.prime_file and not os.path.exists(args.prime_file): utils.log( 'Error: prime file {} does not exist. Exiting.'.format( args.prime_file), True) exit(1) else: if not os.path.isdir(args.data_dir): utils.log( 'Error: data dir {} does not exist. Exiting.'.format( args.prime_file), True) exit(1) midi_files = [args.prime_file] if args.prime_file else \ [os.path.join(args.data_dir, f) for f in os.listdir(args.data_dir) \ if '.mid' in f or '.midi' in f] experiment_dir = get_experiment_dir(args.experiment_dir) utils.log('Using {} as --experiment_dir'.format(experiment_dir), args.verbose) if not args.save_dir: args.save_dir = os.path.join(experiment_dir, 'generated') if not os.path.isdir(args.save_dir): os.makedirs(args.save_dir) utils.log('Created directory {}'.format(args.save_dir), args.verbose) if not args.from_checkpoint: model, epoch = train.get_model(args, experiment_dir=experiment_dir) utils.log( 'Model loaded from {}'.format( os.path.join(experiment_dir, 'model.json')), args.verbose) else: # Load from checkpoint with open(os.path.join(experiment_dir, 'model.json'), 'r') as f: model = utils.model_from_json(f.read()) epoch = int(args.from_checkpoint) newest_checkpoint = os.path.join( experiment_dir, f"checkpoints/checkpoint-epoch_{args.from_checkpoint}.hdf5") utils.load_checkpoint(model, newest_checkpoint) utils.log('Model loaded from checkpoint {}'.format(newest_checkpoint), args.verbose) window_size = model.layers[0].get_input_shape_at(0)[1] seed_generator = utils.get_data_generator( midi_files, window_size=window_size, batch_size=32, num_threads=1, use_instrument=args.use_instrument, ignore_empty=args.ignore_empty, encode_section=args.encode_section, max_files_in_ram=10) # validate midi instrument name try: # try and parse the instrument name as an int instrument_num = int(args.midi_instrument) if not (instrument_num >= 0 and instrument_num <= 127): utils.log('Error: {} is not a supported instrument. Number values must be ' \ 'be 0-127. Exiting'.format(args.midi_instrument), True) exit(1) args.midi_instrument = pretty_midi.program_to_instrument_name( instrument_num) except ValueError as err: # if the instrument name is a string try: # validate that it can be converted to a program number _ = pretty_midi.instrument_name_to_program(args.midi_instrument) except ValueError as er: utils.log('Error: {} is not a valid General MIDI instrument. Exiting.' \ .format(args.midi_instrument), True) exit(1) if args.multi_instruments: if not args.prime_file: utils.log( 'Error: You need to specify a prime file when generating a multi instrument track. Exiting.', True) exit(1) utils.log(f"Sampling from single seed file: {args.prime_file}", args.verbose) generated_midi = pretty_midi.PrettyMIDI(initial_tempo=80) source_midi = utils.parse_midi(args.prime_file) melody_instruments = source_midi.instruments # melody_instruments = utils.filter_monophonic(source_midi.instruments, 1.0) for instrument in melody_instruments: instrument_group = utils.get_family_id_by_instrument_normalized( instrument.program) # Get source track seed X, y = [], [] windows = utils._encode_sliding_windows(instrument, window_size) for w in windows: if np.min(w[0][:, 0]) == 1: # Window only contains pauses.. ignore! continue X.append(w[0]) if len(X) <= 5: continue seed = X[random.randint(0, len(X) - 1)] # Generate track for this instrument generated = [] buf = np.copy(seed).tolist() while len(generated) < args.file_length: buf_expanded = [x for x in buf] # Add instrument class to input if args.use_instrument: buf_expanded = [[instrument_group] + x for x in buf_expanded] # Add section encoding to input if args.encode_section: sections = [0] * 4 active_section = int( (len(generated) / args.file_length) * 4) sections[active_section] = 1 buf_expanded = [sections + x for x in buf_expanded] # Get prediction arr = np.expand_dims(np.asarray(buf_expanded), 0) pred = model.predict(arr) # prob distribution sampling index = np.random.choice(range(0, seed.shape[1]), p=pred[0]) pred = np.zeros(seed.shape[1]) pred[index] = 1 generated.append(pred) buf.pop(0) buf.append(pred.tolist()) # Create instrument instrument = utils._network_output_to_instrument( generated, instrument.program) # Add to target midi generated_midi.instruments.append(instrument) if len(generated_midi.instruments) == 0: raise Exception( f"Found no monophonic instruments in {args.prime_file}") # Save midi time = datetime.now().strftime("%Y%m%d%H%M%S") sample_name = f"{args.save_dir}/sampled_{time}.mid" print(f"Writing generated sample to {sample_name}") generated_midi.write(sample_name) else: # generate 10 tracks using random seeds utils.log('Loading seed files...', args.verbose) X, y = next(seed_generator) generated = utils.generate(model, X, window_size, args.file_length, args.num_files, args.midi_instrument, use_instrument=args.use_instrument, encode_section=args.encode_section) for i, midi in enumerate(generated): file = os.path.join( args.save_dir, f"{i+1}_instrument{midi.instruments[0].program}.mid") midi.write(file.format(i + 1)) utils.log('wrote midi file to {}'.format(file), True)
train_data = [] test_data = [] for file in os.listdir("./../data/beeth_train"): if file.endswith(".mid"): midi_files_train.append(os.path.join("./../data/beeth_train", file)) for item in midi_files_train: midi_data = pretty_midi.PrettyMIDI(item) time = midi_data.get_end_time() midi_data.time_to_tick(time) instrument = midi_data.instruments instrument_notes = [] for instrument in midi_data.instruments: print("Instrument: " + pretty_midi.program_to_instrument_name(instrument.program) + " " + str(instrument.get_piano_roll().shape)) if pretty_midi.program_to_instrument_name( instrument.program) == "Acoustic Grand Piano": train_data.append(instrument.get_piano_roll()) for file in os.listdir("./../data/beeth_test"): if file.endswith(".mid"): midi_files_test.append(os.path.join("./../data/beeth_test", file)) for item in midi_files_test: midi_data = pretty_midi.PrettyMIDI(item) time = midi_data.get_end_time() midi_data.time_to_tick(time) instrument = midi_data.instruments instrument_notes = []
def instrument_to_option(idx, instrument): label = "{} - {} ({})".format(idx, pretty_midi.program_to_instrument_name(instrument.program), instrument.program) return dict(label=label, value=idx)
mid = MidiFile(sys.argv[1]) new_mid = MidiFile() tracks_metadata = [] for t in mid.tracks: tracks_metadata.append( (program_of_track(t), len(t), max_velocity_of_track(t), min_note_of_track(t), range_of_track(t), bass_penalty(t))) t = np.array(tracks_metadata).astype('float32') # print(t) # t[:, 0] = np.exp(t[:, 0] / t[:, 0].max()) # t = t / t.sum(axis=0) res = t[:, 2] * t[:, 4] * t[:, 5] # print(t) # print(t[:, 0]) print(res) index = np.argmax(res) program = int(t[index, 0]) if program != -1: chosen_instrument = pretty_midi.program_to_instrument_name(program) else: chosen_instrument = 'Unknown (Probabily Piano)' print("Chose index {} ({} - {}) for {}".format(index, program, chosen_instrument, sys.argv[1])) new_mid.tracks.append(mid.tracks[index]) new_mid.ticks_per_beat = mid.ticks_per_beat new_mid.save(sys.argv[1] + '.mono')
def get_notes_multiple(): """ Get all the notes and chords from the midi files in the ./midi_songs directory """ velocity = [] pitch = [] offset = [] duration = [] songlengths = [] BadFiles = 0 GoodFiles = 0 for file in glob.glob("Yuge_Data_Anime2/*.mid"): print("--------------------------------------") print("Parsing %s" % file) print("--------------------------------------") notes = [] notesVar = [] try: pm = pretty_midi.PrettyMIDI(file) GoodFiles += 1 except: print("This file did not work: ", file) BadFiles += 1 continue for i in range(0, len(pm.instruments)): pm.instruments[i].remove_invalid_notes() if pm.instruments[i].program != 0: print(pretty_midi.program_to_instrument_name(pm.instruments[i].program)) print(len(pm.instruments[i].notes)) notes.append(pm.instruments[i].notes) if len(pm.instruments[i].pitch_bends) > 0: print("Pitch Bends", len(pm.instruments[i].pitch_bends)) if len(pm.instruments[i].control_changes) > 0: print("Control changes", len(pm.instruments[i].control_changes)) for list in notes: length = 0 for note in list: notesVar.append((note.start, note.get_duration(), note.pitch, note.velocity)) length += 1 notesVar = sorted(notesVar) prevOffset = 0 songlengths.append(length) for note in notesVar: offset.append(round(note[0] - prevOffset, 1)) duration.append(round(note[1], 1)) pitch.append(note[2]) velocity.append(note[3]) prevOffset = note[0] notesVar = [] # print("Offset") # print(len(offset)) # print("Unique Offset", len(set(offset))) # print(sorted(set(offset))) # print("Duration") # print(len(duration)) # print("Unique Duration", len(set(duration))) # print(sorted(set(duration))) # print("Notes") # print(len(pitch)) # print("Unique Pitches", len(set(pitch))) # print("Notes") # print(len(velocity)) # print("Unique Velocity", len(set(velocity))) # print("This many files did work", GoodFiles) # print("This many files did not work", BadFiles) # print(len(songlengths)) # print(songlengths) with open('data/pitch', 'wb') as filepath: pickle.dump(pitch, filepath) with open('data/offset', 'wb') as filepath: pickle.dump(offset, filepath) with open('data/duration', 'wb') as filepath: pickle.dump(duration, filepath) with open('data/velocity', 'wb') as filepath: pickle.dump(velocity, filepath) with open('data/songlengths', 'wb') as filepath: pickle.dump(songlengths, filepath) return pitch, velocity, offset, duration, songlengths
import pretty_midi import matplotlib.pyplot as plt title = 'evans' midi_data = pretty_midi.PrettyMIDI(title + '.mid') instrument_name = 'Distortion Guitar' instruments = midi_data.instruments dg = pretty_midi.PrettyMIDI() for instrument in instruments: if pretty_midi.program_to_instrument_name( instrument.program).__eq__(instrument_name): dg.instruments.append(instrument) print(dg.instruments[0].notes) dg_pitch_list = [] for note in dg.instruments[0].notes: dg_pitch_list.append(note.pitch) print(dg_pitch_list) def pitchToNote(pitch): picth_mod = (pitch + 4) % 12 pitch_div = (pitch + 4) // 12
beats = pm.get_beats(start_time=first_ts_after_0) # .. downbeats, too downbeats = pm.get_downbeats(start_time=first_ts_after_0) #Process 8 bar sections for each instrument. for instrument_channel in range(len(pm.instruments)): # Retrieve piano roll of one of the instruments. Defined in 16th beats piano_roll = pm.instruments[instrument_channel].get_piano_roll( fs=4 / (beats[1] - beats[0])) #beats is seconds. Input is frequency. # Use 7 octaves starting from C1 #piano_roll = piano_roll[12:96] # Get instrument name program_name = pretty_midi.program_to_instrument_name( pm.instruments[instrument_channel].program) #Skip instrument if drum. if pm.instruments[instrument_channel].is_drum: continue # pretty_midi also provides direct access to the pitch and start/end time of each note intervals = np.array( [[note.start, note.end] for note in pm.instruments[instrument_channel].notes]) notes = np.array( [note.pitch for note in pm.instruments[instrument_channel].notes]) # Get key data for each MIDI file. for key_change in pm.key_signature_changes: # print('Key {} starting at time {:.2f}'.format( # pretty_midi.key_number_to_key_name(key_change.key_number), key_change.time))