Skip to content

Commit

Permalink
roc-streaminggh-765: Port LatencyTuner & FreqEstimator to STS time & …
Browse files Browse the repository at this point in the history
…fix bugs

- Use STS instead of system clock for timeouts. This allows to write
  fast pipeline tests not tied to real time.

- Properly compare STS timestamps in LatencyEstimator. Old code was
  doing comparison without handling possible wrap in several places.

- Adaptive latency fix: if new target is below minimum, but current
  target is above minimum, set target to the minimum instead of
  keeping target unmodified.
  • Loading branch information
gavv committed Aug 7, 2024
1 parent d0cd5fe commit 75ff495
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 97 deletions.
40 changes: 25 additions & 15 deletions src/internal_modules/roc_audio/freq_estimator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,20 @@ bool FreqEstimatorConfig::deduce_defaults(LatencyTunerProfile latency_profile) {

FreqEstimator::FreqEstimator(const FreqEstimatorConfig& config,
packet::stream_timestamp_t target_latency,
const SampleSpec& sample_spec,
dbgio::CsvDumper* dumper)
: config_(config)
, target_(target_latency)
, dec1_ind_(0)
, dec2_ind_(0)
, samples_counter_(0)
, accum_(0)
, target_(target_latency)
, coeff_(1)
, stable_(false)
, last_unstable_time_(core::timestamp(core::ClockMonotonic))
, last_unstable_time_(0)
, stability_duration_criteria_(
sample_spec.ns_2_stream_timestamp_delta(config.stability_duration_criteria))
, current_stream_pos_(0)
, dumper_(dumper) {
roc_log(LogDebug, "freq estimator: initializing: P=%e I=%e dc1=%lu dc2=%lu",
config_.P, config_.I, (unsigned long)config_.decimation_factor1,
Expand Down Expand Up @@ -125,8 +129,12 @@ float FreqEstimator::freq_coeff() const {
return (float)coeff_;
}

bool FreqEstimator::is_stable() const {
return stable_;
}

void FreqEstimator::update_current_latency(packet::stream_timestamp_t current_latency) {
double filtered;
double filtered = 0;

if (run_decimators_(current_latency, filtered)) {
if (dumper_) {
Expand All @@ -136,6 +144,17 @@ void FreqEstimator::update_current_latency(packet::stream_timestamp_t current_la
}
}

void FreqEstimator::update_target_latency(packet::stream_timestamp_t target_latency) {
target_ = (double)target_latency;
}

void FreqEstimator::update_stream_position(packet::stream_timestamp_t stream_position) {
roc_panic_if_msg(!packet::stream_timestamp_ge(stream_position, current_stream_pos_),
"freq estimator: expected monotonic stream position");

current_stream_pos_ = stream_position;
}

bool FreqEstimator::run_decimators_(packet::stream_timestamp_t current,
double& filtered) {
samples_counter_++;
Expand Down Expand Up @@ -181,18 +200,17 @@ double FreqEstimator::run_controller_(double current) {
" current latency error: %.0f",
error);

const core::nanoseconds_t now = core::timestamp(core::ClockMonotonic);

if (std::abs(error) > target_ * config_.stable_criteria && stable_) {
stable_ = false;
accum_ = 0;
last_unstable_time_ = now;
last_unstable_time_ = current_stream_pos_;
roc_log(LogDebug,
"freq estimator:"
" unstable, %0.f > %.0f / %0.f",
config_.stable_criteria, error, target_);
} else if (std::abs(error) < target_ * config_.stable_criteria && !stable_
&& now - last_unstable_time_ > config_.stability_duration_criteria) {
&& packet::stream_timestamp_diff(current_stream_pos_, last_unstable_time_)
> stability_duration_criteria_) {
stable_ = true;
roc_log(LogDebug,
"freq estimator:"
Expand Down Expand Up @@ -228,13 +246,5 @@ void FreqEstimator::dump_(double filtered) {
dumper_->write(e);
}

void FreqEstimator::update_target_latency(packet::stream_timestamp_t target_latency) {
target_ = (double)target_latency;
}

bool FreqEstimator::is_stable() const {
return stable_;
}

} // namespace audio
} // namespace roc
32 changes: 21 additions & 11 deletions src/internal_modules/roc_audio/freq_estimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "roc_audio/freq_estimator_decim.h"
#include "roc_audio/latency_config.h"
#include "roc_audio/sample.h"
#include "roc_audio/sample_spec.h"
#include "roc_core/attributes.h"
#include "roc_core/noncopyable.h"
#include "roc_dbgio/csv_dumper.h"
Expand Down Expand Up @@ -81,31 +82,34 @@ class FreqEstimator : public core::NonCopyable<> {
//! - @p target_latency defines latency we want to archive.
FreqEstimator(const FreqEstimatorConfig& config,
packet::stream_timestamp_t target_latency,
const SampleSpec& sample_spec,
dbgio::CsvDumper* dumper);

//! Get current frequency coefficient.
//! Get current frequency coefficient to be passed to resampler.
float freq_coeff() const;

//! Compute new value of frequency coefficient.
void update_current_latency(packet::stream_timestamp_t current_latency);

//! Update target latency.
void update_target_latency(packet::stream_timestamp_t target_latency);

//! Is FreqEstimator in stable state.
//! @remarks
//! If current_latency is in kept within certain limits around target_latency
//! FreqEstimator is in 'stable' state, otherwise it is 'not-stable' state.
//! The state affects internal regulator strategy and it effectiveness.
bool is_stable() const;

//! Tell FreqEstimator what is the new target.
void update_target_latency(packet::stream_timestamp_t target_latency);

//! Tell FreqEstimator what is the actual measured latency.
void update_current_latency(packet::stream_timestamp_t current_latency);

//! Tell FreqEstimator what is the current stream offset.
void update_stream_position(packet::stream_timestamp_t stream_position);

private:
bool run_decimators_(packet::stream_timestamp_t current, double& filtered);
double run_controller_(double current);
void dump_(double filtered);

const FreqEstimatorConfig config_;
double target_; // Target latency.

double dec1_casc_buff_[fe_decim_len];
size_t dec1_ind_;
Expand All @@ -116,11 +120,17 @@ class FreqEstimator : public core::NonCopyable<> {
size_t samples_counter_; // Input samples counter.
double accum_; // Integrator value.

double coeff_; // Current frequency coefficient value.
double target_; // Target latency.
double coeff_; // Current frequency coefficient value.

bool stable_; // True if FreqEstimator has stabilized.
// True if FreqEstimator has stabilized.
bool stable_;
// Last time when FreqEstimator was out of range.
core::nanoseconds_t last_unstable_time_;
packet::stream_timestamp_t last_unstable_time_;
// How long stabilization takes.
const packet::stream_timestamp_diff_t stability_duration_criteria_;
// Current time.
packet::stream_timestamp_t current_stream_pos_;

dbgio::CsvDumper* dumper_;
};
Expand Down
Loading

0 comments on commit 75ff495

Please sign in to comment.