-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved VinylControlXwax::establishQuality #3279
Changes from all commits
508b216
b68dcd0
d68188f
9423935
d323cb2
78f9803
fe2b854
49da32a
e0099af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,8 +31,10 @@ VinylControlXwax::VinylControlXwax(UserSettingsPointer pConfig, const QString& g | |
m_dVinylPositionOld(0.0), | ||
m_pWorkBuffer(MAX_BUFFER_LEN), | ||
m_workBufferSize(MAX_BUFFER_LEN), | ||
m_iQualPos(0), | ||
m_iQualFilled(0), | ||
m_iQualityRingIndex(0), | ||
m_iQualityRingFilled(0), | ||
m_iQualityLastPosition(-1), | ||
m_dQualityLastPitch(0.0), | ||
m_iPosition(-1), | ||
m_bAtRecordEnd(false), | ||
m_bForceResync(false), | ||
|
@@ -230,20 +232,20 @@ void VinylControlXwax::analyzeSamples(CSAMPLE* pSamples, size_t nFrames) { | |
// Check if vinyl control is enabled... | ||
m_bIsEnabled = enabled && checkEnabled(m_bIsEnabled, enabled->toBool()); | ||
|
||
double dVinylPitch = timecoder_get_pitch(&timecoder); | ||
|
||
if(bHaveSignal) { | ||
// Always analyze the input samples | ||
m_iPosition = timecoder_get_position(&timecoder, nullptr); | ||
//Notify the UI if the timecode quality is good | ||
establishQuality(m_iPosition != -1); | ||
establishQuality(dVinylPitch); | ||
} | ||
|
||
//are we even playing and enabled at all? | ||
if (!m_bIsEnabled) { | ||
return; | ||
} | ||
|
||
double dVinylPitch = timecoder_get_pitch(&timecoder); | ||
|
||
// Has a new track been loaded? Currently we use track duration which is | ||
// integer seconds in the song. However, for calculations we need the | ||
// higher-accuracy duration found by dividing the track samples by the | ||
|
@@ -626,10 +628,10 @@ void VinylControlXwax::analyzeSamples(CSAMPLE* pSamples, size_t nFrames) { | |
//resetSteadyPitch(dVinylPitch, filePosition); | ||
// Notify the UI that the timecode quality is garbage/missing. | ||
m_fTimecodeQuality = 0.0f; | ||
m_iPitchRingPos = 0; | ||
m_iPitchRingFilled = 0; | ||
m_iQualPos = 0; | ||
m_iQualFilled = 0; | ||
m_dQualityLastPitch = 0.0; | ||
m_iQualityLastPosition = -1; | ||
m_iQualityRingIndex = 0; | ||
m_iQualityRingFilled = 0; | ||
m_bForceResync = true; | ||
vinylStatus->set(VINYL_STATUS_OK); | ||
} | ||
|
@@ -789,22 +791,75 @@ bool VinylControlXwax::uiUpdateTime(double now) { | |
return false; | ||
} | ||
|
||
void VinylControlXwax::establishQuality(bool quality_sample) { | ||
m_bQualityRing[m_iQualPos] = quality_sample; | ||
if (m_iQualFilled < QUALITY_RING_SIZE) { | ||
m_iQualFilled++; | ||
int VinylControlXwax::getPositionQuality() { | ||
int positionQualityPercent; | ||
|
||
if (m_iPosition == -1) { | ||
// No position code - happens when control vinyl is spinning slow (or during scratching) or the setup is incorrect | ||
positionQualityPercent = 0; | ||
} else if ((m_iPosition <= m_iQualityLastPosition - 5) || | ||
(m_iPosition >= m_iQualityLastPosition + 5)) { | ||
// Position code changed not by more than 5. This indicates a normal spinning control vinyl. | ||
positionQualityPercent = 100; | ||
} else { | ||
// Position code changed by more than 5. This indicates a fast spinning control vinyl, a jumping needle or a false signal. | ||
// This covers also the case of m_iQualityLastPosition == -1 | ||
positionQualityPercent = 50; | ||
} | ||
|
||
m_iQualityLastPosition = m_iPosition; | ||
|
||
return positionQualityPercent; | ||
} | ||
|
||
int VinylControlXwax::getPitchQuality(double& pitch) { | ||
int pitchQualityPercent; | ||
|
||
if (m_iQualityRingFilled == 0) { | ||
m_dQualityLastPitch = pitch; | ||
pitchQualityPercent = 0; | ||
return pitchQualityPercent; // First value - but at least two values needed for calculation | ||
} | ||
|
||
int quality = 0; | ||
for (int i = 0; i < m_iQualFilled; ++i) { | ||
if (m_bQualityRing[i]) { | ||
quality++; | ||
double pitchDifference = pitch - m_dQualityLastPitch; | ||
m_dQualityLastPitch = pitch; | ||
|
||
if (pitchDifference != 0) { | ||
double pitchStability = std::fabs(pitch / pitchDifference); | ||
|
||
if (pitchStability < 3.0) { | ||
// Unlikely that this pitch difference is from a proper set up control vinyl | ||
pitchQualityPercent = 0; | ||
} else if (pitchStability > 6.0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. again can you represent this set of thresholds with a simple linear equation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (1 + tanh( pitchstability + 3 ) ) * 50 could work. |
||
// Typical pitch difference for normal spinning control vinyl | ||
pitchQualityPercent = 100; | ||
} else { | ||
// Weak pitch difference for a control vinyl slow spinning ,or for scratching | ||
pitchQualityPercent = 75; | ||
} | ||
} else { | ||
// Unlikely case of two identical float values for pitch | ||
pitchQualityPercent = 0; | ||
} | ||
return pitchQualityPercent; | ||
} | ||
|
||
void VinylControlXwax::establishQuality(double& pitch) { | ||
m_iQualityRing[m_iQualityRingIndex] = getPositionQuality() + getPitchQuality(pitch); | ||
m_fTimecodeQuality = std::max<float>(0.0, | ||
std::min<float>(1.0, | ||
static_cast<float>(std::accumulate(m_iQualityRing, | ||
m_iQualityRing + m_iQualityRingFilled, | ||
0)) / | ||
2.0f / 100.0f / | ||
static_cast<float>( | ||
m_iQualityRingFilled))); // Two information in percent per datapoint | ||
|
||
if (m_iQualityRingFilled < QUALITY_RING_SIZE) { | ||
m_iQualityRingFilled++; | ||
} | ||
|
||
m_fTimecodeQuality = static_cast<float>(quality) / | ||
static_cast<float>(m_iQualFilled); | ||
m_iQualPos = (m_iQualPos + 1) % QUALITY_RING_SIZE; | ||
m_iQualityRingIndex = (m_iQualityRingIndex + 1) % QUALITY_RING_SIZE; | ||
} | ||
|
||
float VinylControlXwax::getAngle() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if we use a simple calculation that gradually reduces the qualitypercent as the velocity increases? Rather than a three-step threshold.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see, how this can be expressed by a linear expression: