Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: webrtc/modules/audio_processing/aec/aec_resampler.c

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

Powered by Google App Engine
This is Rietveld 408576698