def testQuantizeNoteSequenceAbsolute(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(12, 100, 0.01, 10.0), (11, 55, 0.22, 0.50), (40, 45, 2.50, 3.50), (55, 120, 4.0, 4.01), (52, 99, 4.75, 5.0)]) testing_lib.add_chords_to_sequence( self.note_sequence, [('B7', 0.22), ('Em9', 4.0)]) testing_lib.add_control_changes_to_sequence( self.note_sequence, 0, [(2.0, 64, 127), (4.0, 64, 0)]) expected_quantized_sequence = copy.deepcopy(self.note_sequence) expected_quantized_sequence.quantization_info.steps_per_second = 4 testing_lib.add_quantized_steps_to_sequence( expected_quantized_sequence, [(0, 40), (1, 2), (10, 14), (16, 17), (19, 20)]) testing_lib.add_quantized_chord_steps_to_sequence( expected_quantized_sequence, [1, 16]) testing_lib.add_quantized_control_steps_to_sequence( expected_quantized_sequence, [8, 16]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=4) self.assertProtoEquals(expected_quantized_sequence, quantized_sequence)
def testExtractPerformances(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_lib.extract_performances(quantized_sequence) self.assertEqual(1, len(perfs)) perfs, _ = performance_lib.extract_performances( quantized_sequence, min_events_discard=1, max_events_truncate=10) self.assertEqual(1, len(perfs)) perfs, _ = performance_lib.extract_performances( quantized_sequence, min_events_discard=8, max_events_truncate=10) self.assertEqual(0, len(perfs)) perfs, _ = performance_lib.extract_performances( quantized_sequence, min_events_discard=1, max_events_truncate=3) self.assertEqual(1, len(perfs)) self.assertEqual(3, len(perfs[0])) perfs, _ = performance_lib.extract_performances( quantized_sequence, max_steps_truncate=100) self.assertEqual(1, len(perfs)) self.assertEqual(100, perfs[0].num_steps)
def testQuantizeNoteSequenceAbsolute(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(12, 100, 0.01, 10.0), (11, 55, 0.22, 0.50), (40, 45, 2.50, 3.50), (55, 120, 4.0, 4.01), (52, 99, 4.75, 5.0)]) testing_lib.add_chords_to_sequence( self.note_sequence, [('B7', 0.22), ('Em9', 4.0)]) testing_lib.add_control_changes_to_sequence( self.note_sequence, 0, [(2.0, 64, 127), (4.0, 64, 0)]) expected_quantized_sequence = copy.deepcopy(self.note_sequence) expected_quantized_sequence.quantization_info.steps_per_second = 4 testing_lib.add_quantized_steps_to_sequence( expected_quantized_sequence, [(0, 40), (1, 2), (10, 14), (16, 17), (19, 20)]) testing_lib.add_quantized_chord_steps_to_sequence( expected_quantized_sequence, [1, 16]) testing_lib.add_quantized_control_steps_to_sequence( expected_quantized_sequence, [8, 16]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=4) self.assertProtoEquals(expected_quantized_sequence, quantized_sequence)
def testFromQuantizedNoteSequenceWithQuantizedVelocity(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 127, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = list(performance_lib.Performance( quantized_sequence, num_velocity_bins=16)) pe = performance_lib.PerformanceEvent expected_performance = [ pe(pe.VELOCITY, 13), pe(pe.NOTE_ON, 60), pe(pe.NOTE_ON, 64), pe(pe.TIME_SHIFT, 100), pe(pe.VELOCITY, 16), pe(pe.NOTE_ON, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 64), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 60), ] self.assertEqual(expected_performance, performance)
def testNotePerformanceFromQuantizedNoteSequence(self): testing_lib.add_track_to_sequence(self.note_sequence, 0, [(60, 97, 0.0, 4.0), (64, 97, 0.0, 3.0), (67, 121, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.NotePerformance(quantized_sequence, num_velocity_bins=16) pe = performance_lib.PerformanceEvent expected_performance = [ (pe(pe.TIME_SHIFT, 0), pe(pe.NOTE_ON, 60), pe(pe.VELOCITY, 13), pe(pe.DURATION, 400)), (pe(pe.TIME_SHIFT, 0), pe(pe.NOTE_ON, 64), pe(pe.VELOCITY, 13), pe(pe.DURATION, 300)), (pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_ON, 67), pe(pe.VELOCITY, 16), pe(pe.DURATION, 100)), ] self.assertEqual(expected_performance, list(performance)) ns = performance.to_sequence(instrument=0) self.assertEqual(self.note_sequence, ns)
def transform(self, note_sequence): try: if self._steps_per_quarter is not None: quantized_sequence = sequences_lib.quantize_note_sequence( note_sequence, self._steps_per_quarter) else: quantized_sequence = sequences_lib.quantize_note_sequence_absolute( note_sequence, self._steps_per_second) return [quantized_sequence] except sequences_lib.MultipleTimeSignatureError as e: tf.logging.warning('Multiple time signatures in NoteSequence %s: %s', note_sequence.filename, e) self._set_stats([statistics.Counter( 'sequences_discarded_because_multiple_time_signatures', 1)]) return [] except sequences_lib.MultipleTempoError as e: tf.logging.warning('Multiple tempos found in NoteSequence %s: %s', note_sequence.filename, e) self._set_stats([statistics.Counter( 'sequences_discarded_because_multiple_tempos', 1)]) return [] except sequences_lib.BadTimeSignatureError as e: tf.logging.warning('Bad time signature in NoteSequence %s: %s', note_sequence.filename, e) self._set_stats([statistics.Counter( 'sequences_discarded_because_bad_time_signature', 1)]) return []
def testProgramAndIsDrumFromQuantizedNoteSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)], program=1) testing_lib.add_track_to_sequence( self.note_sequence, 1, [(36, 100, 0.0, 4.0), (48, 100, 0.0, 4.0)], program=2) testing_lib.add_track_to_sequence( self.note_sequence, 2, [(57, 100, 0.0, 0.1)], is_drum=True) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.Performance(quantized_sequence, instrument=0) self.assertEqual(1, performance.program) self.assertFalse(performance.is_drum) performance = performance_lib.Performance(quantized_sequence, instrument=1) self.assertEqual(2, performance.program) self.assertFalse(performance.is_drum) performance = performance_lib.Performance(quantized_sequence, instrument=2) self.assertIsNone(performance.program) self.assertTrue(performance.is_drum) performance = performance_lib.Performance(quantized_sequence) self.assertIsNone(performance.program) self.assertIsNone(performance.is_drum)
def testProgramAndIsDrumFromQuantizedNoteSequence(self): testing_lib.add_track_to_sequence(self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)], program=1) testing_lib.add_track_to_sequence(self.note_sequence, 1, [(36, 100, 0.0, 4.0), (48, 100, 0.0, 4.0)], program=2) testing_lib.add_track_to_sequence(self.note_sequence, 2, [(57, 100, 0.0, 0.1)], is_drum=True) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.Performance(quantized_sequence, instrument=0) self.assertEqual(1, performance.program) self.assertFalse(performance.is_drum) performance = performance_lib.Performance(quantized_sequence, instrument=1) self.assertEqual(2, performance.program) self.assertFalse(performance.is_drum) performance = performance_lib.Performance(quantized_sequence, instrument=2) self.assertIsNone(performance.program) self.assertTrue(performance.is_drum) performance = performance_lib.Performance(quantized_sequence) self.assertIsNone(performance.program) self.assertIsNone(performance.is_drum)
def transform(self, note_sequence): try: if self._steps_per_quarter is not None: quantized_sequence = sequences_lib.quantize_note_sequence( note_sequence, self._steps_per_quarter) else: quantized_sequence = sequences_lib.quantize_note_sequence_absolute( note_sequence, self._steps_per_second) return [quantized_sequence] except sequences_lib.MultipleTimeSignatureError as e: tf.logging.warning( 'Multiple time signatures in NoteSequence %s: %s', note_sequence.filename, e) self._set_stats([ statistics.Counter( 'sequences_discarded_because_multiple_time_signatures', 1) ]) return [] except sequences_lib.MultipleTempoError as e: tf.logging.warning('Multiple tempos found in NoteSequence %s: %s', note_sequence.filename, e) self._set_stats([ statistics.Counter( 'sequences_discarded_because_multiple_tempos', 1) ]) return [] except sequences_lib.BadTimeSignatureError as e: tf.logging.warning('Bad time signature in NoteSequence %s: %s', note_sequence.filename, e) self._set_stats([ statistics.Counter( 'sequences_discarded_because_bad_time_signature', 1) ]) return []
def testFromQuantizedNoteSequence(self): testing_lib.add_track_to_sequence(self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.Performance(quantized_sequence) self.assertEqual(100, performance.steps_per_second) pe = performance_lib.PerformanceEvent expected_performance = [ pe(pe.NOTE_ON, 60), pe(pe.NOTE_ON, 64), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_ON, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 64), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 60), ] self.assertEqual(expected_performance, list(performance))
def testFromQuantizedNoteSequenceWithQuantizedVelocity(self): testing_lib.add_track_to_sequence(self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 127, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = list( performance_lib.Performance(quantized_sequence, num_velocity_bins=16)) pe = performance_lib.PerformanceEvent expected_performance = [ pe(pe.VELOCITY, 13), pe(pe.NOTE_ON, 60), pe(pe.NOTE_ON, 64), pe(pe.TIME_SHIFT, 100), pe(pe.VELOCITY, 16), pe(pe.NOTE_ON, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 64), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 60), ] self.assertEqual(expected_performance, performance)
def testExtractPerformances(self): music_testing_lib.add_track_to_sequence(self.note_sequence, 0, [(60, 100, 0.0, 4.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_pipeline.extract_performances( quantized_sequence) self.assertEqual(1, len(perfs)) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, min_events_discard=1, max_events_truncate=10) self.assertEqual(1, len(perfs)) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, min_events_discard=8, max_events_truncate=10) self.assertEqual(0, len(perfs)) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, min_events_discard=1, max_events_truncate=3) self.assertEqual(1, len(perfs)) self.assertEqual(3, len(perfs[0])) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, max_steps_truncate=100) self.assertEqual(1, len(perfs)) self.assertEqual(100, perfs[0].num_steps)
def testExtractPerformancesMultiProgram(self): music_testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)]) self.note_sequence.notes[0].program = 2 quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_pipeline.extract_performances(quantized_sequence) self.assertEmpty(perfs)
def testExtractPerformancesMultiProgram(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)]) self.note_sequence.notes[0].program = 2 quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_lib.extract_performances(quantized_sequence) self.assertEqual(0, len(perfs))
def testExtractPerformancesNonZeroStart(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_lib.extract_performances( quantized_sequence, start_step=400, min_events_discard=1) self.assertEqual(0, len(perfs)) perfs, _ = performance_lib.extract_performances( quantized_sequence, start_step=0, min_events_discard=1) self.assertEqual(1, len(perfs))
def testExtractPerformancesNonZeroStart(self): music_testing_lib.add_track_to_sequence(self.note_sequence, 0, [(60, 100, 0.0, 4.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, start_step=400, min_events_discard=1) self.assertEqual(0, len(perfs)) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, start_step=0, min_events_discard=1) self.assertEqual(1, len(perfs))
def testToSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.Performance(quantized_sequence) performance_ns = performance.to_sequence() # Make comparison easier by sorting. performance_ns.notes.sort(key=lambda n: (n.start_time, n.pitch)) self.note_sequence.notes.sort(key=lambda n: (n.start_time, n.pitch)) self.assertEqual(self.note_sequence, performance_ns)
def testToSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.Performance(quantized_sequence) performance_ns = performance.to_sequence() # Make comparison easier by sorting. performance_ns.notes.sort(key=lambda n: (n.start_time, n.pitch)) self.note_sequence.notes.sort(key=lambda n: (n.start_time, n.pitch)) self.assertEqual(self.note_sequence, performance_ns)
def testAssertIsQuantizedNoteSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(12, 100, 0.01, 10.0), (11, 55, 0.22, 0.50), (40, 45, 2.50, 3.50), (55, 120, 4.0, 4.01), (52, 99, 4.75, 5.0)]) relative_quantized_sequence = sequences_lib.quantize_note_sequence( self.note_sequence, steps_per_quarter=self.steps_per_quarter) absolute_quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=4) sequences_lib.assert_is_quantized_sequence(relative_quantized_sequence) sequences_lib.assert_is_quantized_sequence(absolute_quantized_sequence) with self.assertRaises(sequences_lib.QuantizationStatusException): sequences_lib.assert_is_quantized_sequence(self.note_sequence)
def testAssertIsQuantizedNoteSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(12, 100, 0.01, 10.0), (11, 55, 0.22, 0.50), (40, 45, 2.50, 3.50), (55, 120, 4.0, 4.01), (52, 99, 4.75, 5.0)]) relative_quantized_sequence = sequences_lib.quantize_note_sequence( self.note_sequence, steps_per_quarter=self.steps_per_quarter) absolute_quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=4) sequences_lib.assert_is_quantized_sequence(relative_quantized_sequence) sequences_lib.assert_is_quantized_sequence(absolute_quantized_sequence) with self.assertRaises(sequences_lib.QuantizationStatusException): sequences_lib.assert_is_quantized_sequence(self.note_sequence)
def testExtractPerformancesSplitInstruments(self): music_testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0)]) music_testing_lib.add_track_to_sequence( self.note_sequence, 1, [(62, 100, 0.0, 2.0), (64, 100, 2.0, 4.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, split_instruments=True) self.assertLen(perfs, 2) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, min_events_discard=8, split_instruments=True) self.assertLen(perfs, 1) perfs, _ = performance_pipeline.extract_performances( quantized_sequence, min_events_discard=16, split_instruments=True) self.assertEmpty(perfs)
def testExtractPerformancesSplitInstruments(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0)]) testing_lib.add_track_to_sequence( self.note_sequence, 1, [(62, 100, 0.0, 2.0), (64, 100, 2.0, 4.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) perfs, _ = performance_lib.extract_performances( quantized_sequence, split_instruments=True) self.assertEqual(2, len(perfs)) perfs, _ = performance_lib.extract_performances( quantized_sequence, min_events_discard=8, split_instruments=True) self.assertEqual(1, len(perfs)) perfs, _ = performance_lib.extract_performances( quantized_sequence, min_events_discard=16, split_instruments=True) self.assertEqual(0, len(perfs))
def testNotePerformanceFromQuantizedNoteSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 97, 0.0, 4.0), (64, 97, 0.0, 3.0), (67, 121, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.NotePerformance( quantized_sequence, num_velocity_bins=16) pe = performance_lib.PerformanceEvent expected_performance = [ (pe(pe.TIME_SHIFT, 0), pe(pe.NOTE_ON, 60), pe(pe.VELOCITY, 13), pe(pe.DURATION, 400)), (pe(pe.TIME_SHIFT, 0), pe(pe.NOTE_ON, 64), pe(pe.VELOCITY, 13), pe(pe.DURATION, 300)), (pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_ON, 67), pe(pe.VELOCITY, 16), pe(pe.DURATION, 100)), ] self.assertEqual(expected_performance, list(performance)) ns = performance.to_sequence(instrument=0) self.assertEqual(self.note_sequence, ns)
def testFromQuantizedNoteSequence(self): testing_lib.add_track_to_sequence( self.note_sequence, 0, [(60, 100, 0.0, 4.0), (64, 100, 0.0, 3.0), (67, 100, 1.0, 2.0)]) quantized_sequence = sequences_lib.quantize_note_sequence_absolute( self.note_sequence, steps_per_second=100) performance = performance_lib.Performance(quantized_sequence) self.assertEqual(100, performance.steps_per_second) pe = performance_lib.PerformanceEvent expected_performance = [ pe(pe.NOTE_ON, 60), pe(pe.NOTE_ON, 64), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_ON, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 67), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 64), pe(pe.TIME_SHIFT, 100), pe(pe.NOTE_OFF, 60), ] self.assertEqual(expected_performance, list(performance))
def split_performance(performance, steps_per_segment, new_performance_fn, clip_tied_notes=False): """Splits a performance into multiple fixed-length segments. Args: performance: A Performance (or MetricPerformance) object to split. steps_per_segment: The number of quantized steps per segment. new_performance_fn: A function to create new Performance (or MetricPerformance objects). Takes `quantized_sequence` and `start_step` arguments. clip_tied_notes: If True, clip tied notes across segments by converting each segment to NoteSequence and back. Returns: A list of performance segments. """ segments = [] cur_segment = new_performance_fn(quantized_sequence=None, start_step=0) cur_step = 0 for e in performance: if e.event_type != performance_lib.PerformanceEvent.TIME_SHIFT: if cur_step == steps_per_segment: # At a segment boundary, note-offs happen before the cutoff. # Everything else happens after. if e.event_type != performance_lib.PerformanceEvent.NOTE_OFF: segments.append(cur_segment) cur_segment = new_performance_fn( quantized_sequence=None, start_step=len(segments) * steps_per_segment) cur_step = 0 cur_segment.append(e) else: # We're not at a segment boundary. cur_segment.append(e) else: if cur_step + e.event_value <= steps_per_segment: # If it's a time shift, but we're still within the current segment, # just append to current segment. cur_segment.append(e) cur_step += e.event_value else: # If it's a time shift that goes beyond the current segment, possibly # split the time shift into two events and create a new segment. cur_segment_steps = steps_per_segment - cur_step if cur_segment_steps > 0: cur_segment.append(performance_lib.PerformanceEvent( event_type=performance_lib.PerformanceEvent.TIME_SHIFT, event_value=cur_segment_steps)) segments.append(cur_segment) cur_segment = new_performance_fn( quantized_sequence=None, start_step=len(segments) * steps_per_segment) cur_step = 0 new_segment_steps = e.event_value - cur_segment_steps if new_segment_steps > 0: cur_segment.append(performance_lib.PerformanceEvent( event_type=performance_lib.PerformanceEvent.TIME_SHIFT, event_value=new_segment_steps)) cur_step += new_segment_steps segments.append(cur_segment) # There may be a final segment with zero duration. If so, remove it. if segments and segments[-1].num_steps == 0: segments = segments[:-1] if clip_tied_notes: # Convert each segment to NoteSequence and back to remove notes that are # held across segment boundaries. for i in range(len(segments)): sequence = segments[i].to_sequence() if isinstance(segments[i], performance_lib.MetricPerformance): # Performance is quantized relative to meter. quantized_sequence = sequences_lib.quantize_note_sequence( sequence, steps_per_quarter=segments[i].steps_per_quarter) else: # Performance is quantized with absolute timing. quantized_sequence = sequences_lib.quantize_note_sequence_absolute( sequence, steps_per_second=segments[i].steps_per_second) segments[i] = new_performance_fn( quantized_sequence=quantized_sequence, start_step=segments[i].start_step) segments[i].set_length(steps_per_segment) return segments
def split_performance(performance, steps_per_segment, new_performance_fn, clip_tied_notes=False): """Splits a performance into multiple fixed-length segments. Args: performance: A Performance (or MetricPerformance) object to split. steps_per_segment: The number of quantized steps per segment. new_performance_fn: A function to create new Performance (or MetricPerformance objects). Takes `quantized_sequence` and `start_step` arguments. clip_tied_notes: If True, clip tied notes across segments by converting each segment to NoteSequence and back. Returns: A list of performance segments. """ segments = [] cur_segment = new_performance_fn(quantized_sequence=None, start_step=0) cur_step = 0 for e in performance: if e.event_type != performance_lib.PerformanceEvent.TIME_SHIFT: if cur_step == steps_per_segment: # At a segment boundary, note-offs happen before the cutoff. # Everything else happens after. if e.event_type != performance_lib.PerformanceEvent.NOTE_OFF: segments.append(cur_segment) cur_segment = new_performance_fn(quantized_sequence=None, start_step=len(segments) * steps_per_segment) cur_step = 0 cur_segment.append(e) else: # We're not at a segment boundary. cur_segment.append(e) else: if cur_step + e.event_value <= steps_per_segment: # If it's a time shift, but we're still within the current segment, # just append to current segment. cur_segment.append(e) cur_step += e.event_value else: # If it's a time shift that goes beyond the current segment, possibly # split the time shift into two events and create a new segment. cur_segment_steps = steps_per_segment - cur_step if cur_segment_steps > 0: cur_segment.append( performance_lib.PerformanceEvent( event_type=performance_lib.PerformanceEvent. TIME_SHIFT, event_value=cur_segment_steps)) segments.append(cur_segment) cur_segment = new_performance_fn(quantized_sequence=None, start_step=len(segments) * steps_per_segment) cur_step = 0 new_segment_steps = e.event_value - cur_segment_steps if new_segment_steps > 0: cur_segment.append( performance_lib.PerformanceEvent( event_type=performance_lib.PerformanceEvent. TIME_SHIFT, event_value=new_segment_steps)) cur_step += new_segment_steps segments.append(cur_segment) # There may be a final segment with zero duration. If so, remove it. if segments and segments[-1].num_steps == 0: segments = segments[:-1] if clip_tied_notes: # Convert each segment to NoteSequence and back to remove notes that are # held across segment boundaries. for i in range(len(segments)): sequence = segments[i].to_sequence() if isinstance(segments[i], performance_lib.MetricPerformance): # Performance is quantized relative to meter. quantized_sequence = sequences_lib.quantize_note_sequence( sequence, steps_per_quarter=segments[i].steps_per_quarter) else: # Performance is quantized with absolute timing. quantized_sequence = sequences_lib.quantize_note_sequence_absolute( sequence, steps_per_second=segments[i].steps_per_second) segments[i] = new_performance_fn( quantized_sequence=quantized_sequence, start_step=segments[i].start_step) segments[i].set_length(steps_per_segment) return segments