asigalov61 commited on
Commit
4c2d8a6
1 Parent(s): 5af8537

Upload midi_synthesizer.py

Browse files
Files changed (1) hide show
  1. midi_synthesizer.py +53 -0
midi_synthesizer.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fluidsynth
2
+ import numpy as np
3
+
4
+
5
+ def synthesis(midi_opus, soundfont_path, sample_rate=44100):
6
+ ticks_per_beat = midi_opus[0]
7
+ event_list = []
8
+ for track_idx, track in enumerate(midi_opus[1:]):
9
+ abs_t = 0
10
+ for event in track:
11
+ abs_t += event[1]
12
+ event_new = [*event]
13
+ event_new[1] = abs_t
14
+ event_list.append(event_new)
15
+ event_list = sorted(event_list, key=lambda e: e[1])
16
+
17
+ tempo = int((60 / 120) * 10 ** 6) # default 120 bpm
18
+ ss = np.empty((0, 2), dtype=np.int16)
19
+ fl = fluidsynth.Synth(samplerate=float(sample_rate))
20
+ sfid = fl.sfload(soundfont_path)
21
+ last_t = 0
22
+ for c in range(16):
23
+ fl.program_select(c, sfid, 128 if c == 9 else 0, 0)
24
+ for event in event_list:
25
+ name = event[0]
26
+ sample_len = int(((event[1] / ticks_per_beat) * tempo / (10 ** 6)) * sample_rate)
27
+ sample_len -= int(((last_t / ticks_per_beat) * tempo / (10 ** 6)) * sample_rate)
28
+ last_t = event[1]
29
+ if sample_len > 0:
30
+ sample = fl.get_samples(sample_len).reshape(sample_len, 2)
31
+ ss = np.concatenate([ss, sample])
32
+ if name == "set_tempo":
33
+ tempo = event[2]
34
+ elif name == "patch_change":
35
+ c, p = event[2:4]
36
+ fl.program_select(c, sfid, 128 if c == 9 else 0, p)
37
+ elif name == "control_change":
38
+ c, cc, v = event[2:5]
39
+ fl.cc(c, cc, v)
40
+ elif name == "note_on" and event[3] > 0:
41
+ c, p, v = event[2:5]
42
+ fl.noteon(c, p, v)
43
+ elif name == "note_off" or (name == "note_on" and event[3] == 0):
44
+ c, p = event[2:4]
45
+ fl.noteoff(c, p)
46
+
47
+ fl.delete()
48
+ if ss.shape[0] > 0:
49
+ max_val = np.abs(ss).max()
50
+ if max_val != 0:
51
+ ss = (ss / max_val) * np.iinfo(np.int16).max
52
+ ss = ss.astype(np.int16)
53
+ return ss