def save_midi(self, midi_file_path, onehot_mat, ticksPerQuarterNote=1024): """ :param midi_file_path: path to save midi file which is made after predicting :param onehot_mat: matrix having notes infomation made after predicting :param ticksPerQuarterNote: criterion of note`s length(duration) :return: """ # tick step = 8th note, quaver tick_step = ticksPerQuarterNote / 2 # extract note info from one-hot matrix result = [] for i in range(onehot_mat.shape[0]): for j in range(onehot_mat.shape[1]): # if flow is started with new note info, then add new info to result list if i == 0: if onehot_mat[i, j] == 1: result.append({'time': i * tick_step, 'note': j}) else: if onehot_mat[i, j] == 1 and onehot_mat[i - 1, j] == 0: result.append({'time': i * tick_step, 'note': j}) # manufacture result list with unroll package`s Keystrike ks = KeyStrikes(result) # convert ks to have duration ks = ks.quantized(ticksPerQuarterNote) # convert ks to music21`s stream s = ks._to_music21stream() # convert s to midi format, again T^T mf = music21.midi.translate.streamToMidiFile(s) # save mf info with file mf.open(midi_file_path, 'wb') mf.write() mf.close() print '\tMidi file(=%s) successfully saved. Total 1/8 beats = %d' % ( midi_file_path, onehot_mat.shape[0])
def save_midi(self, midi_file_path, onehot_mat, ticksPerQuarterNote=1024): """ :param midi_file_path: predict 후 만들어진 midi file 을 저장할 path :param onehot_mat: predict 결과 만들어진 notes 정보를 가진 matrix :param ticksPerQuarterNote: note 의 길이 기준 :return: """ # 틱 간격은 8분의 1음표 단위로 tick_step = ticksPerQuarterNote / 2 # onehot matrix에서 note 정보 추출. result = [] for i in range(onehot_mat.shape[0]): for j in range(onehot_mat.shape[1]): # 새로운 노트가 시작될 경우에 리스트에 추가. if i == 0: if onehot_mat[i, j] == 1: result.append({'time': i * tick_step, 'note': j}) else: if onehot_mat[i, j] == 1 and onehot_mat[i - 1, j] == 0: result.append({'time': i * tick_step, 'note': j}) # unroll 패키지의 Keystrike를 이용해서 가공. ks = KeyStrikes(result) # 리스트 형태를 duration 을 가지도록 변환. ks = ks.quantized(ticksPerQuarterNote) # music21 스트림으로 변환. s = ks._to_music21stream() # 다시 midi 파일 형식으로 변환. ( ㅠ.ㅠ ) mf = music21.midi.translate.streamToMidiFile(s) # 파일로 저장. mf.open(midi_file_path, 'wb') mf.write() mf.close() print '\tMidi file(=%s) successfully saved. Total 1/8 beats = %d' % (midi_file_path, onehot_mat.shape[0])
def save_midi(self, midi_file_path, onehot_mat, ticksPerQuarterNote=1024): """ :param midi_file_path: path to save midi file which is made after predicting :param onehot_mat: matrix having notes infomation made after predicting :param ticksPerQuarterNote: criterion of note`s length(duration) :return: """ # tick step = 8th note, quaver tick_step = ticksPerQuarterNote / 2 # extract note info from one-hot matrix result = [] for i in range(onehot_mat.shape[0]): for j in range(onehot_mat.shape[1]): # if flow is started with new note info, then add new info to result list if i == 0: if onehot_mat[i, j] == 1: result.append({'time': i * tick_step, 'note': j}) else: if onehot_mat[i, j] == 1 and onehot_mat[i - 1, j] == 0: result.append({'time': i * tick_step, 'note': j}) # manufacture result list with unroll package`s Keystrike ks = KeyStrikes(result) # convert ks to have duration ks = ks.quantized(ticksPerQuarterNote) # convert ks to music21`s stream s = ks._to_music21stream() # convert s to midi format, again T^T mf = music21.midi.translate.streamToMidiFile(s) # save mf info with file mf.open(midi_file_path, 'wb') mf.write() mf.close() print '\tMidi file(=%s) successfully saved. Total 1/8 beats = %d' % (midi_file_path, onehot_mat.shape[0])
def load_midi(self, path_data, filename, get_longest_length=False): """ . :param path_data: midi files 가 저장되어있는 path :param filename: midi file name :param get_longest_length: longest play time 을 가진 파일의 길이만 받을지 말지. :return: """ # read midi file mf = music21.midi.MidiFile() path_midifile = path_data + '/' + filename mf.open(path_midifile) mf.read() mf.close() # midi -> music21 stream -> midi # mf 파일의 ticksperQuarterNote 를 1024 기준으로 바꿔주기 s = music21.midi.translate.midiFileToStream(mf) mf = music21.midi.translate.streamToMidiFile(s) # # 트랙별 루프 돌면서 note 정보 읽기 # # 트랙별 event 의 구조는 다음과 같다. # <MidiTrack 1 -- 1092 events # <MidiEvent DeltaTime, t=0, track=1, channel=1> # ..... # <MidiEvent TIME_SIGNATURE, t=0, track=1, channel=1, data='\x04\x02\x18\x08'> # <MidiEvent DeltaTime, t=0, track=1, channel=1> # <MidiEvent NOTE_ON, t=0, track=1, channel=1, pitch=76, velocity=105> # <MidiEvent DeltaTime, t=512, track=1, channel=1> # <MidiEvent NOTE_OFF, t=0, track=1, channel=1, pitch=76, velocity=0> # result = [] for i in range(len(mf.tracks)): t = 0 for e in mf.tracks[i].events: if e.isDeltaTime() and e.time is not None: t += e.time elif e.isNoteOn() and e.pitch is not None and e.velocity != 0: result.append({'time': t, 'note': e.pitch}) # unroll.KeyStrikes 이용 ks = KeyStrikes(result) # duration 가지도록 list 변환 ks = ks.quantized(mf.ticksPerQuarterNote) # 가장 sequence 가 긴 파일의 sequence 를 알고 싶을 때 # get_longest_length = True 로 setting 해주면 가장 긴 sequence 와 # mf.ticksPerQuarterNote 만 반환. if get_longest_length: return ks, mf.ticksPerQuarterNote # # one-hot vector 형식으로 변환 # # tick 간격 = 1/8분 음표 단위로 self.tick_step = mf.ticksPerQuarterNote / 2 # 총 틱 카운트 total_tick = ks.keystrikes[-1]['time'] + ks.keystrikes[-1]['duration'] * mf.ticksPerQuarterNote # 총 sequence 갯수 total_beat = total_tick / self.tick_step # 하나의 midi 파일의 one hot vector 를 저장할 임시 matrix one_X_train = np.zeros((total_beat + 1, self.data_dim), dtype='int32') # 1024 기준으로 convert 된 건반 정보를 루프를 돌면서 디코딩 for strike in ks.keystrikes: # 1/8 음표 단위의 index idx = strike['time'] / self.tick_step # 1/8 음표 단위 기준 note 의 지속시간 (index 를 몇개 채울거니? 를 계산) dur = int(strike['duration'] * 2) # note 별로 one-hot vector 채우기 for note in strike['note']: # 지속시간 만큼 making for i in range(dur): one_X_train[idx + i, note] = 1 # 끝에 EOS 추가 = EOS 는 data_dim[-1] = 1 인 경우. one_X_train[-1, self.note_dim] = 1 print '\tMidi file(=%s) successfully loaded. Total 1/8 beats = %d' % (path_midifile, total_beat) return one_X_train
def load_midi(self, path_data, filename, get_longest_length=False): """ . :param path_data: path including midi files :param filename: midi file name :param get_longest_length: Flag to get only the length of files having longest play time, or not :return: """ # read midi file mf = music21.midi.MidiFile() path_midifile = path_data + '/' + filename mf.open(path_midifile) mf.read() mf.close() # midi -> music21 stream -> midi # change criterion of ticksperQuarterNote of mf s = music21.midi.translate.midiFileToStream(mf) mf = music21.midi.translate.streamToMidiFile(s) # # get notes infomation while loop tracks # # track`s event structure # <MidiTrack 1 -- 1092 events # <MidiEvent DeltaTime, t=0, track=1, channel=1> # ..... # <MidiEvent TIME_SIGNATURE, t=0, track=1, channel=1, data='\x04\x02\x18\x08'> # <MidiEvent DeltaTime, t=0, track=1, channel=1> # <MidiEvent NOTE_ON, t=0, track=1, channel=1, pitch=76, velocity=105> # <MidiEvent DeltaTime, t=512, track=1, channel=1> # <MidiEvent NOTE_OFF, t=0, track=1, channel=1, pitch=76, velocity=0> # result = [] for i in range(len(mf.tracks)): t = 0 for e in mf.tracks[i].events: if e.isDeltaTime() and e.time is not None: t += e.time elif e.isNoteOn() and e.pitch is not None and e.velocity != 0: result.append({'time': t, 'note': e.pitch}) # use unroll.KeyStrikes ks = KeyStrikes(result) # convert list to have duration ks = ks.quantized(mf.ticksPerQuarterNote) # use If u wanna know the sequence length of file having longest play time, # set get_longest_length = True, then this function will return # the longest sequence length and mf.ticksPerQuarterNote 만 반환. if get_longest_length: return ks, mf.ticksPerQuarterNote # # conver one-hot vector format # # tick step = 8th note, quaver self.tick_step = mf.ticksPerQuarterNote / 2 # total tick count total_tick = ks.keystrikes[-1][ 'time'] + ks.keystrikes[-1]['duration'] * mf.ticksPerQuarterNote # total sequence number total_beat = total_tick / self.tick_step # temporary matrix to save one hot vector of one midi file one_X_train = np.zeros((total_beat + 1, self.data_dim), dtype='int32') # decoding the notes info while loop with having 1024 criterion for strike in ks.keystrikes: # index, criterion = 8th note(quaver) idx = strike['time'] / self.tick_step # during time of note, criterion = 8th note(quaver), calculate how many indices will be filled dur = int(strike['duration'] * 2) # set one-hot vector by note for note in strike['note']: # set 1 to index as many as duration of note for i in range(dur): one_X_train[idx + i, note] = 1 # add EOS at end of sequence, EOS is case that data_dim[-1] = 1 one_X_train[-1, self.note_dim] = 1 print '\tMidi file(=%s) successfully loaded. Total 1/8 beats = %d' % ( path_midifile, total_beat) return one_X_train
def load_midi(self, path_data, filename, get_longest_length=False): """ . :param path_data: path including midi files :param filename: midi file name :param get_longest_length: Flag to get only the length of files having longest play time, or not :return: """ # read midi file mf = music21.midi.MidiFile() path_midifile = path_data + '/' + filename mf.open(path_midifile) mf.read() mf.close() # midi -> music21 stream -> midi # change criterion of ticksperQuarterNote of mf s = music21.midi.translate.midiFileToStream(mf) mf = music21.midi.translate.streamToMidiFile(s) # # get notes infomation while loop tracks # # track`s event structure # <MidiTrack 1 -- 1092 events # <MidiEvent DeltaTime, t=0, track=1, channel=1> # ..... # <MidiEvent TIME_SIGNATURE, t=0, track=1, channel=1, data='\x04\x02\x18\x08'> # <MidiEvent DeltaTime, t=0, track=1, channel=1> # <MidiEvent NOTE_ON, t=0, track=1, channel=1, pitch=76, velocity=105> # <MidiEvent DeltaTime, t=512, track=1, channel=1> # <MidiEvent NOTE_OFF, t=0, track=1, channel=1, pitch=76, velocity=0> # result = [] for i in range(len(mf.tracks)): t = 0 for e in mf.tracks[i].events: if e.isDeltaTime() and e.time is not None: t += e.time elif e.isNoteOn() and e.pitch is not None and e.velocity != 0: result.append({'time': t, 'note': e.pitch}) # use unroll.KeyStrikes ks = KeyStrikes(result) # convert list to have duration ks = ks.quantized(mf.ticksPerQuarterNote) # use If u wanna know the sequence length of file having longest play time, # set get_longest_length = True, then this function will return # the longest sequence length and mf.ticksPerQuarterNote 만 반환. if get_longest_length: return ks, mf.ticksPerQuarterNote # # conver one-hot vector format # # tick step = 8th note, quaver self.tick_step = mf.ticksPerQuarterNote / 2 # total tick count total_tick = ks.keystrikes[-1]['time'] + ks.keystrikes[-1]['duration'] * mf.ticksPerQuarterNote # total sequence number total_beat = total_tick / self.tick_step # temporary matrix to save one hot vector of one midi file one_X_train = np.zeros((total_beat + 1, self.data_dim), dtype='int32') # decoding the notes info while loop with having 1024 criterion for strike in ks.keystrikes: # index, criterion = 8th note(quaver) idx = strike['time'] / self.tick_step # during time of note, criterion = 8th note(quaver), calculate how many indices will be filled dur = int(strike['duration'] * 2) # set one-hot vector by note for note in strike['note']: # set 1 to index as many as duration of note for i in range(dur): one_X_train[idx + i, note] = 1 # add EOS at end of sequence, EOS is case that data_dim[-1] = 1 one_X_train[-1, self.note_dim] = 1 print '\tMidi file(=%s) successfully loaded. Total 1/8 beats = %d' % (path_midifile, total_beat) return one_X_train