def testStartCapture_Multiple(self): captor_1 = self.midi_hub.start_capture( 120, 0.0, stop_signal=midi_hub.MidiSignal(note=3)) captor_2 = self.midi_hub.start_capture(120, 1.0, stop_signal=midi_hub.MidiSignal( type='control_change', control=1)) self.send_capture_messages() captor_1.join() captor_2.join() captured_seq_1 = captor_1.captured_sequence() expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 4.0 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(0, 64, 0.01, 3), Note(1, 64, 2, 4), Note(2, 64, 3, 4)]) self.assertProtoEquals(captured_seq_1, expected_seq) captured_seq_2 = captor_2.captured_sequence() expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 6.0 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, 5), Note(2, 64, 3, 4), Note(3, 64, 4, 6)]) self.assertProtoEquals(captured_seq_2, expected_seq)
def main(unused_argv): tf.logging.set_verbosity(FLAGS.log) # Initialize MidiHub. hub = midi_hub.MidiHub(None, FLAGS.output_ports.split(','), midi_hub.TextureType.MONOPHONIC) cc = FLAGS.clock_control_number # Assumes 4 beats per bar. metronome_signals = ([midi_hub.MidiSignal(control=cc, value=127)] + [midi_hub.MidiSignal(control=cc, value=0)] * 3) hub.start_metronome(FLAGS.qpm, start_time=0, signals=metronome_signals, channel=FLAGS.channel) try: while True: time.sleep(1) except KeyboardInterrupt: hub.stop_metronome() print('Clock stopped.')
def testMidiSignal_Args_InferredType(self): sig = midi_hub.MidiSignal(note=1) self.assertEqual(r'^.* channel=\d+ note=1 velocity=\d+ time=\d+.\d+$', str(sig)) sig = midi_hub.MidiSignal(value=2) self.assertEqual( r'^control_change channel=\d+ control=\d+ value=2 time=\d+.\d+$', str(sig))
def testStartCapture_Iterate_Signal(self): start_time = 1.0 captor = self.midi_hub.start_capture(120, start_time, stop_signal=midi_hub.MidiSignal( type='control_change', control=1)) for msg in self.capture_messages[:-1]: threading.Timer(0.2 * msg.time, self.port.callback, args=[msg]).start() captured_seqs = [] for captured_seq in captor.iterate(signal=midi_hub.MidiSignal( type='note_off')): captured_seqs.append(captured_seq) self.assertEqual(4, len(captured_seqs)) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 3 testing_lib.add_track_to_sequence(expected_seq, 0, [Note(1, 64, 2, 3)]) self.assertProtoEquals(captured_seqs[0], expected_seq) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 4 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, 4), Note(2, 64, 3, 4)]) self.assertProtoEquals(captured_seqs[1], expected_seq) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 5 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, 5), Note(2, 64, 3, 4), Note(3, 64, 4, 5)]) self.assertProtoEquals(captured_seqs[2], expected_seq) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 6 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, 5), Note(2, 64, 3, 4), Note(3, 64, 4, 6)]) self.assertProtoEquals(captured_seqs[3], expected_seq)
def testMidiSignal_Args(self): sig = midi_hub.MidiSignal(type='note_on', note=1) self.assertEquals(r'^note_on channel=\d+ note=1 velocity=\d+ time=\d+.\d+$', str(sig)) sig = midi_hub.MidiSignal(type='note_off', velocity=127) self.assertEquals( r'^note_off channel=\d+ note=\d+ velocity=127 time=\d+.\d+$', str(sig)) sig = midi_hub.MidiSignal(type='control_change', value=2) self.assertEquals( r'^control_change channel=\d+ control=\d+ value=2 time=\d+.\d+$', str(sig))
def testMidiSignal_Message(self): sig = midi_hub.MidiSignal(msg=mido.Message(type='note_on', note=1)) self.assertEquals(r'^note_on channel=0 note=1 velocity=64 time=\d+.\d+$', str(sig)) sig = midi_hub.MidiSignal(msg=mido.Message(type='note_off', velocity=127)) self.assertEquals(r'^note_off channel=0 note=0 velocity=127 time=\d+.\d+$', str(sig)) sig = midi_hub.MidiSignal( msg=mido.Message(type='control_change', control=1, value=2)) self.assertEquals( r'^control_change channel=0 control=1 value=2 time=\d+.\d+$', str(sig))
def testStartCapture_Iterate_Period_Overrun(self): start_time = 1.0 captor = self.midi_hub.start_capture( 120, start_time, stop_signal=midi_hub.MidiSignal(type='control_change', control=1)) for msg in self.capture_messages[:-1]: threading.Timer(0.1 * msg.time, self.port.callback, args=[msg]).start() period = 0.26 captured_seqs = [] wall_start_time = time.time() for captured_seq in captor.iterate(period=period): time.sleep(0.5) captured_seqs.append(captured_seq) self.assertEquals(2, len(captured_seqs)) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) end_time = captured_seqs[0].total_time self.assertAlmostEqual(wall_start_time + period, end_time, delta=0.005) expected_seq.total_time = end_time testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, end_time)]) self.assertProtoEquals(captured_seqs[0], expected_seq) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 6 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, 5), Note(2, 64, 3, 4), Note(3, 64, 4, 6)]) self.assertProtoEquals(captured_seqs[1], expected_seq)
def main(unused_argv): tf.logging.set_verbosity(FLAGS.log) if not _validate_flags(): return # Load generators. generators = [] for bundle_file in FLAGS.bundle_files.split(','): generators.append(_load_generator_from_bundle_file(bundle_file)) if generators[-1] is None: return # Initialize MidiHub. if FLAGS.input_port not in midi_hub.get_available_input_ports(): print "Opening '%s' as a virtual MIDI port for input." % FLAGS.input_port if FLAGS.output_port not in midi_hub.get_available_output_ports(): print "Opening '%s' as a virtual MIDI port for output." % FLAGS.output_port hub = midi_hub.MidiHub(FLAGS.input_port, FLAGS.output_port, midi_hub.TextureType.MONOPHONIC) start_call_signal = ( None if FLAGS.start_call_control_number is None else midi_hub.MidiSignal(control=FLAGS.start_call_control_number, value=0)) end_call_signal = ( None if FLAGS.end_call_control_number is None else midi_hub.MidiSignal(control=FLAGS.end_call_control_number, value=0)) interaction = midi_interaction.CallAndResponseMidiInteraction( hub, generators, FLAGS.qpm, generator_select_control_number=FLAGS.generator_select_control_number, phrase_bars=FLAGS.phrase_bars, start_call_signal=start_call_signal, end_call_signal=end_call_signal, temperature_control_number=FLAGS.temperature_control_number) _print_instructions() interaction.start() try: while True: time.sleep(1) except KeyboardInterrupt: interaction.stop() print 'Interaction stopped.'
def testWaitForEvent_Signal(self): for msg in self.capture_messages[3:-1]: threading.Timer(0.2 * msg.time, self.port.callback, args=[msg]).start() wait_start = time.time() self.midi_hub.wait_for_event( signal=midi_hub.MidiSignal(type='control_change', value=1)) self.assertAlmostEqual(time.time() - wait_start, 1.2, delta=0.01)
def testCaptureSequence_StopSignal(self): start_time = 1.0 threading.Timer(0.1, self.send_capture_messages).start() captured_seq = self.midi_hub.capture_sequence( 120, start_time, stop_signal=midi_hub.MidiSignal(type='control_change', control=1)) expected_seq = music_pb2.NoteSequence() expected_seq.tempos.add(qpm=120) expected_seq.total_time = 6.0 testing_lib.add_track_to_sequence( expected_seq, 0, [Note(1, 64, 2, 5), Note(2, 64, 3, 4), Note(3, 64, 4, 6)]) self.assertProtoEquals(captured_seq, expected_seq)
def update_map(self): """Enters a loop that receives user input to set signal controls.""" while True: print self._print_instructions() response = raw_input('Selection: ') if response == 'q': return try: signal = self._signals[int(response) - 1] except (ValueError, IndexError): print 'Invalid response:', response continue self._update_event.clear() self._midi_hub.register_callback( partial(self._update_signal, signal), midi_hub.MidiSignal(type='control_change')) print('Send a control signal using the control number you wish to ' 'associate with `%s`.' % signal) self._update_event.wait()
def testMidiSignal_ValidityChecks(self): # Unsupported type. with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal(type='sysex') with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal(msg=mido.Message(type='sysex')) # Invalid arguments. with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal() with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal(type='note_on', value=1) with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal(type='control', note=1) with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal(msg=mido.Message(type='control_change'), value=1) # Non-inferrale type. with self.assertRaises(midi_hub.MidiHubException): midi_hub.MidiSignal(note=1, value=1)
def main(unused_argv): tf.logging.set_verbosity(FLAGS.log) if not _validate_flags(): return # Load generators. generators = [] for bundle_file in FLAGS.bundle_files.split(','): generators.append(_load_generator_from_bundle_file(bundle_file)) if generators[-1] is None: return # Initialize MidiHub. if FLAGS.input_port not in midi_hub.get_available_input_ports(): print "Opening '%s' as a virtual MIDI port for input." % FLAGS.input_port if FLAGS.output_port not in midi_hub.get_available_output_ports(): print "Opening '%s' as a virtual MIDI port for output." % FLAGS.output_port hub = midi_hub.MidiHub(FLAGS.input_port, FLAGS.output_port, midi_hub.TextureType.MONOPHONIC, passthrough=FLAGS.passthrough, playback_channel=FLAGS.playback_channel, playback_offset=FLAGS.playback_offset) if FLAGS.clock_control_number is None: # Set the tick duration to be a single bar, assuming a 4/4 time signature. clock_signal = None tick_duration = 4 * (60. / FLAGS.qpm) else: clock_signal = midi_hub.MidiSignal(control=FLAGS.clock_control_number, value=127) tick_duration = None end_call_signal = (None if FLAGS.end_call_control_number is None else midi_hub.MidiSignal( control=FLAGS.end_call_control_number, value=127)) panic_signal = (None if FLAGS.panic_control_number is None else midi_hub.MidiSignal(control=FLAGS.panic_control_number, value=127)) mutate_signal = (None if FLAGS.mutate_control_number is None else midi_hub.MidiSignal(control=FLAGS.mutate_control_number, value=127)) interaction = midi_interaction.CallAndResponseMidiInteraction( hub, generators, FLAGS.qpm, FLAGS.generator_select_control_number, clock_signal=clock_signal, tick_duration=tick_duration, end_call_signal=end_call_signal, panic_signal=panic_signal, mutate_signal=mutate_signal, allow_overlap=FLAGS.allow_overlap, enable_metronome=FLAGS.enable_metronome, min_listen_ticks_control_number=FLAGS.min_listen_ticks_control_number, max_listen_ticks_control_number=FLAGS.max_listen_ticks_control_number, response_ticks_control_number=FLAGS.response_ticks_control_number, tempo_control_number=FLAGS.tempo_control_number, temperature_control_number=FLAGS.temperature_control_number, loop_control_number=FLAGS.loop_control_number, state_control_number=FLAGS.state_control_number) _print_instructions() interaction.start() try: while True: time.sleep(1) except KeyboardInterrupt: interaction.stop() print 'Interaction stopped.'
def main(unused_argv): tf.logging.set_verbosity(FLAGS.log) if not _validate_flags(): return # Load generators. generators = [] for bundle_file in FLAGS.bundle_files.split(','): generators.append(_load_generator_from_bundle_file(bundle_file)) if generators[-1] is None: return # Initialize MidiHub. hub = midi_hub.MidiHub(FLAGS.input_ports.split(','), FLAGS.output_ports.split(','), midi_hub.TextureType.POLYPHONIC, passthrough=FLAGS.passthrough, playback_channel=FLAGS.playback_channel, playback_offset=FLAGS.playback_offset) control_map = { re.sub('_control_number$', '', f): FLAGS.__getattr__(f) for f in _CONTROL_FLAGS } if FLAGS.learn_controls: CCMapper(control_map, hub).update_map() if control_map['clock'] is None: # Set the tick duration to be a single bar, assuming a 4/4 time signature. clock_signal = None tick_duration = 4 * (60. / FLAGS.qpm) else: clock_signal = midi_hub.MidiSignal(control=control_map['clock'], value=127) tick_duration = None end_call_signal = (None if control_map['end_call'] is None else midi_hub.MidiSignal(control=control_map['end_call'], value=127)) panic_signal = (None if control_map['panic'] is None else midi_hub.MidiSignal(control=control_map['panic'], value=127)) mutate_signal = (None if control_map['mutate'] is None else midi_hub.MidiSignal(control=control_map['mutate'], value=127)) metronome_channel = (FLAGS.metronome_channel if FLAGS.enable_metronome else None) interaction = midi_interaction.CallAndResponseMidiInteraction( hub, generators, FLAGS.qpm, FLAGS.generator_select_control_number, clock_signal=clock_signal, tick_duration=tick_duration, end_call_signal=end_call_signal, panic_signal=panic_signal, mutate_signal=mutate_signal, allow_overlap=FLAGS.allow_overlap, metronome_channel=metronome_channel, min_listen_ticks_control_number=control_map['min_listen_ticks'], max_listen_ticks_control_number=control_map['max_listen_ticks'], response_ticks_control_number=control_map['response_ticks'], tempo_control_number=control_map['tempo'], temperature_control_number=control_map['temperature'], loop_control_number=control_map['loop'], state_control_number=control_map['state']) _print_instructions() interaction.start() try: while True: time.sleep(1) except KeyboardInterrupt: interaction.stop() print 'Interaction stopped.'
def _signal_from_control_map(name): if control_map[name] is None: return None return midi_hub.MidiSignal(control=control_map[name], value=127)
def main(unused_argv): 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 if FLAGS.bundle_file is None: print '--bundle_file must be specified.' return if (FLAGS.end_call_control_number, FLAGS.phrase_bars).count(None) != 1: print( 'Exactly one of --end_call_control_number or --phrase_bars should be ' 'specified.') return try: bundle = magenta.music.sequence_generator_bundle.read_bundle_file( FLAGS.bundle_file) except magenta.music.sequence_generator_bundle.GeneratorBundleParseException: print 'Failed to parse bundle file: %s' % FLAGS.bundle_file return generator_id = bundle.generator_details.id if generator_id not in _GENERATOR_FACTORY_MAP: print "Unrecognized SequenceGenerator ID '%s' in bundle file: %s" % ( generator_id, FLAGS.bundle_file) return generator = _GENERATOR_FACTORY_MAP[generator_id].create_generator( checkpoint=None, bundle=bundle) generator.initialize() print "Loaded '%s' generator bundle from file '%s'." % ( bundle.generator_details.id, FLAGS.bundle_file) if FLAGS.input_port not in midi_hub.get_available_input_ports(): print "Opening '%s' as a virtual MIDI port for input." % FLAGS.input_port if FLAGS.output_port not in midi_hub.get_available_output_ports(): print "Opening '%s' as a virtual MIDI port for output." % FLAGS.output_port hub = midi_hub.MidiHub(FLAGS.input_port, FLAGS.output_port, midi_hub.TextureType.MONOPHONIC) end_call_signal = (None if FLAGS.end_call_control_number is None else midi_hub.MidiSignal( control=FLAGS.end_call_control_number, value=0)) interaction = midi_interaction.CallAndResponseMidiInteraction( hub, FLAGS.qpm, generator, phrase_bars=FLAGS.phrase_bars, end_call_signal=end_call_signal) print '' print 'Instructions:' print 'Play when you hear the metronome ticking.' if FLAGS.phrase_bars is not None: print('After %d bars (4 beats), Magenta will play its response.' % FLAGS.phrase_bars) print( 'Once the response completes, the metronome will tick and you can ' 'play again.') else: print( 'When you want to end the call phrase, signal control number %d ' 'with value 0' % FLAGS.end_call_control_number) print( 'At the end of the current bar (4 beats), Magenta will play its ' 'response.') print( 'Once the response completes, the metronome will tick and you can ' 'play again.') print '' print 'To end the interaction, press CTRL-C.' interaction.start() try: while True: time.sleep(1) except KeyboardInterrupt: interaction.stop() print 'Interaction stopped.'