Skip to content

Commit

Permalink
Merge pull request #324 from ywwg/pitch_knob_stuck
Browse files Browse the repository at this point in the history
When disabling keylock, explicitly reset musical pitch.
  • Loading branch information
ywwg committed Sep 8, 2014
2 parents 6abf5f8 + 70e9c95 commit fa79563
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/engine/enginebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ EngineBuffer::EngineBuffer(const char* _group, ConfigObject<ConfigValue>* _confi
m_dSlipRate(1.0),
m_slipEnabled(0),
m_bSlipEnabledProcessing(false),
m_bWasKeylocked(false),
m_pRepeat(NULL),
m_startButton(NULL),
m_endButton(NULL),
Expand Down Expand Up @@ -257,6 +258,7 @@ EngineBuffer::EngineBuffer(const char* _group, ConfigObject<ConfigValue>* _confi

m_pKeyControl = new KeyControl(_group, _config);
addControl(m_pKeyControl);
m_pPitchControl = new ControlObjectSlave(m_group, "pitch", this);

// Create the clock controller
m_pClockControl = new ClockControl(_group, _config);
Expand Down Expand Up @@ -525,6 +527,8 @@ void EngineBuffer::slotTrackLoaded(TrackPointer pTrack,
m_file_length_old = iTrackNumSamples;
m_pTrackSamples->set(iTrackNumSamples);
m_pTrackSampleRate->set(iTrackSampleRate);
// Reset the pitch value for the new track.
m_pPitchControl->set(0.0);
m_pause.unlock();

// All EngineControls are connected directly
Expand Down Expand Up @@ -737,6 +741,11 @@ void EngineBuffer::process(CSAMPLE* pOutput, const int iBufferSize)
bool is_scratching = false;
bool keylock_enabled = m_pKeylock->get() > 0;

// If keylock was on, and the user disabled it, also reset the pitch.
if (m_bWasKeylocked && !keylock_enabled) {
m_pPitchControl->set(0.0);
}

// speed is the percentage change in player speed. Depending on whether
// keylock is enabled, this is applied to either the rate or the tempo.
double speed = m_pRateControl->calculateRate(
Expand Down Expand Up @@ -809,6 +818,7 @@ void EngineBuffer::process(CSAMPLE* pOutput, const int iBufferSize)
m_baserate_old = baserate;
m_speed_old = speed;
m_pitch_old = pitch;
m_bWasKeylocked = keylock_enabled;

// The way we treat rate inside of EngineBuffer is actually a
// description of "sample consumption rate" or percentage of samples
Expand Down
3 changes: 3 additions & 0 deletions src/engine/enginebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ class EngineBuffer : public EngineObject {
QAtomicInt m_slipEnabled;
// m_bSlipEnabledProcessing is only used by the engine processing thread.
bool m_bSlipEnabledProcessing;
bool m_bWasKeylocked;


ControlObject* m_pTrackSamples;
ControlObject* m_pTrackSampleRate;
Expand All @@ -328,6 +330,7 @@ class EngineBuffer : public EngineObject {
ControlPotmeter* m_playposSlider;
ControlObjectSlave* m_pSampleRate;
ControlObjectSlave* m_pKeylockEngine;
ControlObjectSlave* m_pPitchControl;
ControlPushButton* m_pKeylock;
QScopedPointer<ControlObjectSlave> m_pPassthroughEnabled;

Expand Down
40 changes: 40 additions & 0 deletions src/test/enginebuffertest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Tests for enginebuffer.cpp

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <QtDebug>

#include "configobject.h"
#include "controlobject.h"
#include "test/mockedenginebackendtest.h"
#include "test/mixxxtest.h"


class EngineBufferTest : public MockedEngineBackendTest {
};

TEST_F(EngineBufferTest, DisableKeylockResetsPitch) {
// To prevent one-slider users from getting stuck on a key, unsetting
// keylock resets the musical pitch.
ControlObject::getControl(ConfigKey(m_sGroup1, "file_bpm"))->set(128.0);
ControlObject::getControl(ConfigKey(m_sGroup1, "keylock"))->set(1.0);
ControlObject::getControl(ConfigKey(m_sGroup1, "pitch"))->set(0.5);
ProcessBuffer();

ControlObject::getControl(ConfigKey(m_sGroup1, "keylock"))->set(0.0);
// We require a buffer process to see that the keylock state has changed.
ProcessBuffer();
ASSERT_EQ(0.0, ControlObject::getControl(ConfigKey(m_sGroup1, "pitch"))->get());
}

TEST_F(EngineBufferTest, TrackLoadResetsPitch) {
// When a new track is loaded, the pitch value should be reset.
ControlObject::getControl(ConfigKey(m_sGroup1, "file_bpm"))->set(128.0);
ControlObject::getControl(ConfigKey(m_sGroup1, "pitch"))->set(0.5);
ProcessBuffer();
ASSERT_EQ(0.5, ControlObject::getControl(ConfigKey(m_sGroup1, "pitch"))->get());

m_pChannel1->getEngineBuffer()->loadFakeTrack();
ASSERT_EQ(0.0, ControlObject::getControl(ConfigKey(m_sGroup1, "pitch"))->get());
}
1 change: 0 additions & 1 deletion src/test/enginesynctest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Tests for Master Sync.
// There are no tests for actual deck playback, since I don't know how to mock that out yet.
// The following manual tests should probably be performed:
// * Quantize mode nudges tracks in sync, whether internal or deck master.
// * Flinging tracks with the waveform should work.
Expand Down

1 comment on commit fa79563

@ywwg
Copy link
Member Author

@ywwg ywwg commented on fa79563 Sep 8, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Achievement unlocked -- #2 all-time developer by number of commits :)

Please sign in to comment.