def render(self, sf2_path=None, max_duration=None, sample_rate=44100): """Generate waveform for the stored sequence params: sf2_path: needs to be specified on first run. To run without the ability to render set to None The soundfont file will be loaded and shared across all instances of the class. If a new filename is specified, the new one will be loaded. """ if note_sequence.fl is None or note_sequence.sfid is None: if sf2_path is None: raise ValueError("sf2_path needs to specified on first \ instance creation or class method \ _init_fluidsynth should be called first.") if sf2_path is not None and note_sequence.sf_path != sf2_path: note_sequence._init_fluidsynth(sf2_path, fs=44100) note_sequence.sf_path = sf2_path mid = midi_io.note_sequence_to_pretty_midi(self.sequence) wf = self._fluidsynth_midi_stateful(mid, fs=sample_rate, normalize=False) vel_max = max(note.velocity for note in self.sequence.notes) if len(self.sequence.notes) == 1: vel_max = max(1, vel_max - 12) wf = wf * (vel_max / 128.0)**4 / np.abs(wf).max() if max_duration is None: return wf else: return wf[:max_duration * sample_rate]
def synthesize(sequence, sample_rate, wave=np.sin): """Synthesizes audio from a music_pb2.NoteSequence using a waveform. This uses the pretty_midi `synthesize` method. Sound quality will be lower than using `fluidsynth` with a good SoundFont. Args: sequence: A music_pb2.NoteSequence to synthesize. sample_rate: An integer audio sampling rate in Hz. wave: Function that returns a periodic waveform. Returns: A 1-D numpy float array containing the synthesized waveform. """ midi = midi_io.note_sequence_to_pretty_midi(sequence) return midi.synthesize(fs=sample_rate, wave=wave)
def fluidsynth(sequence, sample_rate, sf2_path=None): """Synthesizes audio from a music_pb2.NoteSequence using FluidSynth. This uses the pretty_midi `fluidsynth` method. In order to use this synth, you must have FluidSynth and pyFluidSynth installed. Args: sequence: A music_pb2.NoteSequence to synthesize. sample_rate: An integer audio sampling rate in Hz. sf2_path: A string path to a SoundFont. If None, uses the TimGM6mb.sf2 file included with pretty_midi. Returns: A 1-D numpy float array containing the synthesized waveform. """ midi = midi_io.note_sequence_to_pretty_midi(sequence) return midi.fluidsynth(fs=sample_rate, sf2_path=sf2_path)
def decode(self, ids, strip_extraneous=False, return_pm=False): """Transform a sequence of event indices into a performance MIDI file. Args: ids: List of performance event indices. strip_extraneous: Whether to strip EOS and padding from the end of `ids`. Returns: Path to the temporary file where the MIDI was saved. """ if strip_extraneous: ids = text_encoder.strip_ids(ids, list(range(self.num_reserved_ids))) # Decode indices corresponding to event n-grams back into the n-grams. event_ids = [] for i in ids: if i >= self.unigram_vocab_size: event_ids += self._ngrams[i - self.unigram_vocab_size] else: event_ids.append(i) performance = magenta.music.Performance( quantized_sequence=None, steps_per_second=self._steps_per_second, num_velocity_bins=self._num_velocity_bins, is_ctrl_changes=self.is_ctrl_changes) for i in event_ids: performance.append( self._encoding.decode_event(i - self.num_reserved_ids)) ns = performance.to_sequence(is_ctrl_changes=self.is_ctrl_changes) if return_pm: pm = note_sequence_to_pretty_midi(ns) return pm else: _, tmp_file_path = tempfile.mkstemp('_decode.mid') magenta.music.sequence_proto_to_midi_file(ns, tmp_file_path) return tmp_file_path
def generate(unused_argv): # Bundle TODO describe notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) # Generator TODO describe generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() # TODO describe magenta.music.DrumTrack([frozenset([36])]) primer_drums = magenta.music.DrumTrack([ frozenset(pitches) for pitches in [(36, ), (), (), (), (46, ), (), (), ()] ]) primer_sequence = primer_drums.to_sequence(qpm=120) # TODO describe qpm = 120 # TODO describe # steps_per_quarter = 4 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter # TODO describe num_steps = 32 # TODO describe total_seconds = num_steps * seconds_per_step # TODO describe # TODO same as min / max in 02 primer_end_time = primer_sequence.total_time # TODO describe start_time = primer_end_time + seconds_per_step end_time = total_seconds # TODO describe generator_options = generator_pb2.GeneratorOptions() generator_options.generate_sections.add(start_time=1, end_time=end_time) # TODO describe generator_options.args['temperature'].float_value = 0.1 generator_options.args['beam_size'].int_value = 1 generator_options.args['branch_factor'].int_value = 1 generator_options.args['steps_per_iteration'].int_value = 1 # TODO describe sequence = generator.generate(primer_sequence, generator_options) # TODO print last_end_time = max(n.end_time for n in sequence.notes) first_start_time = min(n.start_time for n in sequence.notes) primer_length = last_end_time - first_start_time print("seconds_per_step: " + str(seconds_per_step)) print("num_steps: " + str(num_steps)) print("total_seconds: " + str(total_seconds)) print("primer_end_time: " + str(primer_end_time)) print("start_time: " + str(start_time)) print("end_time: " + str(end_time)) print("last_end_time: " + str(last_end_time)) print("first_start_time: " + str(first_start_time)) print("primer_length: " + str(primer_length)) # TODO describe midi_file = os.path.join("output", "out.mid") midi_io.note_sequence_to_midi_file(sequence, midi_file) print(midi_file) # TODO describe plot_file = os.path.join("output", "out.html") print(plot_file) pm = midi_io.note_sequence_to_pretty_midi(sequence) output_file(plot_file) plot = plot_midi(pm) show(plot) return 0
def run(self): magenta.music.DrumTrack([frozenset([36])]) primer_drums = magenta.music.DrumTrack( [frozenset(pitches) for pitches in [(36, ), (), (), (), (46, )]]) sequence = primer_drums.to_sequence(qpm=120) player = self._midi_hub.start_playback(sequence, allow_updates=True) wall_start_time = time.time() # TODO describe qpm = 120 # TODO describe # steps_per_quarter = 4 seconds_per_step = 60.0 / qpm / self._sequence_generator.steps_per_quarter # TODO describe num_steps = 32 # TODO describe total_seconds = num_steps * seconds_per_step # TODO describe primer_end_time = sequence.total_time # TODO describe start_time = primer_end_time + seconds_per_step end_time = total_seconds for index in range(0, sys.maxsize): tick_wall_start_time = time.time() # TODO describe start_time2 = start_time + index * total_seconds end_time2 = end_time + index * total_seconds # TODO describe generator_options = generator_pb2.GeneratorOptions() generator_options.generate_sections.add(start_time=start_time2, end_time=end_time2) # TODO describe generator_options.args['temperature'].float_value = 0.1 generator_options.args['beam_size'].int_value = 1 generator_options.args['branch_factor'].int_value = 1 generator_options.args['steps_per_iteration'].int_value = 1 # TODO describe print("index: " + str(index)) print("primer_end_time: " + str(primer_end_time)) print("start_time: " + str(start_time)) print("start_time2: " + str(start_time2)) print("end_time: " + str(end_time)) print("end_time2: " + str(end_time2)) print("wall_start_time: " + str(wall_start_time)) print("tick_wall_start_time: " + str(tick_wall_start_time)) print("tick_wall_start_time (adjusted): " + str(tick_wall_start_time - wall_start_time)) sequence = self._sequence_generator.generate( sequence, generator_options) sequence_adjusted = music_pb2.NoteSequence() sequence_adjusted.CopyFrom(sequence) sequence_adjusted = adjust_sequence_times(sequence_adjusted, wall_start_time) player.update_sequence(sequence_adjusted, start_time=tick_wall_start_time) pm = midi_io.note_sequence_to_pretty_midi(sequence) output_file(self._output_file) plot = plot_midi(pm) show(plot) time.sleep(total_seconds - ((time.time() - wall_start_time) % total_seconds))