Refactor three signal processing library files. WebRTC issue 545 is solved by the way.
Review URL: https://webrtc-codereview.appspot.com/692007
git-svn-id: http://webrtc.googlecode.com/svn/trunk@2562 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/common_audio/signal_processing/auto_correlation.c b/src/common_audio/signal_processing/auto_correlation.c
index a00fde4..bd954cf 100644
--- a/src/common_audio/signal_processing/auto_correlation.c
+++ b/src/common_audio/signal_processing/auto_correlation.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@@ -8,134 +8,61 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-
-/*
- * This file contains the function WebRtcSpl_AutoCorrelation().
- * The description header can be found in signal_processing_library.h
- *
- */
-
#include "signal_processing_library.h"
-int WebRtcSpl_AutoCorrelation(G_CONST WebRtc_Word16* in_vector,
+int WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
int in_vector_length,
int order,
- WebRtc_Word32* result,
- int* scale)
-{
- WebRtc_Word32 sum;
- int i, j;
- WebRtc_Word16 smax; // Sample max
- G_CONST WebRtc_Word16* xptr1;
- G_CONST WebRtc_Word16* xptr2;
- WebRtc_Word32* resultptr;
- int scaling = 0;
+ int32_t* result,
+ int* scale) {
+ int32_t sum = 0;
+ int i = 0, j = 0;
+ int16_t smax = 0;
+ int scaling = 0;
-#ifdef _ARM_OPT_
-#pragma message("NOTE: _ARM_OPT_ optimizations are used")
- WebRtc_Word16 loops4;
-#endif
+ if (order > in_vector_length) {
+ /* Undefined */
+ return -1;
+ } else if (order < 0) {
+ order = in_vector_length;
+ }
- if (order < 0)
- order = in_vector_length;
+ // Find the maximum absolute value of the samples.
+ smax = WebRtcSpl_MaxAbsValueW16(in_vector, in_vector_length);
- // Find the max. sample
- smax = WebRtcSpl_MaxAbsValueW16(in_vector, in_vector_length);
+ // In order to avoid overflow when computing the sum we should scale the
+ // samples so that (in_vector_length * smax * smax) will not overflow.
+ if (smax == 0) {
+ scaling = 0;
+ } else {
+ // Number of bits in the sum loop.
+ int nbits = WebRtcSpl_GetSizeInBits(in_vector_length);
+ // Number of bits to normalize smax.
+ int t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax));
- // In order to avoid overflow when computing the sum we should scale the samples so that
- // (in_vector_length * smax * smax) will not overflow.
-
- if (smax == 0)
- {
- scaling = 0;
- } else
- {
- int nbits = WebRtcSpl_GetSizeInBits(in_vector_length); // # of bits in the sum loop
- int t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax)); // # of bits to normalize smax
-
- if (t > nbits)
- {
- scaling = 0;
- } else
- {
- scaling = nbits - t;
- }
-
+ if (t > nbits) {
+ scaling = 0;
+ } else {
+ scaling = nbits - t;
}
+ }
- resultptr = result;
-
- // Perform the actual correlation calculation
- for (i = 0; i < order + 1; i++)
- {
- int loops = (in_vector_length - i);
- sum = 0;
- xptr1 = in_vector;
- xptr2 = &in_vector[i];
-#ifndef _ARM_OPT_
- for (j = loops; j > 0; j--)
- {
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1++, *xptr2++, scaling);
- }
-#else
- loops4 = (loops >> 2) << 2;
-
- if (scaling == 0)
- {
- for (j = 0; j < loops4; j = j + 4)
- {
- sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
- xptr1++;
- xptr2++;
- sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
- xptr1++;
- xptr2++;
- sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
- xptr1++;
- xptr2++;
- sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
- xptr1++;
- xptr2++;
- }
-
- for (j = loops4; j < loops; j++)
- {
- sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
- xptr1++;
- xptr2++;
- }
- }
- else
- {
- for (j = 0; j < loops4; j = j + 4)
- {
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
- xptr1++;
- xptr2++;
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
- xptr1++;
- xptr2++;
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
- xptr1++;
- xptr2++;
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
- xptr1++;
- xptr2++;
- }
-
- for (j = loops4; j < loops; j++)
- {
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
- xptr1++;
- xptr2++;
- }
- }
-
-#endif
- *resultptr++ = sum;
+ // Perform the actual correlation calculation.
+ for (i = 0; i < order + 1; i++) {
+ sum = 0;
+ /* Unroll the loop to improve performance. */
+ for (j = 0; j < in_vector_length - i - 3; j += 4) {
+ sum += (in_vector[j + 0] * in_vector[i + j + 0]) >> scaling;
+ sum += (in_vector[j + 1] * in_vector[i + j + 1]) >> scaling;
+ sum += (in_vector[j + 2] * in_vector[i + j + 2]) >> scaling;
+ sum += (in_vector[j + 3] * in_vector[i + j + 3]) >> scaling;
}
+ for (; j < in_vector_length - i; j++) {
+ sum += (in_vector[j] * in_vector[i + j]) >> scaling;
+ }
+ *result++ = sum;
+ }
- *scale = scaling;
-
- return order + 1;
+ *scale = scaling;
+ return order + 1;
}
diff --git a/src/common_audio/signal_processing/cross_correlation.c b/src/common_audio/signal_processing/cross_correlation.c
index 39eeb3c..cf7705c 100644
--- a/src/common_audio/signal_processing/cross_correlation.c
+++ b/src/common_audio/signal_processing/cross_correlation.c
@@ -8,258 +8,23 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-
-/*
- * This file contains the function WebRtcSpl_CrossCorrelation().
- * The description header can be found in signal_processing_library.h
- *
- */
-
-/* TODO(kma): Clean up the code in this file, and break it up for
- * various platforms (Xscale, ARM/Neon etc.).
- */
-
#include "signal_processing_library.h"
-void WebRtcSpl_CrossCorrelation(WebRtc_Word32* cross_correlation, WebRtc_Word16* seq1,
- WebRtc_Word16* seq2, WebRtc_Word16 dim_seq,
- WebRtc_Word16 dim_cross_correlation,
- WebRtc_Word16 right_shifts,
- WebRtc_Word16 step_seq2)
-{
- int i, j;
- WebRtc_Word16* seq1Ptr;
- WebRtc_Word16* seq2Ptr;
- WebRtc_Word32* CrossCorrPtr;
+void WebRtcSpl_CrossCorrelation(int32_t* cross_correlation,
+ const int16_t* seq1,
+ const int16_t* seq2,
+ int16_t dim_seq,
+ int16_t dim_cross_correlation,
+ int16_t right_shifts,
+ int16_t step_seq2) {
+ int i = 0, j = 0;
-#ifdef _XSCALE_OPT_
-
-#ifdef _WIN32
-#pragma message("NOTE: _XSCALE_OPT_ optimizations are used (overrides _ARM_OPT_ and requires /QRxscale compiler flag)")
-#endif
-
- __int64 macc40;
-
- int iseq1[250];
- int iseq2[250];
- int iseq3[250];
- int * iseq1Ptr;
- int * iseq2Ptr;
- int * iseq3Ptr;
- int len, i_len;
-
- seq1Ptr = seq1;
- iseq1Ptr = iseq1;
- for(i = 0; i < ((dim_seq + 1) >> 1); i++)
- {
- *iseq1Ptr = (unsigned short)*seq1Ptr++;
- *iseq1Ptr++ |= (WebRtc_Word32)*seq1Ptr++ << 16;
-
+ for (i = 0; i < dim_cross_correlation; i++) {
+ *cross_correlation = 0;
+ /* Unrolling doesn't seem to improve performance. */
+ for (j = 0; j < dim_seq; j++) {
+ *cross_correlation += (seq1[j] * seq2[step_seq2 * i + j]) >> right_shifts;
}
-
- if(dim_seq%2)
- {
- *(iseq1Ptr-1) &= 0x0000ffff;
- }
- *iseq1Ptr = 0;
- iseq1Ptr++;
- *iseq1Ptr = 0;
- iseq1Ptr++;
- *iseq1Ptr = 0;
-
- if(step_seq2 < 0)
- {
- seq2Ptr = seq2 - dim_cross_correlation + 1;
- CrossCorrPtr = &cross_correlation[dim_cross_correlation - 1];
- }
- else
- {
- seq2Ptr = seq2;
- CrossCorrPtr = cross_correlation;
- }
-
- len = dim_seq + dim_cross_correlation - 1;
- i_len = (len + 1) >> 1;
- iseq2Ptr = iseq2;
-
- iseq3Ptr = iseq3;
- for(i = 0; i < i_len; i++)
- {
- *iseq2Ptr = (unsigned short)*seq2Ptr++;
- *iseq3Ptr = (unsigned short)*seq2Ptr;
- *iseq2Ptr++ |= (WebRtc_Word32)*seq2Ptr++ << 16;
- *iseq3Ptr++ |= (WebRtc_Word32)*seq2Ptr << 16;
- }
-
- if(len % 2)
- {
- iseq2[i_len - 1] &= 0x0000ffff;
- iseq3[i_len - 1] = 0;
- }
- else
- iseq3[i_len - 1] &= 0x0000ffff;
-
- iseq2[i_len] = 0;
- iseq3[i_len] = 0;
- iseq2[i_len + 1] = 0;
- iseq3[i_len + 1] = 0;
- iseq2[i_len + 2] = 0;
- iseq3[i_len + 2] = 0;
-
- // Set pointer to start value
- iseq2Ptr = iseq2;
- iseq3Ptr = iseq3;
-
- i_len = (dim_seq + 7) >> 3;
- for (i = 0; i < dim_cross_correlation; i++)
- {
-
- iseq1Ptr = iseq1;
-
- macc40 = 0;
-
- _WriteCoProcessor(macc40, 0);
-
- if((i & 1))
- {
- iseq3Ptr = iseq3 + (i >> 1);
- for (j = i_len; j > 0; j--)
- {
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
- }
- }
- else
- {
- iseq2Ptr = iseq2 + (i >> 1);
- for (j = i_len; j > 0; j--)
- {
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
- _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
- }
-
- }
-
- macc40 = _ReadCoProcessor(0);
- *CrossCorrPtr = (WebRtc_Word32)(macc40 >> right_shifts);
- CrossCorrPtr += step_seq2;
- }
-#else // #ifdef _XSCALE_OPT_
-#ifdef _ARM_OPT_
- WebRtc_Word16 dim_seq8 = (dim_seq >> 3) << 3;
-#endif
-
- CrossCorrPtr = cross_correlation;
-
- for (i = 0; i < dim_cross_correlation; i++)
- {
- // Set the pointer to the static vector, set the pointer to the sliding vector
- // and initialize cross_correlation
- seq1Ptr = seq1;
- seq2Ptr = seq2 + (step_seq2 * i);
- (*CrossCorrPtr) = 0;
-
-#ifndef _ARM_OPT_
- // Perform the cross correlation
- for (j = 0; j < dim_seq; j++)
- {
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- }
-#else
- if (right_shifts == 0)
- {
- // Perform the optimized cross correlation
- for (j = 0; j < dim_seq8; j = j + 8)
- {
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- }
-
- for (j = dim_seq8; j < dim_seq; j++)
- {
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
- seq1Ptr++;
- seq2Ptr++;
- }
- }
- else // right_shifts != 0
-
- {
- // Perform the optimized cross correlation
- for (j = 0; j < dim_seq8; j = j + 8)
- {
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- }
-
- for (j = dim_seq8; j < dim_seq; j++)
- {
- (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
- right_shifts);
- seq1Ptr++;
- seq2Ptr++;
- }
- }
-#endif
- CrossCorrPtr++;
- }
-#endif
+ cross_correlation++;
+ }
}
diff --git a/src/common_audio/signal_processing/dot_product_with_scale.c b/src/common_audio/signal_processing/dot_product_with_scale.c
index 6e085fd..4868260 100644
--- a/src/common_audio/signal_processing/dot_product_with_scale.c
+++ b/src/common_audio/signal_processing/dot_product_with_scale.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@@ -8,84 +8,25 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-
-/*
- * This file contains the function WebRtcSpl_DotProductWithScale().
- * The description header can be found in signal_processing_library.h
- *
- */
-
#include "signal_processing_library.h"
-WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16 *vector1, WebRtc_Word16 *vector2,
- int length, int scaling)
-{
- WebRtc_Word32 sum;
- int i;
-#ifdef _ARM_OPT_
-#pragma message("NOTE: _ARM_OPT_ optimizations are used")
- WebRtc_Word16 len4 = (length >> 2) << 2;
-#endif
+int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
+ const int16_t* vector2,
+ int length,
+ int scaling) {
+ int32_t sum = 0;
+ int i = 0;
- sum = 0;
+ /* Unroll the loop to improve performance. */
+ for (i = 0; i < length - 3; i += 4) {
+ sum += (vector1[i + 0] * vector2[i + 0]) >> scaling;
+ sum += (vector1[i + 1] * vector2[i + 1]) >> scaling;
+ sum += (vector1[i + 2] * vector2[i + 2]) >> scaling;
+ sum += (vector1[i + 3] * vector2[i + 3]) >> scaling;
+ }
+ for (; i < length; i++) {
+ sum += (vector1[i] * vector2[i]) >> scaling;
+ }
-#ifndef _ARM_OPT_
- for (i = 0; i < length; i++)
- {
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1++, *vector2++, scaling);
- }
-#else
- if (scaling == 0)
- {
- for (i = 0; i < len4; i = i + 4)
- {
- sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
- vector1++;
- vector2++;
- sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
- vector1++;
- vector2++;
- sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
- vector1++;
- vector2++;
- sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
- vector1++;
- vector2++;
- }
-
- for (i = len4; i < length; i++)
- {
- sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
- vector1++;
- vector2++;
- }
- }
- else
- {
- for (i = 0; i < len4; i = i + 4)
- {
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
- vector1++;
- vector2++;
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
- vector1++;
- vector2++;
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
- vector1++;
- vector2++;
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
- vector1++;
- vector2++;
- }
-
- for (i = len4; i < length; i++)
- {
- sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
- vector1++;
- vector2++;
- }
- }
-#endif
-
- return sum;
+ return sum;
}
diff --git a/src/common_audio/signal_processing/include/signal_processing_library.h b/src/common_audio/signal_processing/include/signal_processing_library.h
index 4bcf68a..38b89cb 100644
--- a/src/common_audio/signal_processing/include/signal_processing_library.h
+++ b/src/common_audio/signal_processing/include/signal_processing_library.h
@@ -419,32 +419,146 @@
int vector_length);
// End: iLBC specific functions.
-// Signal processing operations. Descriptions at bottom of this file.
-int WebRtcSpl_AutoCorrelation(G_CONST WebRtc_Word16* vector,
- int vector_length, int order,
- WebRtc_Word32* result_vector,
+// Signal processing operations.
+
+// A 32-bit fix-point implementation of auto-correlation computation
+//
+// Input:
+// - in_vector : Vector to calculate autocorrelation upon
+// - in_vector_length : Length (in samples) of |vector|
+// - order : The order up to which the autocorrelation should be
+// calculated
+//
+// Output:
+// - result : auto-correlation values (values should be seen
+// relative to each other since the absolute values
+// might have been down shifted to avoid overflow)
+//
+// - scale : The number of left shifts required to obtain the
+// auto-correlation in Q0
+//
+// Return value :
+// - -1, if |order| > |in_vector_length|;
+// - Number of samples in |result|, i.e. (order+1), otherwise.
+int WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
+ int in_vector_length,
+ int order,
+ int32_t* result,
int* scale);
+
+// A 32-bit fix-point implementation of the Levinson-Durbin algorithm that
+// does NOT use the 64 bit class
+//
+// Input:
+// - auto_corr : Vector with autocorrelation values of length >=
+// |use_order|+1
+// - use_order : The LPC filter order (support up to order 20)
+//
+// Output:
+// - lpc_coef : lpc_coef[0..use_order] LPC coefficients in Q12
+// - refl_coef : refl_coef[0...use_order-1]| Reflection coefficients in
+// Q15
+//
+// Return value : 1 for stable 0 for unstable
WebRtc_Word16 WebRtcSpl_LevinsonDurbin(WebRtc_Word32* auto_corr,
WebRtc_Word16* lpc_coef,
WebRtc_Word16* refl_coef,
WebRtc_Word16 order);
+
+// Converts reflection coefficients |refl_coef| to LPC coefficients |lpc_coef|.
+// This version is a 16 bit operation.
+//
+// NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a
+// "slightly unstable" filter (i.e., a pole just outside the unit circle) in
+// "rare" cases even if the reflection coefficients are stable.
+//
+// Input:
+// - refl_coef : Reflection coefficients in Q15 that should be converted
+// to LPC coefficients
+// - use_order : Number of coefficients in |refl_coef|
+//
+// Output:
+// - lpc_coef : LPC coefficients in Q12
void WebRtcSpl_ReflCoefToLpc(G_CONST WebRtc_Word16* refl_coef,
int use_order,
WebRtc_Word16* lpc_coef);
+
+// Converts LPC coefficients |lpc_coef| to reflection coefficients |refl_coef|.
+// This version is a 16 bit operation.
+// The conversion is implemented by the step-down algorithm.
+//
+// Input:
+// - lpc_coef : LPC coefficients in Q12, that should be converted to
+// reflection coefficients
+// - use_order : Number of coefficients in |lpc_coef|
+//
+// Output:
+// - refl_coef : Reflection coefficients in Q15.
void WebRtcSpl_LpcToReflCoef(WebRtc_Word16* lpc_coef,
int use_order,
WebRtc_Word16* refl_coef);
+
+// Calculates reflection coefficients (16 bit) from auto-correlation values
+//
+// Input:
+// - auto_corr : Auto-correlation values
+// - use_order : Number of coefficients wanted be calculated
+//
+// Output:
+// - refl_coef : Reflection coefficients in Q15.
void WebRtcSpl_AutoCorrToReflCoef(G_CONST WebRtc_Word32* auto_corr,
int use_order,
WebRtc_Word16* refl_coef);
-void WebRtcSpl_CrossCorrelation(WebRtc_Word32* cross_corr,
- WebRtc_Word16* vector1,
- WebRtc_Word16* vector2,
- WebRtc_Word16 dim_vector,
- WebRtc_Word16 dim_cross_corr,
- WebRtc_Word16 right_shifts,
- WebRtc_Word16 step_vector2);
+
+// Calculates the cross-correlation between two sequences |seq1| and |seq2|.
+// |seq1| is fixed and |seq2| slides as the pointer is increased with the
+// amount |step_seq2|. Note the arguments should obey the relationship:
+// |dim_seq| - 1 + |step_seq2| * (|dim_cross_correlation| - 1) <
+// buffer size of |seq2|
+//
+// Input:
+// - seq1 : First sequence (fixed throughout the correlation)
+// - seq2 : Second sequence (slides |step_vector2| for each
+// new correlation)
+// - dim_seq : Number of samples to use in the cross-correlation
+// - dim_cross_correlation : Number of cross-correlations to calculate (the
+// start position for |vector2| is updated for each
+// new one)
+// - right_shifts : Number of right bit shifts to use. This will
+// become the output Q-domain.
+// - step_seq2 : How many (positive or negative) steps the
+// |vector2| pointer should be updated for each new
+// cross-correlation value.
+//
+// Output:
+// - cross_correlation : The cross-correlation in Q(-right_shifts)
+void WebRtcSpl_CrossCorrelation(int32_t* cross_correlation,
+ const int16_t* seq1,
+ const int16_t* seq2,
+ int16_t dim_seq,
+ int16_t dim_cross_correlation,
+ int16_t right_shifts,
+ int16_t step_seq2);
+
+// Creates (the first half of) a Hanning window. Size must be at least 1 and
+// at most 512.
+//
+// Input:
+// - size : Length of the requested Hanning window (1 to 512)
+//
+// Output:
+// - window : Hanning vector in Q14.
void WebRtcSpl_GetHanningWindow(WebRtc_Word16* window, WebRtc_Word16 size);
+
+// Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector
+// |in_vector|. Input and output values are in Q15.
+//
+// Inputs:
+// - in_vector : Values to calculate sqrt(1 - x^2) of
+// - vector_length : Length of vector |in_vector|
+//
+// Output:
+// - out_vector : Output values in Q15
void WebRtcSpl_SqrtOfOneMinusXSquared(WebRtc_Word16* in_vector,
int vector_length,
WebRtc_Word16* out_vector);
@@ -478,10 +592,21 @@
int vector_length,
int* scale_factor);
-WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16* vector1,
- WebRtc_Word16* vector2,
- int vector_length,
- int scaling);
+// Calculates the dot product between two (WebRtc_Word16) vectors.
+//
+// Input:
+// - vector1 : Vector 1
+// - vector2 : Vector 2
+// - vector_length : Number of samples used in the dot product
+// - scaling : The number of right bit shifts to apply on each term
+// during calculation to avoid overflow, i.e., the
+// output will be in Q(-|scaling|)
+//
+// Return value : The dot product in Q(-scaling)
+int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
+ const int16_t* vector2,
+ int length,
+ int scaling);
// Filter operations.
int WebRtcSpl_FilterAR(G_CONST WebRtc_Word16* ar_coef, int ar_coef_length,
@@ -1117,147 +1242,6 @@
//
//
-// WebRtcSpl_AutoCorrelation(...)
-//
-// A 32-bit fix-point implementation of auto-correlation computation
-//
-// Input:
-// - vector : Vector to calculate autocorrelation upon
-// - vector_length : Length (in samples) of |vector|
-// - order : The order up to which the autocorrelation should be
-// calculated
-//
-// Output:
-// - result_vector : auto-correlation values (values should be seen
-// relative to each other since the absolute values
-// might have been down shifted to avoid overflow)
-//
-// - scale : The number of left shifts required to obtain the
-// auto-correlation in Q0
-//
-// Return value : Number of samples in |result_vector|, i.e., (order+1)
-//
-
-//
-// WebRtcSpl_LevinsonDurbin(...)
-//
-// A 32-bit fix-point implementation of the Levinson-Durbin algorithm that
-// does NOT use the 64 bit class
-//
-// Input:
-// - auto_corr : Vector with autocorrelation values of length >=
-// |use_order|+1
-// - use_order : The LPC filter order (support up to order 20)
-//
-// Output:
-// - lpc_coef : lpc_coef[0..use_order] LPC coefficients in Q12
-// - refl_coef : refl_coef[0...use_order-1]| Reflection coefficients in
-// Q15
-//
-// Return value : 1 for stable 0 for unstable
-//
-
-//
-// WebRtcSpl_ReflCoefToLpc(...)
-//
-// Converts reflection coefficients |refl_coef| to LPC coefficients |lpc_coef|.
-// This version is a 16 bit operation.
-//
-// NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a
-// "slightly unstable" filter (i.e., a pole just outside the unit circle) in
-// "rare" cases even if the reflection coefficients are stable.
-//
-// Input:
-// - refl_coef : Reflection coefficients in Q15 that should be converted
-// to LPC coefficients
-// - use_order : Number of coefficients in |refl_coef|
-//
-// Output:
-// - lpc_coef : LPC coefficients in Q12
-//
-
-//
-// WebRtcSpl_LpcToReflCoef(...)
-//
-// Converts LPC coefficients |lpc_coef| to reflection coefficients |refl_coef|.
-// This version is a 16 bit operation.
-// The conversion is implemented by the step-down algorithm.
-//
-// Input:
-// - lpc_coef : LPC coefficients in Q12, that should be converted to
-// reflection coefficients
-// - use_order : Number of coefficients in |lpc_coef|
-//
-// Output:
-// - refl_coef : Reflection coefficients in Q15.
-//
-
-//
-// WebRtcSpl_AutoCorrToReflCoef(...)
-//
-// Calculates reflection coefficients (16 bit) from auto-correlation values
-//
-// Input:
-// - auto_corr : Auto-correlation values
-// - use_order : Number of coefficients wanted be calculated
-//
-// Output:
-// - refl_coef : Reflection coefficients in Q15.
-//
-
-//
-// WebRtcSpl_CrossCorrelation(...)
-//
-// Calculates the cross-correlation between two sequences |vector1| and
-// |vector2|. |vector1| is fixed and |vector2| slides as the pointer is
-// increased with the amount |step_vector2|
-//
-// Input:
-// - vector1 : First sequence (fixed throughout the correlation)
-// - vector2 : Second sequence (slides |step_vector2| for each
-// new correlation)
-// - dim_vector : Number of samples to use in the cross-correlation
-// - dim_cross_corr : Number of cross-correlations to calculate (the
-// start position for |vector2| is updated for each
-// new one)
-// - right_shifts : Number of right bit shifts to use. This will
-// become the output Q-domain.
-// - step_vector2 : How many (positive or negative) steps the
-// |vector2| pointer should be updated for each new
-// cross-correlation value.
-//
-// Output:
-// - cross_corr : The cross-correlation in Q(-right_shifts)
-//
-
-//
-// WebRtcSpl_GetHanningWindow(...)
-//
-// Creates (the first half of) a Hanning window. Size must be at least 1 and
-// at most 512.
-//
-// Input:
-// - size : Length of the requested Hanning window (1 to 512)
-//
-// Output:
-// - window : Hanning vector in Q14.
-//
-
-//
-// WebRtcSpl_SqrtOfOneMinusXSquared(...)
-//
-// Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector
-// |in_vector|. Input and output values are in Q15.
-//
-// Inputs:
-// - in_vector : Values to calculate sqrt(1 - x^2) of
-// - vector_length : Length of vector |in_vector|
-//
-// Output:
-// - out_vector : Output values in Q15
-//
-
-//
// WebRtcSpl_IncreaseSeed(...)
//
// Increases the seed (and returns the new value)
@@ -1492,23 +1476,6 @@
// - out_vector : Filtered samples
//
-
-//
-// WebRtcSpl_DotProductWithScale(...)
-//
-// Calculates the dot product between two (WebRtc_Word16) vectors
-//
-// Input:
-// - vector1 : Vector 1
-// - vector2 : Vector 2
-// - vector_length : Number of samples used in the dot product
-// - scaling : The number of right bit shifts to apply on each term
-// during calculation to avoid overflow, i.e., the
-// output will be in Q(-|scaling|)
-//
-// Return value : The dot product in Q(-scaling)
-//
-
//
// WebRtcSpl_ComplexIFFT(...)
//
diff --git a/src/common_audio/signal_processing/signal_processing_unittest.cc b/src/common_audio/signal_processing/signal_processing_unittest.cc
index f6d1123..1a37161 100644
--- a/src/common_audio/signal_processing/signal_processing_unittest.cc
+++ b/src/common_audio/signal_processing/signal_processing_unittest.cc
@@ -11,6 +11,10 @@
#include "signal_processing_library.h"
#include "gtest/gtest.h"
+static const int kVector16Size = 9;
+static const int16_t vector16[kVector16Size] = {1, -15511, 4323, 1963,
+ WEBRTC_SPL_WORD16_MAX, 0, WEBRTC_SPL_WORD16_MIN + 5, -3333, 345};
+
class SplTest : public testing::Test {
protected:
virtual ~SplTest() {
@@ -253,7 +257,6 @@
int B[] = {4, 12, 133, 1100};
WebRtc_Word16 a16[kVectorSize];
WebRtc_Word16 b16[kVectorSize];
- WebRtc_Word32 b32[kVectorSize];
WebRtc_Word16 bTmp16[kVectorSize];
for (int kk = 0; kk < kVectorSize; ++kk) {
@@ -275,13 +278,6 @@
EXPECT_EQ(((B[kk]*3+B[kk]*2+2)>>2)+((b16[kk]*3+7)>>2), bTmp16[kk]);
}
- WebRtcSpl_CrossCorrelation(b32, b16, bTmp16, kVectorSize, 2, 2, 0);
- for (int kk = 0; kk < 2; ++kk) {
- EXPECT_EQ(614236, b32[kk]);
- }
-// EXPECT_EQ(, WebRtcSpl_DotProduct(b16, bTmp16, 4));
- EXPECT_EQ(306962, WebRtcSpl_DotProductWithScale(b16, b16, kVectorSize, 2));
-
WebRtcSpl_ScaleVector(b16, bTmp16, 13, kVectorSize, 2);
for (int kk = 0; kk < kVectorSize; ++kk) {
EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]);
@@ -391,6 +387,47 @@
}
}
+TEST_F(SplTest, DotProductWithScaleTest) {
+ EXPECT_EQ(605362796, WebRtcSpl_DotProductWithScale(vector16,
+ vector16, kVector16Size, 2));
+}
+
+TEST_F(SplTest, CrossCorrelationTest) {
+ // Note the function arguments relation specificed by API.
+ const int kCrossCorrelationDimension = 3;
+ const int kShift = 2;
+ const int kStep = 1;
+ const int kSeqDimension = 6;
+
+ const int16_t vector16_b[kVector16Size] = {1, 4323, 1963,
+ WEBRTC_SPL_WORD16_MAX, WEBRTC_SPL_WORD16_MIN + 5, -3333, -876, 8483, 142};
+ const int32_t expected[3] = {-266947903, -15579555, -171282001};
+ int32_t vector32[kCrossCorrelationDimension] = {0};
+
+ WebRtcSpl_CrossCorrelation(vector32, vector16, vector16_b, kSeqDimension,
+ kCrossCorrelationDimension, kShift, kStep);
+
+ for (int i = 0; i < kCrossCorrelationDimension; ++i) {
+ EXPECT_EQ(expected[i], vector32[i]);
+ }
+}
+
+TEST_F(SplTest, AutoCorrelationTest) {
+ int scale = 0;
+ int32_t vector32[kVector16Size];
+ const int32_t expected[kVector16Size] = {302681398, 14223410, -121705063,
+ -85221647, -17104971, 61806945, 6644603, -669329, 43};
+
+ EXPECT_EQ(-1, WebRtcSpl_AutoCorrelation(vector16,
+ kVector16Size, kVector16Size + 1, vector32, &scale));
+ EXPECT_EQ(kVector16Size, WebRtcSpl_AutoCorrelation(vector16,
+ kVector16Size, kVector16Size - 1, vector32, &scale));
+ EXPECT_EQ(3, scale);
+ for (int i = 0; i < kVector16Size; ++i) {
+ EXPECT_EQ(expected[i], vector32[i]);
+ }
+}
+
TEST_F(SplTest, SignalProcessingTest) {
const int kVectorSize = 4;
int A[] = {1, 2, 33, 100};
@@ -398,7 +435,6 @@
WebRtc_Word16 b16[kVectorSize];
WebRtc_Word16 bTmp16[kVectorSize];
- WebRtc_Word32 bTmp32[kVectorSize];
int bScale = 0;
@@ -406,7 +442,6 @@
b16[kk] = A[kk];
}
- EXPECT_EQ(2, WebRtcSpl_AutoCorrelation(b16, kVectorSize, 1, bTmp32, &bScale));
// TODO(bjornv): Activate the Reflection Coefficient tests when refactoring.
// WebRtcSpl_ReflCoefToLpc(b16, kVectorSize, bTmp16);
//// for (int kk = 0; kk < kVectorSize; ++kk) {