TIMBOVILL commited on
Commit
22890fa
1 Parent(s): 2eed0a1

Upload midi_creator.py

Browse files
Files changed (1) hide show
  1. src/modules/midi_creator.py +124 -0
src/modules/midi_creator.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Midi creator module"""
2
+
3
+ import math
4
+ from collections import Counter
5
+
6
+ import librosa
7
+ import numpy as np
8
+ import pretty_midi
9
+
10
+ from modules.Pitcher.pitcher import get_frequencies_with_high_confidence
11
+ from modules.Ultrastar.ultrastar_converter import (
12
+ get_end_time_from_ultrastar,
13
+ get_start_time_from_ultrastar,
14
+ ultrastar_note_to_midi_note,
15
+ )
16
+ from modules.console_colors import (
17
+ ULTRASINGER_HEAD,
18
+ red_highlighted,
19
+ )
20
+ from modules.Ultrastar.ultrastar_txt import UltrastarTxtValue
21
+ from modules.Pitcher.pitched_data import PitchedData
22
+
23
+
24
+ def convert_ultrastar_to_midi_instrument(ultrastar_class: UltrastarTxtValue) -> object:
25
+ """Converts an Ultrastar data to a midi instrument"""
26
+
27
+ print(f"{ULTRASINGER_HEAD} Creating midi instrument from Ultrastar txt")
28
+
29
+ instrument = pretty_midi.Instrument(program=0)
30
+ velocity = 100
31
+
32
+ for i in enumerate(ultrastar_class.words):
33
+ pos = i[0]
34
+ start_time = get_start_time_from_ultrastar(ultrastar_class, pos)
35
+ end_time = get_end_time_from_ultrastar(ultrastar_class, pos)
36
+ pitch = ultrastar_note_to_midi_note(int(ultrastar_class.pitches[pos]))
37
+
38
+ note = pretty_midi.Note(velocity, pitch, start_time, end_time)
39
+ instrument.notes.append(note)
40
+
41
+ return instrument
42
+
43
+
44
+ def instruments_to_midi(instruments: list[object], bpm: float, midi_output: str) -> None:
45
+ """Write instruments to midi file"""
46
+
47
+ print(f"{ULTRASINGER_HEAD} Creating midi file -> {midi_output}")
48
+
49
+ midi_data = pretty_midi.PrettyMIDI(initial_tempo=bpm)
50
+ for instrument in instruments:
51
+ midi_data.instruments.append(instrument)
52
+ midi_data.write(midi_output)
53
+
54
+
55
+ class MidiCreator:
56
+ """Docstring"""
57
+
58
+
59
+ def convert_frequencies_to_notes(frequency: [str]) -> list[list[str]]:
60
+ """Converts frequencies to notes"""
61
+ notes = []
62
+ for freq in frequency:
63
+ notes.append(librosa.hz_to_note(float(freq)))
64
+ return notes
65
+
66
+
67
+ def most_frequent(array: [str]) -> list[tuple[str, int]]:
68
+ """Get most frequent item in array"""
69
+ return Counter(array).most_common(1)
70
+
71
+
72
+ def find_nearest_index(array: list[float], value: float) -> int:
73
+ """Nearest index in array"""
74
+ idx = np.searchsorted(array, value, side="left")
75
+ if idx > 0 and (
76
+ idx == len(array)
77
+ or math.fabs(value - array[idx - 1]) < math.fabs(value - array[idx])
78
+ ):
79
+ return idx - 1
80
+
81
+ return idx
82
+
83
+
84
+ def create_midi_notes_from_pitched_data(start_times: list[float], end_times: list[float], pitched_data: PitchedData) -> list[str]:
85
+ """Create midi notes from pitched data"""
86
+ print(f"{ULTRASINGER_HEAD} Creating midi notes from pitched data")
87
+
88
+ midi_notes = []
89
+
90
+ for i in enumerate(start_times):
91
+ pos = i[0]
92
+ start_time = start_times[pos]
93
+ end_time = end_times[pos]
94
+
95
+ note = create_midi_note_from_pitched_data(
96
+ start_time, end_time, pitched_data
97
+ )
98
+
99
+ midi_notes.append(note)
100
+ # todo: Progress?
101
+ # print(filename + " f: " + str(mean))
102
+ return midi_notes
103
+
104
+
105
+ def create_midi_note_from_pitched_data(start_time: float, end_time: float, pitched_data: PitchedData) -> str:
106
+ """Create midi note from pitched data"""
107
+
108
+ start = find_nearest_index(pitched_data.times, start_time)
109
+ end = find_nearest_index(pitched_data.times, end_time)
110
+
111
+ if start == end:
112
+ freqs = [pitched_data.frequencies[start]]
113
+ confs = [pitched_data.confidence[start]]
114
+ else:
115
+ freqs = pitched_data.frequencies[start:end]
116
+ confs = pitched_data.confidence[start:end]
117
+
118
+ conf_f = get_frequencies_with_high_confidence(freqs, confs)
119
+
120
+ notes = convert_frequencies_to_notes(conf_f)
121
+
122
+ note = most_frequent(notes)[0][0]
123
+
124
+ return note