blob: 8c85d2a837eb5477022b64b0b1d5440ee0475d0a [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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.org0946a562013-04-09 00:28:06 +000020const int16_t WebRtcNetEQ_kPrblCf[17][3] = { { 120, 32, 64 }, { 140, 44, 75 },
niklase@google.com470e71d2011-07-07 08:21:25 +000021 { 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.org0946a562013-04-09 00:28:06 +000030int16_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.com470e71d2011-07-07 08:21:25 +000034{
35 /* Local variables */
36 int i;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000037 int16_t w16_tmp;
38 int16_t w16_tmp2;
39 int16_t indMin = 0;
40 int16_t indMax = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000041
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.org0946a562013-04-09 00:28:06 +000056 pw16_winIndex[i] = WebRtcSpl_MaxIndexW16(pw16_data, (int16_t) (w16_dataLen - 1));
niklase@google.com470e71d2011-07-07 08:21:25 +000057
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.org0946a562013-04-09 00:28:06 +0000106int16_t WebRtcNetEQ_PrblFit(int16_t *pw16_3pts, int16_t *pw16_Ind,
107 int16_t *pw16_outVal, int16_t fs_mult)
niklase@google.com470e71d2011-07-07 08:21:25 +0000108{
109 /* Variables */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000110 int32_t Num, Den;
111 int32_t temp;
112 int16_t flag, stp, strt, lmt;
113 uint16_t PFind[13];
niklase@google.com470e71d2011-07-07 08:21:25 +0000114
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.org0946a562013-04-09 00:28:06 +0000165 temp = (int32_t) WEBRTC_SPL_MUL(Num, (int32_t)120); /* need 32_16 really */
niklase@google.com470e71d2011-07-07 08:21:25 +0000166 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.org0946a562013-04-09 00:28:06 +0000171 if (temp < (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)strt))
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 {
173 lmt = strt - stp;
174 while (flag)
175 {
176 if ((flag == fs_mult) || (temp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000177 > (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)lmt)))
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 {
179 *pw16_outVal
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000180 = (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.com470e71d2011-07-07 08:21:25 +0000183 + 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.org0946a562013-04-09 00:28:06 +0000194 else if (temp > (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)(strt+stp)))
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 {
196 lmt = strt + (stp << 1);
197 while (flag)
198 {
199 if ((flag == fs_mult) || (temp
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000200 < (int32_t) WEBRTC_SPL_MUL(-Den,(int32_t)lmt)))
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000202 int32_t temp_term_1, temp_term_2, temp_term_3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203
204 temp_term_1 = WEBRTC_SPL_MUL(Den,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000205 (int32_t) WebRtcNetEQ_kPrblCf[PFind[fs_mult+flag]][1]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000206 temp_term_2 = WEBRTC_SPL_MUL(Num,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000207 (int32_t) WebRtcNetEQ_kPrblCf[PFind[fs_mult+flag]][2]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 temp_term_3 = WEBRTC_SPL_MUL_16_16(pw16_3pts[0],256);
209
210 *pw16_outVal
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000211 = (int16_t) ((temp_term_1 + temp_term_2 + temp_term_3) >> 8);
niklase@google.com470e71d2011-07-07 08:21:25 +0000212
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