diff options
Diffstat (limited to 'src/common_audio/vad/main/source/vad_sp.c')
-rw-r--r-- | src/common_audio/vad/main/source/vad_sp.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/common_audio/vad/main/source/vad_sp.c b/src/common_audio/vad/main/source/vad_sp.c new file mode 100644 index 0000000000..f347ab5904 --- /dev/null +++ b/src/common_audio/vad/main/source/vad_sp.c @@ -0,0 +1,231 @@ +/* + * 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]; +} |