return;
}
+ assert(duration<double>(ts.time_since_epoch()).count() >= 0.0);
+
bool good_sample = (rate_adjustment_policy == ADJUST_RATE);
if (good_sample && a1.good_sample) {
a0 = a1;
return true;
}
+ // This can happen when we get dropped frames on the master card.
+ if (duration<double>(ts.time_since_epoch()).count() <= 0.0) {
+ rate_adjustment_policy = DO_NOT_ADJUST_RATE;
+ }
+
if (rate_adjustment_policy == ADJUST_RATE && (a0.good_sample || a1.good_sample)) {
// Estimate the current number of input samples produced at
// this instant in time, by extrapolating from the last known
// good point. Note that we could be extrapolating backward or
// forward, depending on the timing of the calls.
const InputPoint &base_point = a1.good_sample ? a1 : a0;
+ assert(duration<double>(base_point.ts.time_since_epoch()).count() >= 0.0);
+
+ // NOTE: Due to extrapolation, input_samples_received can
+ // actually go negative here the few first calls (ie., we asked
+ // about a timestamp where we hadn't actually started producing
+ // samples yet), but that is harmless.
const double input_samples_received = base_point.input_samples_received +
current_estimated_freq_in * duration<double>(ts - base_point.ts).count();
double actual_delay = input_samples_received - input_samples_consumed;
actual_delay += vresampler.inpdist(); // Delay in the resampler itself.
double err = actual_delay - expected_delay;
- if (first_output && err < 0.0) {
+ if (first_output) {
// Before the very first block, insert artificial delay based on our initial estimate,
// so that we don't need a long period to stabilize at the beginning.
- int delay_samples_to_add = lrintf(-err);
- for (ssize_t i = 0; i < delay_samples_to_add * num_channels; ++i) {
- buffer.push_front(0.0f);
+ if (err < 0.0) {
+ int delay_samples_to_add = lrintf(-err);
+ for (ssize_t i = 0; i < delay_samples_to_add * num_channels; ++i) {
+ buffer.push_front(0.0f);
+ }
+ total_consumed_samples -= delay_samples_to_add; // Equivalent to increasing input_samples_received on a0 and a1.
+ err += delay_samples_to_add;
+ } else if (err > 0.0) {
+ int delay_samples_to_remove = min<int>(lrintf(err), buffer.size() / num_channels);
+ buffer.erase(buffer.begin(), buffer.begin() + delay_samples_to_remove * num_channels);
+ total_consumed_samples += delay_samples_to_remove;
+ err -= delay_samples_to_remove;
}
- total_consumed_samples -= delay_samples_to_add; // Equivalent to increasing input_samples_received on a0 and a1.
- err += delay_samples_to_add;
}
first_output = false;
if (rcorr < 0.95) rcorr = 0.95;
assert(!isnan(rcorr));
vresampler.set_rratio(rcorr);
- } else {
- assert(rate_adjustment_policy == DO_NOT_ADJUST_RATE);
}
// Finally actually resample, producing exactly <num_samples> output samples.
fprintf(stderr, "Card %u: PANIC: Out of input samples to resample, still need %d output samples! (correction factor is %f)\n",
card_num, int(vresampler.out_count), rcorr);
memset(vresampler.out_data, 0, vresampler.out_count * num_channels * sizeof(float));
+
+ // Reset the loop filter.
+ z1 = z2 = z3 = 0.0;
+
return false;
}