Skip to content

Commit

Permalink
Changed establishQuality function in vinylcontrolxwax to consider the…
Browse files Browse the repository at this point in the history
… pitch information additional to the position code.

This results in faster response and the function provides also quality information at slow rotation
  • Loading branch information
JoergAtGithub committed Nov 9, 2020
1 parent be85660 commit 1b667d7
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 30 deletions.
104 changes: 79 additions & 25 deletions src/vinylcontrol/vinylcontrolxwax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@
* *
***************************************************************************/

#include <QtDebug>
#include "vinylcontrol/vinylcontrolxwax.h"

#include <limits.h>

#include "vinylcontrol/vinylcontrolxwax.h"
#include "util/timer.h"
#include "control/controlproxy.h"
#include <QtDebug>
#include <numeric>

#include "control/controlobject.h"
#include "util/math.h"
#include "control/controlproxy.h"
#include "util/defs.h"
#include "util/math.h"
#include "util/timer.h"

/****** TODO *******
Stuff to maybe implement here
Expand All @@ -53,8 +56,10 @@ VinylControlXwax::VinylControlXwax(UserSettingsPointer pConfig, QString group)
m_dVinylPositionOld(0.0),
m_pWorkBuffer(new short[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),
Expand Down Expand Up @@ -258,20 +263,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, NULL);
//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
Expand Down Expand Up @@ -653,10 +658,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->slotSet(VINYL_STATUS_OK);
}
Expand Down Expand Up @@ -816,21 +821,70 @@ 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 conrol 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
}

float pitchDifference = pitch - m_dQualityLastPitch;
m_dQualityLastPitch = pitch;

if (pitchDifference != 0) {
float 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) {
// 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;
}

int quality = 0;
for (int i = 0; i < m_iQualFilled; ++i) {
if (m_bQualityRing[i])
quality++;
void VinylControlXwax::establishQuality(double& pitch) {
m_iQualityRing[m_iQualityRingIndex] = getPositionQuality() + getPitchQuality(pitch);
m_fTimecodeQuality = static_cast<float>(std::accumulate(m_iQualityRing, m_iQualityRing + m_iQualityRingFilled, 0)) / 2.0 / 100.0 / 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;

//qDebug() << "m_fTimecodeQuality: " << m_fTimecodeQuality;
}

float VinylControlXwax::getAngle() {
Expand Down
15 changes: 10 additions & 5 deletions src/vinylcontrol/vinylcontrolxwax.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extern "C" {

#define XWAX_DEVICE_FRAME 32
#define XWAX_SMOOTHING (128 / XWAX_DEVICE_FRAME) /* result value is in frames */
#define QUALITY_RING_SIZE 100
#define QUALITY_RING_SIZE 32

class VinylControlXwax : public VinylControl {
public:
Expand All @@ -45,7 +45,9 @@ class VinylControlXwax : public VinylControl {
void enableConstantMode();
void enableConstantMode(double rate);
bool uiUpdateTime(double time);
void establishQuality(bool quality_sample);
void establishQuality(double& pitch);
int getPositionQuality();
int getPitchQuality(double& pitch);

// Cache the position of the end of record
unsigned int m_uiSafeZone;
Expand All @@ -60,9 +62,12 @@ class VinylControlXwax : public VinylControl {
// Signal quality ring buffer.
// TODO(XXX): Replace with CircularBuffer instead of handling the ring logic
// in VinylControlXwax.
bool m_bQualityRing[QUALITY_RING_SIZE];
int m_iQualPos;
int m_iQualFilled;
int m_iQualityRing[QUALITY_RING_SIZE];
int m_iQualityRingIndex;
int m_iQualityRingFilled;

int m_iQualityLastPosition;
double m_dQualityLastPitch;

// Keeps track of the most recent position as reported by xwax.
int m_iPosition;
Expand Down

0 comments on commit 1b667d7

Please sign in to comment.