DelayEstimator: Updates delay_quality and adds soft reset.

These changes are currently not used in webrtc/ but helps in using the delay estimator.
* The last_delay_quality() is updated with respect to robust_validation and changed to return float.
* Tests are updated wtih respect to above.
* Adds the possibility to make a soft reset based on external circumstances like a known delay shift has been made.
* The soft reset change the lookahead dynamically. An API to ask for current lookahead has been added as well.

BUG=N/A
TESTED=trybots, modules_unittest
R=aluebs@webrtc.org, andrew@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/10409004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5761 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
bjornv@webrtc.org
2014-03-24 15:26:52 +00:00
parent 92c0e29963
commit 28e83d1a56
7 changed files with 207 additions and 75 deletions

View File

@ -304,6 +304,37 @@ void WebRtc_InitBinaryDelayEstimatorFarend(BinaryDelayEstimatorFarend* self) {
memset(self->far_bit_counts, 0, sizeof(int) * self->history_size);
}
void WebRtc_SoftResetBinaryDelayEstimatorFarend(
BinaryDelayEstimatorFarend* self, int delay_shift) {
int abs_shift = abs(delay_shift);
int shift_size = 0;
assert(self != NULL);
shift_size = self->history_size - abs_shift;
if (delay_shift > 0) {
memmove(&self->binary_far_history[abs_shift],
self->binary_far_history,
sizeof(*self->binary_far_history) * shift_size);
memmove(&self->far_bit_counts[abs_shift],
self->far_bit_counts,
sizeof(*self->far_bit_counts) * shift_size);
memset(self->binary_far_history, 0,
sizeof(*self->binary_far_history) * abs_shift);
memset(self->far_bit_counts, 0, sizeof(*self->far_bit_counts) * abs_shift);
} else if (delay_shift < 0) {
memmove(self->binary_far_history,
&self->binary_far_history[abs_shift],
sizeof(*self->binary_far_history) * shift_size);
memmove(self->far_bit_counts,
&self->far_bit_counts[abs_shift],
sizeof(*self->far_bit_counts) * shift_size);
memset(&self->binary_far_history[shift_size], 0,
sizeof(*self->binary_far_history) * abs_shift);
memset(&self->far_bit_counts[shift_size], 0,
sizeof(*self->far_bit_counts) * abs_shift);
}
}
void WebRtc_AddBinaryFarSpectrum(BinaryDelayEstimatorFarend* handle,
uint32_t binary_far_spectrum) {
assert(handle != NULL);
@ -345,10 +376,10 @@ void WebRtc_FreeBinaryDelayEstimator(BinaryDelayEstimator* self) {
}
BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator(
BinaryDelayEstimatorFarend* farend, int lookahead) {
BinaryDelayEstimatorFarend* farend, int max_lookahead, int lookahead) {
BinaryDelayEstimator* self = NULL;
if ((farend != NULL) && (lookahead >= 0)) {
if ((farend != NULL) && (lookahead >= 0) && (max_lookahead >= lookahead)) {
// Sanity conditions fulfilled.
self = malloc(sizeof(BinaryDelayEstimator));
}
@ -357,10 +388,12 @@ BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator(
int malloc_fail = 0;
self->farend = farend;
self->near_history_size = lookahead + 1;
self->near_history_size = max_lookahead + 1;
self->robust_validation_enabled = 0; // Disabled by default.
self->allowed_offset = 0;
self->lookahead = lookahead;
// Allocate memory for spectrum buffers. The extra array element in
// |mean_bit_counts| and |histogram| is a dummy element only used while
// |last_delay| == -2, i.e., before we have a valid estimate.
@ -398,8 +431,8 @@ void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* self) {
self->mean_bit_counts[i] = (20 << 9); // 20 in Q9.
self->histogram[i] = 0.f;
}
self->minimum_probability = (32 << 9); // 32 in Q9.
self->last_delay_probability = (32 << 9); // 32 in Q9.
self->minimum_probability = kMaxBitCountsQ9; // 32 in Q9.
self->last_delay_probability = (int) kMaxBitCountsQ9; // 32 in Q9.
// Default return value if we're unable to estimate. -1 is used for errors.
self->last_delay = -2;
@ -410,13 +443,28 @@ void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* self) {
self->last_delay_histogram = 0.f;
}
int WebRtc_SoftResetBinaryDelayEstimator(BinaryDelayEstimator* self,
int delay_shift) {
int lookahead = 0;
assert(self != NULL);
lookahead = self->lookahead;
self->lookahead -= delay_shift;
if (self->lookahead < 0) {
self->lookahead = 0;
}
if (self->lookahead > self->near_history_size - 1) {
self->lookahead = self->near_history_size - 1;
}
return lookahead - self->lookahead;
}
int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* self,
uint32_t binary_near_spectrum) {
int i = 0;
int candidate_delay = -1;
int valid_candidate = 0;
int32_t value_best_candidate = 32 << 9; // 32 in Q9, (max |mean_bit_counts|).
int32_t value_best_candidate = kMaxBitCountsQ9;
int32_t value_worst_candidate = 0;
int32_t valley_depth = 0;
@ -427,8 +475,7 @@ int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* self,
memmove(&(self->binary_near_history[1]), &(self->binary_near_history[0]),
(self->near_history_size - 1) * sizeof(uint32_t));
self->binary_near_history[0] = binary_near_spectrum;
binary_near_spectrum =
self->binary_near_history[self->near_history_size - 1];
binary_near_spectrum = self->binary_near_history[self->lookahead];
}
// Compare with delayed spectra and store the |bit_counts| for each delay.
@ -544,21 +591,23 @@ int WebRtc_binary_last_delay(BinaryDelayEstimator* self) {
return self->last_delay;
}
int WebRtc_binary_last_delay_quality(BinaryDelayEstimator* self) {
int delay_quality = 0;
float WebRtc_binary_last_delay_quality(BinaryDelayEstimator* self) {
float quality = 0;
assert(self != NULL);
// |last_delay_probability| is the opposite of quality and states how deep the
// minimum of the cost function is. The value states how many non-matching
// bits we have between the binary spectra for the corresponding delay
// estimate. The range is thus from 0 to 32, since we use 32 bits in the
// binary spectra.
// Return the |delay_quality| = 1 - |last_delay_probability| / 32 (in Q14).
delay_quality = (32 << 9) - self->last_delay_probability;
if (delay_quality < 0) {
delay_quality = 0;
if (self->robust_validation_enabled) {
// Simply a linear function of the histogram height at delay estimate.
quality = self->histogram[self->compare_delay] / kHistogramMax;
} else {
// Note that |last_delay_probability| states how deep the minimum of the
// cost function is, so it is rather an error probability.
quality = (float) (kMaxBitCountsQ9 - self->last_delay_probability) /
kMaxBitCountsQ9;
if (quality < 0) {
quality = 0;
}
}
return delay_quality;
return quality;
}
void WebRtc_MeanEstimatorFix(int32_t new_value,