UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
AudioDriftFixer Class Reference

#include <decklink_drift_fix.hpp>

Collaboration diagram for AudioDriftFixer:
Collaboration graph

Public Member Functions

void enable ()
 
double get_buffer_avg ()
 Get the average sample count per channel.
 
double scale_buffer_delta (int delta)
 This function will check the buffer delta and will return a delta in the sample rate that is required in order to offset the delta. This is scaled between the class members of min_hz and max_hz. The delta also has a max and min for the scaling which are defined by the min_buffer and the max_buffer. This ensures that very large deltas cannot cause large jumps in the resample rate that are audible (and that small deltas) do not create a resampling rate that is too small to have impact on the buffer.
 
void set_max_hz (uint32_t max_hz)
 Set the max hz object.
 
void set_min_hz (uint32_t min_hz)
 Set the min hz object.
 
void set_root (module *root)
 Set the root object.
 
void set_target_buffer (uint32_t target_buffer)
 Set the target buffer object.
 
void update (uint32_t buffered_count, uint32_t sample_frame_count, uint32_t sampleFramesWritten)
 

Private Attributes

DecklinkAudioSummary audio_summary {}
 
MovingAverage average_buffer_samples = 250
 
MovingAverage average_delta = 25
 
long long dst_frame_rate_set = 0
 
bool m_enabled = false
 
struct module * m_root = nullptr
 
uint32_t max_avg = 3650
 
uint32_t max_buffer = 600
 
uint32_t max_hz = MAX_RESAMPLE_DELTA_DEFAULT
 
uint32_t min_avg = 1800
 
uint32_t min_buffer = 100
 
uint32_t min_hz = MIN_RESAMPLE_DELTA_DEFAULT
 
uint32_t neg_jitter = 5
 
uint32_t pos_jitter = 5
 
uint32_t previous_buffer = 0
 
uint32_t target_buffer_fill = TARGET_BUFFER_DEFAULT
 

Static Private Attributes

static constexpr unsigned long BASE = (1U<<8U)
 
static const uint32_t NEG_JITTER_DEFAULT = 600
 
static const uint32_t POS_JITTER_DEFAULT = 600
 

Detailed Description

Todo
  • handle network losses
  • handle underruns
  • what about jitter - while computing the dst sample rate, the sampling interval (m_total) must be "long"

Definition at line 308 of file decklink_drift_fix.hpp.

Member Function Documentation

◆ enable()

void AudioDriftFixer::enable ( )
inline

Definition at line 310 of file decklink_drift_fix.hpp.

310 {
311 m_enabled = true;
312 if (commandline_params.find("resampler") == commandline_params.end()) {
313 LOG(LOG_LEVEL_INFO) << MOD_NAME << "Using SoxR resampler by default when DecKlink audio drift fixer is enabled.\n";
314 commandline_params["resampler"] = "soxr";
315 }
316 }
#define MOD_NAME
Definition audio.cpp:110
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG(level)
Definition debug.h:313
std::unordered_map< std::string, std::string > commandline_params
Definition host.cpp:184

References commandline_params, LOG, LOG_LEVEL_INFO, m_enabled, and MOD_NAME.

Referenced by settings_init().

◆ get_buffer_avg()

double AudioDriftFixer::get_buffer_avg ( )
inline

Get the average sample count per channel.

Returns
double The average of the buffer over the last X frames

Definition at line 358 of file decklink_drift_fix.hpp.

358 {
359 return this->average_buffer_samples.avg();
360 }
MovingAverage average_buffer_samples
double avg() const

References average_buffer_samples, and MovingAverage::avg().

Referenced by update().

Here is the call graph for this function:

◆ scale_buffer_delta()

double AudioDriftFixer::scale_buffer_delta ( int delta)
inline

This function will check the buffer delta and will return a delta in the sample rate that is required in order to offset the delta. This is scaled between the class members of min_hz and max_hz. The delta also has a max and min for the scaling which are defined by the min_buffer and the max_buffer. This ensures that very large deltas cannot cause large jumps in the resample rate that are audible (and that small deltas) do not create a resampling rate that is too small to have impact on the buffer.

