示例#1
0
def evaluate_tabs(all_songs) -> None:
    """
    Evaluate all lab files based on tab parsing and alignment.

    :param all_songs: All songs in our data set.
    """
    result_csv_path = filehandler.TABLABS_RESULTS_PATH
    if not path.isfile(result_csv_path):
        # Results were not calculated yet
        with open(result_csv_path, 'w') as write_file:
            for song_key in all_songs:
                song = all_songs[song_key]
                for tab_path in song.full_tab_paths:
                    tab_write_path = filehandler.get_full_tab_chord_labs_path(
                        tab_path)
                    if filehandler.file_exists(tab_write_path):
                        likelihood, transposition = filehandler.read_log_likelihood(
                            song_key, tab_write_path)
                        if filehandler.file_exists(tab_write_path):
                            csr, overseg, underseg, seg = evaluate(
                                song.full_ground_truth_chord_labs_path,
                                tab_write_path)
                            write_file.write(
                                '{0};{1};{2};{3};{4};{5};{6};{7};{8}\n'.format(
                                    str(song_key), str(song.duration),
                                    str(
                                        filehandler.get_relative_path(
                                            tab_write_path)), str(likelihood),
                                    str(transposition), str(csr), str(overseg),
                                    str(underseg), str(seg)))
示例#2
0
def predict_single_song(song: Song, hmm_parameters: HMMParameters) -> None:
    """
    Estimate chords for each tab matched to the song and export them to a lab file.

    :param song: Song for which we estimate tab-based chords
    :param hmm_parameters: Parameters of the trained HMM
    """
    for full_tab_path in song.full_tab_paths:
        tab_chord_path = filehandler.get_chords_from_tab_filename(
            full_tab_path)
        tab_write_path = filehandler.get_full_tab_chord_labs_path(
            full_tab_path)
        if not filehandler.file_exists(tab_write_path):
            log_likelihood, transposition_semitone = \
                jump_align(tab_chord_path, song.full_audio_path, tab_write_path, hmm_parameters)
            if log_likelihood is not None:
                # We found an alignment, write this to our log-likelihoods file
                if not tab_write_path.startswith(filehandler.DATA_PATH):
                    print('WRITING ERROR')
                # Remove start of path
                tab_write_path = tab_write_path[len(filehandler.DATA_PATH) +
                                                1:]
                filehandler.write_log_likelihood(song.key, tab_write_path,
                                                 log_likelihood,
                                                 transposition_semitone)
示例#3
0
def get_expected_best_tab_lab(song: Song) -> str:
    """
    Find the lab file of the expected best tab for this Song (based on log-likelihood returned by Jump Alignment)

    :param song: Song in our data set
    """
    best_tab_lab, best_tab_quality = '', 0

    for tab_path in song.full_tab_paths:
        tab_write_path = filehandler.get_full_tab_chord_labs_path(tab_path)
        if filehandler.file_exists(tab_write_path):
            tab_quality, _ = filehandler.read_log_likelihood(
                song.key, tab_path)
            if tab_quality > best_tab_quality:
                best_tab_lab, best_tab_quality = tab_write_path, tab_quality

    return best_tab_lab
