34
34
from midi_ddsp .utils .audio_io import save_wav
35
35
from midi_ddsp .utils .training_utils import get_hp
36
36
from midi_ddsp .utils .inference_utils import ensure_same_length
37
+ from midi_ddsp .utils .file_utils import pickle_dump
37
38
from midi_ddsp .hparams_synthesis_generator import hparams as hp
38
39
from midi_ddsp .modules .get_synthesis_generator import get_synthesis_generator , \
39
40
get_fake_data_synthesis_generator
@@ -92,7 +93,8 @@ def synthesize_midi(synthesis_generator, expression_generator, midi_file,
92
93
use_fluidsynth = False ,
93
94
sf2_path = '/usr/share/sounds/sf2/FluidR3_GM.sf2' ,
94
95
display_progressbar = True ,
95
- skip_existing_files = False ):
96
+ skip_existing_files = False ,
97
+ save_synth_params = False ):
96
98
"""
97
99
Synthesize a midi file using MIDI-DDSP.
98
100
Args:
@@ -101,13 +103,15 @@ def synthesize_midi(synthesis_generator, expression_generator, midi_file,
101
103
midi_file: The path to the MIDI file.
102
104
pitch_offset: Pitch in semitone to transpose.
103
105
speed_rate: The speed to synthesize the MIDI file.
104
- output_dir: The directory for output audio.
106
+ output_dir: The directory for saving outputs.
107
+ If output_dir is None, outputs will not be written to disk.
105
108
use_fluidsynth: Whether to use FluidSynth for synthesizing instruments
106
109
that are not available in MIDI-DDSP.
107
110
sf2_path: The path to a sf2 soundfont file used for FluidSynth.
108
111
display_progressbar: Whether to display progress bar.
109
112
skip_existing_files: Skip synthesizing MIDI files if already exist
110
113
output folders.
114
+ save_synth_params: also save synthesis parameters.
111
115
112
116
Returns: A dict of output:
113
117
'mix_audio': mix audio,
@@ -134,6 +138,8 @@ def synthesize_midi(synthesis_generator, expression_generator, midi_file,
134
138
conditioning_df_all = []
135
139
part_synth_by_model = []
136
140
midi_audio_all = {}
141
+ midi_synth_params_all = {}
142
+ midi_control_params_all = {}
137
143
138
144
# For each part, predict expressions using MIDI-DDSP,
139
145
# or synthesize using FluidSynth.
@@ -173,12 +179,27 @@ def synthesize_midi(synthesis_generator, expression_generator, midi_file,
173
179
instrument_id_all ,
174
180
display_progressbar = display_progressbar )
175
181
182
+ midi_synth_params = midi_synth_params ['inputs' ]
176
183
for i in range (midi_audio .shape [0 ]):
177
184
part_number = part_synth_by_model [i ]
185
+
186
+ # align audio with part number
178
187
midi_audio_all [part_number ] = midi_audio [i ].numpy ()
179
- else :
180
- midi_control_params = None
181
- midi_synth_params = None
188
+
189
+ # align synthesis parameters with part number
190
+ # get the midi synth parameters
191
+ midi_synth_params_all [part_number ] = {
192
+ k : v [i ].numpy () for k , v in midi_synth_params .items ()}
193
+
194
+ # align control parameters with part number
195
+ # (yusongwu) sorry for mis-aligned variable names between
196
+ # synth_params and control_params due to historical issues
197
+ midi_control_params_all [part_number ] = {
198
+ 'amplitudes' : midi_control_params [1 ][i ].numpy (),
199
+ 'harmonic_distribution' : midi_control_params [2 ][i ].numpy (),
200
+ 'noise_magnitudes' : midi_control_params [3 ][i ].numpy (),
201
+ 'f0_hz' : midi_control_params [0 ][i ].numpy (),
202
+ }
182
203
183
204
# Sorting out and save the wav.
184
205
if output_dir is not None :
@@ -205,17 +226,20 @@ def synthesize_midi(synthesis_generator, expression_generator, midi_file,
205
226
if midi_audio_all :
206
227
midi_audio_mix = np .sum (
207
228
np .stack (ensure_same_length (
208
- [a .astype (np .float ) for a in midi_audio_all .values ()], axis = 0 ),
229
+ [a .astype (np .float64 ) for a in midi_audio_all .values ()], axis = 0 ),
209
230
axis = - 1 ),
210
231
axis = - 1 )
211
232
if output_dir is not None :
212
233
save_wav (midi_audio_mix , os .path .join (output_dir , 'mix.wav' ), 16000 )
234
+ if save_synth_params :
235
+ pickle_dump (midi_synth_params_all ,
236
+ os .path .join (output_dir , 'synth_params.pickle' ))
213
237
output = {
214
238
'mix_audio' : midi_audio_mix ,
215
239
'stem_audio' : midi_audio_all ,
216
240
'part_synth_by_model' : part_synth_by_model ,
217
- 'midi_control_params' : midi_control_params ,
218
- 'midi_synth_params' : midi_synth_params ,
241
+ 'midi_control_params' : midi_control_params_all ,
242
+ 'midi_synth_params' : midi_synth_params_all ,
219
243
'conditioning_df' : conditioning_df_all ,
220
244
}
221
245
else :
@@ -259,6 +283,10 @@ def main():
259
283
action = 'store_true' ,
260
284
help = 'Skip synthesizing MIDI files if already exist '
261
285
'output folders.' )
286
+ parser .add_argument ('--save_synth_params' , dest = 'save_synth_params' ,
287
+ action = 'store_true' ,
288
+ help = 'Save synthesis parameters generated by MIDI-DDSP.' )
289
+
262
290
args = parser .parse_args ()
263
291
264
292
synthesis_generator , expression_generator = load_pretrained_model (
@@ -304,7 +332,8 @@ def main():
304
332
sf2_path = args .sf2_path ,
305
333
use_fluidsynth = args .use_fluidsynth ,
306
334
display_progressbar = True ,
307
- skip_existing_files = args .skip_existing_files
335
+ skip_existing_files = args .skip_existing_files ,
336
+ save_synth_params = args .save_synth_params
308
337
)
309
338
310
339
0 commit comments