def generateNewSequence(input_sequence, num_steps, temperature, write_to_file = False): input_sequence = mm.quantize_note_sequence(input_sequence, 8) bundle = sequence_generator_bundle.read_bundle_file('drum_kit_rnn.mag') generator_map = drums_rnn_sequence_generator.get_generator_map() drum_rnn = generator_map['drum_kit'](checkpoint=None, bundle=bundle) drum_rnn.initialize() qpm = input_sequence.tempos[0].qpm last_end_time = (max(n.end_time for n in input_sequence.notes) if input_sequence.notes else 0) total_seconds = num_steps * input_sequence.quantization_info.steps_per_quarter; generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = temperature generate_section = generator_options.generate_sections.add(start_time=last_end_time, end_time=total_seconds) new_sequence = drum_rnn.generate(input_sequence, generator_options) new_sequence.quantization_info.steps_per_quarter = 8 mm.quantize_note_sequence(new_sequence, 8) if (write_to_file == True): mm.sequence_proto_to_midi_file(input_sequence, 'oldSequence.mid') mm.sequence_proto_to_midi_file(new_sequence, 'newSequence.mid') return new_sequence
def generateNewSequence(input_sequence, temperature, write_to_file): input_sequence = mm.quantize_note_sequence(input_sequence, 8) bundle = sequence_generator_bundle.read_bundle_file( '/Library/Application Support/Quin Scacheri/Magenta Beats/drum_kit_rnn.mag' ) generator_map = drums_rnn_sequence_generator.get_generator_map() drum_rnn = generator_map['drum_kit'](checkpoint=None, bundle=bundle) drum_rnn.initialize() qpm = input_sequence.tempos[0].qpm last_end_time = (max( n.end_time for n in input_sequence.notes) if input_sequence.notes else 0) # total_seconds = num_steps * input_sequence.quantization_info.steps_per_quarter; generator_options = generator_pb2.GeneratorOptions() generator_options.args['temperature'].float_value = temperature generate_section = generator_options.generate_sections.add( start_time=last_end_time, end_time=8.0) new_sequence = drum_rnn.generate(input_sequence, generator_options) new_sequence = mm.trim_note_sequence(new_sequence, 2.0, 4.0) new_sequence = mm.quantize_note_sequence(new_sequence, 4) # # new_sequence.quantization_info.steps_per_quarter = 8 if (True): mm.sequence_proto_to_midi_file(input_sequence, 'primer.mid') mm.sequence_proto_to_midi_file(new_sequence, 'new_sequence.mid') return new_sequence
def _init_generator(): bundle_file = mm.sequence_generator_bundle.read_bundle_file( './lib/drum_kit_rnn.mag') generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map['drum_kit'](bundle=bundle_file) return generator
def produce_drum_generator(): BUNDLE_DIR = '/home/jovyan/models/' MODEL_NAME = 'drum_kit' BUNDLE_NAME = 'drum_kit_rnn.mag' mm.notebook_utils.download_bundle(BUNDLE_NAME, BUNDLE_DIR) bundle = mm.sequence_generator_bundle.read_bundle_file( os.path.join(BUNDLE_DIR, BUNDLE_NAME)) drum_generator_map = drums_rnn_sequence_generator.get_generator_map() drum_generator = drum_generator_map[MODEL_NAME](checkpoint=None, bundle=bundle) return drum_generator
def get_drums_generator(bundle, ) -> DrumsRnnSequenceGenerator: """ Initializes a drums_rnn generator, not taking a checkpoint as an argument Returns: DrumsRnnSequenceGenerator: a sequence generator for the drums_rnn model """ generator_map = drums_rnn_sequence_generator.get_generator_map() generator = generator_map[DRUMS_KIT_RNN_GENERATOR_ID](checkpoint=None, bundle=bundle) generator.initialize() return generator
def app(unused_argv): """TODO app""" 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() sequence_generator = generator_map["drum_kit"](checkpoint=None, bundle=bundle) sequence_generator.initialize() primer_drums = magenta.music.DrumTrack( [frozenset(pitches) for pitches in [(36, ), (), (), (), (46, )]]) primer_sequence = primer_drums.to_sequence(qpm=120) qpm = 120 # TODO Parameters output_file = os.path.join("output", "out.html") # TODO Parameters bar_per_loop = 2 # TODO Parameters num_loops = 4 # TODO hub = midi_hub.MidiHub(["magenta_in 1"], ["VirtualMIDISynth #1 0"], midi_hub.TextureType.POLYPHONIC) # TODO looper = LooperMidi( hub, sequence_generator, primer_sequence, output_file=output_file, qpm=qpm, bar_per_loop=bar_per_loop, num_loops=num_loops, ) looper.start() looper.join() return 0
def extendDrums(): dt = createDrumTrack() print("Initializing Drums RNN...") bundle = sequence_generator_bundle.read_bundle_file('drum_kit_rnn.mag') generator_map = drums_rnn_sequence_generator.get_generator_map() drum_rnn = generator_map['drum_kit'](checkpoint=None, bundle=bundle) drum_rnn.initialize() input_sequence = drums # change this to teapot if you want num_steps = 128 # change this for shorter or longer sequences temperature = 1.0 # the higher the temperature the more random the sequence. # Set the start time to begin on the next step after the last note ends. # new_start_time = generator_options = generator_pb2.GeneratorOptions() # generator_options.args['primer_sequence'].string_value = "drums.mid" generate_section = generator_options.generate_sections.add(start_time=last_end_time + seconds_per_step, end_time=total_seconds) # Ask the model to continue the sequence. drum_rnn.generateDrumTrack(128, )
def app(unused_argv): # Initialize MidiHub. hub = midi_hub.MidiHub(["magenta_in 1"], ["VirtualMIDISynth #1 0"], midi_hub.TextureType.POLYPHONIC) # TODO ex # 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() output_file = os.path.join("output", "out.html") interaction = LooperMidi(hub, generator, output_file) interaction.start() interaction.join() 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): # 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
tf.app.flags.DEFINE_float( 'playback_offset', 0.0, 'Time in seconds to adjust playback time by.') tf.app.flags.DEFINE_integer( 'playback_channel', 0, 'MIDI channel to send play events.') tf.app.flags.DEFINE_string( 'log', 'WARN', 'The threshold for what messages will be logged. DEBUG, INFO, WARN, ERROR, ' 'or FATAL.') # A map from a string generator name to its class. _GENERATOR_MAP = melody_rnn_sequence_generator.get_generator_map() _GENERATOR_MAP.update(drums_rnn_sequence_generator.get_generator_map()) _GENERATOR_MAP.update(polyphony_sequence_generator.get_generator_map()) def _validate_flags(): """Returns True if flag values are valid or prints error and returns False.""" if FLAGS.list_ports: print "Input ports: '%s'" % ( "', '".join(midi_hub.get_available_input_ports())) print "Ouput ports: '%s'" % ( "', '".join(midi_hub.get_available_output_ports())) return False if FLAGS.bundle_files is None: print '--bundle_files must be specified.' return False
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): """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
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
tf.app.flags.DEFINE_integer( 'state_control_number', None, 'The control number to use for sending the state. A value of 0 represents ' '`IDLE`, 1 is `LISTENING`, and 2 is `RESPONDING`.') tf.app.flags.DEFINE_float('playback_offset', 0.0, 'Time in seconds to adjust playback time by.') tf.app.flags.DEFINE_integer('playback_channel', 0, 'MIDI channel to send play events.') tf.app.flags.DEFINE_string( 'log', 'WARN', 'The threshold for what messages will be logged. DEBUG, INFO, WARN, ERROR, ' 'or FATAL.') # A map from a string generator name to its class. _GENERATOR_MAP = melody_rnn_sequence_generator.get_generator_map() _GENERATOR_MAP.update(drums_rnn_sequence_generator.get_generator_map()) _GENERATOR_MAP.update(polyphony_sequence_generator.get_generator_map()) def _validate_flags(): """Returns True if flag values are valid or prints error and returns False.""" if FLAGS.list_ports: print "Input ports: '%s'" % ("', '".join( midi_hub.get_available_input_ports())) print "Ouput ports: '%s'" % ("', '".join( midi_hub.get_available_output_ports())) return False if FLAGS.bundle_files is None: print '--bundle_files must be specified.' return False
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): 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): """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): # 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