def export_result_image(song: Song,
                        chords_vocabulary: ChordVocabulary,
                        midi: bool = True,
                        tab: bool = True,
                        audio: str = 'CHF_2017',
                        df: bool = True):
    """
    Export visualisation to a png file.

    :param song: Song for which we want to export the visualisation
    :param chords_vocabulary: Chord vocabulary
    :param midi: Show MIDI files?
    :param tab: Show Tab files?
    :param audio: Audio ACE method
    :param df: Show all DF results?
    """
    if filehandler.file_exists(
            filehandler.get_lab_visualisation_path(song, audio)):
        return song.title + " was already visualised for the ACE method " + audio + "."

    nr_of_samples = int(ceil(song.duration * 100))
    alphabet = ChordAlphabet(chords_vocabulary)

    # Select labs based on parameter setting
    label_data = [{
        'name': 'Ground truth',
        'index': 0,
        'lab_path': song.full_ground_truth_chord_labs_path,
        'csr': 1.0,
        'ovs': 1.0,
        'uns': 1.0,
        'seg': 1.0
    }]
    i = 1
    best_indices = []  # For expected best MIDI and tab
    if midi:
        duplicate_midis = filehandler.find_duplicate_midis(song)
        best_midi_name, best_segmentation = data_fusion.get_expected_best_midi(
            song)
        full_midi_paths = song.full_midi_paths
        full_midi_paths.sort()
        for full_midi_path in full_midi_paths:
            midi_name = filehandler.get_file_name_from_full_path(
                full_midi_path)
            for segmentation_method in ['bar', 'beat']:
                full_midi_chords_path = filehandler.get_full_midi_chord_labs_path(
                    midi_name, segmentation_method)
                if filehandler.file_exists(full_midi_chords_path) \
                        and midi_name not in duplicate_midis:
                    # Evaluate song
                    csr, ovs, uns, seg = evaluate(
                        song.full_ground_truth_chord_labs_path,
                        full_midi_chords_path)
                    # Save evaluation values to label_data
                    label_data.append({
                        'name':
                        'MIDI ' + midi_name + ' | ' + segmentation_method,
                        'index': i,
                        'lab_path': full_midi_chords_path,
                        'csr': csr,
                        'ovs': ovs,
                        'uns': uns,
                        'seg': seg
                    })
                    # Check if this is the expected best MIDI & segmentation method for this song
                    if midi_name == best_midi_name and segmentation_method == best_segmentation:
                        best_indices.append(i)
                    i += 1

    if tab:
        best_tab = data_fusion.get_expected_best_tab_lab(song)
        for tab_counter, full_tab_path in enumerate(song.full_tab_paths, 1):
            tab_chord_labs_path = filehandler.get_full_tab_chord_labs_path(
                full_tab_path)
            if filehandler.file_exists(tab_chord_labs_path):
                # Evaluate song
                csr, ovs, uns, seg = evaluate(
                    song.full_ground_truth_chord_labs_path,
                    tab_chord_labs_path)
                # Save evaluation values to label_data
                label_data.append({
                    'name': 'Tab ' + str(tab_counter),
                    'index': i,
                    'lab_path': tab_chord_labs_path,
                    'csr': csr,
                    'ovs': ovs,
                    'uns': uns,
                    'seg': seg
                })
                if tab_chord_labs_path == best_tab:
                    best_indices.append(i)
                i += 1
    if df:
        csr, ovs, uns, seg = evaluate(
            song.full_ground_truth_chord_labs_path,
            filehandler.get_full_mirex_chord_labs_path(song, audio))
        label_data.append({
            'name':
            audio,
            'index':
            i,
            'lab_path':
            filehandler.get_full_mirex_chord_labs_path(song, audio),
            'csr':
            csr,
            'ovs':
            ovs,
            'uns':
            uns,
            'seg':
            seg
        })

        for selection_name in 'all', 'best':
            for combination_name in 'rnd', 'mv', 'df':
                df_lab_path = filehandler.get_data_fusion_path(
                    song.key, combination_name, selection_name, audio)
                csr, ovs, uns, seg = evaluate(
                    song.full_ground_truth_chord_labs_path, df_lab_path)
                label_data.append({
                    'name':
                    audio + '-' + combination_name.upper() + '-' +
                    selection_name.upper(),
                    'index':
                    i,
                    'lab_path':
                    df_lab_path,
                    'csr':
                    csr,
                    'ovs':
                    ovs,
                    'uns':
                    uns,
                    'seg':
                    seg
                })

    # Fill a numpy array with chord labels for each of the lab files
    chord_matrix = np.zeros((len(label_data), nr_of_samples), dtype=int)
    for lab_nr in range(len(label_data)):
        data_fusion.load_lab_file_into_chord_matrix(
            label_data[lab_nr]['lab_path'], lab_nr, chord_matrix, alphabet,
            nr_of_samples)

    all_chords = [chord_matrix[x] for x in range(len(label_data))]

    # Find names
    names = [label_dict['name'] for label_dict in label_data]

    # Find results
    results = ['CSR  OvS  UnS  Seg']
    for label_dict in label_data[1:]:
        results.append(' '.join([
            str(round(label_dict[measure], 2)).ljust(4, '0')
            for measure in ['csr', 'ovs', 'uns', 'seg']
        ]))

    # Show result
    plt1 = _show_chord_sequences(song, all_chords, best_indices, names,
                                 results, alphabet)

    plt1.savefig(filehandler.get_lab_visualisation_path(song, audio),
                 bbox_inches="tight",
                 pad_inches=0)

    return song.title + " was visualised for the ACE method " + audio + "."