Parameters
deltaThe delta between the average buffer size and the target buffer size to calculate a resample delta to offset the difference.
Returns
double A resample delta that can be added or subtracted from the original resample rate to move the average buffer size to the target buffer size.

Definition at line 375 of file decklink_drift_fix.hpp.

375 {
376 // Get a positive delta so that the scale can be calculated properly
377 delta = abs(delta);
378 // Check the boundaries for the scaling calculation
379 if((uint32_t)delta > this->max_buffer) {
380 delta = this->max_buffer;
381 }
382 else if ((uint32_t)delta < this->min_buffer) {
383 delta = this->min_buffer;
384 }
385 return (((this->max_hz - this->min_hz) * (delta - this->min_buffer)) / (this->max_buffer - this->min_buffer)) + this->min_hz;
386 }
static __device__ vec2 abs(const vec2 &v)
Definition cuda_dxt.cu:118

References abs(), max_buffer, max_hz, min_buffer, and min_hz.

Referenced by update().

Here is the call graph for this function:

◆ set_max_hz()

void AudioDriftFixer::set_max_hz ( uint32_t max_hz)
inline

Set the max hz object.

Parameters
max_hzThe maximum hz delta that can be applied to fix the drift

Definition at line 322 of file decklink_drift_fix.hpp.

322 {
323 this->max_hz = max_hz;
324 }

References max_hz.

Referenced by settings_init().

◆ set_min_hz()

void AudioDriftFixer::set_min_hz ( uint32_t min_hz)
inline

Set the min hz object.

Parameters
min_hzThe minimum hz delta that can be applied to fix the drift

Definition at line 331 of file decklink_drift_fix.hpp.

331 {
332 this->min_hz = min_hz;
333 }

References min_hz.

Referenced by settings_init().

◆ set_root()

void AudioDriftFixer::set_root ( module * root)
inline

Set the root object.

Parameters
rootThe root module

Definition at line 349 of file decklink_drift_fix.hpp.

349 {
350 m_root = root;
351 }
struct module * m_root

References m_root.

Referenced by display_decklink_init().

◆ set_target_buffer()

void AudioDriftFixer::set_target_buffer ( uint32_t target_buffer)
inline

Set the target buffer object.

Parameters
target_bufferThe target buffer of samples per channel

Definition at line 340 of file decklink_drift_fix.hpp.

340 {
341 this->target_buffer_fill = target_buffer;
342 }

References target_buffer_fill.

Referenced by settings_init().

◆ update()

void AudioDriftFixer::update ( uint32_t buffered_count,
uint32_t sample_frame_count,
uint32_t sampleFramesWritten )
inline
Return values
flagif the audio frame should be written

Definition at line 389 of file decklink_drift_fix.hpp.

389 {
390 if (!this->m_enabled) {
391 return;
392 }
393
395 audio_summary.calculate_missing(buffered_count, sample_frame_count);
396 if (buffered_count == 0) {
398 }
399
400 // Add the amount currently in the buffer to the moving average, and calculate the delta between that and the previous amount
401 // Store the previous buffer count so we can calculate this next frame.
402 this->average_buffer_samples.add((double)buffered_count);
403 this->average_delta.add((double)abs((int32_t)buffered_count - (int32_t)previous_buffer));
404 this->previous_buffer = buffered_count;
405
406 long long dst_frame_rate = 0;
407 // Calculate the average
408 uint32_t average_buffer_depth = (uint32_t)(this->average_buffer_samples.avg());
409
410 int resample_hz = dst_frame_rate = (bmdAudioSampleRate48kHz) * BASE;
411
412 // Check to see if our buffered samples has enough to calculate a good average
413 if (this->average_buffer_samples.filled()) {
414 // @todo might be worth trying to make this more dynamic so that certain input values
415 // for different cards can be applied
416 // Check to see if we have a target amount of the buffer we'd like to fill
417 if(this->pos_jitter == 0) {
419 }
420 if(this->neg_jitter == 0) {
422 }
423
424 // Check whether there needs to be any resampling
425 if (average_buffer_depth > target_buffer_fill + this->pos_jitter)
426 {
427 // The buffer is too large, so we need to resample down to remove some frames
428 resample_hz = (int)this->scale_buffer_delta(average_buffer_depth - target_buffer_fill - this->pos_jitter);
429 dst_frame_rate = (bmdAudioSampleRate48kHz - resample_hz) * BASE;
431 } else if(average_buffer_depth < target_buffer_fill - this->neg_jitter) {
432 // The buffer is too small, so we need to resample up to generate some additional frames
433 resample_hz = (int)this->scale_buffer_delta(target_buffer_fill - average_buffer_depth - this->neg_jitter);
434 dst_frame_rate = (bmdAudioSampleRate48kHz + resample_hz) * BASE;
436 } else {
437 dst_frame_rate = (bmdAudioSampleRate48kHz) * BASE;
438 }
439 }
440
441 LOG(LOG_LEVEL_DEBUG) << MOD_NAME << " UPDATE playing speed " << average_buffer_depth << " vs " << buffered_count << " " << average_delta.avg() << " average_velocity " << resample_hz << " resample_hz\n";
442
443 if (dst_frame_rate != 0 &&
444 dst_frame_rate != dst_frame_rate_set) {
445 auto *m = new msg_universal((std::string(MSG_UNIVERSAL_TAG_AUDIO_DECODER) + std::to_string(dst_frame_rate << ADEC_CH_RATE_SHIFT | BASE)).c_str());
447 << MOD_NAME "Sending resample request "
448 << dst_frame_rate << "/" << BASE << "\n";
449 assert(m_root != nullptr);
450 auto *response = send_message_sync(m_root, "audio.receiver.decoder", reinterpret_cast<message *>(m), 100, SEND_MESSAGE_FLAG_NO_STORE);
452 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Unable to send resample message: " << response_get_text(response) << " (" << response_get_status(response) << ")\n";
453 } else {
454 dst_frame_rate_set = dst_frame_rate;
455 }
457 }
458
459
460 if (sampleFramesWritten != sample_frame_count) {
462 }
467 }
#define ADEC_CH_RATE_SHIFT
#define MSG_UNIVERSAL_TAG_AUDIO_DECODER
double get_buffer_avg()
Get the average sample count per channel.
static const uint32_t NEG_JITTER_DEFAULT
static const uint32_t POS_JITTER_DEFAULT
static constexpr unsigned long BASE
DecklinkAudioSummary audio_summary
double scale_buffer_delta(int delta)
This function will check the buffer delta and will return a delta in the sample rate that is required...
MovingAverage average_delta
void add(double val)
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
struct response * send_message_sync(struct module *root, const char *const_path, struct message *msg, int timeout_ms, int flags)
Sends message without waiting for response.
int response_get_status(struct response *r)
void free_response(struct response *r)
const char * response_get_text(struct response *r)
#define RESPONSE_SUCCESSFUL(code)
Definition messaging.h:66
#define SEND_MESSAGE_FLAG_NO_STORE
if receiver doesn't exist, doesn't store it and retur 404 instead
Definition messaging.h:172

References abs(), MovingAverage::add(), ADEC_CH_RATE_SHIFT, audio_summary, average_buffer_samples, average_delta, MovingAverage::avg(), BASE, DecklinkAudioSummary::calculate_missing(), dst_frame_rate_set, MovingAverage::filled(), free_response(), get_buffer_avg(), DecklinkAudioSummary::increment_audio_frames_played(), DecklinkAudioSummary::increment_buffer_overflow(), DecklinkAudioSummary::increment_buffer_underflow(), DecklinkAudioSummary::increment_resample_high(), DecklinkAudioSummary::increment_resample_low(), LOG, LOG_LEVEL_DEBUG, LOG_LEVEL_WARNING, m_enabled, m_root, DecklinkAudioSummary::mark_audio_time_end(), MOD_NAME, MSG_UNIVERSAL_TAG_AUDIO_DECODER, neg_jitter, NEG_JITTER_DEFAULT, pos_jitter, POS_JITTER_DEFAULT, previous_buffer, DecklinkAudioSummary::record_audio_time_diff(), DecklinkAudioSummary::report(), response_get_status(), response_get_text(), RESPONSE_SUCCESSFUL, scale_buffer_delta(), SEND_MESSAGE_FLAG_NO_STORE, send_message_sync(), DecklinkAudioSummary::set_buffer_average(), and target_buffer_fill.

