|
43 | 43 | from ddsp.training import postprocessing
|
44 | 44 | from ddsp.training import train_util
|
45 | 45 | import gin
|
| 46 | +import librosa |
| 47 | +import note_seq |
46 | 48 | import tensorflow as tf
|
47 | 49 | from tensorflowjs.converters import converter
|
48 | 50 |
|
|
99 | 101 | 'training examples. Only used if no binding to train.data_provider can '
|
100 | 102 | 'be found.')
|
101 | 103 |
|
| 104 | +# Reverb Impulse Response. |
| 105 | +flags.DEFINE_boolean('reverb', True, |
| 106 | + 'Save reverb impulse response as a wav file.') |
| 107 | +flags.DEFINE_integer('reverb_sample_rate', 44100, |
| 108 | + 'If not None, also save resampled reverb ir.') |
| 109 | + |
102 | 110 | FLAGS = flags.FLAGS
|
103 | 111 |
|
104 | 112 |
|
@@ -143,6 +151,7 @@ def get_metadata_dict(data_provider, model_path):
|
143 | 151 | # Get power rate and size.
|
144 | 152 | frame_size = gin.query_parameter('%frame_size')
|
145 | 153 | frame_rate = gin.query_parameter('%frame_rate')
|
| 154 | + sample_rate = gin.query_parameter('%sample_rate') |
146 | 155 |
|
147 | 156 | # Compute stats.
|
148 | 157 | full_metadata = postprocessing.compute_dataset_statistics(
|
@@ -171,6 +180,12 @@ def get_metadata_dict(data_provider, model_path):
|
171 | 180 | output_splits['harmonic_distribution'],
|
172 | 181 | 'num_noise_amps':
|
173 | 182 | output_splits['noise_magnitudes'],
|
| 183 | + 'frame_rate': |
| 184 | + frame_rate, |
| 185 | + 'frame_size': |
| 186 | + frame_size, |
| 187 | + 'sample_rate': |
| 188 | + sample_rate, |
174 | 189 | }
|
175 | 190 | return lite_metadata
|
176 | 191 |
|
@@ -243,6 +258,35 @@ def saved_model_to_tflite(input_dir, save_dir, metadata_file=None):
|
243 | 258 | print('TFLite Conversion Success!')
|
244 | 259 |
|
245 | 260 |
|
| 261 | +def export_impulse_response(model_path, save_dir, target_sr=None): |
| 262 | + """Extracts and saves the reverb impulse response.""" |
| 263 | + with gin.unlock_config(): |
| 264 | + ddsp.training.inference.parse_operative_config(model_path) |
| 265 | + model = ddsp.training.models.Autoencoder() |
| 266 | + model.restore(model_path) |
| 267 | + sr = model.processor_group.harmonic.sample_rate |
| 268 | + reverb = model.processor_group.reverb |
| 269 | + reverb.build(unused_input_shape=[]) |
| 270 | + ir = reverb.get_controls(audio=tf.zeros([1, 1]))['ir'].numpy()[0] |
| 271 | + print(f'Reverb Impulse Response is {ir.shape[0] / sr} seconds long') |
| 272 | + |
| 273 | + def save_ir(ir, sr): |
| 274 | + """Save the impulse response.""" |
| 275 | + ir_path = os.path.join(save_dir, f'reverb_ir_{sr}_hz.wav') |
| 276 | + with tf.io.gfile.GFile(ir_path, 'wb') as f: |
| 277 | + wav_data = note_seq.audio_io.samples_to_wav_data(ir, sr) |
| 278 | + f.write(wav_data) |
| 279 | + |
| 280 | + # Save to original impulse response. |
| 281 | + save_ir(ir, sr) |
| 282 | + |
| 283 | + # Save the resampled impulse response. |
| 284 | + if target_sr is not None: |
| 285 | + sr = target_sr |
| 286 | + ir = librosa.resample(ir, orig_sr=sr, target_sr=target_sr) |
| 287 | + save_ir(ir, sr) |
| 288 | + |
| 289 | + |
246 | 290 | def ensure_exits(dir_path):
|
247 | 291 | """Make directory if none exists."""
|
248 | 292 | if not tf.io.gfile.exists(dir_path):
|
@@ -275,6 +319,10 @@ def main(unused_argv):
|
275 | 319 | save_dir = train_util.expand_path(save_dir)
|
276 | 320 | ensure_exits(save_dir)
|
277 | 321 |
|
| 322 | + # Save reverb impulse response. |
| 323 | + if FLAGS.reverb: |
| 324 | + export_impulse_response(model_path, save_dir, FLAGS.reverb_sample_rate) |
| 325 | + |
278 | 326 | # Save metadata.
|
279 | 327 | if FLAGS.metadata:
|
280 | 328 | metadata_path = os.path.join(save_dir, 'metadata.json')
|
|
0 commit comments