示例#5
0
def get_actual_best_tab_lab(song: Song) -> str:
    best_tab_name, _ = filehandler.get_actual_best_tab_for_song(song.key)
    return filehandler.get_full_tab_chord_labs_path(best_tab_name)
示例#6
0
def data_fuse_song(song: Song, chord_vocabulary: ChordVocabulary):
    """
    Data fuse a song using all combinations of selection and combination methods, write the final labels to .lab files

    :param song: The song on which we want to apply data fusion
    :param chord_vocabulary: The chord vocabulary
    """
    # Check if data fusion has already been calculated  TODO: make this check more robust
    if path.isfile(
            filehandler.get_data_fusion_path(song.key, 'df', 'besttab',
                                             'CHF_2017')):
        return

    # Get list of symbolic lab files (all / expected best)
    # well_aligned_midis = get_well_aligned_midis(song)
    # all_symbolic_lab_paths = \
    #     [filehandler.get_full_midi_chord_labs_path(wam, 'bar') for wam in well_aligned_midis] + \
    #     [filehandler.get_full_midi_chord_labs_path(wam, 'beat') for wam in well_aligned_midis] + \
    #     [filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths]
    # expected_best_symbolic_lab_paths = []
    # if well_aligned_midis:
    #     expected_best_symbolic_lab_paths.append(
    #         filehandler.get_full_midi_chord_labs_path(*get_expected_best_midi(song)))
    # if [filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths]:
    #     expected_best_symbolic_lab_paths.append(
    #         filehandler.get_full_tab_chord_labs_path(get_expected_best_tab_lab(song)))

    well_aligned_midis = get_well_aligned_midis(song)
    all_midi_bar_lab_paths = [
        filehandler.get_full_midi_chord_labs_path(wam, 'bar')
        for wam in well_aligned_midis if filehandler.file_exists(
            filehandler.get_full_midi_chord_labs_path(wam, 'bar'))
    ]
    all_midi_beat_lab_paths = [
        filehandler.get_full_midi_chord_labs_path(wam, 'beat')
        for wam in well_aligned_midis if filehandler.file_exists(
            filehandler.get_full_midi_chord_labs_path(wam, 'beat'))
    ]
    all_midi_lab_paths = all_midi_bar_lab_paths + all_midi_beat_lab_paths
    all_tab_lab_paths = [
        filehandler.get_full_tab_chord_labs_path(t)
        for t in song.full_tab_paths
        if filehandler.file_exists(filehandler.get_full_tab_chord_labs_path(t))
    ]
    all_audio_lab_paths = {
        **song.full_mirex_chord_lab_paths,
        **{
            'CHF_2017': song.full_chordify_chord_labs_path
        }
    }

    # expected_best_symbolic_lab_paths = []
    # if well_aligned_midis:
    #     expected_best_symbolic_lab_paths.append(
    #         filehandler.get_full_midi_chord_labs_path(*get_expected_best_midi(song)))
    # if [filehandler.get_full_tab_chord_labs_path(t) for t in song.full_tab_paths]:
    #     expected_best_symbolic_lab_paths.append(
    #         filehandler.get_full_tab_chord_labs_path(get_expected_best_tab_lab(song)))

    expected_best_midi_lab_paths = []
    if well_aligned_midis:
        expected_best_midi_lab_paths.append(
            filehandler.get_full_midi_chord_labs_path(
                *get_expected_best_midi(song)))
    expected_best_tab_lab_paths = []
    if [
            filehandler.get_full_tab_chord_labs_path(t)
            for t in song.full_tab_paths
    ]:
        expected_best_tab_lab_paths.append(
            filehandler.get_full_tab_chord_labs_path(
                get_expected_best_tab_lab(song)))

    all_symbolic_lab_paths = all_midi_lab_paths + all_tab_lab_paths
    expected_best_symbolic_lab_paths = expected_best_midi_lab_paths + expected_best_tab_lab_paths

    # # Remove non-existing files (e.g. tab files in which too little chords were observed)
    # all_symbolic_lab_paths = [lab for lab in all_symbolic_lab_paths if filehandler.file_exists(lab)]
    # expected_best_symbolic_lab_paths = [lab for lab in expected_best_symbolic_lab_paths if filehandler.file_exists(lab)]

    # Get list of audio lab files
    # audio_labs = song.full_mirex_chord_lab_paths
    # audio_labs['CHF_2017'] = song.full_chordify_chord_labs_path

    # Sample every 10ms, so 100 samples per second
    song_duration = song.duration
    nr_of_samples = int(ceil(song_duration * 100))

    # Turn the chords list (a list of (key, mode-str, chroma-list) tuples) into an chord_vocabulary (a list of strings)
    alphabet = ChordAlphabet(chord_vocabulary)

    selection_dict = {
        'all': all_symbolic_lab_paths,
        'best': expected_best_symbolic_lab_paths,
        'allmidi': all_midi_lab_paths,
        'bestmidi': expected_best_midi_lab_paths,
        'alltab': all_tab_lab_paths,
        'besttab': expected_best_tab_lab_paths
    }

    # Iterate over the two types of selection (all / best)
    # for lab_list_i in [0, 1]:
    #     lab_list = [all_symbolic_lab_paths, expected_best_symbolic_lab_paths,
    #                 all_midi_lab_paths, expected_best_midi_lab_paths,
    #                 all_tab_lab_paths, expected_best_tab_lab_paths][lab_list_i]
    #     lab_list = [i for i in lab_list if i != '']
    # selection_name = ['all', 'best', 'allmidi', 'bestmidi', 'alltab', 'besttab'][lab_list_i]

    for selection_name, lab_list in selection_dict.items():
        lab_list = [i for i in lab_list if i != '']

        # Fill a numpy array with chord labels for each of the lab files
        chord_matrix = np.zeros((len(lab_list) + 1, nr_of_samples), dtype=int)
        for lab_nr in range(len(lab_list)):
            load_lab_file_into_chord_matrix(lab_list[lab_nr], lab_nr,
                                            chord_matrix, alphabet,
                                            nr_of_samples)

        # Iterate over the audio types:
        for audio_name, audio_lab in all_audio_lab_paths.items():
            if filehandler.file_exists(audio_lab):
                if any([
                        not filehandler.file_exists(
                            filehandler.get_data_fusion_path(
                                song.key, df_type_str, selection_name,
                                audio_name))
                        for df_type_str in ['rnd', 'mv', 'df']
                ]):
                    # Add the lab file to our chord matrix
                    load_lab_file_into_chord_matrix(audio_lab, len(lab_list),
                                                    chord_matrix, alphabet,
                                                    nr_of_samples)

                    # Iterate over the three combination types; calculate labels and write them:
                    if not filehandler.file_exists(
                            filehandler.get_data_fusion_path(
                                song.key, 'rnd', selection_name, audio_name)):
                        final_labels_random = _random_chord_label_combination(
                            chord_matrix, nr_of_samples)
                        _write_final_labels(
                            final_labels_random,
                            filehandler.get_data_fusion_path(
                                song.key, 'rnd', selection_name, audio_name),
                            alphabet)

                    if not filehandler.file_exists(
                            filehandler.get_data_fusion_path(
                                song.key, 'mv', selection_name, audio_name)):
                        final_labels_majority = _majority_vote_chord_label_combination(
                            chord_matrix, nr_of_samples, alphabet)
                        _write_final_labels(
                            final_labels_majority,
                            filehandler.get_data_fusion_path(
                                song.key, 'mv', selection_name, audio_name),
                            alphabet)

                    if not filehandler.file_exists(
                            filehandler.get_data_fusion_path(
                                song.key, 'df', selection_name, audio_name)):
                        final_labels_data_fusion = _data_fusion_chord_label_combination(
                            chord_matrix, nr_of_samples, alphabet)
                        _write_final_labels(
                            final_labels_data_fusion,
                            filehandler.get_data_fusion_path(
                                song.key, 'df', selection_name, audio_name),
                            alphabet)