summaryrefslogtreecommitdiff
path: root/common_audio
diff options
context:
space:
mode:
authortina.legrand@webrtc.org <tina.legrand@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2012-11-15 08:34:38 +0000
committertina.legrand@webrtc.org <tina.legrand@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2012-11-15 08:34:38 +0000
commita049d6ebe5dacfef278c0d9086d1522854c56b39 (patch)
treeaaedc0884c64df9c09a0a7d0c238271bd520e9a0 /common_audio
parentd75680a372c87ad97394a15f49340109c6f2d3ed (diff)
downloadwebrtc-a049d6ebe5dacfef278c0d9086d1522854c56b39.tar.gz
Wraparound distortion in Opus
This CL solves the wraparound distortion in Opus. In the Opus decoder-wrapper we are downsampling the signal from 48 kHz to 32 kHz. This is done in two steps, using the following functions from the signal processing library: WebRtcSpl_Resample48khzTo32khz() and WebRtcSpl_VectorBitShiftW32ToW16 The latter does not have a saturation check, and the signal can suffer from wraparound. I've added saturation control to the function. BUG=issue1089 Review URL: https://webrtc-codereview.appspot.com/967004 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@3103 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'common_audio')
-rw-r--r--common_audio/signal_processing/include/signal_processing_library.h12
-rw-r--r--common_audio/signal_processing/signal_processing_unittest.cc44
-rw-r--r--common_audio/signal_processing/vector_scaling_operations.c36
3 files changed, 66 insertions, 26 deletions
diff --git a/common_audio/signal_processing/include/signal_processing_library.h b/common_audio/signal_processing/include/signal_processing_library.h
index 1738e8e9..50a89c37 100644
--- a/common_audio/signal_processing/include/signal_processing_library.h
+++ b/common_audio/signal_processing/include/signal_processing_library.h
@@ -377,11 +377,10 @@ void WebRtcSpl_VectorBitShiftW32(WebRtc_Word32* out_vector,
WebRtc_Word16 vector_length,
G_CONST WebRtc_Word32* in_vector,
WebRtc_Word16 right_shifts);
-void WebRtcSpl_VectorBitShiftW32ToW16(WebRtc_Word16* out_vector,
- WebRtc_Word16 vector_length,
- G_CONST WebRtc_Word32* in_vector,
- WebRtc_Word16 right_shifts);
-
+void WebRtcSpl_VectorBitShiftW32ToW16(int16_t* out_vector,
+ int vector_length,
+ const int32_t* in_vector,
+ int right_shifts);
void WebRtcSpl_ScaleVector(G_CONST WebRtc_Word16* in_vector,
WebRtc_Word16* out_vector,
WebRtc_Word16 gain,
@@ -1180,7 +1179,8 @@ void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band,
// WebRtcSpl_VectorBitShiftW32ToW16(...)
//
// Bit shifts all the values in a WebRtc_Word32 vector up or downwards and
-// stores the result as a WebRtc_Word16 vector
+// stores the result as an int16_t vector. The function will saturate the
+// signal if needed, before storing in the output vector.
//
// Input:
// - vector_length : Length of vector
diff --git a/common_audio/signal_processing/signal_processing_unittest.cc b/common_audio/signal_processing/signal_processing_unittest.cc
index d5026fb8..cf7cb27f 100644
--- a/common_audio/signal_processing/signal_processing_unittest.cc
+++ b/common_audio/signal_processing/signal_processing_unittest.cc
@@ -615,3 +615,47 @@ TEST_F(SplTest, FFTTest) {
//EXPECT_EQ(A[kk], B[kk]);
}
}
+
+TEST_F(SplTest, Resample48WithSaturationTest) {
+ // The test resamples 3*kBlockSize number of samples to 2*kBlockSize number
+ // of samples.
+ const int kBlockSize = 16;
+
+ // Saturated input vector of 48 samples.
+ const int32_t kVectorSaturated[3 * kBlockSize + 7] = {
+ -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768,
+ -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768,
+ -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768,
+ 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767, 32767, 32767, 32767
+ };
+
+ // All values in |out_vector| should be |kRefValue32kHz|.
+ const int32_t kRefValue32kHz1 = -1077493760;
+ const int32_t kRefValue32kHz2 = 1077493645;
+
+ // After bit shift with saturation, |out_vector_w16| is saturated.
+
+ const int16_t kRefValue16kHz1 = -32768;
+ const int16_t kRefValue16kHz2 = 32767;
+ // Vector for storing output.
+ int32_t out_vector[2 * kBlockSize];
+ int16_t out_vector_w16[2 * kBlockSize];
+
+ WebRtcSpl_Resample48khzTo32khz(kVectorSaturated, out_vector, kBlockSize);
+ WebRtcSpl_VectorBitShiftW32ToW16(out_vector_w16, 2 * kBlockSize, out_vector,
+ 15);
+
+ // Comparing output values against references. The values at position
+ // 12-15 are skipped to account for the filter lag.
+ for (int i = 0; i < 12; ++i) {
+ EXPECT_EQ(kRefValue32kHz1, out_vector[i]);
+ EXPECT_EQ(kRefValue16kHz1, out_vector_w16[i]);
+ }
+ for (int i = 16; i < 2 * kBlockSize; ++i) {
+ EXPECT_EQ(kRefValue32kHz2, out_vector[i]);
+ EXPECT_EQ(kRefValue16kHz2, out_vector_w16[i]);
+ }
+}
diff --git a/common_audio/signal_processing/vector_scaling_operations.c b/common_audio/signal_processing/vector_scaling_operations.c
index 242955cc..c4b1df9c 100644
--- a/common_audio/signal_processing/vector_scaling_operations.c
+++ b/common_audio/signal_processing/vector_scaling_operations.c
@@ -66,27 +66,23 @@ void WebRtcSpl_VectorBitShiftW32(WebRtc_Word32 *out_vector,
}
}
-void WebRtcSpl_VectorBitShiftW32ToW16(WebRtc_Word16 *res,
- WebRtc_Word16 length,
- G_CONST WebRtc_Word32 *in,
- WebRtc_Word16 right_shifts)
-{
- int i;
-
- if (right_shifts >= 0)
- {
- for (i = length; i > 0; i--)
- {
- (*res++) = (WebRtc_Word16)((*in++) >> right_shifts);
- }
- } else
- {
- WebRtc_Word16 left_shifts = -right_shifts;
- for (i = length; i > 0; i--)
- {
- (*res++) = (WebRtc_Word16)((*in++) << left_shifts);
- }
+void WebRtcSpl_VectorBitShiftW32ToW16(int16_t* out, int length,
+ const int32_t* in, int right_shifts) {
+ int i;
+ int32_t tmp_w32;
+
+ if (right_shifts >= 0) {
+ for (i = length; i > 0; i--) {
+ tmp_w32 = (*in++) >> right_shifts;
+ (*out++) = WebRtcSpl_SatW32ToW16(tmp_w32);
+ }
+ } else {
+ int16_t left_shifts = -right_shifts;
+ for (i = length; i > 0; i--) {
+ tmp_w32 = (*in++) << left_shifts;
+ (*out++) = WebRtcSpl_SatW32ToW16(tmp_w32);
}
+ }
}
void WebRtcSpl_ScaleVector(G_CONST WebRtc_Word16 *in_vector, WebRtc_Word16 *out_vector,