static int sync_to_timecode(struct player_t *pl) { float when; double tcpos; signed int timecode; timecode = timecoder_get_position(pl->timecoder, &when); /* Instruct the caller to disconnect the timecoder if the needle * is outside the 'safe' zone of the record */ if(timecode != -1 && timecode > timecoder_get_safe(pl->timecoder)) return -1; /* If the timecoder is alive, use the pitch from the sine wave */ pl->pitch = timecoder_get_pitch(pl->timecoder); /* If we can read an absolute time from the timecode, then use it */ if(timecode == -1) pl->target_valid = 0; else { tcpos = (double)timecode / timecoder_get_resolution(pl->timecoder); pl->target_position = tcpos + pl->pitch * when; pl->target_valid = 1; } return 0; }
VinylControlXwax::VinylControlXwax(ConfigObject<ConfigValue>* pConfig, QString group) : VinylControl(pConfig, group), m_dVinylPositionOld(0.0), m_pWorkBuffer(new short[MAX_BUFFER_LEN]), m_workBufferSize(MAX_BUFFER_LEN), m_iQualPos(0), m_iQualFilled(0), m_iPosition(-1), m_bAtRecordEnd(false), m_bForceResync(false), m_iVCMode(mode->get()), m_iOldVCMode(MIXXX_VCMODE_ABSOLUTE), m_dOldFilePos(0.0), m_dOldDuration(0.0), m_dOldDurationInaccurate(-1.0), m_pPitchRing(NULL), m_iPitchRingSize(0), m_iPitchRingPos(0), m_iPitchRingFilled(0), m_dDisplayPitch(0.0), m_pSteadySubtle(new SteadyPitch(0.12)), m_pSteadyGross(new SteadyPitch(0.5)), m_bCDControl(false), m_bTrackSelectMode(false), m_pControlTrackSelector(NULL), m_pControlTrackLoader(NULL), m_dLastTrackSelectPos(0.0), m_dCurTrackSelectPos(0.0), m_dDriftAmt(0.0), m_dUiUpdateTime(-1.0) { // TODO(rryan): Should probably live in VinylControlManager since it's not // specific to a VC deck. signalenabled->slotSet(m_pConfig->getValueString( ConfigKey(VINYL_PREF_KEY, "show_signal_quality")).toInt()); // Get the vinyl type and speed. QString strVinylType = m_pConfig->getValueString( ConfigKey(group,"vinylcontrol_vinyl_type")); QString strVinylSpeed = m_pConfig->getValueString( ConfigKey(group,"vinylcontrol_speed_type")); // libxwax indexes by C-strings so we pass libxwax string literals so we // don't have to deal with freeing the strings later char* timecode = NULL; if (strVinylType == MIXXX_VINYL_SERATOCV02VINYLSIDEA) { timecode = (char*)"serato_2a"; } else if (strVinylType == MIXXX_VINYL_SERATOCV02VINYLSIDEB) { timecode = (char*)"serato_2b"; } else if (strVinylType == MIXXX_VINYL_SERATOCD) { timecode = (char*)"serato_cd"; m_bCDControl = true; } else if (strVinylType == MIXXX_VINYL_TRAKTORSCRATCHSIDEA) { timecode = (char*)"traktor_a"; } else if (strVinylType == MIXXX_VINYL_TRAKTORSCRATCHSIDEB) { timecode = (char*)"traktor_b"; } else if (strVinylType == MIXXX_VINYL_MIXVIBESDVS) { timecode = (char*)"mixvibes_v2"; } else { qDebug() << "Unknown vinyl type, defaulting to serato_2a"; timecode = (char*)"serato_2a"; } timecode_def* tc_def = timecoder_find_definition(timecode); if (tc_def == NULL) { qDebug() << "Error finding timecode definition for " << timecode << ", defaulting to serato_2a"; timecode = (char*)"serato_2a"; tc_def = timecoder_find_definition(timecode); } double speed = 1.0; double rpm = 100.0 / 3.0; if (strVinylSpeed == MIXXX_VINYL_SPEED_45) { rpm = 45.0; speed = 1.35; } double latency = ControlObject::getControl( ConfigKey("[Master]", "latency"))->get(); if (latency <= 0 || latency > 200) { qDebug() << "Failed to get sane latency, assuming 20 as a reasonable value"; latency = 20; } int iSampleRate = m_pConfig->getValueString( ConfigKey("[Soundcard]","Samplerate")).toULong(); // Set pitch ring size to 1/4 of one revolution -- a full revolution adds // too much stickiness to the pitch. m_iPitchRingSize = static_cast<int>(60000 / (rpm * latency * 4)); m_pPitchRing = new double[m_iPitchRingSize]; qDebug() << "Xwax Vinyl control starting with a sample rate of:" << iSampleRate; qDebug() << "Building timecode lookup tables for" << strVinylType << "with speed" << strVinylSpeed; // Initialize the timecoder structure. Use the static mutex so that we only // do this once across the VinylControlXwax instances. s_xwaxLUTMutex.lock(); timecoder_init(&timecoder, tc_def, speed, iSampleRate, /* phono */ false); timecoder_monitor_init(&timecoder, MIXXX_VINYL_SCOPE_SIZE); //Note that timecoder_init will not double-malloc the LUTs, and after this we are guaranteed //that the LUT has been generated unless we ran out of memory. s_bLUTInitialized = true; m_uiSafeZone = timecoder_get_safe(&timecoder); //} s_xwaxLUTMutex.unlock(); qDebug() << "Starting vinyl control xwax thread"; }