def generate(unused_argv): """Generates a basic drum sequence of 4 seconds based on a hard coded primer""" # TODO doc mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() qpm = 120 num_bars = 3 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR seconds_per_bar = num_steps_per_bar * seconds_per_step # Creates a primer sequence that is fed into the model for the generator, # which will generate a sequence based on this one # A DrumTrack models a drum sequence by step, so you have step 1 being the # midi note 36 (bass drum), followed by 3 steps of silence (those four steps # constitutes the first beat or quarter), followed by both notes 36 and 41 # being struck at the same time (followed by silence by these are optional) primer_drums = mm.DrumTrack( [frozenset(pitches) for pitches in [(38, 51), (), (36,), (), (38, 44, 51), (), (36,), (), (), (), (38,), (), (38, 44), (), (36, 51), (), ]]) primer_sequence = primer_drums.to_sequence(qpm=qpm) primer_start_time = 0 primer_end_time = primer_start_time + seconds_per_bar # Defines the start and end of the generation, which starts at the step # after the end of the primer (we'll see in 03.py this calculation makes # it harder to fall on proper beats) and ends at total seconds # The complete generation will thus contain the primer and the total length # needs to be at least the size of the primer # TODO doc generation_start_time = primer_end_time generation_end_time = generation_start_time + (seconds_per_bar * num_bars) generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = 1.1 generator_options.generate_sections.add( start_time=generation_start_time, end_time=generation_end_time) # We are using the primer sequence here instead of an empty sequence sequence = generator.generate(primer_sequence, generator_options) # TODO doc plot_file = os.path.join("output", "out.html") print("Generated plot file: " + str(os.path.abspath(plot_file))) pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) # TODO doc input_ports = [name for name in mido.get_output_names() if "VirtualMIDISynth" in name or "FLUID Synth" in name] if not input_ports: print("Cannot find proper input port in " + str(mido.get_output_names())) print("Playing generated MIDI in input port names: " + str(input_ports)) midi_hub = mh.MidiHub([], input_ports, None) # TODO doc empty_sequence = music_pb2.NoteSequence() player = midi_hub.start_playback(empty_sequence, allow_updates=True) player._channel = 9 # TODO doc wall_start_time = time.time() 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=wall_start_time) # TODO doc try: player.join(generation_end_time) except KeyboardInterrupt: return 0 finally: return 0
def generate(unused_argv): mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() qpm = 120 num_bars = 3 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR seconds_per_bar = num_steps_per_bar * seconds_per_step primer_sequence = mm.midi_io.midi_file_to_note_sequence( os.path.join("primers", "Jazz_Drum_Basic_1_bar.mid")) primer_start_time = 0 primer_end_time = primer_start_time + seconds_per_bar generation_start_time = primer_end_time generation_end_time = generation_start_time + (seconds_per_bar * num_bars) generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = 1.1 generator_options.generate_sections.add(start_time=generation_start_time, end_time=generation_end_time) sequence = generator.generate(primer_sequence, generator_options) plot_file = os.path.join("output", "out.html") pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) print(f"Generated plot file: {os.path.abspath(plot_file)}") input_ports = [ name for name in mido.get_output_names() if "VirtualMIDISynth" in name or "FLUID Synth" in name ] if not input_ports: raise Exception(f"Cannot find proper input port in: " f"{mido.get_output_names()}") print(f"Playing generated MIDI in input port names: {input_ports}") midi_hub = mh.MidiHub([], input_ports, None) empty_sequence = music_pb2.NoteSequence() player = midi_hub.start_playback(empty_sequence, allow_updates=True) player._channel = 9 # We calculate the length of the generated sequence in seconds, # which gives up the loop time in seconds loop_time = generation_end_time - primer_start_time print(f"Loop time is {loop_time}") # We get the current wall time before the loop starts wall_start_time = time.time() while True: try: # We get the current wall time for this loop start tick_wall_start_time = time.time() sequence_adjusted = music_pb2.NoteSequence() sequence_adjusted.CopyFrom(sequence) sequence_adjusted = adjust_sequence_times(sequence_adjusted, tick_wall_start_time) player.update_sequence(sequence_adjusted, start_time=tick_wall_start_time) # We calculate the elapsed time from the start of the program tick_start_time = time.time() - wall_start_time # We sleep for the remaining time in the loop. It means that whatever # how much time this loop took, we'll be waking up at the proper # next bar. # For example, if the loop needs to be 8 seconds, and we took 2.4 seconds # executing and arriving here, then we'll sleep only 5.6 seconds to wake # up with proper timing. sleep_time = loop_time - (tick_start_time % loop_time) print(f"Sleeping for {sleep_time}") time.sleep(sleep_time) except KeyboardInterrupt: print(f"Stopping") return 0
def generate(unused_argv): # Downloads the bundle from the magenta website mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) # Initialize the generator "drum_kit" generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() # Define constants qpm = 120 num_bars = 3 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR seconds_per_bar = num_steps_per_bar * seconds_per_step # Use a priming sequence primer_sequence = mm.midi_io.midi_file_to_note_sequence( os.path.join("primers", "Jazz_Drum_Basic_1_bar.mid")) primer_start_time = 0 primer_end_time = primer_start_time + seconds_per_bar # Calculates the generation start and end time generation_start_time = primer_end_time generation_end_time = generation_start_time + (seconds_per_bar * num_bars) generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = 1.1 generator_options.generate_sections.add(start_time=generation_start_time, end_time=generation_end_time) # Generates on primer sequence sequence = generator.generate(primer_sequence, generator_options) # Outputs the plot os.makedirs("output", exist_ok=True) plot_file = os.path.join("output", "out.html") pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) print(f"Generated plot file: {os.path.abspath(plot_file)}") # We find the proper input port for the software synth # (which is the output port for Magenta) output_ports = [ name for name in mido.get_output_names() if args.midi_port in name ] if not output_ports: raise Exception(f"Cannot find proper output ports in: " f"{mido.get_output_names()}") print(f"Playing generated MIDI in output port names: {output_ports}") # Start a new MIDI hub on that port (output only) midi_hub = MidiHub(input_midi_ports=[], output_midi_ports=output_ports, texture_type=None) # Start on a empty sequence, allowing the update of the # sequence for later. We don't especially need that right # now, because we could play the sequence immediately, but # it will be useful for later examples to have a player to # update new sequences with. empty_sequence = music_pb2.NoteSequence() player = midi_hub.start_playback(empty_sequence, allow_updates=True) # Remember that GM 1 compatible synthesizer will play the drums # sound bank if the MIDI channel is 10 (but the channel is zero # indexed in Magenta MIDI hub so you have to use 9). player._channel = 9 # Now we can play our sequence, but we need to adjust it first. # The MIDI player will play the sequence according to wall time, # but our sequence starts at 0. # Create a new empty note sequence, copy the sequence # we want to play in the empty sequence, then move the # start of the sequence by wall_start_time amount wall_start_time = time.time() sequence_adjusted = music_pb2.NoteSequence() sequence_adjusted.CopyFrom(sequence) sequence_adjusted = adjust_sequence_times(sequence_adjusted, wall_start_time) # The update sequence is the equivalent of "play" player.update_sequence(sequence_adjusted, start_time=wall_start_time) # We "join" on the thread, meaning the call will block # until the player has finished. Because the thread # never stops, this call will block indefinitely. By # adding a timeout of generation_end_time, the call will # return after the end of the sequence being played. try: print(f"Playing for {generation_end_time}") player.join(generation_end_time) except KeyboardInterrupt: # The KeyboardInterrupt is important if you want to press # CTRL-C during the playback to stop the player. print(f"Stopping") return 0
def generate(unused_argv): """Generates a basic drum sequence of 4 seconds""" # Downloads the bundle from the magenta website, a bundle (.mag file) is a # trained model that is used by magenta mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) # Initialize the generator "drum_kit", this need to fit the bundle we # downloaded before generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() # Change the number of steps to be generated, which will define the length # of the generated sequence, used with the qpm. At 120 qpm, this # is equal to 4 seconds num_steps = 32 # Change the temperature: the bigger this value, the more random is the # generation, with 1 being the default value, 1.25 being more random, # 0.75 being less random temperature = 1 # Change the quarter per minute (also called BPM or beat per minute), a # measure of tempo. At 120 qpm, you have two beat per seconds qpm = 120 # Calculate the number of seconds per step, useful to find the total time # of the generation in seconds. The steps per quarter in the generator is by # default 4, so the generator will generate 8 steps per bar # TODO why 8 steps per bar seconds_per_step = 60.0 / qpm / generator.steps_per_quarter total_seconds = num_steps * seconds_per_step # The generator options are the parameters passed to the generator, why is # the temperature and the generation section, from 0 to the total of seconds, # where the generator will generate notes generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = temperature generator_options.generate_sections.add(start_time=0, end_time=total_seconds) # Generates the notes from the arguments, starting with an empty note # sequence (no primer) empty_note_sequence = music_pb2.NoteSequence() sequence = generator.generate(empty_note_sequence, generator_options) # Outputs the midi file in the output directory midi_file = os.path.join("output", "out.mid") mm.midi_io.note_sequence_to_midi_file(sequence, midi_file) print("Generated midi file: " + str(os.path.abspath(midi_file))) # Outputs the plot file in the output directory and opens your browser for # visualisation plot_file = os.path.join("output", "out.html") print("Generated plot file: " + str(os.path.abspath(plot_file))) pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) return 0
def generate(unused_argv): # Downloads the bundle from the magenta website mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) # Initialize the generator "drum_kit" generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() # Define constants qpm = 120 num_bars = 3 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR seconds_per_bar = num_steps_per_bar * seconds_per_step # Use a priming sequence primer_sequence = mm.midi_io.midi_file_to_note_sequence( os.path.join("primers", "Jazz_Drum_Basic_1_bar.mid")) primer_start_time = 0 primer_end_time = primer_start_time + seconds_per_bar # Calculates the generation start and end time generation_start_time = primer_end_time generation_end_time = generation_start_time + (seconds_per_bar * num_bars) generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = 1.1 generator_options.generate_sections.add(start_time=generation_start_time, end_time=generation_end_time) # Generates on primer sequence sequence = generator.generate(primer_sequence, generator_options) # Outputs the plot os.makedirs("output", exist_ok=True) plot_file = os.path.join("output", "out.html") pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) print(f"Generated plot file: {os.path.abspath(plot_file)}") # We find the proper input port for the software synth # (which is the output port for Magenta) output_ports = [ name for name in mido.get_output_names() if args.midi_port in name ] if not output_ports: raise Exception(f"Cannot find proper output ports in: " f"{mido.get_output_names()}") print(f"Playing generated MIDI in output port names: {output_ports}") # Start a new MIDI hub on that port (output only) midi_hub = MidiHub(input_midi_ports=[], output_midi_ports=output_ports, texture_type=None) # Start on a empty sequence, allowing the update of the # sequence for later. empty_sequence = music_pb2.NoteSequence() player = midi_hub.start_playback(empty_sequence, allow_updates=True) player._channel = 9 # We want a period in seconds of 4 bars (which is the loop # length). Using 240 / qpm, we have a period of 1 bar, or # 2 seconds at 120 qpm. We multiply that by 4 bars. # (using the Decimal class for more accuracy) period = Decimal(240) / qpm period = period * (num_bars + 1) sleeper = concurrency.Sleeper() while True: try: # We get the next tick time by using the period # to find the absolute tick number (since epoch), # and multiplying by the period length. This is # used to sleep until that time. # We also find the current tick time for the player # to update. # (using the Decimal class for more accuracy) now = Decimal(time.time()) tick_number = int(now // period) tick_number_next = tick_number + 1 tick_time = tick_number * period tick_time_next = tick_number_next * period print( f"now {now} tick_time {tick_time} tick_time_next {tick_time_next}" ) # Update the player time to the current tick time sequence_adjusted = music_pb2.NoteSequence() sequence_adjusted.CopyFrom(sequence) sequence_adjusted = adjust_sequence_times(sequence_adjusted, float(tick_time)) player.update_sequence(sequence_adjusted, start_time=float(tick_time)) # Sleep until the next tick time sleeper.sleep_until(float(tick_time_next)) except KeyboardInterrupt: print(f"Stopping") return 0
def generate(unused_argv): """Generates a basic drum sequence of 4 seconds based on a hard coded primer""" mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() num_steps = 32 temperature = 1 qpm = 120 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter total_seconds = num_steps * seconds_per_step # Creates a primer sequence that is fed into the model for the generator, # which will generate a sequence based on this one # A DrumTrack models a drum sequence by step, so you have step 1 being the # midi note 36 (bass drum), followed by 3 steps of silence (those four steps # constitutes the first beat or quarter), followed by both notes 36 and 41 # being struck at the same time (followed by silence by these are optional) # TODO why quarter # TODO better example # TODO check midi note meaning primer_drums = magenta.music.DrumTrack([ frozenset(pitches) for pitches in [(36, ), (), (), (), (36, 41), (), (), ()] ]) primer_sequence = primer_drums.to_sequence(qpm=120) primer_end_time = primer_sequence.total_time # Defines the start and end of the generation, which starts at the step # after the end of the primer (we'll see in 03.py this calculation makes # it harder to fall on proper beats) and ends at total seconds # The complete generation will thus contain the primer and the total length # needs to be at least the size of the primer generation_start_time = primer_end_time + seconds_per_step generation_end_time = total_seconds generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = temperature generator_options.generate_sections.add(start_time=generation_start_time, end_time=generation_end_time) # We are using the primer sequence here instead of an empty sequence sequence = generator.generate(primer_sequence, generator_options) midi_file = os.path.join("output", "out.mid") mm.midi_io.note_sequence_to_midi_file(sequence, midi_file) print("Generated midi file: " + str(os.path.abspath(midi_file))) plot_file = os.path.join("output", "out.html") print("Generated plot file: " + str(os.path.abspath(plot_file))) pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) return 0
from visual_midi import Plotter import magenta.music as mm import os import sys import glob f = '*.mid' d = os.getcwd() for file in glob.glob(os.path.join(d, f)): sequence = mm.midi_io.midi_file_to_note_sequence( os.path.join("simplemidi", file)) plot_filename = "%s.html" % (file) plot_path = os.path.join("output", plot_filename) pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_path) plotter.save(pretty_midi, plot_path) print("Generated plot file: " + str(os.path.abspath(plot_path)))
def generate(unused_argv): mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() qpm = 120 num_bars = 3 seconds_per_step = 60.0 / qpm / generator.steps_per_quarter num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR seconds_per_bar = num_steps_per_bar * seconds_per_step # This time we get the primer from disk instead of hard coding it primer_sequence = mm.midi_io.midi_file_to_note_sequence( os.path.join("primers", "Jazz_Drum_Basic_1_bar.mid")) primer_start_time = 0 primer_end_time = primer_start_time + seconds_per_bar generation_start_time = primer_end_time generation_end_time = generation_start_time + (seconds_per_bar * num_bars) generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = 1.1 generator_options.generate_sections.add(start_time=generation_start_time, end_time=generation_end_time) sequence = generator.generate(primer_sequence, generator_options) plot_file = os.path.join("output", "out.html") pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) print("Generated plot file: " + str(os.path.abspath(plot_file))) # We find the proper input port for the software synth, # this should work on all platforms (if you followed the # installation instructions) input_ports = [ name for name in mido.get_output_names() if "VirtualMIDISynth" in name or "FLUID Synth" in name ] if not input_ports: print("Cannot find proper input port in " + str(mido.get_output_names())) print("Playing generated MIDI in input port names: " + str(input_ports)) # Start a new MIDI hub on that port (incoming only) midi_hub = mh.MidiHub([], input_ports, None) # Start on a empty sequence, allowing the update of the # sequence for later. We don't especially need that right # now, because we could play the sequence immediately, but # it will be useful for later examples to have a player to # update new sequences with. empty_sequence = music_pb2.NoteSequence() player = midi_hub.start_playback(empty_sequence, allow_updates=True) # Remember that GM 1 compatible synthesizer will play the drums # sound bank if the MIDI channel is 10 (but the channel is zero # indexed in Magenta MIDI hub so you have to use 9). player._channel = 9 # Now we can play our sequence, but we need to adjust it first. # The MIDI player will play the sequence according to wall time, # but our sequence starts at 0. # Create a new empty note sequence, copy the sequence # we want to play in the empty sequence, then move the # start of the sequence by wall_start_time amount wall_start_time = time.time() sequence_adjusted = music_pb2.NoteSequence() sequence_adjusted.CopyFrom(sequence) sequence_adjusted = adjust_sequence_times(sequence_adjusted, wall_start_time) # The update sequence is the equivalent of "play" player.update_sequence(sequence_adjusted, start_time=wall_start_time) # We "join" on the thread, meaning the call will block # until the player has finished. Because the thread # never stops, this call will block indefinitely. By # adding a timeout of generation_end_time, the call will # return after the end of the sequence being played. try: player.join(generation_end_time) except KeyboardInterrupt: # The KeyboardInterrupt is important if you want to press # CTRL-C during the playback to stop the player. return 0 finally: return 0
def run(self): # TODO sequence = self._primer_sequence player = self._midi_hub.start_playback(sequence, allow_updates=True) # TODO seconds_per_step = 60.0 / self._qpm / self._sequence_generator.steps_per_quarter num_steps_per_bar = self._sequence_generator.steps_per_quarter * 2 seconds_per_bar = num_steps_per_bar * seconds_per_step seconds_per_loop = self._bar_per_loop * seconds_per_bar # TODO MOVE plotter = Plotter(max_bar=16, live_reload=True) pretty_midi = pm.PrettyMIDI() pretty_midi.instruments.append(pm.Instrument(0)) pretty_midi.instruments[0].append(pm.Note(100, 36, 0, 1)) # TODO wall_start_time = time.time() # TODO for bar_count in range(0, sys.maxsize): # TODO cursor_time = bar_count * seconds_per_loop # TODO 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=cursor_time) # TODO MOVE TO UTILS pretty_sequence = mm.midi_io.note_sequence_to_pretty_midi(sequence) for instrument in pretty_sequence.instruments: for note in instrument.notes: pretty_midi.instruments[0].notes.append(note) plotter.show(pretty_midi, self._output_file) # TODO loop_start_time = cursor_time loop_end_time = loop_start_time + seconds_per_loop generation_start_time = loop_end_time generation_end_time = generation_start_time + seconds_per_loop generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = 1 generator_options.generate_sections.add( start_time=generation_start_time, end_time=generation_end_time) # TODO if bar_count % self._num_loops == 0: print("GENERATING") sequence = self._sequence_generator.generate( sequence, generator_options) sequence = sequences_lib.trim_note_sequence( sequence, generation_start_time, generation_end_time) else: print("LOOPING") sequence = sequences_lib.trim_note_sequence( sequence, loop_start_time, loop_end_time) sequence = sequences_lib.shift_sequence_times( sequence, seconds_per_loop) # TODO 1 wake up per bar sleep_time = seconds_per_loop - ( (time.time() - wall_start_time) % seconds_per_loop) time.sleep(sleep_time)
def generate(unused_argv): # Downloads the bundle from the magenta website, a bundle (.mag file) is a # trained model that is used by magenta mm.notebook_utils.download_bundle("drum_kit_rnn.mag", "bundles") bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join("bundles", "drum_kit_rnn.mag")) # Initialize the generator "drum_kit", this need to fit the bundle we # downloaded before generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) generator.initialize() # We will generate 3 bars, so with a # 1 bar primer we'll have 4 bars total num_bars = 3 qpm = 120 # The steps per quarter for this generator # is 4 steps per quarter seconds_per_step = 60.0 / qpm / generator.steps_per_quarter # We are using a default 16 steps per bar, which is # 4/4 music sampled at 4 steps per quarter note num_steps_per_bar = constants.DEFAULT_STEPS_PER_BAR # We calculate how many seconds per bar for # the generation time seconds_per_bar = num_steps_per_bar * seconds_per_step print(f"Seconds per step: {seconds_per_step}") print(f"Seconds per bar: {seconds_per_bar}") # Creates a primer sequence that is fed into the model for the generator, # which will generate a sequence based on this one # A DrumTrack models a drum sequence by step, so you have step 1 being the # midi note 36 (bass drum), followed by 3 steps of silence (those four steps # constitutes the first beat or quarter), followed by both notes 36 and 41 # being struck at the same time (followed by silence by these are optional) primer_drums = mm.DrumTrack([ frozenset(pitches) for pitches in [ (38, 51), (), (36, ), (), (38, 44, 51), (), (36, ), (), (), (), (38, ), (), (38, 44), (), (36, 51), (), ] ]) primer_sequence = primer_drums.to_sequence(qpm=qpm) # We store those time because the generation # will start after the end of the primer primer_start_time = 0 primer_end_time = primer_start_time + seconds_per_bar # We calculate the generation start and end # for a duration of num_bars generation_start_time = primer_end_time generation_end_time = generation_start_time + (seconds_per_bar * num_bars) print(f"Primer start and end:" f"[{primer_start_time}, {primer_end_time}]") print(f"Generation start and end:" f"[{generation_start_time}, {generation_end_time}]") # The generator interface is common for all models generator_options = generator_pb2.GeneratorOptions() # Add a bit of temperature for more flavor temperature = 1.1 print(f"Temperature: {temperature}") generator_options.args['temperature'].float_value = temperature # Defines the generation section generator_options.generate_sections.add(start_time=generation_start_time, end_time=generation_end_time) # We are using the primer sequence here instead of an empty sequence, # the resulting sequence is a NoteSequence instance sequence = generator.generate(primer_sequence, generator_options) # Write the resulting midi file to the output directory midi_file = os.path.join("output", "out.mid") mm.midi_io.note_sequence_to_midi_file(sequence, midi_file) print(f"Generated midi file: {os.path.abspath(midi_file)}") # Write the resulting plot file to the output directory plot_file = os.path.join("output", "out.html") pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence) plotter = Plotter() plotter.show(pretty_midi, plot_file) print(f"Generated plot file: {os.path.abspath(plot_file)}") return 0