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 { 25 kEstimateLengthFrames = 400 26 }; 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 } resampler_t; 37 38 static int EstimateSkew(const int* rawSkew, 39 int size, 40 int absLimit, 41 float* skewEst); 42 43 int WebRtcAec_CreateResampler(void** resampInst) { 44 resampler_t* obj = malloc(sizeof(resampler_t)); 45 *resampInst = obj; 46 if (obj == NULL) { 47 return -1; 48 } 49 50 return 0; 51 } 52 53 int WebRtcAec_InitResampler(void* resampInst, int deviceSampleRateHz) { 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 66 int WebRtcAec_FreeResampler(void* resampInst) { 67 resampler_t* obj = (resampler_t*)resampInst; 68 free(obj); 69 70 return 0; 71 } 72 73 void WebRtcAec_ResampleLinear(void* resampInst, 74 const float* inspeech, 75 int size, 76 float skew, 77 float* outspeech, 78 int* size_out) { 79 resampler_t* obj = (resampler_t*)resampInst; 80 81 float* y; 82 float be, tnew; 83 int tn, mm; 84 85 assert(!(size < 0 || size > 2 * FRAME_LEN)); 86 assert(resampInst != NULL); 87 assert(inspeech != NULL); 88 assert(outspeech != NULL); 89 assert(size_out != NULL); 90 91 // Add new frame data in lookahead 92 memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay], 93 inspeech, 94 size * sizeof(inspeech[0])); 95 96 // Sample rate ratio 97 be = 1 + skew; 98 99 // Loop over input frame 100 mm = 0; 101 y = &obj->buffer[FRAME_LEN]; // Point at current frame 102 103 tnew = be * mm + obj->position; 104 tn = (int)tnew; 105 106 while (tn < size) { 107 108 // Interpolation 109 outspeech[mm] = y[tn] + (tnew - tn) * (y[tn + 1] - y[tn]); 110 mm++; 111 112 tnew = be * mm + obj->position; 113 tn = (int)tnew; 114 } 115 116 *size_out = mm; 117 obj->position += (*size_out) * be - size; 118 119 // Shift buffer 120 memmove(obj->buffer, 121 &obj->buffer[size], 122 (kResamplerBufferSize - size) * sizeof(obj->buffer[0])); 123 } 124 125 int WebRtcAec_GetSkew(void* resampInst, int rawSkew, float* skewEst) { 126 resampler_t* obj = (resampler_t*)resampInst; 127 int err = 0; 128 129 if (obj->skewDataIndex < kEstimateLengthFrames) { 130 obj->skewData[obj->skewDataIndex] = rawSkew; 131 obj->skewDataIndex++; 132 } else if (obj->skewDataIndex == kEstimateLengthFrames) { 133 err = EstimateSkew( 134 obj->skewData, kEstimateLengthFrames, obj->deviceSampleRateHz, skewEst); 135 obj->skewEstimate = *skewEst; 136 obj->skewDataIndex++; 137 } else { 138 *skewEst = obj->skewEstimate; 139 } 140 141 return err; 142 } 143 144 int EstimateSkew(const int* rawSkew, 145 int size, 146 int deviceSampleRateHz, 147 float* skewEst) { 148 const int absLimitOuter = (int)(0.04f * deviceSampleRateHz); 149 const int absLimitInner = (int)(0.0025f * deviceSampleRateHz); 150 int i = 0; 151 int n = 0; 152 float rawAvg = 0; 153 float err = 0; 154 float rawAbsDev = 0; 155 int upperLimit = 0; 156 int lowerLimit = 0; 157 float cumSum = 0; 158 float x = 0; 159 float x2 = 0; 160 float y = 0; 161 float xy = 0; 162 float xAvg = 0; 163 float denom = 0; 164 float skew = 0; 165 166 *skewEst = 0; // Set in case of error below. 167 for (i = 0; i < size; i++) { 168 if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) { 169 n++; 170 rawAvg += rawSkew[i]; 171 } 172 } 173 174 if (n == 0) { 175 return -1; 176 } 177 assert(n > 0); 178 rawAvg /= n; 179 180 for (i = 0; i < size; i++) { 181 if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) { 182 err = rawSkew[i] - rawAvg; 183 rawAbsDev += err >= 0 ? err : -err; 184 } 185 } 186 assert(n > 0); 187 rawAbsDev /= n; 188 upperLimit = (int)(rawAvg + 5 * rawAbsDev + 1); // +1 for ceiling. 189 lowerLimit = (int)(rawAvg - 5 * rawAbsDev - 1); // -1 for floor. 190 191 n = 0; 192 for (i = 0; i < size; i++) { 193 if ((rawSkew[i] < absLimitInner && rawSkew[i] > -absLimitInner) || 194 (rawSkew[i] < upperLimit && rawSkew[i] > lowerLimit)) { 195 n++; 196 cumSum += rawSkew[i]; 197 x += n; 198 x2 += n * n; 199 y += cumSum; 200 xy += n * cumSum; 201 } 202 } 203 204 if (n == 0) { 205 return -1; 206 } 207 assert(n > 0); 208 xAvg = x / n; 209 denom = x2 - xAvg * x; 210 211 if (denom != 0) { 212 skew = (xy - xAvg * y) / denom; 213 } 214 215 *skewEst = skew; 216 return 0; 217 } 218