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; }
TEST( BaseAudioEvent, PositionInSeconds ) { BaseAudioEvent* audioEvent = new BaseAudioEvent(); float startPosition = randomFloat( 0, 10 ); float endPosition = startPosition + randomFloat( 0, 10 ); int SAMPLE_RATE = 44100; float expectedDuration = endPosition - startPosition; int expectedSampleStart = BufferUtility::secondsToBuffer( startPosition, SAMPLE_RATE ); int expectedSampleEnd = BufferUtility::secondsToBuffer( endPosition, SAMPLE_RATE ); int expectedSampleLength = ( expectedSampleEnd - expectedSampleStart ) - 1; audioEvent->setStartPosition( startPosition ); EXPECT_FLOAT_EQ( startPosition, audioEvent->getStartPosition() ); EXPECT_FLOAT_EQ( startPosition, audioEvent->getEndPosition() ) << "expected end position to equal start position (hasn't been explicitly set yet)"; EXPECT_FLOAT_EQ( 0, audioEvent->getDuration()) << "expected zero duration (duration nor end haven't been explicitly set yet)"; EXPECT_EQ( 0, audioEvent->getSampleLength()) << "expected zero sample length (duration nor end haven't been explicitly set yet)"; EXPECT_EQ( expectedSampleStart, audioEvent->getSampleStart() ) << "expected sample start to have been updated after setting start position"; audioEvent->setEndPosition( endPosition ); EXPECT_FLOAT_EQ( startPosition, audioEvent->getStartPosition() ); EXPECT_FLOAT_EQ( endPosition, audioEvent->getEndPosition() ); EXPECT_FLOAT_EQ( expectedDuration, audioEvent->getDuration() ); EXPECT_EQ( expectedSampleEnd, audioEvent->getSampleEnd()) << "expected sample end to have been updated after setting end position"; EXPECT_EQ( expectedSampleLength, audioEvent->getSampleLength()) << "expected sample length to have been updated after setting end position"; expectedDuration /= 2; float expectedEndPosition = startPosition + expectedDuration; audioEvent->setDuration( expectedDuration ); EXPECT_FLOAT_EQ( expectedDuration, audioEvent->getDuration() ); EXPECT_FLOAT_EQ( expectedEndPosition, audioEvent->getEndPosition()) << "expected end position to have corrected after updating of duration"; deleteAudioEvent( audioEvent ); }
TEST( BaseAudioEvent, MixBuffer ) { BaseAudioEvent* audioEvent = new BaseAudioEvent(); int sampleLength = randomInt( 8, 24 ); int sampleStart = randomInt( 0, ( int )( sampleLength / 2 )); audioEvent->setSampleStart ( sampleStart ); audioEvent->setSampleLength( sampleLength ); int sampleEnd = audioEvent->getSampleEnd(); AudioBuffer* buffer = fillAudioBuffer( new AudioBuffer( randomInt( 1, 4 ), sampleLength )); audioEvent->setBuffer( buffer, true ); float volume = randomFloat(); audioEvent->setVolume( volume ); //std::cout << " ss: " << sampleStart << " se: " << sampleEnd << " sl: " << sampleLength << " ch: " << buffer->amountOfChannels; // create a temporary buffer to write output in, ensure it is smaller than the event buffer AudioBuffer* targetBuffer = new AudioBuffer( buffer->amountOfChannels, randomInt( 2, 4 )); int buffersToWrite = targetBuffer->bufferSize; ASSERT_FALSE( bufferHasContent( targetBuffer )) << "expected target buffer to be silent after creation, but it has content"; // test 1. mix without loopable range int maxBufferPos = sampleLength * 2; // use a "loop range" larger than the size of the events length int minBufferPos = randomInt( 0, maxBufferPos / 2 ); int bufferPos = randomInt( minBufferPos, maxBufferPos - 1 ); bool loopStarted = false; int loopOffset = 0; // if the random bufferPosition wasn't within the events sampleStart and sampleEnd range, we expect no content bool expectContent = ( bufferPos >= sampleStart && bufferPos <= sampleEnd ) || (( bufferPos + buffersToWrite ) >= sampleStart && ( bufferPos + buffersToWrite ) <= sampleEnd ); //std::cout << " expected content: " << expectContent << " for buffer size: " << buffersToWrite; //std::cout << " min: " << minBufferPos << " max: " << maxBufferPos << " cur: " << bufferPos; audioEvent->mixBuffer( targetBuffer, bufferPos, minBufferPos, maxBufferPos, loopStarted, loopOffset, false ); // validate buffer contents after mixing if ( expectContent ) { for ( int c = 0, ca = targetBuffer->amountOfChannels; c < ca; ++c ) { SAMPLE_TYPE* buffer = targetBuffer->getBufferForChannel( c ); SAMPLE_TYPE* sourceBuffer = audioEvent->getBuffer()->getBufferForChannel( c ); SAMPLE_TYPE expectedSample; for ( int i = 0; i < buffersToWrite; ++i ) { int r = i + bufferPos; // read pointer for the source buffer if ( r >= maxBufferPos && !loopStarted ) r -= ( maxBufferPos - minBufferPos ); if ( r >= sampleStart && r <= sampleEnd ) { r -= sampleStart; // substract audioEvent start position expectedSample = sourceBuffer[ r ] * volume; } else { expectedSample = 0.0; } SAMPLE_TYPE sample = buffer[ i ]; EXPECT_EQ( expectedSample, sample ) << "expected mixed sample at " << i << " to be equal to the calculated expected sample at read offset " << r; } } } else { ASSERT_FALSE( bufferHasContent( targetBuffer )) << "expected target buffer to contain no content after mixing for an out-of-range buffer position"; } // test 2. mixing within a loopable range (implying sequencer is starting a loop) targetBuffer->silenceBuffers(); ASSERT_FALSE( bufferHasContent( targetBuffer )) << "expected target buffer to be silent after silencing, but it still has content"; bufferPos = randomInt( minBufferPos, maxBufferPos - 1 ); loopStarted = true; loopOffset = ( maxBufferPos - bufferPos ) + 1; // pre calculate at which buffer iterator the looping will commence // loopStartIteratorPosition describes at which sequencer position the loop starts // loopStartWritePointer describes at which position in the targetBuffer the loop is written to // amountOfLoopedWrites is the amount of samples written in the loop // loopStartReadPointer describes at which position the samples from the source audioEvent will be read when loop starts // loopStartReadPointerEnd describes the last position the samples from the source audioEvent will be read for the amount of loop writes int loopStartIteratorPosition = maxBufferPos + 1; int loopStartWritePointer = loopOffset; int loopStartReadPointer = minBufferPos; int amountOfLoopedWrites = ( bufferPos + buffersToWrite ) - loopStartIteratorPosition; int loopStartReadPointerEnd = ( loopStartReadPointer + amountOfLoopedWrites ) - 1; expectContent = ( bufferPos >= sampleStart && bufferPos <= sampleEnd ) || (( bufferPos + buffersToWrite ) >= sampleStart && ( bufferPos + buffersToWrite ) <= sampleEnd ) || ( loopStartIteratorPosition > maxBufferPos && ( ( loopStartReadPointer >= sampleStart && loopStartReadPointer <= sampleEnd ) || ( loopStartReadPointerEnd >= sampleStart && loopStartReadPointerEnd <= sampleEnd ))); audioEvent->mixBuffer( targetBuffer, bufferPos, minBufferPos, maxBufferPos, loopStarted, loopOffset, false ); //std::cout << " expected content: " << expectContent << " for buffer size: " << buffersToWrite; //std::cout << " min: " << minBufferPos << " max: " << maxBufferPos << " cur: " << bufferPos << " loop offset: " << loopOffset; if ( expectContent ) { for ( int c = 0, ca = targetBuffer->amountOfChannels; c < ca; ++c ) { SAMPLE_TYPE* buffer = targetBuffer->getBufferForChannel( c ); SAMPLE_TYPE* sourceBuffer = audioEvent->getBuffer()->getBufferForChannel( c ); for ( int i = 0; i < buffersToWrite; ++i ) { SAMPLE_TYPE expectedSample = 0.0; int r = i + bufferPos; // read pointer for the source buffer if ( i >= loopOffset ) r = minBufferPos + ( i - loopOffset ); if ( r >= sampleStart && r <= sampleEnd ) { r -= sampleStart; // substract audioEvent start position expectedSample = sourceBuffer[ r ] * volume; } SAMPLE_TYPE sample = buffer[ i ]; EXPECT_EQ( expectedSample, sample ) << "expected mixed sample at " << i << " to be equal to the calculated expected sample at read " << "offset " << r << " ( sanitized from " << ( i + bufferPos ) << " )"; } } } else { ASSERT_FALSE( bufferHasContent( targetBuffer )) << "expected output buffer to contain no content after mixing for an out-of-range buffer position"; } delete audioEvent; delete targetBuffer; delete buffer; }
TEST( BaseAudioEvent, PositionInSamples ) { BaseAudioEvent* audioEvent = new BaseAudioEvent(); int sampleLength = randomInt( 512, 8192 ); int sampleStart = randomInt( 0, sampleLength / 2 ); int expectedEnd = sampleStart + ( sampleLength - 1 ); audioEvent->setSampleStart ( sampleStart ); audioEvent->setSampleLength( sampleLength ); EXPECT_EQ( sampleStart, audioEvent->getSampleStart() ); EXPECT_EQ( expectedEnd, audioEvent->getSampleEnd() ); EXPECT_EQ( sampleLength, audioEvent->getSampleLength() ); // test whether values in seconds have updated accordingly int SAMPLE_RATE = 44100; float expectedStartPosition = BufferUtility::bufferToSeconds( sampleStart, SAMPLE_RATE ); float expectedEndPosition = BufferUtility::bufferToSeconds( expectedEnd, SAMPLE_RATE ); float expectedDuration = expectedEndPosition - expectedStartPosition; EXPECT_FLOAT_EQ( expectedStartPosition, audioEvent->getStartPosition() ); EXPECT_FLOAT_EQ( expectedEndPosition, audioEvent->getEndPosition() ); EXPECT_FLOAT_EQ( expectedDuration, audioEvent->getDuration() ); // test auto sanitation of properties audioEvent->setSampleEnd( expectedEnd * 2 ); EXPECT_EQ( expectedEnd, audioEvent->getSampleEnd() ) << "expected sample end not to exceed the range set by the sample start and length properties"; sampleLength /= 2; audioEvent->setSampleLength( sampleLength ); expectedEnd = sampleStart + ( sampleLength - 1 ); EXPECT_EQ( expectedEnd, audioEvent->getSampleEnd() ) << "expected sample end not to exceed the range set by the sample start and updated length properties"; // test non sanitation of properties for loopeable events audioEvent->setLoopeable( true ); expectedEnd *= 2; audioEvent->setSampleEnd( expectedEnd ); EXPECT_EQ( expectedEnd, audioEvent->getSampleEnd() ) << "expected sample end to exceed the range set by the sample start and length properties for loopeable event"; sampleLength /= 2; audioEvent->setSampleLength( sampleLength ); EXPECT_EQ( expectedEnd, audioEvent->getSampleEnd() ) << "expected sample end to exceed the range set by the sample start and updated length properties for loopeable event"; deleteAudioEvent( audioEvent ); }