'Converts the PolyphonicSequence to NoteSequence proto.
Assumes that the sequences ends with a STEP_END followed by an END event. To
ensure this is true, call set_length before calling this method.
Args:
velocity: Midi velocity to give each note. Between 1 and 127 (inclusive).
instrument: Midi instrument to give each note.
program: Midi program to give each note.
qpm: Quarter notes per minute (float).
base_note_sequence: A NoteSequence to use a starting point. Must match the
specified qpm.
Raises:
ValueError: if an unknown event is encountered.
Returns:
A NoteSequence proto.'

def to_sequence(self, velocity=100, instrument=0, program=0, qpm=constants.DEFAULT_QUARTERS_PER_MINUTE, base_note_sequence=None):

    seconds_per_step = ((60.0 / qpm) / self._steps_per_quarter)
    sequence_start_time = (self.start_step * seconds_per_step)
    if base_note_sequence:
        sequence = copy.deepcopy(base_note_sequence)
        if (sequence.tempos[0].qpm != qpm):
            raise ValueError(('Supplied    QPM    (%d)    does    not    match    QPM    of    base_note_sequence    (%d)' % (qpm, sequence.tempos[0].qpm)))
    else:
        sequence = music_pb2.NoteSequence()
        sequence.tempos.add().qpm = qpm
        sequence.ticks_per_quarter = STANDARD_PPQ
    step = 0
    pitch_start_steps = []
    pitches_to_end = []
    for (i, event) in enumerate(self):
        if (event.event_type == PolyphonicEvent.START):
            if (i != 0):
                tf.logging.debug(('Ignoring    START    marker    not    at    beginning    of    sequence    at    position    %d' % i))
        elif ((event.event_type == PolyphonicEvent.END) and (i < (len(self) - 1))):
            tf.logging.debug(('Ignoring    END    maker    before    end    of    sequence    at    position    %d' % i))
        elif (event.event_type == PolyphonicEvent.NEW_NOTE):
            pitch_start_steps.append((event.pitch, step))
        elif (event.event_type == PolyphonicEvent.CONTINUED_NOTE):
            try:
                pitches_to_end.remove(event.pitch)
            except ValueError:
                tf.logging.debug(('Attempted    to    continue    pitch    %s    at    step    %s,    but    pitch    was    not    active.    Ignoring.' % (event.pitch, step)))
        elif ((event.event_type == PolyphonicEvent.STEP_END) or (event.event_type == PolyphonicEvent.END)):
            for pitch_start_step in list(pitch_start_steps):
                if (pitch_start_step[0] in pitches_to_end):
                    pitches_to_end.remove(pitch_start_step[0])
                    pitch_start_steps.remove(pitch_start_step)
                    note = sequence.notes.add()
                    note.start_time = ((pitch_start_step[1] * seconds_per_step) + sequence_start_time)
                    note.end_time = ((step * seconds_per_step) + sequence_start_time)
                    note.pitch = pitch_start_step[0]
                    note.velocity = velocity
                    note.instrument = instrument
                    note.program = program
            assert (not pitches_to_end)
            step += 1
            pitches_to_end = [ps[0] for ps in pitch_start_steps]
        else:
            raise ValueError(('Unknown    event    type:    %s' % event.event_type))
    if pitch_start_steps:
        raise ValueError('Sequence    ended,    but    not    all    pitches    were    ended.    This    likely    means    the    sequence    was    missing    a    STEP_END    event    before    the    end    of    the    sequence.    To    ensure    a    well-formed    sequence,    call    set_length    first.')
    sequence.total_time = ((seconds_per_step * (step - 1)) + sequence_start_time)
    if sequence.notes:
        assert (sequence.total_time >= sequence.notes[(-1)].end_time)
    return sequence
