# WHERE DID I USE SCALING FACTORS TO CONVERT WAV TO MAP? _SAMPLING_RATE = 16000 # Parameter to pass continuous signal to a discrete one _INSTRUMENT_NAME = "Acoustic Grand Piano" # MIDI instrument used _SCALING_FACTORS = pd.Series( {"pitch": 64.024558, "step": 0.101410, "duration": 0.199386} ) # Factors used to normalize song maps def midi_to_notes(midi_file: str) -> pd.DataFrame: pm = pretty_midi.PrettyMIDI(midi_file) instrument = pm.instruments[0] notes = collections.defaultdict(list) # Sort the notes by start time sorted_notes = sorted(instrument.notes, key=lambda note: note.start) prev_start = sorted_notes[0].start for note in sorted_notes: start = note.start end = note.end notes['pitch'].append(note.pitch) notes['start'].append(start) notes['end'].append(end) notes['step'].append(start - prev_start) notes['duration'].append(end - start) prev_start = start return pd.DataFrame({name: np.array(value) for name, value in notes.items()}) def notes_to_midi( notes: pd.DataFrame, out_file: str, velocity: int = 100, # note loudness ) -> pretty_midi.PrettyMIDI: pm = pretty_midi.PrettyMIDI() instrument = pretty_midi.Instrument( program=pretty_midi.instrument_name_to_program( _INSTRUMENT_NAME)) prev_start = 0 for i, note in notes.iterrows(): start = float(prev_start + note['step']) end = float(start + note['duration']) note = pretty_midi.Note( velocity=velocity, pitch=int(note['pitch']), start=start, end=end, ) instrument.notes.append(note) prev_start = start pm.instruments.append(instrument) pm.write(out_file) return pm def display_audio(pm: pretty_midi.PrettyMIDI, seconds=120): waveform = pm.fluidsynth(fs=_SAMPLING_RATE) # Take a sample of the generated waveform to mitigate kernel resets waveform_short = waveform[:seconds*_SAMPLING_RATE] return display.Audio(waveform_short, rate=_SAMPLING_RATE) # Define function to convert song map to wav def map_to_wav(song_map, out_file, instrument_name, velocity=100): contracted_map = tf.squeeze(song_map) song_map_T = contracted_map.numpy().T notes = pd.DataFrame(song_map_T, columns=["pitch", "step", "duration"]).mul(_SCALING_FACTORS, axis=1) notes["pitch"] = notes["pitch"].astype('int32').clip(1, 127) pm = pretty_midi.PrettyMIDI() instrument = pretty_midi.Instrument( program=pretty_midi.instrument_name_to_program( instrument_name)) prev_start = 0 for i, note in notes.iterrows(): start = float(prev_start + note['step']) end = float(start + note['duration']) note = pretty_midi.Note( velocity=velocity, pitch=int(note['pitch']), start=start, end=end, ) instrument.notes.append(note) prev_start = start pm.instruments.append(instrument) pm.write(out_file) return pm def generate_and_display(out_file, instrument_name, model, z_sample=None, velocity=100, seconds=120): song_map = model.generate(z_sample) display.display(imshow(tf.squeeze(song_map)[:,:50])) wav = map_to_wav(song_map, out_file, instrument_name, velocity) return display_audio(wav, seconds)