niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | /* |
| 12 | * Implementation of the peak detection used for finding correlation peaks. |
| 13 | */ |
| 14 | |
| 15 | #include "dsp_helpfunctions.h" |
| 16 | |
| 17 | #include "signal_processing_library.h" |
| 18 | |
| 19 | /* Table of constants used in parabolic fit function WebRtcNetEQ_PrblFit */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 20 | const int16_t WebRtcNetEQ_kPrblCf[17][3] = { { 120, 32, 64 }, { 140, 44, 75 }, |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 21 | { 150, 50, 80 }, { 160, 57, 85 }, |
| 22 | { 180, 72, 96 }, { 200, 89, 107 }, |
| 23 | { 210, 98, 112 }, { 220, 108, 117 }, |
| 24 | { 240, 128, 128 }, { 260, 150, 139 }, |
| 25 | { 270, 162, 144 }, { 280, 174, 149 }, |
| 26 | { 300, 200, 160 }, { 320, 228, 171 }, |
| 27 | { 330, 242, 176 }, { 340, 257, 181 }, |
| 28 | { 360, 288, 192 } }; |
| 29 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 30 | int16_t WebRtcNetEQ_PeakDetection(int16_t *pw16_data, int16_t w16_dataLen, |
| 31 | int16_t w16_nmbPeaks, int16_t fs_mult, |
| 32 | int16_t *pw16_winIndex, |
| 33 | int16_t *pw16_winValue) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 34 | { |
| 35 | /* Local variables */ |
| 36 | int i; |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 37 | int16_t w16_tmp; |
| 38 | int16_t w16_tmp2; |
| 39 | int16_t indMin = 0; |
| 40 | int16_t indMax = 0; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 41 | |
| 42 | /* Peak detection */ |
| 43 | |
| 44 | for (i = 0; i <= (w16_nmbPeaks - 1); i++) |
| 45 | { |
| 46 | if (w16_nmbPeaks == 1) |
| 47 | { |
| 48 | /* |
| 49 | * Single peak |
| 50 | * The parabola fit assumes that an extra point is available; worst case it gets |
| 51 | * a zero on the high end of the signal. |
| 52 | */ |
| 53 | w16_dataLen++; |
| 54 | } |
| 55 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 56 | pw16_winIndex[i] = WebRtcSpl_MaxIndexW16(pw16_data, (int16_t) (w16_dataLen - 1)); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 57 | |
| 58 | if (i != w16_nmbPeaks - 1) |
| 59 | { |
| 60 | w16_tmp = pw16_winIndex[i] - 2; /* *fs_mult; */ |
| 61 | indMin = WEBRTC_SPL_MAX(0, w16_tmp); |
| 62 | w16_tmp = pw16_winIndex[i] + 2; /* *fs_mult; */ |
| 63 | w16_tmp2 = w16_dataLen - 1; |
| 64 | indMax = WEBRTC_SPL_MIN(w16_tmp2, w16_tmp); |
| 65 | } |
| 66 | |
| 67 | if ((pw16_winIndex[i] != 0) && (pw16_winIndex[i] != (w16_dataLen - 2))) |
| 68 | { |
| 69 | /* Parabola fit*/ |
| 70 | WebRtcNetEQ_PrblFit(&(pw16_data[pw16_winIndex[i] - 1]), &(pw16_winIndex[i]), |
| 71 | &(pw16_winValue[i]), fs_mult); |
| 72 | } |
| 73 | else |
| 74 | { |
| 75 | if (pw16_winIndex[i] == (w16_dataLen - 2)) |
| 76 | { |
| 77 | if (pw16_data[pw16_winIndex[i]] > pw16_data[pw16_winIndex[i] + 1]) |
| 78 | { |
| 79 | WebRtcNetEQ_PrblFit(&(pw16_data[pw16_winIndex[i] - 1]), |
| 80 | &(pw16_winIndex[i]), &(pw16_winValue[i]), fs_mult); |
| 81 | } |
| 82 | else if (pw16_data[pw16_winIndex[i]] <= pw16_data[pw16_winIndex[i] + 1]) |
| 83 | { |
| 84 | pw16_winValue[i] = (pw16_data[pw16_winIndex[i]] |
| 85 | + pw16_data[pw16_winIndex[i] + 1]) >> 1; /* lin approx */ |
| 86 | pw16_winIndex[i] = (pw16_winIndex[i] * 2 + 1) * fs_mult; |
| 87 | } |
| 88 | } |
| 89 | else |
| 90 | { |
| 91 | pw16_winValue[i] = pw16_data[pw16_winIndex[i]]; |
| 92 | pw16_winIndex[i] = pw16_winIndex[i] * 2 * fs_mult; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | if (i != w16_nmbPeaks - 1) |
| 97 | { |
| 98 | WebRtcSpl_MemSetW16(&(pw16_data[indMin]), 0, (indMax - indMin + 1)); |
| 99 | /* for (j=indMin; j<=indMax; j++) pw16_data[j] = 0; */ |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | return 0; |
| 104 | } |
| 105 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 106 | int16_t WebRtcNetEQ_PrblFit(int16_t *pw16_3pts, int16_t *pw16_Ind, |
| 107 | int16_t *pw16_outVal, int16_t fs_mult) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 108 | { |
| 109 | /* Variables */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 110 | int32_t Num, Den; |
| 111 | int32_t temp; |
| 112 | int16_t flag, stp, strt, lmt; |
| 113 | uint16_t PFind[13]; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 114 | |
| 115 | if (fs_mult == 1) |
| 116 | { |
| 117 | PFind[0] = 0; |
| 118 | PFind[1] = 8; |
| 119 | PFind[2] = 16; |
| 120 | } |
| 121 | else if (fs_mult == 2) |
| 122 | { |
| 123 | PFind[0] = 0; |
| 124 | PFind[1] = 4; |
| 125 | PFind[2] = 8; |
| 126 | PFind[3] = 12; |
| 127 | PFind[4] = 16; |
| 128 | } |
| 129 | else if (fs_mult == 4) |
| 130 | { |
| 131 | PFind[0] = 0; |
| 132 | PFind[1] = 2; |
| 133 | PFind[2] = 4; |
| 134 | PFind[3] = 6; |
| 135 | PFind[4] = 8; |
| 136 | PFind[5] = 10; |
| 137 | PFind[6] = 12; |
| 138 | PFind[7] = 14; |
| 139 | PFind[8] = 16; |
| 140 | } |
| 141 | else |
| 142 | { |
| 143 | PFind[0] = 0; |
| 144 | PFind[1] = 1; |
| 145 | PFind[2] = 3; |
| 146 | PFind[3] = 4; |
| 147 | PFind[4] = 5; |
| 148 | PFind[5] = 7; |
| 149 | PFind[6] = 8; |
| 150 | PFind[7] = 9; |
| 151 | PFind[8] = 11; |
| 152 | PFind[9] = 12; |
| 153 | PFind[10] = 13; |
| 154 | PFind[11] = 15; |
| 155 | PFind[12] = 16; |
| 156 | } |
| 157 | |
| 158 | /* Num = -3*pw16_3pts[0] + 4*pw16_3pts[1] - pw16_3pts[2]; */ |
| 159 | /* Den = pw16_3pts[0] - 2*pw16_3pts[1] + pw16_3pts[2]; */ |
| 160 | Num = WEBRTC_SPL_MUL_16_16(pw16_3pts[0],-3) + WEBRTC_SPL_MUL_16_16(pw16_3pts[1],4) |
| 161 | - pw16_3pts[2]; |
| 162 | |
| 163 | Den = pw16_3pts[0] + WEBRTC_SPL_MUL_16_16(pw16_3pts[1],-2) + pw16_3pts[2]; |
| 164 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 165 | temp = (int32_t) WEBRTC_SPL_MUL(Num, (int32_t)120); /* need 32_16 really */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 166 | flag = 1; |
| 167 | stp = WebRtcNetEQ_kPrblCf[PFind[fs_mult]][0] - WebRtcNetEQ_kPrblCf[PFind[fs_mult - 1]][0]; |
| 168 | strt = (WebRtcNetEQ_kPrblCf[PFind[fs_mult]][0] |
| 169 | + WebRtcNetEQ_kPrblCf[PFind[fs_mult - 1]][0]) >> 1; |
| 170 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 171 | if (temp < (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)strt)) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 172 | { |
| 173 | lmt = strt - stp; |
| 174 | while (flag) |
| 175 | { |
| 176 | if ((flag == fs_mult) || (temp |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 177 | > (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)lmt))) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 178 | { |
| 179 | *pw16_outVal |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 180 | = (int16_t) |
| 181 | (((int32_t) ((int32_t) WEBRTC_SPL_MUL(Den,(int32_t)WebRtcNetEQ_kPrblCf[PFind[fs_mult-flag]][1]) |
| 182 | + (int32_t) WEBRTC_SPL_MUL(Num,(int32_t)WebRtcNetEQ_kPrblCf[PFind[fs_mult-flag]][2]) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 183 | + WEBRTC_SPL_MUL_16_16(pw16_3pts[0],256))) >> 8); |
| 184 | *pw16_Ind = (*pw16_Ind) * (fs_mult << 1) - flag; |
| 185 | flag = 0; |
| 186 | } |
| 187 | else |
| 188 | { |
| 189 | flag++; |
| 190 | lmt -= stp; |
| 191 | } |
| 192 | } |
| 193 | } |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 194 | else if (temp > (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)(strt+stp))) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 195 | { |
| 196 | lmt = strt + (stp << 1); |
| 197 | while (flag) |
| 198 | { |
| 199 | if ((flag == fs_mult) || (temp |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 200 | < (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)lmt))) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 201 | { |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 202 | int32_t temp_term_1, temp_term_2, temp_term_3; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 203 | |
| 204 | temp_term_1 = WEBRTC_SPL_MUL(Den, |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 205 | (int32_t) WebRtcNetEQ_kPrblCf[PFind[fs_mult+flag]][1]); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 206 | temp_term_2 = WEBRTC_SPL_MUL(Num, |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 207 | (int32_t) WebRtcNetEQ_kPrblCf[PFind[fs_mult+flag]][2]); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 208 | temp_term_3 = WEBRTC_SPL_MUL_16_16(pw16_3pts[0],256); |
| 209 | |
| 210 | *pw16_outVal |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 211 | = (int16_t) ((temp_term_1 + temp_term_2 + temp_term_3) >> 8); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 212 | |
| 213 | *pw16_Ind = (*pw16_Ind) * (fs_mult << 1) + flag; |
| 214 | flag = 0; |
| 215 | } |
| 216 | else |
| 217 | { |
| 218 | flag++; |
| 219 | lmt += stp; |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | } |
| 224 | else |
| 225 | { |
| 226 | *pw16_outVal = pw16_3pts[1]; |
| 227 | *pw16_Ind = (*pw16_Ind) * 2 * fs_mult; |
| 228 | } |
| 229 | |
| 230 | return 0; |
| 231 | } |
| 232 | |