| /* |
| * 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. |
| */ |
| |
| /* |
| * Implementation of the peak detection used for finding correlation peaks. |
| */ |
| |
| #include "dsp_helpfunctions.h" |
| |
| #include "signal_processing_library.h" |
| |
| /* Table of constants used in parabolic fit function WebRtcNetEQ_PrblFit */ |
| const WebRtc_Word16 WebRtcNetEQ_kPrblCf[17][3] = { { 120, 32, 64 }, { 140, 44, 75 }, |
| { 150, 50, 80 }, { 160, 57, 85 }, |
| { 180, 72, 96 }, { 200, 89, 107 }, |
| { 210, 98, 112 }, { 220, 108, 117 }, |
| { 240, 128, 128 }, { 260, 150, 139 }, |
| { 270, 162, 144 }, { 280, 174, 149 }, |
| { 300, 200, 160 }, { 320, 228, 171 }, |
| { 330, 242, 176 }, { 340, 257, 181 }, |
| { 360, 288, 192 } }; |
| |
| WebRtc_Word16 WebRtcNetEQ_PeakDetection(WebRtc_Word16 *pw16_data, WebRtc_Word16 w16_dataLen, |
| WebRtc_Word16 w16_nmbPeaks, WebRtc_Word16 fs_mult, |
| WebRtc_Word16 *pw16_winIndex, |
| WebRtc_Word16 *pw16_winValue) |
| { |
| /* Local variables */ |
| int i; |
| WebRtc_Word16 w16_tmp; |
| WebRtc_Word16 w16_tmp2; |
| WebRtc_Word16 indMin = 0; |
| WebRtc_Word16 indMax = 0; |
| |
| /* Peak detection */ |
| |
| for (i = 0; i <= (w16_nmbPeaks - 1); i++) |
| { |
| if (w16_nmbPeaks == 1) |
| { |
| /* |
| * Single peak |
| * The parabola fit assumes that an extra point is available; worst case it gets |
| * a zero on the high end of the signal. |
| */ |
| w16_dataLen++; |
| } |
| |
| pw16_winIndex[i] = WebRtcSpl_MaxIndexW16(pw16_data, (WebRtc_Word16) (w16_dataLen - 1)); |
| |
| if (i != w16_nmbPeaks - 1) |
| { |
| w16_tmp = pw16_winIndex[i] - 2; /* *fs_mult; */ |
| indMin = WEBRTC_SPL_MAX(0, w16_tmp); |
| w16_tmp = pw16_winIndex[i] + 2; /* *fs_mult; */ |
| w16_tmp2 = w16_dataLen - 1; |
| indMax = WEBRTC_SPL_MIN(w16_tmp2, w16_tmp); |
| } |
| |
| if ((pw16_winIndex[i] != 0) && (pw16_winIndex[i] != (w16_dataLen - 2))) |
| { |
| /* Parabola fit*/ |
| WebRtcNetEQ_PrblFit(&(pw16_data[pw16_winIndex[i] - 1]), &(pw16_winIndex[i]), |
| &(pw16_winValue[i]), fs_mult); |
| } |
| else |
| { |
| if (pw16_winIndex[i] == (w16_dataLen - 2)) |
| { |
| if (pw16_data[pw16_winIndex[i]] > pw16_data[pw16_winIndex[i] + 1]) |
| { |
| WebRtcNetEQ_PrblFit(&(pw16_data[pw16_winIndex[i] - 1]), |
| &(pw16_winIndex[i]), &(pw16_winValue[i]), fs_mult); |
| } |
| else if (pw16_data[pw16_winIndex[i]] <= pw16_data[pw16_winIndex[i] + 1]) |
| { |
| pw16_winValue[i] = (pw16_data[pw16_winIndex[i]] |
| + pw16_data[pw16_winIndex[i] + 1]) >> 1; /* lin approx */ |
| pw16_winIndex[i] = (pw16_winIndex[i] * 2 + 1) * fs_mult; |
| } |
| } |
| else |
| { |
| pw16_winValue[i] = pw16_data[pw16_winIndex[i]]; |
| pw16_winIndex[i] = pw16_winIndex[i] * 2 * fs_mult; |
| } |
| } |
| |
| if (i != w16_nmbPeaks - 1) |
| { |
| WebRtcSpl_MemSetW16(&(pw16_data[indMin]), 0, (indMax - indMin + 1)); |
| /* for (j=indMin; j<=indMax; j++) pw16_data[j] = 0; */ |
| } |
| } |
| |
| return 0; |
| } |
| |
| WebRtc_Word16 WebRtcNetEQ_PrblFit(WebRtc_Word16 *pw16_3pts, WebRtc_Word16 *pw16_Ind, |
| WebRtc_Word16 *pw16_outVal, WebRtc_Word16 fs_mult) |
| { |
| /* Variables */ |
| WebRtc_Word32 Num, Den; |
| WebRtc_Word32 temp; |
| WebRtc_Word16 flag, stp, strt, lmt; |
| WebRtc_UWord16 PFind[13]; |
| |
| if (fs_mult == 1) |
| { |
| PFind[0] = 0; |
| PFind[1] = 8; |
| PFind[2] = 16; |
| } |
| else if (fs_mult == 2) |
| { |
| PFind[0] = 0; |
| PFind[1] = 4; |
| PFind[2] = 8; |
| PFind[3] = 12; |
| PFind[4] = 16; |
| } |
| else if (fs_mult == 4) |
| { |
| PFind[0] = 0; |
| PFind[1] = 2; |
| PFind[2] = 4; |
| PFind[3] = 6; |
| PFind[4] = 8; |
| PFind[5] = 10; |
| PFind[6] = 12; |
| PFind[7] = 14; |
| PFind[8] = 16; |
| } |
| else |
| { |
| PFind[0] = 0; |
| PFind[1] = 1; |
| PFind[2] = 3; |
| PFind[3] = 4; |
| PFind[4] = 5; |
| PFind[5] = 7; |
| PFind[6] = 8; |
| PFind[7] = 9; |
| PFind[8] = 11; |
| PFind[9] = 12; |
| PFind[10] = 13; |
| PFind[11] = 15; |
| PFind[12] = 16; |
| } |
| |
| /* Num = -3*pw16_3pts[0] + 4*pw16_3pts[1] - pw16_3pts[2]; */ |
| /* Den = pw16_3pts[0] - 2*pw16_3pts[1] + pw16_3pts[2]; */ |
| Num = WEBRTC_SPL_MUL_16_16(pw16_3pts[0],-3) + WEBRTC_SPL_MUL_16_16(pw16_3pts[1],4) |
| - pw16_3pts[2]; |
| |
| Den = pw16_3pts[0] + WEBRTC_SPL_MUL_16_16(pw16_3pts[1],-2) + pw16_3pts[2]; |
| |
| temp = (WebRtc_Word32) WEBRTC_SPL_MUL(Num, (WebRtc_Word32)120); /* need 32_16 really */ |
| flag = 1; |
| stp = WebRtcNetEQ_kPrblCf[PFind[fs_mult]][0] - WebRtcNetEQ_kPrblCf[PFind[fs_mult - 1]][0]; |
| strt = (WebRtcNetEQ_kPrblCf[PFind[fs_mult]][0] |
| + WebRtcNetEQ_kPrblCf[PFind[fs_mult - 1]][0]) >> 1; |
| |
| if (temp < (WebRtc_Word32) WEBRTC_SPL_MUL(-Den,(WebRtc_Word32)strt)) |
| { |
| lmt = strt - stp; |
| while (flag) |
| { |
| if ((flag == fs_mult) || (temp |
| > (WebRtc_Word32) WEBRTC_SPL_MUL(-Den,(WebRtc_Word32)lmt))) |
| { |
| *pw16_outVal |
| = (WebRtc_Word16) |
| (((WebRtc_Word32) ((WebRtc_Word32) WEBRTC_SPL_MUL(Den,(WebRtc_Word32)WebRtcNetEQ_kPrblCf[PFind[fs_mult-flag]][1]) |
| + (WebRtc_Word32) WEBRTC_SPL_MUL(Num,(WebRtc_Word32)WebRtcNetEQ_kPrblCf[PFind[fs_mult-flag]][2]) |
| + WEBRTC_SPL_MUL_16_16(pw16_3pts[0],256))) >> 8); |
| *pw16_Ind = (*pw16_Ind) * (fs_mult << 1) - flag; |
| flag = 0; |
| } |
| else |
| { |
| flag++; |
| lmt -= stp; |
| } |
| } |
| } |
| else if (temp > (WebRtc_Word32) WEBRTC_SPL_MUL(-Den,(WebRtc_Word32)(strt+stp))) |
| { |
| lmt = strt + (stp << 1); |
| while (flag) |
| { |
| if ((flag == fs_mult) || (temp |
| < (WebRtc_Word32) WEBRTC_SPL_MUL(-Den,(WebRtc_Word32)lmt))) |
| { |
| WebRtc_Word32 temp_term_1, temp_term_2, temp_term_3; |
| |
| temp_term_1 = WEBRTC_SPL_MUL(Den, |
| (WebRtc_Word32) WebRtcNetEQ_kPrblCf[PFind[fs_mult+flag]][1]); |
| temp_term_2 = WEBRTC_SPL_MUL(Num, |
| (WebRtc_Word32) WebRtcNetEQ_kPrblCf[PFind[fs_mult+flag]][2]); |
| temp_term_3 = WEBRTC_SPL_MUL_16_16(pw16_3pts[0],256); |
| |
| *pw16_outVal |
| = (WebRtc_Word16) ((temp_term_1 + temp_term_2 + temp_term_3) >> 8); |
| |
| *pw16_Ind = (*pw16_Ind) * (fs_mult << 1) + flag; |
| flag = 0; |
| } |
| else |
| { |
| flag++; |
| lmt += stp; |
| } |
| } |
| |
| } |
| else |
| { |
| *pw16_outVal = pw16_3pts[1]; |
| *pw16_Ind = (*pw16_Ind) * 2 * fs_mult; |
| } |
| |
| return 0; |
| } |
| |