/**
     * used by the getAudioEvents-method of the sequencer, this validates
     * the present AudioEvents against the requested position
     * and updates and flushes the removal queue
     *
     * @param instrument     {BaseInstrument*} instrument to gather events from
     * @param bufferPosition {int} the current buffers start pointer
     * @param bufferEnd      {int} the current buffers end pointer
     */
    void collectSequencedEvents( BaseInstrument* instrument, int bufferPosition, int bufferEnd )
    {
        if ( !instrument->hasEvents() )
            return;

        AudioChannel* channel                     = instrument->audioChannel;
        std::vector<BaseAudioEvent*>* audioEvents = instrument->getEvents();

        // removal queue
        std::vector<BaseAudioEvent*> removes;

        // channel has an internal loop (e.g. drum machine) ? recalculate requested
        // buffer position by subtracting all measures above the first
        if ( channel->maxBufferPosition > 0 )
        {
            int samplesPerBar = AudioEngine::samples_per_bar;

            while ( bufferPosition >= channel->maxBufferPosition )
            {
                bufferPosition -= samplesPerBar;
                bufferEnd      -= samplesPerBar;
            }
        }
        int i = 0, amount = audioEvents->size();
        for ( i; i < amount; i++ )
        {
            BaseAudioEvent* audioEvent = audioEvents->at( i );

            if ( audioEvent->isEnabled() )
            {
                int sampleStart = audioEvent->getSampleStart();
                int sampleEnd   = audioEvent->getSampleEnd();

                if ( audioEvent->isLoopeable() ||
                   ( sampleStart >= bufferPosition && sampleStart <= bufferEnd ) ||
                   ( sampleStart <  bufferPosition && sampleEnd >= bufferPosition ))
                {
                    if ( !audioEvent->isDeletable())
                        channel->addEvent( audioEvent );
                    else
                        removes.push_back( audioEvent );
                }
            }
        }
        // removal queue filled ? process it so we can safely
        // remove "deleted" AudioEvents without errors occurring
        if ( removes.size() > 0 )
        {
            int i = 0;
            for ( i; i < removes.size(); i++ )
            {
                BaseAudioEvent* audioEvent = removes[ i ];
                instrument->removeEvent( audioEvent, false );
            }
        }
    }
TEST( BaseAudioEvent, LoopeableState )
{
    BaseAudioEvent* audioEvent = new BaseAudioEvent();

    ASSERT_FALSE( audioEvent->isLoopeable() )
        << "expected audio event not to be loopeable after construction";

    audioEvent->setLoopeable( true );

    ASSERT_TRUE( audioEvent->isLoopeable() )
        << "expected audio event to be loopeable after enabling loop";

    audioEvent->setLoopeable( false );

    ASSERT_FALSE( audioEvent->isLoopeable() )
        << "expected audio event not to be loopeable after disabling loop";

    deleteAudioEvent( audioEvent );
}