-
Notifications
You must be signed in to change notification settings - Fork 4
/
utils.py
executable file
·202 lines (152 loc) · 5.09 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import os
import sys
import shutil
import numpy as np
import time
import errno
sys.path.append(os.path.join('RenderMan-master', 'Builds', 'MacOSX', 'build', 'Debug'))
import librenderman as rm
def copy_and_rename_def(src_dir, src_file, dest_dir):
"""
:param src_dir:
:param src_file:
:param dest_dir:
:return:
"""
src_path = os.path.join(src_dir, src_file)
temp_path = os.path.join(src_dir, 'kontakt_def.nkm') # The file has to be renamed
shutil.copy(src_path, temp_path)
shutil.copy(temp_path, dest_dir)
def get_inst_class(inst_classes, inst, pgm0_is_piano=False):
"""
:param inst_classes:
:param inst:
:param pgm0_is_piano:
:return:
"""
if inst.is_drum:
return u'Drums'
if inst.program == 0:
return inst_classes['0']['class'] if pgm0_is_piano else u'Unknown'
return inst_classes[str(inst.program)]['class']
def get_inst_program_name(inst_classes, inst, pgm0_is_piano=False):
"""
:param inst_classes:
:param inst:
:param pgm0_is_piano:
:return:
"""
if inst.is_drum:
return u'Drums'
if inst.program == 0:
return inst_classes['0']['name'] if pgm0_is_piano else u'Unknown'
return inst_classes[str(inst.program)]['name']
def select_plugin(engine_dict, inst_class):
"""
Chooses which Renderman Engine (& thus plugin) randomly
:param engine_dict:
:param inst_class:
:return:
"""
idx = np.random.randint(0, len(engine_dict[inst_class]))
return engine_dict[inst_class].values()[idx], engine_dict[inst_class].keys()[idx]
def parse_parameter_names(param_str, program_name):
result = {}
suf = ' - ' + program_name
for s in param_str.split('\n'):
if not s:
continue
# idx, name, text = s.split(', ')
idx, name = s.split(', ')
if '#' in name or suf not in name:
# '#' means the parameter is not used and
# if the suffix is not in the name, then
# the parameter is for another instrument.
continue
idx = int(idx)
name = name.rsplit(' - ')[0] # TODO: use program name suffix
result[idx] = name
return result
def set_parameters(eng):
parameter_names = parse_parameter_names(eng.get_plugin_parameters_description(),
eng.get_program_name())
params = {}
for idx, name in parameter_names.items():
val = np.random.rand()
eng.set_parameter(idx, val)
params[idx] = {'name': name, 'value': val}
return eng, params
def load_engine(sr, buf, plugin_path, sleep=7.0, verbose=True):
"""
:param sr:
:param buf:
:param plugin_path:
:param preset:
:param sleep:
:param verbose:
:return:
"""
eng = rm.RenderEngine(sr, buf)
assert eng.load_plugin(str(plugin_path))
# Set parameters like so:
# eng.set_parameter(90, 0.5)
time.sleep(sleep)
return eng
def load_engine_konkakt(sr, buf, plugin_path, def_dir, def_name, dest_dir, sleep=7.0, verbose=True):
"""
:param sr: Sample rate to render audio
:param buf: Buffer size (in samples) for rendering frames
:param plugin_path: Absolute path to Kontakt.vst or Kontakt.component (AU)
:param def_dir: Absolute path to the Konkakt defaults directory
:param def_name: Default Kontakt .nkm file to load Kontakt with a state
:param sleep: Sleeps for the specified amount of time. Sometimes Kontakt takes some
time to load all of the samples.
:return: RenderMan engine that has Konkakt plugin loaded with state provided by def_name
"""
copy_and_rename_def(def_dir, def_name, dest_dir)
eng = rm.RenderEngine(sr, buf)
assert eng.load_plugin(plugin_path)
if verbose:
print('Loaded {}'.format(def_name))
time.sleep(sleep)
return eng
def safe_make_dirs(path):
"""
Safe way to make dirs. If the dirs exist, will ignore that error.
:param path:
:return:
"""
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise exc
def get_midi_rule(name):
import midi_inst_rules, inspect
return dict(inspect.getmembers(midi_inst_rules, inspect.isfunction))[name]
def make_output_dir(output_base_path, midi_path):
"""
Output directories mirror the LMD directories. Except every midi file
in LMD is instead a folder that has all of the sources and metadata.
Args:
output_base_path:
midi_path:
Returns:
"""
dirs = midi_path.split(os.sep)[-5:] # get the last 4 directories and midi file name
dirs[-1] = os.path.splitext(dirs[-1])[0] # remove the extension from the file name
dirs = os.sep.join(dirs)
result = os.path.join(output_base_path, dirs)
safe_make_dirs(result)
return result
def file_ready_string(string):
"""
Change a string from 'Something Like This" to "something_like_this"
for ease of saving it as a filename or directory name.
Args:
string:
Returns:
"""
return string.replace(' ', '_').lower()