Spaces:
Sleeping
Sleeping
| """Midi creator module""" | |
| import math | |
| from collections import Counter | |
| import librosa | |
| import numpy as np | |
| import pretty_midi | |
| from modules.Pitcher.pitcher import get_frequencies_with_high_confidence | |
| from modules.Ultrastar.ultrastar_converter import ( | |
| get_end_time_from_ultrastar, | |
| get_start_time_from_ultrastar, | |
| ultrastar_note_to_midi_note, | |
| ) | |
| from modules.console_colors import ( | |
| ULTRASINGER_HEAD, | |
| red_highlighted, | |
| ) | |
| from modules.Ultrastar.ultrastar_txt import UltrastarTxtValue | |
| from modules.Pitcher.pitched_data import PitchedData | |
| def convert_ultrastar_to_midi_instrument(ultrastar_class: UltrastarTxtValue) -> object: | |
| """Converts an Ultrastar data to a midi instrument""" | |
| print(f"{ULTRASINGER_HEAD} Creating midi instrument from Ultrastar txt") | |
| instrument = pretty_midi.Instrument(program=0) | |
| velocity = 100 | |
| for i in enumerate(ultrastar_class.words): | |
| pos = i[0] | |
| start_time = get_start_time_from_ultrastar(ultrastar_class, pos) | |
| end_time = get_end_time_from_ultrastar(ultrastar_class, pos) | |
| pitch = ultrastar_note_to_midi_note(int(ultrastar_class.pitches[pos])) | |
| note = pretty_midi.Note(velocity, pitch, start_time, end_time) | |
| instrument.notes.append(note) | |
| return instrument | |
| def instruments_to_midi(instruments: list[object], bpm: float, midi_output: str) -> None: | |
| """Write instruments to midi file""" | |
| print(f"{ULTRASINGER_HEAD} Creating midi file -> {midi_output}") | |
| midi_data = pretty_midi.PrettyMIDI(initial_tempo=bpm) | |
| for instrument in instruments: | |
| midi_data.instruments.append(instrument) | |
| midi_data.write(midi_output) | |
| class MidiCreator: | |
| """Docstring""" | |
| def convert_frequencies_to_notes(frequency: [str]) -> list[list[str]]: | |
| """Converts frequencies to notes""" | |
| notes = [] | |
| for freq in frequency: | |
| notes.append(librosa.hz_to_note(float(freq))) | |
| return notes | |
| def most_frequent(array: [str]) -> list[tuple[str, int]]: | |
| """Get most frequent item in array""" | |
| return Counter(array).most_common(1) | |
| def find_nearest_index(array: list[float], value: float) -> int: | |
| """Nearest index in array""" | |
| idx = np.searchsorted(array, value, side="left") | |
| if idx > 0 and ( | |
| idx == len(array) | |
| or math.fabs(value - array[idx - 1]) < math.fabs(value - array[idx]) | |
| ): | |
| return idx - 1 | |
| return idx | |
| def create_midi_notes_from_pitched_data(start_times: list[float], end_times: list[float], pitched_data: PitchedData) -> list[str]: | |
| """Create midi notes from pitched data""" | |
| print(f"{ULTRASINGER_HEAD} Creating midi notes from pitched data") | |
| midi_notes = [] | |
| for i in enumerate(start_times): | |
| pos = i[0] | |
| start_time = start_times[pos] | |
| end_time = end_times[pos] | |
| note = create_midi_note_from_pitched_data( | |
| start_time, end_time, pitched_data | |
| ) | |
| midi_notes.append(note) | |
| # todo: Progress? | |
| # print(filename + " f: " + str(mean)) | |
| return midi_notes | |
| def create_midi_note_from_pitched_data(start_time: float, end_time: float, pitched_data: PitchedData) -> str: | |
| """Create midi note from pitched data""" | |
| start = find_nearest_index(pitched_data.times, start_time) | |
| end = find_nearest_index(pitched_data.times, end_time) | |
| if start == end: | |
| freqs = [pitched_data.frequencies[start]] | |
| confs = [pitched_data.confidence[start]] | |
| else: | |
| freqs = pitched_data.frequencies[start:end] | |
| confs = pitched_data.confidence[start:end] | |
| conf_f = get_frequencies_with_high_confidence(freqs, confs) | |
| notes = convert_frequencies_to_notes(conf_f) | |
| note = most_frequent(notes)[0][0] | |
| return note | |