def from_stream(stream, time_unit=4, tick_offset=0, name=None, only_notes=True, truncate=None, gold=None, sequence_index=None): """ Creates a L{SegmentedMidiInput} from a midi event stream. @type only_notes: bool @param only_notes: if True, only includes note-on/note-off events in the segments. If False, the stream will be sliced so that each segment repeats things like program change events at the beginning. Including only notes, however, makes the preprocessing very much faster """ # Divide the stream up into slices of the right size # Number of ticks in each slice tick_unit = int(stream.resolution * time_unit) if len(stream.trackpool) == 0: end_time = 0 else: end_time = max(stream.trackpool).tick if only_notes: from midi import EventStream, NoteOnEvent, NoteOffEvent, EndOfTrackEvent # Only include notes in the stream # This is much simpler and faster than the alternative events = [ev for ev in list(sorted(stream.trackpool)) if \ type(ev) in [NoteOnEvent, NoteOffEvent]] events = iter(events) try: current_event = events.next() # Get up to the start point in the stream while current_event.tick < tick_offset: current_event = events.next() except StopIteration: # Got to the end of the stream before we even started inputs = [] else: inputs = [] for chunk_start in range(tick_offset, end_time, tick_unit): chunk_end = chunk_start + tick_unit slc = EventStream() slc.add_track() slc.format = stream.format slc.resolution = stream.resolution slc.segment_start = chunk_start # Add all the note events in this time period try: while current_event.tick < chunk_end: slc.add_event(current_event) current_event = events.next() # Add the end of track event eot = EndOfTrackEvent() eot.tick = chunk_end slc.add_event(eot) except StopIteration: # Reached the end of the stream inputs.append(slc) break inputs.append(slc) else: # Use slices to do all the necessary repetition of ongoing events from midi.slice import EventStreamSlice start_times = range(tick_offset, end_time, tick_unit) # First slice starts at the offset value slices = [ EventStreamSlice(stream, chunk_start, chunk_start + tick_unit) for chunk_start in start_times ] inputs = [slc.to_event_stream(repeat_playing=False, cancel_playing=False) \ for slc in slices] # Associate the start time with each segment for slc, start_time in zip(inputs, start_times): slc.segment_start = start_time # Remove empty segments from the start and end current = 0 # There's always one event - the end of track while len(inputs[current].trackpool) < 2: current += 1 inputs = inputs[current:] # And the end current = len(inputs) - 1 while len(inputs[current].trackpool) < 2: current -= 1 inputs = inputs[:current + 1] if truncate is not None: inputs = inputs[:truncate] return SegmentedMidiInput(inputs, time_unit=time_unit, tick_offset=tick_offset, name=name, stream=stream, gold=gold, sequence_index=sequence_index)
def from_stream( stream, time_unit=4, tick_offset=0, name=None, only_notes=True, truncate=None, gold=None, sequence_index=None ): """ Creates a L{SegmentedMidiInput} from a midi event stream. @type only_notes: bool @param only_notes: if True, only includes note-on/note-off events in the segments. If False, the stream will be sliced so that each segment repeats things like program change events at the beginning. Including only notes, however, makes the preprocessing very much faster """ # Divide the stream up into slices of the right size # Number of ticks in each slice tick_unit = int(stream.resolution * time_unit) if len(stream.trackpool) == 0: end_time = 0 else: end_time = max(stream.trackpool).tick if only_notes: from midi import EventStream, NoteOnEvent, NoteOffEvent, EndOfTrackEvent # Only include notes in the stream # This is much simpler and faster than the alternative events = [ev for ev in list(sorted(stream.trackpool)) if type(ev) in [NoteOnEvent, NoteOffEvent]] events = iter(events) try: current_event = events.next() # Get up to the start point in the stream while current_event.tick < tick_offset: current_event = events.next() except StopIteration: # Got to the end of the stream before we even started inputs = [] else: inputs = [] for chunk_start in range(tick_offset, end_time, tick_unit): chunk_end = chunk_start + tick_unit slc = EventStream() slc.add_track() slc.format = stream.format slc.resolution = stream.resolution slc.segment_start = chunk_start # Add all the note events in this time period try: while current_event.tick < chunk_end: slc.add_event(current_event) current_event = events.next() # Add the end of track event eot = EndOfTrackEvent() eot.tick = chunk_end slc.add_event(eot) except StopIteration: # Reached the end of the stream inputs.append(slc) break inputs.append(slc) else: # Use slices to do all the necessary repetition of ongoing events from midi.slice import EventStreamSlice start_times = range(tick_offset, end_time, tick_unit) # First slice starts at the offset value slices = [EventStreamSlice(stream, chunk_start, chunk_start + tick_unit) for chunk_start in start_times] inputs = [slc.to_event_stream(repeat_playing=False, cancel_playing=False) for slc in slices] # Associate the start time with each segment for slc, start_time in zip(inputs, start_times): slc.segment_start = start_time # Remove empty segments from the start and end current = 0 # There's always one event - the end of track while len(inputs[current].trackpool) < 2: current += 1 inputs = inputs[current:] # And the end current = len(inputs) - 1 while len(inputs[current].trackpool) < 2: current -= 1 inputs = inputs[: current + 1] if truncate is not None: inputs = inputs[:truncate] return SegmentedMidiInput( inputs, time_unit=time_unit, tick_offset=tick_offset, name=name, stream=stream, gold=gold, sequence_index=sequence_index, )