TEST_F(LoopingControlTest, ReloopExitButton_TogglesLoop) { m_pQuantizeEnabled->set(0); m_pClosestBeat->set(-1); m_pNextBeat->set(-1); seekToSampleAndProcess(500); m_pLoopStartPoint->slotSet(0); m_pButtonLoopOut->slotSet(1); m_pButtonLoopOut->slotSet(0); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(500, m_pLoopEndPoint->get()); m_pButtonReloopExit->slotSet(1); m_pButtonReloopExit->slotSet(0); EXPECT_FALSE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(500, m_pLoopEndPoint->get()); m_pButtonReloopExit->slotSet(1); m_pButtonReloopExit->slotSet(0); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(500, m_pLoopEndPoint->get()); // Ensure that the Loop Exit button works, and that it doesn't act as a // toggle. m_pButtonLoopExit->slotSet(1); m_pButtonLoopExit->slotSet(0); EXPECT_FALSE(isLoopEnabled()); m_pButtonLoopExit->slotSet(1); m_pButtonLoopExit->slotSet(0); EXPECT_FALSE(isLoopEnabled()); }
TEST_F(LoopingControlTest, LoopHalveButton_HalvesLoop) { m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(2000); seekToSampleAndProcess(1800); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(2000, m_pLoopEndPoint->get()); EXPECT_EQ(1800, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); EXPECT_FALSE(isLoopEnabled()); m_pButtonLoopHalve->slotSet(1); m_pButtonLoopHalve->slotSet(0); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(1000, m_pLoopEndPoint->get()); // The loop was not enabled so halving the loop should not move the playhead // even though it is outside the loop. EXPECT_EQ(1800, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); m_pButtonReloopExit->slotSet(1); EXPECT_TRUE(isLoopEnabled()); m_pButtonLoopHalve->slotSet(1); m_pButtonLoopHalve->slotSet(0); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(500, m_pLoopEndPoint->get()); // Since the current sample was out of range of the new loop, // the current sample should reseek based on the new loop size. EXPECT_EQ(300, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); }
TEST_F(LoopingControlTest, LoopScale_HalvesLoop) { m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(2000); seekToSampleAndProcess(1800); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(2000, m_pLoopEndPoint->get()); EXPECT_EQ(1800, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getSampleOfTrack().current); EXPECT_FALSE(isLoopEnabled()); m_pLoopScale->set(0.5); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(1000, m_pLoopEndPoint->get()); // The loop was not enabled so halving the loop should not move the playhead // even though it is outside the loop. EXPECT_EQ(1800, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getSampleOfTrack().current); m_pButtonReloopToggle->slotSet(1); EXPECT_TRUE(isLoopEnabled()); m_pLoopScale->set(0.5); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(500, m_pLoopEndPoint->get()); // Since the current sample was out of range of the new loop, // the current sample should reseek based on the new loop size. double target; double trigger = m_pChannel1->getEngineBuffer()->m_pLoopingControl->nextTrigger( false, 1800, &target); EXPECT_EQ(300, target); EXPECT_EQ(1800, trigger); }
TEST_F(LoopingControlTest, LoopMoveTest) { // Set a crazy bpm so our super-short track of 1000 samples has a couple beats in it. m_pTrack1->setBpm(23520); m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(300); seekToSampleAndProcess(10); m_pButtonReloopExit->slotSet(1); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(300, m_pLoopEndPoint->get()); EXPECT_EQ(10, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Move the loop out from under the playposition. m_pButtonBeatMoveForward->set(1.0); m_pButtonBeatMoveForward->set(0.0); ProcessBuffer(); EXPECT_EQ(224, m_pLoopStartPoint->get()); EXPECT_EQ(524, m_pLoopEndPoint->get()); EXPECT_EQ(310, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Move backward so that the current position is off the end of the loop. m_pChannel1->getEngineBuffer()->queueNewPlaypos(500, EngineBuffer::SEEK_STANDARD); ProcessBuffer(); m_pButtonBeatMoveBackward->set(1.0); m_pButtonBeatMoveBackward->set(0.0); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(300, m_pLoopEndPoint->get()); EXPECT_EQ(200, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Now repeat the test with looping disabled (should not affect the // playhead). m_pButtonReloopExit->slotSet(1); EXPECT_FALSE(isLoopEnabled()); // Move the loop out from under the playposition. m_pButtonBeatMoveForward->set(1.0); m_pButtonBeatMoveForward->set(0.0); ProcessBuffer(); EXPECT_EQ(224, m_pLoopStartPoint->get()); EXPECT_EQ(524, m_pLoopEndPoint->get()); EXPECT_EQ(200, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Move backward so that the current position is off the end of the loop. m_pChannel1->getEngineBuffer()->queueNewPlaypos(500, EngineBuffer::SEEK_STANDARD); ProcessBuffer(); m_pButtonBeatMoveBackward->set(1.0); m_pButtonBeatMoveBackward->set(0.0); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(300, m_pLoopEndPoint->get()); EXPECT_EQ(500, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); }
TEST_F(LoopingControlTest, LoopOutSetBeforeLoopInIgnored) { m_pLoopStartPoint->slotSet(10); m_pLoopEndPoint->slotSet(100); m_pButtonReloopExit->slotSet(1); m_pButtonReloopExit->slotSet(0); seekToSampleAndProcess(50); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(10, m_pLoopStartPoint->get()); EXPECT_EQ(100, m_pLoopEndPoint->get()); m_pLoopEndPoint->slotSet(0); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(10, m_pLoopStartPoint->get()); EXPECT_EQ(100, m_pLoopEndPoint->get()); }
TEST_F(LoopingControlTest, LoopOutSetInsideLoopContinues) { m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(100); m_pButtonReloopExit->slotSet(1); m_pButtonReloopExit->slotSet(0); seekToSampleAndProcess(50); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(100, m_pLoopEndPoint->get()); m_pLoopEndPoint->slotSet(80); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(80, m_pLoopEndPoint->get()); }
TEST_F(LoopingControlTest, LoopInSetAfterLoopOutStops) { m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(100); m_pButtonReloopExit->slotSet(1); m_pButtonReloopExit->slotSet(0); seekToSampleAndProcess(50); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(100, m_pLoopEndPoint->get()); m_pLoopStartPoint->slotSet(110); EXPECT_FALSE(isLoopEnabled()); EXPECT_EQ(110, m_pLoopStartPoint->get()); EXPECT_EQ(-1, m_pLoopEndPoint->get()); }
TEST_F(LoopingControlTest, LoopResizeSeek) { // Activating a new loop with a loop active should warp the playposition // the same as it does when we scale the loop larger and smaller so we // keep in sync with the beat. // Disable quantize for this test m_pQuantizeEnabled->set(0.0); m_pTrack1->setBpm(23520); m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(600); seekToSampleAndProcess(500); m_pButtonReloopToggle->slotSet(1); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(600, m_pLoopEndPoint->get()); EXPECT_EQ(500, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Activate a shorter loop m_pButtonBeatLoop2Activate->set(1.0); ProcessBuffer(); // The loop is resized and we should have seeked to a mid-beat part of the // loop. EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(450, m_pLoopEndPoint->get()); ProcessBuffer(); EXPECT_EQ(50, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // But if looping is not enabled, no warping occurs. m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(600); seekToSampleAndProcess(500); m_pButtonReloopToggle->slotSet(1); EXPECT_FALSE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(600, m_pLoopEndPoint->get()); EXPECT_EQ(500, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); m_pButtonBeatLoop2Activate->set(1.0); ProcessBuffer(); EXPECT_EQ(500, m_pLoopStartPoint->get()); EXPECT_EQ(950, m_pLoopEndPoint->get()); EXPECT_EQ(500, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); }
TEST_F(LoopingControlTest, LoopSet) { m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(100); seekToSampleAndProcess(50); EXPECT_FALSE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(100, m_pLoopEndPoint->get()); }
TEST_F(LoopingControlTest, LoopEscape) { m_pLoopStartPoint->slotSet(100); m_pLoopEndPoint->slotSet(200); m_pButtonReloopToggle->set(1.0); m_pButtonReloopToggle->set(0.0); ProcessBuffer(); EXPECT_TRUE(isLoopEnabled()); // seek outside a loop should disable it seekToSampleAndProcess(300); EXPECT_FALSE(isLoopEnabled()); m_pButtonReloopToggle->set(1.0); m_pButtonReloopToggle->set(0.0); ProcessBuffer(); EXPECT_TRUE(isLoopEnabled()); // seek outside a loop should disable it seekToSampleAndProcess(50); EXPECT_FALSE(isLoopEnabled()); }
TEST_F(LoopingControlTest, LoopMoveTest) { m_pTrack1->setBpm(120); m_pLoopStartPoint->slotSet(0); m_pLoopEndPoint->slotSet(300); seekToSampleAndProcess(10); m_pButtonReloopToggle->slotSet(1); EXPECT_TRUE(isLoopEnabled()); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_EQ(300, m_pLoopEndPoint->get()); EXPECT_EQ(10, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Move the loop out from under the playposition. m_pButtonBeatMoveForward->set(1.0); m_pButtonBeatMoveForward->set(0.0); ProcessBuffer(); EXPECT_EQ(44100, m_pLoopStartPoint->get()); EXPECT_EQ(44400, m_pLoopEndPoint->get()); ProcessBuffer(); // Should seek to the corresponding offset within the moved loop EXPECT_EQ(44110, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample()); // Move backward so that the current position is outside the new location of the loop m_pChannel1->getEngineBuffer()->queueNewPlaypos(44300, EngineBuffer::SEEK_STANDARD); ProcessBuffer(); m_pButtonBeatMoveBackward->set(1.0); m_pButtonBeatMoveBackward->set(0.0); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_NEAR(300, m_pLoopEndPoint->get(), kLoopPositionMaxAbsError); ProcessBuffer(); EXPECT_NEAR(200, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample(), kLoopPositionMaxAbsError); // Now repeat the test with looping disabled (should not affect the // playhead). m_pButtonReloopToggle->slotSet(1); EXPECT_FALSE(isLoopEnabled()); // Move the loop out from under the playposition. m_pButtonBeatMoveForward->set(1.0); m_pButtonBeatMoveForward->set(0.0); ProcessBuffer(); EXPECT_EQ(44100, m_pLoopStartPoint->get()); EXPECT_EQ(44400, m_pLoopEndPoint->get()); // Should not seek inside the moved loop when the loop is disabled EXPECT_NEAR(200, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample(), kLoopPositionMaxAbsError); // Move backward so that the current position is outside the new location of the loop m_pChannel1->getEngineBuffer()->queueNewPlaypos(500, EngineBuffer::SEEK_STANDARD); ProcessBuffer(); m_pButtonBeatMoveBackward->set(1.0); m_pButtonBeatMoveBackward->set(0.0); ProcessBuffer(); EXPECT_EQ(0, m_pLoopStartPoint->get()); EXPECT_NEAR(300, m_pLoopEndPoint->get(), kLoopPositionMaxAbsError); EXPECT_NEAR(500, m_pChannel1->getEngineBuffer()->m_pLoopingControl->getCurrentSample(), kLoopPositionMaxAbsError); }