Team Ai
Apppublic

becaliang/Music_Generation_Project

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
preprocess.py140 linesDownload Raw Back to root
1from music21 import converter, instrument, key, note, stream, tempo, meter2from collections import OrderedDict3from itertools import groupby4from grammar import parse_melody5import copy6 7# ---------------------------- INTERNAL HELPERS ---------------------------- #8 9def _load_and_extract(data_path):10    midi_data = converter.parse(data_path)11    parts = midi_data.parts.stream()12    solo_parts = []13 14    for p in parts:15        voice = stream.Voice()16        for el in p.recurse():17            if isinstance(el, (note.Note, note.Rest)):18                if el.quarterLength == 0.0:19                    el.quarterLength = 0.2520                voice.insert(el.offset, el)21            elif isinstance(el, (instrument.Instrument, tempo.MetronomeMark, key.KeySignature, meter.TimeSignature)):22                voice.insert(0, el)23        solo_parts.append(voice)24 25    return solo_parts26 27def _split_into_measures(tracks):28    melody_by_track = {}29    chords_by_track = {}30 31    for i, voice_stream in enumerate(tracks):32        track_name = f"Track_{i + 1}"33        melody_measures = OrderedDict()34        melody_offsets = [(int(n.offset / 4), n) for n in voice_stream if isinstance(n, (note.Note, note.Rest))]35 36        for idx, group in groupby(melody_offsets, lambda x: x[0]):37            melody_measures[idx] = [n[1] for n in group]38 39        chord_stream = copy.deepcopy(voice_stream)40        chord_stream.removeByClass(note.Note)41        chord_stream.removeByClass(note.Rest)42        chord_offsets = [(int(n.offset / 4), n) for n in chord_stream]43 44        chords = OrderedDict()45        for idx, group in groupby(chord_offsets, lambda x: x[0]):46            chords[idx] = [n[1] for n in group]47 48        min_len = min(len(chords), len(melody_measures))49        chords = OrderedDict(list(chords.items())[:min_len])50        melody_measures = OrderedDict(list(melody_measures.items())[:min_len])51 52        melody_by_track[track_name] = melody_measures53        chords_by_track[track_name] = chords54 55    return melody_by_track, chords_by_track56 57def _encode_grammars(melody_dict, chord_dict):58    grammars_by_track = {}59 60    for track_name in melody_dict:61        melody_measures = melody_dict.get(track_name)62        chord_measures = chord_dict.get(track_name)63 64        if not isinstance(melody_measures, dict) or not isinstance(chord_measures, dict):65            print(f"⚠️ Skipping {track_name}: Invalid measure format.")66            continue67 68        grammar_list = []69        for idx in sorted(melody_measures.keys()):70            if idx not in chord_measures:71                continue72 73            m_stream = stream.Voice()74            c_stream = stream.Voice()75 76            for n in melody_measures[idx]:77                m_stream.insert(n.offset, n)78            for c in chord_measures[idx]:79                c_stream.insert(c.offset, c)80 81            grammar = parse_melody(m_stream, c_stream)82            grammar_list.append(grammar)83 84        grammars_by_track[track_name] = grammar_list85 86    return grammars_by_track87 88# ---------------------------- PUBLIC INTERFACE ---------------------------- #89 90def get_multi_track_musical_data(data_path):91    solo_parts = _load_and_extract(data_path)92    melody_dict, chord_dict = _split_into_measures(solo_parts)93    grammar_dict = _encode_grammars(melody_dict, chord_dict)94 95    merged_chords = {}96    for chords in chord_dict.values():97        for k, v in chords.items():98            if k not in merged_chords:99                merged_chords[k] = []100            merged_chords[k].extend(v)101 102    return merged_chords, grammar_dict103 104def get_multi_track_corpus_data(grammar_dict):105    corpus_dict = {}106    all_tokens = []107 108    for track, grammar_list in grammar_dict.items():109        tokens = [token for phrase in grammar_list for token in phrase.split(" ")]110        corpus_dict[track] = tokens111        all_tokens.extend(tokens)112 113    vocab = sorted(set(all_tokens))114    token_to_index = {t: i for i, t in enumerate(vocab)}115    index_to_token = {i: t for t, i in token_to_index.items()}116 117    return corpus_dict, vocab, token_to_index, index_to_token118 119def get_musical_data(data_path):120    solo_parts = _load_and_extract(data_path)121    melody_dict, chords_dict = _split_into_measures(solo_parts)122    grammar_dict = _encode_grammars(melody_dict, chords_dict)123 124    merged_chords = {}125    for chords in chords_dict.values():126        for k, v in chords.items():127            if k not in merged_chords:128                merged_chords[k] = []129            merged_chords[k].extend(v)130 131    all_grammars = [g for track_grammars in grammar_dict.values() for g in track_grammars]132    return merged_chords, all_grammars133 134def get_corpus_data(grammar_list):135    corpus = [token for phrase in grammar_list for token in phrase.split()]136    vocab = sorted(set(corpus))137    token_to_index = {t: i for i, t in enumerate(vocab)}138    index_to_token = {i: t for i, t in enumerate(vocab)}139    return corpus, vocab, token_to_index, index_to_token140