// get the adjustment required to match the hardware clocks double SynchCorrection::GetRequiredAdjustment(REFERENCE_TIME rtAHwTime, REFERENCE_TIME rtRCTime, double bias, double adjustment) { double ret = bias* adjustment; double totalAudioDrift = CalculateDrift(rtAHwTime, rtRCTime - m_rtStart) + m_dAudioDelay +m_dEVRAudioDelay; bool bQuality = bias > 1.0 - QUALITY_BIAS_LIMIT && bias < 1.0 + QUALITY_BIAS_LIMIT; if (bQuality) { ret = 1.0; // 1 to 1 playback unless proved otherwise if (m_bQualityCorrectionOn) // we are correcting drift { if (((m_iQualityDir == DIRUP) && (totalAudioDrift > QUALITY_CORRECTION_LIMIT)) || ((m_iQualityDir == DIRDOWN) && (totalAudioDrift < QUALITY_CORRECTION_LIMIT * -1.0))) { //we've corrected enough m_bQualityCorrectionOn = false; m_iQualityDir = 0; } if (m_iQualityDir == DIRUP) //behind so stretch ret = QUALITY_CORRECTION_MULTIPLIER; else if (m_iQualityDir == DIRDOWN) // in front so slow ret = 1.0 / QUALITY_CORRECTION_MULTIPLIER; } else // not correcting now so check for breach { if (totalAudioDrift > QUALITY_DRIFT_LIMIT) { m_bQualityCorrectionOn = true; m_iQualityDir = DIRDOWN; } else if (totalAudioDrift < QUALITY_DRIFT_LIMIT * -1.0) { m_bQualityCorrectionOn = true; m_iQualityDir = DIRUP; } } } else if (totalAudioDrift > ALLOWED_DRIFT && (!bQuality || bias < 1.0)) { // we've stretched too much shift down for a while double msDrift = totalAudioDrift / 10000.0; double quickCorrection = 1.0; if (msDrift > 10.0) quickCorrection = log(msDrift); else quickCorrection = msDrift / 10.0; if (quickCorrection > 5.0) quickCorrection = 5.0; ret = ret * (1.0 / (1 + (CORRECTION_RATE-1) * quickCorrection)); } else if (totalAudioDrift < ALLOWED_DRIFT * -1.0 && (!bQuality || bias > 1.0)) { // haven't streched enough double msDrift = totalAudioDrift / -10000.0; double quickCorrection = 1.0; if (msDrift > 10.0) quickCorrection = log(msDrift); else quickCorrection = msDrift / 10.0; if (quickCorrection > 5.0) quickCorrection = 5.0; ret = ret * (1+(CORRECTION_RATE-1)*quickCorrection); } return ret; }
void TrailRenderer::Draw(Canvas &canvas, const TraceComputer &trace_computer, const WindowProjection &projection, unsigned min_time, bool enable_traildrift, const RasterPoint pos, const NMEAInfo &basic, const DerivedInfo &calculated, const TrailSettings &settings) { if (settings.length == TrailSettings::Length::OFF) return; if (!LoadTrace(trace_computer, min_time, projection)) return; if (!calculated.wind_available) enable_traildrift = false; GeoPoint traildrift; if (enable_traildrift) { GeoPoint tp1 = FindLatitudeLongitude(basic.location, calculated.wind.bearing, calculated.wind.norm); traildrift = basic.location - tp1; } auto minmax = GetMinMax(settings.type, trace); auto value_min = minmax.first; auto value_max = minmax.second; bool scaled_trail = settings.scaling_enabled && projection.GetMapScale() <= 6000; const GeoBounds bounds = projection.GetScreenBounds().Scale(4); RasterPoint last_point = RasterPoint(0, 0); bool last_valid = false; for (auto it = trace.begin(), end = trace.end(); it != end; ++it) { const GeoPoint gp = enable_traildrift ? it->GetLocation().Parametric(traildrift, it->CalculateDrift(basic.time)) : it->GetLocation(); if (!bounds.IsInside(gp)) { /* the point is outside of the MapWindow; don't paint it */ last_valid = false; continue; } RasterPoint pt = projection.GeoToScreen(gp); if (last_valid) { if (settings.type == TrailSettings::Type::ALTITUDE) { unsigned index = GetAltitudeColorIndex(it->GetAltitude(), value_min, value_max); canvas.Select(look.trail_pens[index]); canvas.DrawLinePiece(last_point, pt); } else { unsigned color_index = GetSnailColorIndex(it->GetVario(), value_min, value_max); if (it->GetVario() < 0 && (settings.type == TrailSettings::Type::VARIO_1_DOTS || settings.type == TrailSettings::Type::VARIO_2_DOTS || settings.type == TrailSettings::Type::VARIO_DOTS_AND_LINES)) { canvas.SelectNullPen(); canvas.Select(look.trail_brushes[color_index]); canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2, look.trail_widths[color_index]); } else { // positive vario case if (settings.type == TrailSettings::Type::VARIO_DOTS_AND_LINES) { canvas.Select(look.trail_brushes[color_index]); canvas.Select(look.trail_pens[color_index]); //fixed-width pen canvas.DrawCircle((pt.x + last_point.x) / 2, (pt.y + last_point.y) / 2, look.trail_widths[color_index]); } else if (scaled_trail) // width scaled to vario canvas.Select(look.scaled_trail_pens[color_index]); else // fixed-width pen canvas.Select(look.trail_pens[color_index]); canvas.DrawLinePiece(last_point, pt); } } } last_point = pt; last_valid = true; } if (last_valid) canvas.DrawLine(last_point, pos); }
// get the current drift double SynchCorrection::TotalAudioDrift(REFERENCE_TIME rtAHwTime, REFERENCE_TIME rtRCTime) { return CalculateDrift(rtAHwTime, rtRCTime - m_rtStart) + m_dAudioDelay + m_dEVRAudioDelay; }