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 /* Resamples a signal to an arbitrary rate. Used by the AEC to compensate for clock
12 * skew by resampling the farend signal.
13 */
14
15 #include "aec_resampler.h"
16
17 #include <assert.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21
22 #include "aec_core.h"
23
24 enum { kEstimateLengthFrames = 400 };
25
26 typedef struct {
27 short buffer[kResamplerBufferSize];
28 float position;
29
30 int deviceSampleRateHz;
31 int skewData[kEstimateLengthFrames];
32 int skewDataIndex;
33 float skewEstimate;
34 } resampler_t;
35
36 static int EstimateSkew(const int* rawSkew,
37 int size,
38 int absLimit,
39 float *skewEst);
40
WebRtcAec_CreateResampler(void ** resampInst)41 int WebRtcAec_CreateResampler(void **resampInst)
42 {
43 resampler_t *obj = malloc(sizeof(resampler_t));
44 *resampInst = obj;
45 if (obj == NULL) {
46 return -1;
47 }
48
49 return 0;
50 }
51
WebRtcAec_InitResampler(void * resampInst,int deviceSampleRateHz)52 int WebRtcAec_InitResampler(void *resampInst, int deviceSampleRateHz)
53 {
54 resampler_t *obj = (resampler_t*) resampInst;
55 memset(obj->buffer, 0, sizeof(obj->buffer));
56 obj->position = 0.0;
57
58 obj->deviceSampleRateHz = deviceSampleRateHz;
59 memset(obj->skewData, 0, sizeof(obj->skewData));
60 obj->skewDataIndex = 0;
61 obj->skewEstimate = 0.0;
62
63 return 0;
64 }
65
WebRtcAec_FreeResampler(void * resampInst)66 int WebRtcAec_FreeResampler(void *resampInst)
67 {
68 resampler_t *obj = (resampler_t*) resampInst;
69 free(obj);
70
71 return 0;
72 }
73
WebRtcAec_ResampleLinear(void * resampInst,const short * inspeech,int size,float skew,short * outspeech)74 int WebRtcAec_ResampleLinear(void *resampInst,
75 const short *inspeech,
76 int size,
77 float skew,
78 short *outspeech)
79 {
80 resampler_t *obj = (resampler_t*) resampInst;
81
82 short *y;
83 float be, tnew, interp;
84 int tn, outsize, mm;
85
86 if (size < 0 || size > 2 * FRAME_LEN) {
87 return -1;
88 }
89
90 // Add new frame data in lookahead
91 memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay],
92 inspeech,
93 size * sizeof(short));
94
95 // Sample rate ratio
96 be = 1 + skew;
97
98 // Loop over input frame
99 mm = 0;
100 y = &obj->buffer[FRAME_LEN]; // Point at current frame
101
102 tnew = be * mm + obj->position;
103 tn = (int) tnew;
104
105 while (tn < size) {
106
107 // Interpolation
108 interp = y[tn] + (tnew - tn) * (y[tn+1] - y[tn]);
109
110 if (interp > 32767) {
111 interp = 32767;
112 }
113 else if (interp < -32768) {
114 interp = -32768;
115 }
116
117 outspeech[mm] = (short) interp;
118 mm++;
119
120 tnew = be * mm + obj->position;
121 tn = (int) tnew;
122 }
123
124 outsize = mm;
125 obj->position += outsize * be - size;
126
127 // Shift buffer
128 memmove(obj->buffer,
129 &obj->buffer[size],
130 (kResamplerBufferSize - size) * sizeof(short));
131
132 return outsize;
133 }
134
WebRtcAec_GetSkew(void * resampInst,int rawSkew,float * skewEst)135 int WebRtcAec_GetSkew(void *resampInst, int rawSkew, float *skewEst)
136 {
137 resampler_t *obj = (resampler_t*)resampInst;
138 int err = 0;
139
140 if (obj->skewDataIndex < kEstimateLengthFrames) {
141 obj->skewData[obj->skewDataIndex] = rawSkew;
142 obj->skewDataIndex++;
143 }
144 else if (obj->skewDataIndex == kEstimateLengthFrames) {
145 err = EstimateSkew(obj->skewData,
146 kEstimateLengthFrames,
147 obj->deviceSampleRateHz,
148 skewEst);
149 obj->skewEstimate = *skewEst;
150 obj->skewDataIndex++;
151 }
152 else {
153 *skewEst = obj->skewEstimate;
154 }
155
156 return err;
157 }
158
EstimateSkew(const int * rawSkew,int size,int deviceSampleRateHz,float * skewEst)159 int EstimateSkew(const int* rawSkew,
160 int size,
161 int deviceSampleRateHz,
162 float *skewEst)
163 {
164 const int absLimitOuter = (int)(0.04f * deviceSampleRateHz);
165 const int absLimitInner = (int)(0.0025f * deviceSampleRateHz);
166 int i = 0;
167 int n = 0;
168 float rawAvg = 0;
169 float err = 0;
170 float rawAbsDev = 0;
171 int upperLimit = 0;
172 int lowerLimit = 0;
173 float cumSum = 0;
174 float x = 0;
175 float x2 = 0;
176 float y = 0;
177 float xy = 0;
178 float xAvg = 0;
179 float denom = 0;
180 float skew = 0;
181
182 *skewEst = 0; // Set in case of error below.
183 for (i = 0; i < size; i++) {
184 if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) {
185 n++;
186 rawAvg += rawSkew[i];
187 }
188 }
189
190 if (n == 0) {
191 return -1;
192 }
193 assert(n > 0);
194 rawAvg /= n;
195
196 for (i = 0; i < size; i++) {
197 if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) {
198 err = rawSkew[i] - rawAvg;
199 rawAbsDev += err >= 0 ? err : -err;
200 }
201 }
202 assert(n > 0);
203 rawAbsDev /= n;
204 upperLimit = (int)(rawAvg + 5 * rawAbsDev + 1); // +1 for ceiling.
205 lowerLimit = (int)(rawAvg - 5 * rawAbsDev - 1); // -1 for floor.
206
207 n = 0;
208 for (i = 0; i < size; i++) {
209 if ((rawSkew[i] < absLimitInner && rawSkew[i] > -absLimitInner) ||
210 (rawSkew[i] < upperLimit && rawSkew[i] > lowerLimit)) {
211 n++;
212 cumSum += rawSkew[i];
213 x += n;
214 x2 += n*n;
215 y += cumSum;
216 xy += n * cumSum;
217 }
218 }
219
220 if (n == 0) {
221 return -1;
222 }
223 assert(n > 0);
224 xAvg = x / n;
225 denom = x2 - xAvg*x;
226
227 if (denom != 0) {
228 skew = (xy - xAvg*y) / denom;
229 }
230
231 *skewEst = skew;
232 return 0;
233 }
234