Chromium Code Reviews

Unified Diff: webrtc/modules/audio_coding/neteq/expand.cc

Issue 1908623002: Avoiding overflow in cross correlation in NetEq. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Index: webrtc/modules/audio_coding/neteq/expand.cc
diff --git a/webrtc/modules/audio_coding/neteq/expand.cc b/webrtc/modules/audio_coding/neteq/expand.cc
index ef7af46597e4344156dc48b553d467934622f4b2..965ae89428c12a27204b53d91f06537c3110d062 100644
--- a/webrtc/modules/audio_coding/neteq/expand.cc
+++ b/webrtc/modules/audio_coding/neteq/expand.cc
@@ -26,6 +26,49 @@
namespace webrtc {
+namespace {
+
+// This function decides the overflow-protecting scaling and call
hlundin-webrtc 2016/04/21 08:52:01 call -> calls
hlundin-webrtc 2016/04/22 06:48:56 Still, call -> calls
minyue-webrtc 2016/04/22 07:39:49 Yes, I realized it when I uploaded the patch.
+// WebRtcSpl_CrossCorrelation.s
hlundin-webrtc 2016/04/21 08:52:01 Remove the 's' at the end of the line.
minyue-webrtc 2016/04/21 11:06:50 oh, sorry, typo
+void CrossCorrelation(int32_t* cross_correlation,
+ const int16_t* sequence_1,
+ const int16_t* sequence_2,
+ size_t sequence_1_length,
+ size_t cross_correlation_length,
+ int* right_shifts,
+ int cross_correlation_step) {
hlundin-webrtc 2016/04/21 08:52:01 You are always calling this function with cross_co
minyue-webrtc 2016/04/21 11:06:49 I am about to discuss with you whether we'd put th
hlundin-webrtc 2016/04/22 06:48:56 OK. Keep it like this.
minyue-webrtc 2016/04/22 07:39:49 Do you think it is good that we try to replace Web
hlundin-webrtc 2016/04/22 07:48:20 Replace all in NetEq now. Leave iLBC as it is.
+ // Find the maximum absolute value of sequence_1 and 2.
+ const int16_t max_1 = WebRtcSpl_MaxAbsValueW16(sequence_1, sequence_1_length);
+ const int sequence_2_shift =
+ cross_correlation_step * (cross_correlation_length - 1);
+ const int16_t* sequence_2_start =
+ sequence_2_shift >= 0 ? sequence_2 : sequence_2 + sequence_2_shift;
+ const size_t sequence_2_length = sequence_1_length + abs(sequence_2_shift);
+ const int16_t max_2 =
+ WebRtcSpl_MaxAbsValueW16(sequence_2_start, sequence_2_length);
+
+ // In order to avoid overflow when computing the sum we should scale the
+ // samples so that (in_vector_length * max_1 * max_2) will not overflow.
+ int scaling;
+ const int32_t factor = WEBRTC_SPL_MUL(max_1, max_2) /
hlundin-webrtc 2016/04/21 08:52:01 I think you can omit WEBRTC_SPL_MUL and simply do
minyue-webrtc 2016/04/21 11:06:50 Yes, I should.
+ (WEBRTC_SPL_WORD32_MAX / (int32_t)sequence_1_length);
hlundin-webrtc 2016/04/21 08:52:00 Use c++-style cast.
hlundin-webrtc 2016/04/21 08:52:01 Use std::numeric_limits<int32_t>::max() instead of
minyue-webrtc 2016/04/21 11:06:50 Done.
minyue-webrtc 2016/04/21 11:06:50 Done.
+ scaling = factor == 0 ? 0 : 31 - WebRtcSpl_NormW32(factor);
+
+ assert((double)max_1 * max_2 * sequence_1_length / (1 << scaling) <=
minyue-webrtc 2016/04/20 17:58:59 test code, will remove
hlundin-webrtc 2016/04/21 08:52:00 Acknowledged.
+ WEBRTC_SPL_WORD32_MAX);
+ assert(scaling == 0 ||
+ (double)max_1 * max_2 * sequence_1_length /(1 << scaling) * 2 >
+ WEBRTC_SPL_WORD32_MAX);
+
+ WebRtcSpl_CrossCorrelation(cross_correlation, sequence_1, sequence_2,
+ sequence_1_length, cross_correlation_length,
+ scaling, cross_correlation_step);
+ if (right_shifts)
hlundin-webrtc 2016/04/21 08:52:00 You are not calling this function without a valid
minyue-webrtc 2016/04/21 11:06:50 ok, I was thinking of reducing some uses of the re
hlundin-webrtc 2016/04/22 06:48:56 I see. But then I suggest you let the scaling fact
minyue-webrtc 2016/04/22 07:39:49 Good idea.
+ *right_shifts = scaling;
+}
+
+} // namespace
+
Expand::Expand(BackgroundNoise* background_noise,
SyncBuffer* sync_buffer,
RandomVector* random_vector,
@@ -450,21 +493,13 @@ void Expand::AnalyzeSignal(int16_t* random_vector) {
for (size_t channel_ix = 0; channel_ix < num_channels_; ++channel_ix) {
ChannelParameters& parameters = channel_parameters_[channel_ix];
- // Calculate suitable scaling.
- int16_t signal_max = WebRtcSpl_MaxAbsValueW16(
- &audio_history[signal_length - correlation_length - start_index
- - correlation_lags],
- correlation_length + start_index + correlation_lags - 1);
- correlation_scale = (31 - WebRtcSpl_NormW32(signal_max * signal_max)) +
- (31 - WebRtcSpl_NormW32(static_cast<int32_t>(correlation_length))) - 31;
- correlation_scale = std::max(0, correlation_scale);
// Calculate the correlation, store in |correlation_vector2|.
- WebRtcSpl_CrossCorrelation(
+ CrossCorrelation(
correlation_vector2,
&(audio_history[signal_length - correlation_length]),
&(audio_history[signal_length - correlation_length - start_index]),
- correlation_length, correlation_lags, correlation_scale, -1);
+ correlation_length, correlation_lags, &correlation_scale, -1);
// Find maximizing index.
best_index = WebRtcSpl_MaxIndexW32(correlation_vector2, correlation_lags);
@@ -582,13 +617,6 @@ void Expand::AnalyzeSignal(int16_t* random_vector) {
}
// Calculate the LPC and the gain of the filters.
- // Calculate scale value needed for auto-correlation.
- correlation_scale = WebRtcSpl_MaxAbsValueW16(
- &(audio_history[signal_length - fs_mult_lpc_analysis_len]),
- fs_mult_lpc_analysis_len);
-
- correlation_scale = std::min(16 - WebRtcSpl_NormW32(correlation_scale), 0);
- correlation_scale = std::max(correlation_scale * 2 + 7, 0);
// Calculate kUnvoicedLpcOrder + 1 lags of the auto-correlation function.
size_t temp_index = signal_length - fs_mult_lpc_analysis_len -
@@ -601,11 +629,11 @@ void Expand::AnalyzeSignal(int16_t* random_vector) {
memcpy(&temp_signal[kUnvoicedLpcOrder],
&audio_history[temp_index + kUnvoicedLpcOrder],
sizeof(int16_t) * fs_mult_lpc_analysis_len);
- WebRtcSpl_CrossCorrelation(auto_correlation,
- &temp_signal[kUnvoicedLpcOrder],
- &temp_signal[kUnvoicedLpcOrder],
- fs_mult_lpc_analysis_len, kUnvoicedLpcOrder + 1,
- correlation_scale, -1);
+ CrossCorrelation(auto_correlation,
+ &temp_signal[kUnvoicedLpcOrder],
+ &temp_signal[kUnvoicedLpcOrder],
+ fs_mult_lpc_analysis_len, kUnvoicedLpcOrder + 1,
+ &correlation_scale, -1);
delete [] temp_signal;
// Verify that variance is positive.
@@ -814,13 +842,13 @@ void Expand::Correlation(const int16_t* input,
downsampled_input, norm_shift);
int32_t correlation[kNumCorrelationLags];
- static const int kCorrelationShift = 6;
- WebRtcSpl_CrossCorrelation(
+ int correlation_shift;
+ CrossCorrelation(
correlation,
&downsampled_input[kDownsampledLength - kCorrelationLength],
&downsampled_input[kDownsampledLength - kCorrelationLength
- kCorrelationStartLag],
- kCorrelationLength, kNumCorrelationLags, kCorrelationShift, -1);
+ kCorrelationLength, kNumCorrelationLags, &correlation_shift, -1);
// Normalize and move data from 32-bit to 16-bit vector.
int32_t max_correlation = WebRtcSpl_MaxAbsValueW32(correlation,
@@ -830,7 +858,7 @@ void Expand::Correlation(const int16_t* input,
WebRtcSpl_VectorBitShiftW32ToW16(output, kNumCorrelationLags, correlation,
norm_shift2);
// Total scale factor (right shifts) of correlation value.
- *output_scale = 2 * norm_shift + kCorrelationShift + norm_shift2;
+ *output_scale = 2 * norm_shift + correlation_shift + norm_shift2;
}
void Expand::UpdateLagIndex() {

Powered by Google App Engine