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