TEST( AudioEngine, Output )
{
    AudioEngine::test_program    = 2;   // help mocked OpenSL IO identify which test is running
    AudioEngine::test_successful = false;

    // prepare engine environment

    SequencerController* controller = new SequencerController();
    controller->prepare( 16, 48000, 130.0f, 4, 4 ); // 130 BPM in 4/4 time at 48 kHz sample rate w/buffer size of 16 samples
    controller->setTempoNow( 130.0f, 4, 4 );
    controller->rewind();

    AudioEngine::volume = 1;    // QQQ : later on we test mix volume ;)

    // create an AudioEvent that holds a simple waveform
    // the resulting 16 sample mono buffer contains the following samples:
    //
    // -1,-1,-1,-1,0,0,0,0,1,1,1,1,0,0,0,0
    //
    // the event will last for an entire measure in duration

    BaseInstrument* instrument = new BaseInstrument();
    BaseAudioEvent* event      = new BaseAudioEvent( instrument );

    AudioBuffer* buffer    = new AudioBuffer( 1, 16 );
    SAMPLE_TYPE* rawBuffer = buffer->getBufferForChannel( 0 );

    for ( int i = 0; i < 4; ++i )
        rawBuffer[ i ] = ( SAMPLE_TYPE ) -MAX_PHASE;

    for ( int i = 4; i < 8; ++i )
        rawBuffer[ i ] = ( SAMPLE_TYPE ) 0;

    for ( int i = 8; i < 12; ++i )
        rawBuffer[ i ] = ( SAMPLE_TYPE ) MAX_PHASE;

    for ( int i = 12; i < 16; ++i )
        rawBuffer[ i ] = ( SAMPLE_TYPE ) 0;

    event->setBuffer( buffer, false );
    event->setLoopeable( true );
    event->setSampleLength( AudioEngine::samples_per_bar );
    event->positionEvent( 0, 16, 0 );
    event->addToSequencer();

    // start the engine

    controller->setPlaying( true );
    AudioEngine::start();

    // evaluate results (assertions are made in mock_opensl_io.cpp)

    ASSERT_TRUE( AudioEngine::test_successful )
        << "expected test to be successful";

    EXPECT_EQ( 3, AudioEngine::test_program )
        << "expected test program to have incremented";

    // clean up

    controller->setPlaying( false );
    AudioEngine::render_iterations = 0;

    delete controller;
    delete instrument;
    delete event;
    delete buffer;
}
TEST( BaseAudioEvent, AddRemoveSequencer )
{
    BaseInstrument* instrument = new BaseInstrument();
    BaseAudioEvent* audioEvent = new BaseAudioEvent( instrument );

    // expect AudioEvent not be in any of the event queues of the instrument after construction

    bool found = false;
    for ( int i = 0; i < instrument->getEvents()->size(); ++i )
    {
        if ( instrument->getEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected event not to be present in the event list after construction";

    found = false;
    for ( int i = 0; i < instrument->getLiveEvents()->size(); ++i )
    {
        if ( instrument->getLiveEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected event not to be present in the live event list after construction";

    // 1. add the event to the sequencer

    audioEvent->addToSequencer();

    // expect AudioEvent to be in the sequenced event list, not the live list

    found = false;
    for ( int i = 0; i < instrument->getEvents()->size(); ++i )
    {
        if ( instrument->getEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_TRUE( found )
        << "expected event to be present in the event list after addition";

    found = false;
    for ( int i = 0; i < instrument->getLiveEvents()->size(); ++i )
    {
        if ( instrument->getLiveEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected event not to be present in the live event list after addition";

    // 2. remove the event from the sequencer

    audioEvent->removeFromSequencer();

    // expect AudioEvent not to be in the sequenced event list anymore

    found = false;
    for ( int i = 0; i < instrument->getEvents()->size(); ++i )
    {
        if ( instrument->getEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected event not to be present in the event list after removal";

    // 3. add live event to the sequencer

    audioEvent->isSequenced = false;
    audioEvent->addToSequencer();

    // expect AudioEvent to be in the live event list, not the sequenced list

    found = false;
    for ( int i = 0; i < instrument->getEvents()->size(); ++i )
    {
        if ( instrument->getEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected live event not to be present in the sequenced event list after addition";

    found = false;
    for ( int i = 0; i < instrument->getLiveEvents()->size(); ++i )
    {
        if ( instrument->getLiveEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_TRUE( found )
        << "expected live event to be present in the live event list after addition";

    // 4. remove live event from sequencer

    audioEvent->removeFromSequencer();

    // expect AudioEvent not be in any of the event queues of the instrument after removal

    found = false;
    for ( int i = 0; i < instrument->getEvents()->size(); ++i )
    {
        if ( instrument->getEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected event not to be present in the event list after removal";

    found = false;
    for ( int i = 0; i < instrument->getLiveEvents()->size(); ++i )
    {
        if ( instrument->getLiveEvents()->at( i ) == audioEvent )
            found = true;
    }

    ASSERT_FALSE( found )
        << "expected event not to be present in the live event list after removal";

    delete audioEvent;
    delete instrument;
}