Referenced by display_decklink_put_audio_frame().

Here is the call graph for this function:

Member Data Documentation

◆ audio_summary

DecklinkAudioSummary AudioDriftFixer::audio_summary {}
private

Definition at line 496 of file decklink_drift_fix.hpp.

496{};

Referenced by update().

◆ average_buffer_samples

MovingAverage AudioDriftFixer::average_buffer_samples = 250
private

Definition at line 475 of file decklink_drift_fix.hpp.

Referenced by get_buffer_avg(), and update().

◆ average_delta

MovingAverage AudioDriftFixer::average_delta = 25
private

Definition at line 476 of file decklink_drift_fix.hpp.

Referenced by update().

◆ BASE

unsigned long AudioDriftFixer::BASE = (1U<<8U)
staticconstexprprivate

Definition at line 472 of file decklink_drift_fix.hpp.

Referenced by update().

◆ dst_frame_rate_set

long long AudioDriftFixer::dst_frame_rate_set = 0
private

Definition at line 501 of file decklink_drift_fix.hpp.

Referenced by update().

◆ m_enabled

bool AudioDriftFixer::m_enabled = false
private

Definition at line 470 of file decklink_drift_fix.hpp.

Referenced by enable(), and update().

◆ m_root

struct module* AudioDriftFixer::m_root = nullptr
private

Definition at line 473 of file decklink_drift_fix.hpp.

Referenced by set_root(), and update().

◆ max_avg

uint32_t AudioDriftFixer::max_avg = 3650
private

Definition at line 492 of file decklink_drift_fix.hpp.

◆ max_buffer

uint32_t AudioDriftFixer::max_buffer = 600
private

Definition at line 486 of file decklink_drift_fix.hpp.

Referenced by scale_buffer_delta().

◆ max_hz

uint32_t AudioDriftFixer::max_hz = MAX_RESAMPLE_DELTA_DEFAULT
private

Definition at line 483 of file decklink_drift_fix.hpp.

Referenced by scale_buffer_delta(), and set_max_hz().

◆ min_avg

uint32_t AudioDriftFixer::min_avg = 1800
private

Definition at line 493 of file decklink_drift_fix.hpp.

◆ min_buffer

uint32_t AudioDriftFixer::min_buffer = 100
private

Definition at line 485 of file decklink_drift_fix.hpp.

Referenced by scale_buffer_delta().

◆ min_hz

uint32_t AudioDriftFixer::min_hz = MIN_RESAMPLE_DELTA_DEFAULT
private

Definition at line 482 of file decklink_drift_fix.hpp.

Referenced by scale_buffer_delta(), and set_min_hz().

◆ neg_jitter

uint32_t AudioDriftFixer::neg_jitter = 5
private

Definition at line 489 of file decklink_drift_fix.hpp.

Referenced by update().

◆ NEG_JITTER_DEFAULT

const uint32_t AudioDriftFixer::NEG_JITTER_DEFAULT = 600
staticprivate

Definition at line 499 of file decklink_drift_fix.hpp.

Referenced by update().

◆ pos_jitter

uint32_t AudioDriftFixer::pos_jitter = 5
private

Definition at line 488 of file decklink_drift_fix.hpp.

Referenced by update().

◆ POS_JITTER_DEFAULT

const uint32_t AudioDriftFixer::POS_JITTER_DEFAULT = 600
staticprivate

Definition at line 498 of file decklink_drift_fix.hpp.

Referenced by update().

◆ previous_buffer

uint32_t AudioDriftFixer::previous_buffer = 0
private

Definition at line 479 of file decklink_drift_fix.hpp.

Referenced by update().

◆ target_buffer_fill

uint32_t AudioDriftFixer::target_buffer_fill = TARGET_BUFFER_DEFAULT
private

Definition at line 478 of file decklink_drift_fix.hpp.

Referenced by set_target_buffer(), and update().


The documentation for this class was generated from the following file: