def generate_midi(midi_data, total_seconds=10): primer_sequence = midi_io.midi_to_sequence_proto(midi_data) generate_request = generator_pb2.GenerateSequenceRequest() if len(primer_sequence.notes) > 4: estimated_tempo = midi_data.estimate_tempo() if estimated_tempo > 240: qpm = estimated_tempo / 2 else: qpm = estimated_tempo else: qpm = 120 primer_sequence.tempos[0].qpm = qpm generate_request.input_sequence.CopyFrom(primer_sequence) generate_section = (generate_request.generator_options.generate_sections.add()) # Set the start time to begin on the next step after the last note ends. notes_by_end_time = sorted(primer_sequence.notes, key=lambda n: n.end_time) last_end_time = notes_by_end_time[-1].end_time if notes_by_end_time else 0 generate_section.start_time_seconds = last_end_time + _steps_to_seconds( 1, qpm) generate_section.end_time_seconds = total_seconds # generate_response = generator_map[generator_name].generate(generate_request) generate_response = basic_generator.generate(generate_request) output = tempfile.NamedTemporaryFile() midi_io.sequence_proto_to_midi_file( generate_response.generated_sequence, output.name) output.seek(0) return output
def generate_melody(self, input_sequence): """Calls the SequenceGenerator and returns the generated NoteSequence.""" # TODO(fjord): Align generation time on a measure boundary. notes_by_end_time = sorted(input_sequence.notes, key=lambda n: n.end_time) last_end_time = notes_by_end_time[ -1].end_time if notes_by_end_time else 0 # Assume 4/4 time signature and a single tempo. qpm = input_sequence.tempos[0].qpm seconds_to_generate = (60.0 / qpm) * 4 * self._num_bars_to_generate request = generator_pb2.GenerateSequenceRequest() request.input_sequence.CopyFrom(input_sequence) section = request.generator_options.generate_sections.add() # Start generating 1 quarter note after the sequence ends. section.start_time_seconds = last_end_time + (60.0 / qpm) section.end_time_seconds = section.start_time_seconds + seconds_to_generate response = self._generator.generate(request) return response.generated_sequence
def run_with_flags(melody_rnn_sequence_generator): """Generates melodies and saves them as MIDI files. Uses the options specified by the flags defined in this module. Intended to be called from the main function of one of the melody generator modules. Args: melody_rnn_sequence_generator: A MelodyRnnSequenceGenerator object specific to your model. """ tf.logging.set_verbosity(FLAGS.log) if not FLAGS.output_dir: tf.logging.fatal('--output_dir required') return FLAGS.output_dir = os.path.expanduser(FLAGS.output_dir) if FLAGS.primer_midi: FLAGS.primer_midi = os.path.expanduser(FLAGS.primer_midi) if not os.path.exists(FLAGS.output_dir): os.makedirs(FLAGS.output_dir) primer_sequence = None bpm = FLAGS.bpm if FLAGS.bpm else melodies_lib.DEFAULT_BEATS_PER_MINUTE if FLAGS.primer_melody: primer_melody = melodies_lib.MonophonicMelody() primer_melody.from_event_list(ast.literal_eval(FLAGS.primer_melody)) primer_sequence = primer_melody.to_sequence(bpm=bpm) elif FLAGS.primer_midi: primer_sequence = midi_io.midi_file_to_sequence_proto( FLAGS.primer_midi) if primer_sequence.tempos and primer_sequence.tempos[0].bpm: bpm = primer_sequence.tempos[0].bpm # Derive the total number of seconds to generate based on the BPM of the # priming sequence and the num_steps flag. total_seconds = _steps_to_seconds(FLAGS.num_steps, bpm) # Specify start/stop time for generation based on starting generation at the # end of the priming sequence and continuing until the sequence is num_steps # long. generate_request = generator_pb2.GenerateSequenceRequest() if primer_sequence: generate_request.input_sequence.CopyFrom(primer_sequence) generate_section = ( generate_request.generator_options.generate_sections.add()) # Set the start time to begin on the next step after the last note ends. notes_by_end_time = sorted(primer_sequence.notes, key=lambda n: n.end_time) last_end_time = notes_by_end_time[ -1].end_time if notes_by_end_time else 0 generate_section.start_time_seconds = last_end_time + _steps_to_seconds( 1, bpm) generate_section.end_time_seconds = total_seconds if generate_section.start_time_seconds >= generate_section.end_time_seconds: tf.logging.fatal( 'Priming sequence is longer than the total number of steps ' 'requested: Priming sequence length: %s, Generation length ' 'requested: %s', generate_section.start_time_seconds, total_seconds) return else: generate_section = ( generate_request.generator_options.generate_sections.add()) generate_section.start_time_seconds = 0 generate_section.end_time_seconds = total_seconds generate_request.input_sequence.tempos.add().bpm = bpm tf.logging.info('generate_request: %s', generate_request) # Make the generate request num_outputs times and save the output as midi # files. date_and_time = time.strftime('%Y-%m-%d_%H%M%S') digits = len(str(FLAGS.num_outputs)) for i in range(FLAGS.num_outputs): generate_response = melody_rnn_sequence_generator.generate( generate_request) midi_filename = '%s_%s.mid' % (date_and_time, str(i + 1).zfill(digits)) midi_path = os.path.join(FLAGS.output_dir, midi_filename) midi_io.sequence_proto_to_midi_file( generate_response.generated_sequence, midi_path) tf.logging.info('Wrote %d MIDI files to %s', FLAGS.num_outputs, FLAGS.output_dir)