simplify a little midi.py module
This commit is contained in:
parent
0a297e331d
commit
4aa5916346
80
project/midi.py
Normal file
80
project/midi.py
Normal file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import settings
|
||||
import pypianoroll as roll
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
from math import floor
|
||||
import sys
|
||||
|
||||
def to_samples(midi_file_path, midi_res=settings.midi_resolution):
|
||||
|
||||
# this function export a samples from midi file:
|
||||
# and for every track in midi file chopped pianoroll
|
||||
# for a samples of given beat_lenth (midi_res)
|
||||
# every track is single line
|
||||
|
||||
print('Exporting samples from: {}'.format(midi_file_path))
|
||||
|
||||
all_beats = np.empty((0, settings.midi_resolution, 128))
|
||||
|
||||
for track in roll.Multitrack(midi_file_path).tracks:
|
||||
print('Track: {}'.format(track.name))
|
||||
if not track.is_drum:
|
||||
number_of_beats = floor(track.pianoroll.shape[0] / midi_res)
|
||||
track_pianoroll = track.pianoroll[: number_of_beats * midi_res]
|
||||
track_beats = track_pianoroll.reshape(number_of_beats, midi_res, 128)
|
||||
all_beats = np.concatenate([track_beats, all_beats], axis=0)
|
||||
|
||||
print('Exported {} samples of {}'.format(number_of_beats, settings.midi_program[track.program]))
|
||||
else:
|
||||
# add code for drums samples
|
||||
pass
|
||||
return all_beats
|
||||
|
||||
def to_midi(samples, output_path=settings.generated_midi_path, program=0, tempo=120, beat_resolution=settings.beat_resolution):
|
||||
tracks = [roll.Track(samples, program=program)]
|
||||
return_midi = roll.Multitrack(tracks=tracks, tempo=tempo, downbeat=[0, 96, 192, 288], beat_resolution=beat_resolution)
|
||||
roll.write(return_midi, settings.generated_midi_path)
|
||||
|
||||
def delete_empty_samples(sample_pack):
|
||||
print('Deleting empty samples...')
|
||||
temp_sample_pack = sample_pack
|
||||
index_manipulator = 1
|
||||
for index, sample in enumerate(sample_pack):
|
||||
if sample.sum() == 0:
|
||||
temp_sample_pack = np.delete(temp_sample_pack, index-index_manipulator, axis=0)
|
||||
index_manipulator = index_manipulator + 1
|
||||
print('Deleted {} empty samples'.format(index_manipulator-1))
|
||||
return temp_sample_pack
|
||||
|
||||
def main():
|
||||
|
||||
if sys.argv[1]=='export':
|
||||
print('Exporting started...')
|
||||
|
||||
sample_pack = np.empty((0,settings.midi_resolution,128))
|
||||
|
||||
for midi_file in os.listdir(settings.midi_dir):
|
||||
midi_file_path = '{}/{}'.format(settings.midi_dir, midi_file)
|
||||
midi_samples = to_samples(midi_file_path)
|
||||
if midi_samples is None:
|
||||
continue
|
||||
sample_pack = np.concatenate((midi_samples, sample_pack), axis=0)
|
||||
|
||||
# sample_pack = delete_empty_samples(sample_pack)
|
||||
|
||||
np.savez_compressed(settings.samples_dir, sample_pack)
|
||||
print('Exported {} samples'.format(sample_pack.shape[0]))
|
||||
|
||||
fig, axes = plt.subplots(nrows=10, ncols=10, figsize=(20, 20))
|
||||
for idx, ax in enumerate(axes.ravel()):
|
||||
n = np.random.randint(0, sample_pack.shape[0])
|
||||
sample = sample_pack[n]
|
||||
ax.imshow(sample, cmap = plt.get_cmap('gray'))
|
||||
plt.savefig(settings.sample_preview_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,249 +0,0 @@
|
||||
import settings
|
||||
import pypianoroll as roll
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import os
|
||||
from tqdm import tqdm
|
||||
from math import floor
|
||||
import sys
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
|
||||
midi_program = {
|
||||
0 : 'Perc',
|
||||
1 : 'Acoustic Grand Piano',
|
||||
2 : 'Bright Acoustic Piano',
|
||||
3 : 'Electric Grand Piano',
|
||||
4 : 'Honky-tonk Piano',
|
||||
5 : 'Electric Piano 1',
|
||||
6 : 'Electric Piano 2',
|
||||
7 : 'Harpsichord',
|
||||
8 : 'Clavi',
|
||||
9 : 'Celesta',
|
||||
10 : 'Glockenspiel',
|
||||
11 : 'Music Box',
|
||||
12 : 'Vibraphone',
|
||||
13 : 'Marimba',
|
||||
14 : 'Xylophone',
|
||||
15 : 'Tubular Bells',
|
||||
16 : 'Dulcimer',
|
||||
17 : 'Drawbar Organ',
|
||||
18 : 'Percussive Organ',
|
||||
19 : 'Rock Organ',
|
||||
20 : 'Church Organ',
|
||||
21 : 'Reed Organ',
|
||||
22 : 'Accordion',
|
||||
23 : 'Harmonica',
|
||||
24 : 'Tango Accordion',
|
||||
25 : 'Acoustic Guitar (nylon)',
|
||||
26 : 'Acoustic Guitar (steel)',
|
||||
27 : 'Electric Guitar (jazz)',
|
||||
28 : 'Electric Guitar (clean)',
|
||||
29 : 'Electric Guitar (muted)',
|
||||
30 : 'Overdriven Guitar',
|
||||
31 : 'Distortion Guitar',
|
||||
32 : 'Guitar harmonics',
|
||||
33 : 'Acoustic Bass',
|
||||
34 : 'Electric Bass (finger)',
|
||||
35 : 'Electric Bass (pick)',
|
||||
36 : 'Fretless Bass',
|
||||
37 : 'Slap Bass 1',
|
||||
38 : 'Slap Bass 2',
|
||||
39 : 'Synth Bass 1',
|
||||
40 : 'Synth Bass 2',
|
||||
41 : 'Violin',
|
||||
42 : 'Viola',
|
||||
43 : 'Cello',
|
||||
44 : 'Contrabass',
|
||||
45 : 'Tremolo Strings',
|
||||
46 : 'Pizzicato Strings',
|
||||
47 : 'Orchestral Harp',
|
||||
48 : 'Timpani',
|
||||
49 : 'String Ensemble 1',
|
||||
50 : 'String Ensemble 2',
|
||||
51 : 'SynthStrings 1',
|
||||
52 : 'SynthStrings 2',
|
||||
53 : 'Choir Aahs',
|
||||
54 : 'Voice Oohs',
|
||||
55 : 'Synth Voice',
|
||||
56 : 'Orchestra Hit',
|
||||
57 : 'Trumpet',
|
||||
58 : 'Trombone',
|
||||
59 : 'Tuba',
|
||||
60 : 'Muted Trumpet',
|
||||
61 : 'French Horn',
|
||||
62 : 'Brass Section',
|
||||
63 : 'SynthBrass 1',
|
||||
64 : 'SynthBrass 2',
|
||||
65 : 'Soprano Sax',
|
||||
66 : 'Alto Sax',
|
||||
67 : 'Tenor Sax',
|
||||
68 : 'Baritone Sax',
|
||||
69 : 'Oboe',
|
||||
70 : 'English Horn',
|
||||
71 : 'Bassoon',
|
||||
72 : 'Clarinet',
|
||||
73 : 'Piccolo',
|
||||
74 : 'Flute',
|
||||
75 : 'Recorder',
|
||||
76 : 'Pan Flute',
|
||||
77 : 'Blown Bottle',
|
||||
78 : 'Shakuhachi',
|
||||
79 : 'Whistle',
|
||||
80 : 'Ocarina',
|
||||
81 : 'Lead 1 (square)',
|
||||
82 : 'Lead 2 (sawtooth)',
|
||||
83 : 'Lead 3 (calliope)',
|
||||
84 : 'Lead 4 (chiff)',
|
||||
85 : 'Lead 5 (charang)',
|
||||
86 : 'Lead 6 (voice)',
|
||||
87 : 'Lead 7 (fifths)',
|
||||
88 : 'Lead 8 (bass + lead)',
|
||||
89 : 'Pad 1 (new age)',
|
||||
90 : 'Pad 2 (warm)',
|
||||
91 : 'Pad 3 (polysynth)',
|
||||
92 : 'Pad 4 (choir)',
|
||||
93 : 'Pad 5 (bowed)',
|
||||
94 : 'Pad 6 (metallic)',
|
||||
95 : 'Pad 7 (halo)',
|
||||
96 : 'Pad 8 (sweep)',
|
||||
97 : 'FX 1 (rain)',
|
||||
98 : 'FX 2 (soundtrack)',
|
||||
99 : 'FX 3 (crystal)',
|
||||
100 : 'FX 4 (atmosphere)',
|
||||
101 : 'FX 5 (brightness)',
|
||||
102 : 'FX 6 (goblins)',
|
||||
103 : 'FX 7 (echoes)',
|
||||
104 : 'FX 8 (sci-fi)',
|
||||
105 : 'Sitar',
|
||||
106 : 'Banjo',
|
||||
107 : 'Shamisen',
|
||||
108 : 'Koto',
|
||||
109 : 'Kalimba',
|
||||
110 : 'Bag pipe',
|
||||
111 : 'Fiddle',
|
||||
112 : 'Shanai',
|
||||
113 : 'Tinkle Bell',
|
||||
114 : 'Agogo',
|
||||
115 : 'Steel Drums',
|
||||
116 : 'Woodblock',
|
||||
117 : 'Taiko Drum',
|
||||
118 : 'Melodic Tom',
|
||||
119 : 'Synth Drum',
|
||||
120 : 'Reverse Cymbal',
|
||||
121 : 'Guitar Fret Noise',
|
||||
122 : 'Breath Noise',
|
||||
123 : 'Seashore',
|
||||
124 : 'Bird Tweet',
|
||||
125 : 'Telephone Ring',
|
||||
126 : 'Helicopter',
|
||||
127 : 'Applause',
|
||||
128 : 'Gunshot'
|
||||
}
|
||||
|
||||
# strasznie wolna funcja ;/
|
||||
def trim_notes(pianoroll):
|
||||
now_block = []
|
||||
for x in pianoroll:
|
||||
this = None
|
||||
prev = None
|
||||
new_line =[]
|
||||
for y in x:
|
||||
this = y
|
||||
if prev != None:
|
||||
if this > 0 and prev > 0:
|
||||
new_line.append(0)
|
||||
else:
|
||||
new_line.append(y)
|
||||
else:
|
||||
new_line.append(y)
|
||||
prev = this
|
||||
now_block.append(new_line)
|
||||
return np.array(now_block)
|
||||
|
||||
def metrum_check(midi_lenght, metrum=4, beat_resolution=24):
|
||||
return True if midi_lenght % (metrum * beat_resolution) == 0 else False
|
||||
|
||||
# >>> data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
|
||||
# >>> scaler = MinMaxScaler()
|
||||
# >>> print(scaler.fit(data))
|
||||
# MinMaxScaler(copy=True, feature_range=(0, 1))
|
||||
# >>> print(scaler.data_max_)
|
||||
# [ 1. 18.]
|
||||
# >>> print(scaler.transform(data))
|
||||
# [[0. 0. ]
|
||||
# [0.25 0.25]
|
||||
# [0.5 0.5 ]
|
||||
# [1. 1. ]]
|
||||
# >>> print(scaler.transform([[2, 2]]))
|
||||
# [[1.5 0. ]]
|
||||
|
||||
|
||||
def to_samples(midi_file_path, midi_res=settings.midi_resolution, ignore_note_lenght=settings.ignore_note_lenght):
|
||||
print('exporting samples from: {}'.format(midi_file_path))
|
||||
midi_file = roll.Multitrack(midi_file_path)
|
||||
samples = None
|
||||
all_samples = np.empty((0,settings.midi_resolution,128))
|
||||
for track in midi_file.tracks:
|
||||
# if not track.is_drum:
|
||||
if not metrum_check(track.pianoroll.shape[0]):
|
||||
print('Track skipped')
|
||||
continue
|
||||
else:
|
||||
instrument_track = track.pianoroll
|
||||
instrument_track = trim_notes(instrument_track.T).T if ignore_note_lenght else instrument_track
|
||||
scaler = MinMaxScaler()
|
||||
instrument_track = scaler.fit_transform(instrument_track)
|
||||
whole_beats = int(instrument_track.shape[0] / midi_res)
|
||||
samples = instrument_track.reshape(whole_beats, midi_res, 128)
|
||||
print('Exported {} samples of {}'.format(whole_beats, midi_program[track.program]))
|
||||
all_samples = np.concatenate([samples, all_samples], axis=0)
|
||||
return all_samples
|
||||
|
||||
def to_midi(samples, output_path=settings.generated_midi_path, program=0, tempo=120, beat_resolution=settings.beat_resolution):
|
||||
tracks = [roll.Track(samples, program=program)]
|
||||
return_midi = roll.Multitrack(tracks=tracks, tempo=tempo, downbeat=[0, 96, 192, 288], beat_resolution=beat_resolution)
|
||||
roll.write(return_midi, settings.generated_midi_path)
|
||||
|
||||
def to_png(samples, output_path=settings.generated_pianoroll_path, horizontal=True):
|
||||
img = samples.T if horizontal else samples
|
||||
plt.imshow(img, cmap='gray')
|
||||
plt.savefig(output_path)
|
||||
|
||||
def delete_empty_samples(sample_pack):
|
||||
temp_sample_pack = sample_pack
|
||||
index_manipulator = 1
|
||||
for index, sample in enumerate(sample_pack):
|
||||
if sample.sum() == 0:
|
||||
temp_sample_pack = np.delete(temp_sample_pack, index-index_manipulator, axis=0)
|
||||
index_manipulator = index_manipulator + 1
|
||||
print('Deleted {} empty samples'.format(index_manipulator-1))
|
||||
return temp_sample_pack
|
||||
|
||||
def main():
|
||||
if sys.argv[1]=='-e':
|
||||
print('Exporting started...')
|
||||
sample_pack = np.empty((0,settings.midi_resolution,128))
|
||||
for midi_file in os.listdir(settings.midi_dir):
|
||||
midi_file_path = '{}/{}'.format(settings.midi_dir, midi_file)
|
||||
midi_samples = to_samples(midi_file_path)
|
||||
if midi_samples is None:
|
||||
continue
|
||||
sample_pack = np.concatenate((midi_samples, sample_pack), axis=0)
|
||||
|
||||
sample_pack = delete_empty_samples(sample_pack)
|
||||
np.savez_compressed(settings.samples_dir, sample_pack)
|
||||
print('Exported {} samples'.format(sample_pack.shape[0]))
|
||||
elif sys.argv[1]=='-c':
|
||||
to_midi(settings.generated_sample_path)
|
||||
print('Samples to midi saved to {}'.format(settings.generated_sample_path))
|
||||
elif sys.argv[1]=='-p':
|
||||
sample_pack = np.load(settings.samples_path)['arr_0']
|
||||
for i, sample in tqdm(enumerate(sample_pack)):
|
||||
to_png(sample, output_path='data/preview/{}.png'.format(i))
|
||||
if i>50:
|
||||
sys.exit()
|
||||
else:
|
||||
print('type command afrer -e to export samples, -c to convert samples to midi, -p to preview samples in png')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user