def align_tracks(pr0, pr1, unit_type, gapopen, gapextend): # Get trace from needleman_wunsch algorithm # First extract binary representation, whatever unit_type is pr0_trace = sum_along_instru_dim( Unit_type.from_type_to_binary(pr0, unit_type)) pr1_trace = sum_along_instru_dim( Unit_type.from_type_to_binary(pr1, unit_type)) # Traces are computed from binaries matrices # Traces are binary lists, 0 meaning a gap is inserted trace_0, trace_1, this_sum_score, this_nbId, this_nbDiffs = needleman_chord_wrapper( pr0_trace, pr1_trace, gapopen, gapextend) #################################### # Wrap dictionnaries according to the traces assert (len(trace_0) == len(trace_1)), "size mismatch" pr0_warp = warp_dictionnary_trace(pr0, trace_0) pr1_warp = warp_dictionnary_trace(pr1, trace_1) #################################### # Trace product trace_prod = [e1 * e2 for (e1, e2) in zip(trace_0, trace_1)] duration = sum(trace_prod) if duration == 0: return [None] * 5 # Remove gaps pr0_aligned = remove_zero_in_trace(pr0_warp, trace_prod) pr1_aligned = remove_zero_in_trace(pr1_warp, trace_prod) return pr0_aligned, trace_0, pr1_aligned, trace_1, trace_prod, duration
def remove_match_silence(pr0, pr1): # Detect problems flat_0 = sum_along_instru_dim(pr0).sum(axis=1) flat_1 = sum_along_instru_dim(pr1).sum(axis=1) ind_clean = np.where(np.logical_not((flat_0 == 0) & (flat_1 == 0)))[0] def keep_clean(pr, ind_clean): pr_out = {} for k, v in pr.iteritems(): pr_out[k] = v[ind_clean] return pr_out pr0_clean = keep_clean(pr0, ind_clean) pr1_clean = keep_clean(pr1, ind_clean) duration = len(ind_clean) return pr0_clean, pr1_clean, duration
def file_processing(path, quantization, clip): if re.search(r'.*\.mid$', path): reader_midi = Read_midi(path, quantization) # Read midi pianoroll = reader_midi.read_file() elif re.search(r'.*\.xml$', path): pianoroll, articulation, staccato_curve = mxml_to_pr( path, quantization) pr = sum_along_instru_dim(pianoroll) arti = sum_along_instru_dim(articulation) stacc = sum_along_instru_dim(staccato_curve) else: raise Exception("invalid extension {}, use either mid or xml") # Clip if clip: pianoroll = clip_pr(pianoroll) return pianoroll, get_pianoroll_time(pianoroll)
def visualize_dict(pr, path, file_name_no_extension, time_indices=None): if not os.path.exists(path): os.makedirs(path) AAA = sum_along_instru_dim(pr) if time_indices: start_time, end_time = time_indices AAA = AAA[start_time:end_time, :] temp_csv = path + '/' + file_name_no_extension + '.csv' np.savetxt(temp_csv, AAA, delimiter=',') dump_to_csv(temp_csv, temp_csv) write_numpy_array_html( path + '/' + file_name_no_extension + ".html", file_name_no_extension, d3js_source_path= '/Users/leo/Recherche/GitHub_Aciditeam/acidano/acidano/visualization/d3.v3.min.js' )
def remove_silence(pr): # Detect silences flat = sum_along_instru_dim(pr).sum(axis=1) ind_clean = np.where(np.logical_not(flat == 0))[0] def keep_clean(pr, ind_clean): pr_out = {} for k, v in pr.iteritems(): pr_out[k] = v[ind_clean] return pr_out pr_clean = keep_clean(pr, ind_clean) mapping = np.zeros((flat.shape[0]), dtype=np.int) - 1 counter = 0 for elem in ind_clean: mapping[elem] = counter counter += 1 return pr_clean, mapping
def process_folder_NP(folder_path, quantization, binary_piano, binary_orch, temporal_granularity): """Get the pianoroll from a folder path with containing only an orchestral score. Piano score is created by simply crushing all the instruments on 88 pitches """ # Get instrus and prs from a folder name name pr_orch, instru_orch, T, name = get_instru_and_pr_from_folder_path_NP( folder_path, quantization) # Create the piano score pr_piano = {'Piano': sum_along_instru_dim(pr_orch)} # Process the two files (remember that even in this context, piano can be real-valued and orchestra discrete) pr_piano = process_data_piano(pr_piano, binary_piano) pr_orch = process_data_orch(pr_orch, binary_orch) # Temporal granularity (use only orchestra to compute events) if temporal_granularity == 'event_level': event_orch = get_event_ind_dict(pr_orch) T = len(event_orch) def get_duration(event, last_time): start_ind = event[:] end_ind = np.zeros(event.shape, dtype=np.int) end_ind[:-1] = event[1:] end_ind[-1] = last_time duration_list = end_ind - start_ind return duration_list duration_orch = get_duration(event_orch, T) # Get the duration of each event pr_orch = warp_pr_aux(pr_orch, event_orch) pr_piano = warp_pr_aux(pr_piano, event_orch) else: event_orch = None # Fill identical values event_piano = event_orch duration_piano = duration_orch instru_piano = {'Piano': 'Piano'} name_piano = name return pr_piano, event_piano, duration_piano, instru_piano, name_piano, pr_orch, event_orch, duration_orch, instru_orch, name, T
def get_number_of_file_per_composer(files): dict_orch = {} dict_piano = {} T_orch = 0 T_piano = 0 for file in files: with open(file, 'rb') as csvfile: spamreader = csv.DictReader(csvfile, delimiter=';', fieldnames=[ "id", "path", "orch_composer", "orch_song", "orch_audio_path", "solo_composer", "solo_song", "solo_audio_path" ]) # Avoid header spamreader.next() for row in spamreader: # Name and path orch_composer = row['orch_composer'] piano_composer = row['solo_composer'] path = DATABASE_PATH + '/' + row['path'] # Get instrus and prs from a folder name name pr0, instru0, T0, name0, pr1, instru1, T1, name1 = get_instru_and_pr_from_folder_path( folder_path, quantization) pr_piano, _, _, _, pr_orch, _, _, _=\ discriminate_between_piano_and_orchestra(pr0, instru0, T0, name0, pr1, instru1, T1, name1) if (pr_piano == None) or (pr_orch == None): print("Skipping " + path) continue try: length_piano = len(sum_along_instru_dim(pr_piano)) length_orch = len(sum_along_instru_dim(pr_orch)) except: import pdb pdb.set_trace() if orch_composer in dict_orch.keys(): dict_orch[orch_composer]['num_file'] += 1 dict_orch[orch_composer]['relative_length'] += length_orch else: dict_orch[orch_composer] = {} dict_orch[orch_composer]['num_file'] = 1 dict_orch[orch_composer]['relative_length'] = length_orch T_orch += length_orch if piano_composer in dict_piano.keys(): dict_piano[piano_composer]['num_file'] += 1 dict_piano[piano_composer][ 'relative_length'] += length_piano else: dict_piano[piano_composer] = {} dict_piano[piano_composer]['num_file'] = 1 dict_piano[piano_composer][ 'relative_length'] = length_piano T_piano += length_piano for k, v in dict_orch.iteritems(): dict_orch[k]['relative_length'] = ( 100 * dict_orch[k]['relative_length'] + 0.) / T_orch for k, v in dict_piano.iteritems(): dict_piano[k]['relative_length'] = ( 100 * dict_piano[k]['relative_length'] + 0.) / T_piano # Merge the two dictionnaries merge_dict = {} for k, v in dict_piano.iteritems(): merge_dict[k] = { 'relative_length_piano': v['relative_length'], 'relative_length_orch': None, 'num_file_piano': v['num_file'], 'num_file_orch': None, } for k, v in dict_orch.iteritems(): if k in merge_dict.keys(): merge_dict[k]['relative_length_orch'] = v['relative_length'] merge_dict[k]['num_file_orch'] = v['num_file'] else: merge_dict[k] = { 'relative_length_piano': None, 'relative_length_orch': v['relative_length'], 'num_file_piano': None, 'num_file_orch': v['num_file'], } # Replace '' by unknown merge_dict['unknown'] = merge_dict.pop('', None) merge_dict_name = {} for k, v in merge_dict.iteritems(): name_list = re.split(' ', k) new_name = name_list[-1] + '. ' + ' '.join(name_list[:-1]) merge_dict_name[new_name] = v merge_dict = merge_dict_name # write a csv file containing these information def float_to_string(s): return '' if s is None else "{:2.2f}".format(s) def format_none(s): return '' if s is None else "{}".format(s) with open('stat_composer.csv', 'wb') as f: f.write("composer,numpiano,percentagepiano,numorch,percentageorch\n") for k, v in sorted(merge_dict.items()): # f.write("{};{};{:2.2f};{};{:2.2f}".format(k, v['num_file_piano'], v['relative_length_piano'], v['num_file_orch'], v['relative_length_orch'])) f.write("{},{},{},{},{}\n".format( format_none(k).title(), format_none(v['num_file_piano']), float_to_string(v['relative_length_piano']), format_none(v['num_file_orch']), float_to_string(v['relative_length_orch']))) # barplot fig, ax = plt.subplots() width = 0.35 x = [] y = [] for k, v in merge_dict.iteritems(): if v['relative_length_orch']: x.append(k[:3]) y.append(v['relative_length_orch']) ind = range(len(y)) barplot = ax.bar(ind, y, width, alpha=0.7, color='b') ax.set_title('Representativeness of composers in the database', fontsize=14, fontweight='bold') ax.set_xlabel('Composers') ax.set_ylabel('Ratio of frame occurences per composer') ax.set_xticks([e + width / 2 for e in ind]) ax.set_xticklabels(x) plt.savefig('ratio_composer.pdf') return
def process_folder(folder_path, quantization, binary_piano, binary_orch, temporal_granularity, gapopen=3, gapextend=1, align_bool=True): ############################## # Get instrus and prs from a folder name name pr0, articulation_0, staccato_0, T0, name0, pr1, articulation_1, staccato_1, T1, name1 = get_instru_and_pr_from_folder_path(folder_path, quantization) data_0 = (pr0, articulation_0, staccato_0, T0, name0) data_1 = (pr1, articulation_1, staccato_1, T1, name1) (pr_piano_X, articulation_piano, staccato_piano, T_piano, name_piano), \ (pr_orch, articulation_orch, staccato_orch, T_orch, name_orch)=\ discriminate_between_piano_and_orchestra(data_0, data_1) # if pr_contrabass[:, 62:].sum() > 1: # import pdb; pdb.set_trace() # If corrupted files, pr_piano (and pr_orch) will be None if pr_piano_X is None: return [None] * 9 # Remove from orch if "Remove" in pr_orch.keys(): pr_orch.pop("Remove") # Group in piano pr_piano = {'Piano': sum_along_instru_dim(pr_piano_X)} # try: # write_midi(pr_piano, ticks_per_beat=quantization, write_path="../DEBUG/test_piano.mid", articulation=articulation_piano) # write_midi(pr_orch, ticks_per_beat=quantization, write_path="../DEBUG/test_orch.mid", articulation=articulation_orch) # write_midi({k: v*90 for k,v in pr_piano.items()}, ticks_per_beat=quantization, write_path="../DEBUG/test_piano.mid", articulation=articulation_piano) # write_midi({k: v*90 for k,v in pr_orch.items() if (v.sum()>0)}, ticks_per_beat=quantization, write_path="../DEBUG/test_orch.mid", articulation=articulation_orch) # except: # print("Because of mixed instru cannot write reference") ############################## # Process pr (mostly binarized) pr_piano = process_data_piano(pr_piano, binary_piano) pr_orch = process_data_orch(pr_orch, binary_orch) # Temporal granularity if temporal_granularity == 'event_level': event_piano = get_event_ind_dict(articulation_piano, pr_piano) event_orch = get_event_ind_dict(articulation_orch, pr_orch) def get_duration(event, last_time): start_ind = event[:] end_ind = np.zeros(event.shape, dtype=np.int) end_ind[:-1] = event[1:] end_ind[-1] = last_time duration_list = end_ind - start_ind return duration_list duration_piano = get_duration(event_piano, T_piano) duration_orch = get_duration(event_orch, T_orch) # Get the duration of each event pr_piano_event = warp_pr_aux(pr_piano, event_piano) pr_orch_event = warp_pr_aux(pr_orch, event_orch) else: event_piano = None event_orch = None duration_piano = None duration_orch = None pr_piano_event = pr_piano pr_orch_event = pr_orch ############################## ############################## # # Test for event-leve -> beat reconstruction # ############################## # # Instru mapping # import pickle as pkl # import LOP_database.utils.event_level as event_level # import LOP_database.utils.reconstruct_pr as reconstruct_pr # temp = pkl.load(open("/Users/crestel/Recherche/lop/LOP/Data/Data_A_ref_bp_bo_noEmb_tempGran32/temp.pkl", 'rb')) # instru_mapping = temp['instru_mapping'] # N_orchestra = temp['N_orchestra'] # N_piano = temp['instru_mapping']['Piano']['index_max'] # matrix_orch = cast_small_pr_into_big_pr(pr_orch_event, 0, len(event_orch), instru_mapping, np.zeros((len(event_orch), N_orchestra))) # matrix_piano = cast_small_pr_into_big_pr(pr_piano_event, 0, len(event_piano), instru_mapping, np.zeros((len(event_piano), N_piano))) # ############################## # # Reconstruct rhythm # pr_orchestra_rhythm = event_level.from_event_to_frame(matrix_orch, event_orch) # pr_orchestra_rhythm_I = reconstruct_pr.instrument_reconstruction(pr_orchestra_rhythm, instru_mapping) # pr_piano_rhythm = event_level.from_event_to_frame(matrix_piano, event_piano) # pr_piano_rhythm_I = reconstruct_pr.instrument_reconstruction_piano(pr_piano_rhythm, instru_mapping) # ############################## # # Write midi # write_midi({k: v*90 for k,v in pr_piano_rhythm_I.items()}, ticks_per_beat=quantization, write_path="../DEBUG/test_piano_event.mid", articulation=articulation_piano) # write_midi({k: v*90 for k,v in pr_orchestra_rhythm_I.items() if (v.sum()>0)}, ticks_per_beat=quantization, write_path="../DEBUG/test_orch_event.mid", articulation=articulation_orch) ############################## ############################## # Align tracks if align_bool: # piano_aligned, trace_piano, orch_aligned, trace_orch, trace_prod, total_time = align_pianorolls(pr_piano_event, pr_orch_event, gapopen, gapextend) piano_aligned, trace_piano, orch_aligned, trace_orch, trace_prod, total_time = align_pianorolls(pr_piano_event, pr_orch_event, gapopen, gapextend) # Clean events if (temporal_granularity == 'event_level'): if (trace_piano is None) or (trace_orch is None): event_piano_aligned = None event_orch_aligned = None duration_piano_aligned = None duration_orch_aligned = None else: event_piano_aligned = clean_event(event_piano, trace_piano, trace_prod) event_orch_aligned = clean_event(event_orch, trace_orch, trace_prod) duration_piano_aligned = clean_event(duration_piano, trace_piano, trace_prod) duration_orch_aligned = clean_event(duration_orch, trace_orch, trace_prod) else: event_piano_aligned = [] event_orch_aligned = [] duration_piano_aligned = [] duration_orch_aligned = [] else: piano_aligned = pr_piano_event event_piano_aligned = event_piano duration_piano_aligned = duration_piano orch_aligned = pr_orch_event event_orch_aligned = event_orch duration_orch_aligned = duration_orch total_time = T_piano ############################## ############################## ############################## # Test for aligned event Piano/Orch ############################## # Instru mapping # import pickle as pkl # import LOP_database.utils.event_level as event_level # import LOP_database.utils.reconstruct_pr as reconstruct_pr # temp = pkl.load(open("/Users/leo/Recherche/lop/LOP/Data/Data_DEBUG_bp_bo_noEmb_tempGran32/temp.pkl", 'rb')) # instru_mapping = temp['instru_mapping'] # N_orchestra = temp['N_orchestra'] # N_piano = temp['instru_mapping']['Piano']['index_max'] # matrix_orch = cast_small_pr_into_big_pr(orch_aligned, 0, len(event_orch_aligned), instru_mapping, np.zeros((len(event_orch_aligned), N_orchestra))) # matrix_piano = cast_small_pr_into_big_pr(piano_aligned, 0, len(event_piano_aligned), instru_mapping, np.zeros((len(event_piano_aligned), N_piano))) # ############################## # # Reconstruct rhythm # pr_orchestra_I = reconstruct_pr.instrument_reconstruction(matrix_orch, instru_mapping) # pr_orchestra_rhythm = event_level.from_event_to_frame(matrix_orch, event_orch_aligned) # pr_orchestra_rhythm_I = reconstruct_pr.instrument_reconstruction(pr_orchestra_rhythm, instru_mapping) # # # pr_piano_I = reconstruct_pr.instrument_reconstruction_piano(matrix_piano, instru_mapping) # pr_piano_rhythm = event_level.from_event_to_frame(matrix_piano, event_piano_aligned) # pr_piano_rhythm_I = reconstruct_pr.instrument_reconstruction_piano(pr_piano_rhythm, instru_mapping) # ############################## # # Write midi # write_midi({k: v*90 for k,v in pr_piano_I.items()}, ticks_per_beat=1, write_path="../DEBUG/test_piano_event_aligned.mid", articulation=None) # write_midi({k: v*90 for k,v in pr_piano_rhythm_I.items()}, ticks_per_beat=quantization, write_path="../DEBUG/test_piano_rhythm_aligned.mid", articulation=None) # # # write_midi({k: v*90 for k,v in pr_orchestra_I.items() if (v.sum()>0)}, ticks_per_beat=1, write_path="../DEBUG/test_orch_event_aligned.mid", articulation=None) # write_midi({k: v*90 for k,v in pr_orchestra_rhythm_I.items() if (v.sum()>0)}, ticks_per_beat=quantization, write_path="../DEBUG/test_orch_rhythm_aligned.mid", articulation=None) # import pdb; pdb.set_trace() ############################## return piano_aligned, event_piano_aligned, duration_piano_aligned, name_piano, orch_aligned, event_orch_aligned, duration_orch_aligned, name_orch, total_time
def get_event_ind_dict(pr_dict): pr_flat = sum_along_instru_dim(pr_dict) return get_event_ind(pr_flat)
def align_tracks_removing_silences(pr0, pr1, unit_type, gapopen, gapextend): # Mapping_0 is a vector of size pr0, with values of the index in the new pr and -1 for a silence # Remove zeros pr0_no_silence, mapping_0 = remove_silence(pr0) pr1_no_silence, mapping_1 = remove_silence(pr1) # Get trace from needleman_wunsch algorithm # Traces are computed from binaries matrices # Traces are binary lists, 0 meaning a gap is inserted pr0_trace = sum_along_instru_dim( Unit_type.from_type_to_binary(pr0_no_silence, unit_type)) pr1_trace = sum_along_instru_dim( Unit_type.from_type_to_binary(pr1_no_silence, unit_type)) trace_0, trace_1, this_sum_score, this_nbId, this_nbDiffs = needleman_chord_wrapper( pr0_trace, pr1_trace, gapopen, gapextend) #################################### #################################### # Wrap dictionnaries according to the traces assert (len(trace_0) == len(trace_1)), "size mismatch" pr0_warp = warp_dictionnary_trace(pr0_no_silence, trace_0) pr1_warp = warp_dictionnary_trace(pr1_no_silence, trace_1) #################################### #################################### #################################### #################################### # Trace product trace_prod = [e1 * e2 for (e1, e2) in zip(trace_0, trace_1)] duration = sum(trace_prod) if duration == 0: return [None] * 5 # Remove gaps pr0_aligned = remove_zero_in_trace(pr0_warp, trace_prod) pr1_aligned = remove_zero_in_trace(pr1_warp, trace_prod) # New mapping : # some element are lost, replace them by silences # and decrease the indices def remove_gaps_mapping(mapping, trace, trace_prod): index = 0 counter = 0 for (t, t_prod) in zip(trace, trace_prod): if (t == 1) and (t_prod == 0): # Element lost while (mapping[index] == -1): index += 1 # Replace i with a silence mapping[index] = -1 elif (t == 1) and (t_prod == 1): while (mapping[index] == -1): index += 1 mapping[index] = counter counter += 1 index += 1 return mapping mapping_0_aligned = remove_gaps_mapping(mapping_0, trace_0, trace_prod) mapping_1_aligned = remove_gaps_mapping(mapping_1, trace_1, trace_prod) # Actually it is easier to have the indices of the non silent frames in the original score : non_silent_0 = np.where(mapping_0_aligned != -1)[0] non_silent_1 = np.where(mapping_1_aligned != -1)[0] #################################### #################################### # # Remove zeros in one score, but not in the other # pr0_no_unmatched_silence, pr1_no_unmatched_silence, duration = remove_unmatched_silence(pr0_aligned, pr1_aligned) # # # Remove zeros in both piano and orchestra : we don't want to learn mapping from zero to zero # pr0_out, pr1_out, duration = remove_match_silence(pr0_no_unmatched_silence, pr1_no_unmatched_silence) return pr0_aligned, non_silent_0, pr1_aligned, non_silent_1, duration