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
This commit is contained in:
parent
1e1a250413
commit
8fe5f32ccc
@ -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;
|
||||
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 < 0)
|
||||
if (order > in_vector_length) {
|
||||
/* Undefined */
|
||||
return -1;
|
||||
} else if (order < 0) {
|
||||
order = in_vector_length;
|
||||
}
|
||||
|
||||
// Find the max. sample
|
||||
// Find the maximum absolute value of the samples.
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
} 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));
|
||||
|
||||
if (t > nbits)
|
||||
{
|
||||
if (t > nbits) {
|
||||
scaling = 0;
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
scaling = nbits - t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resultptr = result;
|
||||
|
||||
// Perform the actual correlation calculation
|
||||
for (i = 0; i < order + 1; i++)
|
||||
{
|
||||
int loops = (in_vector_length - i);
|
||||
// Perform the actual correlation calculation.
|
||||
for (i = 0; i < order + 1; 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);
|
||||
/* 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;
|
||||
}
|
||||
#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 < in_vector_length - i; j++) {
|
||||
sum += (in_vector[j] * in_vector[i + j]) >> scaling;
|
||||
}
|
||||
|
||||
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;
|
||||
*result++ = sum;
|
||||
}
|
||||
|
||||
*scale = scaling;
|
||||
|
||||
return order + 1;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
#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;
|
||||
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;
|
||||
|
||||
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;
|
||||
cross_correlation++;
|
||||
}
|
||||
*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
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
#ifndef _ARM_OPT_
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1++, *vector2++, scaling);
|
||||
/* 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;
|
||||
}
|
||||
#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 < length; i++) {
|
||||
sum += (vector1[i] * vector2[i]) >> scaling;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -419,32 +419,146 @@ void WebRtcSpl_AffineTransformVector(WebRtc_Word16* out_vector,
|
||||
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,9 +592,20 @@ WebRtc_Word32 WebRtcSpl_Energy(WebRtc_Word16* vector,
|
||||
int vector_length,
|
||||
int* scale_factor);
|
||||
|
||||
WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16* vector1,
|
||||
WebRtc_Word16* vector2,
|
||||
int vector_length,
|
||||
// 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.
|
||||
@ -1116,147 +1241,6 @@ void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band,
|
||||
// - out_vector : Vector with the output
|
||||
//
|
||||
|
||||
//
|
||||
// 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(...)
|
||||
//
|
||||
@ -1492,23 +1476,6 @@ void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band,
|
||||
// - 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(...)
|
||||
//
|
||||
|
@ -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 @@ TEST_F(SplTest, VectorOperationsTest) {
|
||||
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 @@ TEST_F(SplTest, VectorOperationsTest) {
|
||||
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, RandTest) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ TEST_F(SplTest, SignalProcessingTest) {
|
||||
WebRtc_Word16 b16[kVectorSize];
|
||||
|
||||
WebRtc_Word16 bTmp16[kVectorSize];
|
||||
WebRtc_Word32 bTmp32[kVectorSize];
|
||||
|
||||
int bScale = 0;
|
||||
|
||||
@ -406,7 +442,6 @@ TEST_F(SplTest, SignalProcessingTest) {
|
||||
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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user