232 lines
6.1 KiB
C
232 lines
6.1 KiB
C
/*
|
|
* Copyright (c) 2011 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
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
|
|
/*
|
|
* This file includes the implementation of the VAD internal calls for Downsampling and
|
|
* FindMinimum.
|
|
* For function call descriptions; See vad_sp.h.
|
|
*/
|
|
|
|
#include "vad_sp.h"
|
|
#include "vad_defines.h"
|
|
#include "vad_const.h"
|
|
#include "signal_processing_library.h"
|
|
|
|
// Downsampling filter based on the splitting filter and the allpass functions
|
|
// in vad_filterbank.c
|
|
void WebRtcVad_Downsampling(WebRtc_Word16* signal_in,
|
|
WebRtc_Word16* signal_out,
|
|
WebRtc_Word32* filter_state,
|
|
int inlen)
|
|
{
|
|
WebRtc_Word16 tmp16_1, tmp16_2;
|
|
WebRtc_Word32 tmp32_1, tmp32_2;
|
|
int n, halflen;
|
|
|
|
// Downsampling by 2 and get two branches
|
|
halflen = WEBRTC_SPL_RSHIFT_W16(inlen, 1);
|
|
|
|
tmp32_1 = filter_state[0];
|
|
tmp32_2 = filter_state[1];
|
|
|
|
// Filter coefficients in Q13, filter state in Q0
|
|
for (n = 0; n < halflen; n++)
|
|
{
|
|
// All-pass filtering upper branch
|
|
tmp16_1 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32_1, 1)
|
|
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[0]),
|
|
*signal_in, 14);
|
|
*signal_out = tmp16_1;
|
|
tmp32_1 = (WebRtc_Word32)(*signal_in++)
|
|
- (WebRtc_Word32)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[0]), tmp16_1, 12);
|
|
|
|
// All-pass filtering lower branch
|
|
tmp16_2 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32_2, 1)
|
|
+ (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[1]),
|
|
*signal_in, 14);
|
|
*signal_out++ += tmp16_2;
|
|
tmp32_2 = (WebRtc_Word32)(*signal_in++)
|
|
- (WebRtc_Word32)WEBRTC_SPL_MUL_16_16_RSFT((kAllPassCoefsQ13[1]), tmp16_2, 12);
|
|
}
|
|
filter_state[0] = tmp32_1;
|
|
filter_state[1] = tmp32_2;
|
|
}
|
|
|
|
WebRtc_Word16 WebRtcVad_FindMinimum(VadInstT* inst,
|
|
WebRtc_Word16 x,
|
|
int n)
|
|
{
|
|
int i, j, k, II = -1, offset;
|
|
WebRtc_Word16 meanV, alpha;
|
|
WebRtc_Word32 tmp32, tmp32_1;
|
|
WebRtc_Word16 *valptr, *idxptr, *p1, *p2, *p3;
|
|
|
|
// Offset to beginning of the 16 minimum values in memory
|
|
offset = WEBRTC_SPL_LSHIFT_W16(n, 4);
|
|
|
|
// Pointer to memory for the 16 minimum values and the age of each value
|
|
idxptr = &inst->index_vector[offset];
|
|
valptr = &inst->low_value_vector[offset];
|
|
|
|
// Each value in low_value_vector is getting 1 loop older.
|
|
// Update age of each value in indexVal, and remove old values.
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
p3 = idxptr + i;
|
|
if (*p3 != 100)
|
|
{
|
|
*p3 += 1;
|
|
} else
|
|
{
|
|
p1 = valptr + i + 1;
|
|
p2 = p3 + 1;
|
|
for (j = i; j < 16; j++)
|
|
{
|
|
*(valptr + j) = *p1++;
|
|
*(idxptr + j) = *p2++;
|
|
}
|
|
*(idxptr + 15) = 101;
|
|
*(valptr + 15) = 10000;
|
|
}
|
|
}
|
|
|
|
// Check if x smaller than any of the values in low_value_vector.
|
|
// If so, find position.
|
|
if (x < *(valptr + 7))
|
|
{
|
|
if (x < *(valptr + 3))
|
|
{
|
|
if (x < *(valptr + 1))
|
|
{
|
|
if (x < *valptr)
|
|
{
|
|
II = 0;
|
|
} else
|
|
{
|
|
II = 1;
|
|
}
|
|
} else if (x < *(valptr + 2))
|
|
{
|
|
II = 2;
|
|
} else
|
|
{
|
|
II = 3;
|
|
}
|
|
} else if (x < *(valptr + 5))
|
|
{
|
|
if (x < *(valptr + 4))
|
|
{
|
|
II = 4;
|
|
} else
|
|
{
|
|
II = 5;
|
|
}
|
|
} else if (x < *(valptr + 6))
|
|
{
|
|
II = 6;
|
|
} else
|
|
{
|
|
II = 7;
|
|
}
|
|
} else if (x < *(valptr + 15))
|
|
{
|
|
if (x < *(valptr + 11))
|
|
{
|
|
if (x < *(valptr + 9))
|
|
{
|
|
if (x < *(valptr + 8))
|
|
{
|
|
II = 8;
|
|
} else
|
|
{
|
|
II = 9;
|
|
}
|
|
} else if (x < *(valptr + 10))
|
|
{
|
|
II = 10;
|
|
} else
|
|
{
|
|
II = 11;
|
|
}
|
|
} else if (x < *(valptr + 13))
|
|
{
|
|
if (x < *(valptr + 12))
|
|
{
|
|
II = 12;
|
|
} else
|
|
{
|
|
II = 13;
|
|
}
|
|
} else if (x < *(valptr + 14))
|
|
{
|
|
II = 14;
|
|
} else
|
|
{
|
|
II = 15;
|
|
}
|
|
}
|
|
|
|
// Put new min value on right position and shift bigger values up
|
|
if (II > -1)
|
|
{
|
|
for (i = 15; i > II; i--)
|
|
{
|
|
k = i - 1;
|
|
*(valptr + i) = *(valptr + k);
|
|
*(idxptr + i) = *(idxptr + k);
|
|
}
|
|
*(valptr + II) = x;
|
|
*(idxptr + II) = 1;
|
|
}
|
|
|
|
meanV = 0;
|
|
if ((inst->frame_counter) > 4)
|
|
{
|
|
j = 5;
|
|
} else
|
|
{
|
|
j = inst->frame_counter;
|
|
}
|
|
|
|
if (j > 2)
|
|
{
|
|
meanV = *(valptr + 2);
|
|
} else if (j > 0)
|
|
{
|
|
meanV = *valptr;
|
|
} else
|
|
{
|
|
meanV = 1600;
|
|
}
|
|
|
|
if (inst->frame_counter > 0)
|
|
{
|
|
if (meanV < inst->mean_value[n])
|
|
{
|
|
alpha = (WebRtc_Word16)ALPHA1; // 0.2 in Q15
|
|
} else
|
|
{
|
|
alpha = (WebRtc_Word16)ALPHA2; // 0.99 in Q15
|
|
}
|
|
} else
|
|
{
|
|
alpha = 0;
|
|
}
|
|
|
|
tmp32 = WEBRTC_SPL_MUL_16_16((alpha+1), inst->mean_value[n]);
|
|
tmp32_1 = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_WORD16_MAX - alpha, meanV);
|
|
tmp32 += tmp32_1;
|
|
tmp32 += 16384;
|
|
inst->mean_value[n] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 15);
|
|
|
|
return inst->mean_value[n];
|
|
}
|