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 short 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 short* inspeech, 75 int size, 76 float skew, 77 short* outspeech, 78 int* size_out) { 79 resampler_t* obj = (resampler_t*)resampInst; 80 81 short* y; 82 float be, tnew, interp; 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(short)); 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 interp = y[tn] + (tnew - tn) * (y[tn + 1] - y[tn]); 110 111 if (interp > 32767) { 112 interp = 32767; 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 *size_out = mm; 125 obj->position += (*size_out) * be - size; 126 127 // Shift buffer 128 memmove(obj->buffer, 129 &obj->buffer[size], 130 (kResamplerBufferSize - size) * sizeof(short)); 131 } 132 133 int WebRtcAec_GetSkew(void* resampInst, int rawSkew, float* skewEst) { 134 resampler_t* obj = (resampler_t*)resampInst; 135 int err = 0; 136 137 if (obj->skewDataIndex < kEstimateLengthFrames) { 138 obj->skewData[obj->skewDataIndex] = rawSkew; 139 obj->skewDataIndex++; 140 } else if (obj->skewDataIndex == kEstimateLengthFrames) { 141 err = EstimateSkew( 142 obj->skewData, kEstimateLengthFrames, obj->deviceSampleRateHz, skewEst); 143 obj->skewEstimate = *skewEst; 144 obj->skewDataIndex++; 145 } else { 146 *skewEst = obj->skewEstimate; 147 } 148 149 return err; 150 } 151 152 int EstimateSkew(const int* rawSkew, 153 int size, 154 int deviceSampleRateHz, 155 float* skewEst) { 156 const int absLimitOuter = (int)(0.04f * deviceSampleRateHz); 157 const int absLimitInner = (int)(0.0025f * deviceSampleRateHz); 158 int i = 0; 159 int n = 0; 160 float rawAvg = 0; 161 float err = 0; 162 float rawAbsDev = 0; 163 int upperLimit = 0; 164 int lowerLimit = 0; 165 float cumSum = 0; 166 float x = 0; 167 float x2 = 0; 168 float y = 0; 169 float xy = 0; 170 float xAvg = 0; 171 float denom = 0; 172 float skew = 0; 173 174 *skewEst = 0; // Set in case of error below. 175 for (i = 0; i < size; i++) { 176 if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) { 177 n++; 178 rawAvg += rawSkew[i]; 179 } 180 } 181 182 if (n == 0) { 183 return -1; 184 } 185 assert(n > 0); 186 rawAvg /= n; 187 188 for (i = 0; i < size; i++) { 189 if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) { 190 err = rawSkew[i] - rawAvg; 191 rawAbsDev += err >= 0 ? err : -err; 192 } 193 } 194 assert(n > 0); 195 rawAbsDev /= n; 196 upperLimit = (int)(rawAvg + 5 * rawAbsDev + 1); // +1 for ceiling. 197 lowerLimit = (int)(rawAvg - 5 * rawAbsDev - 1); // -1 for floor. 198 199 n = 0; 200 for (i = 0; i < size; i++) { 201 if ((rawSkew[i] < absLimitInner && rawSkew[i] > -absLimitInner) || 202 (rawSkew[i] < upperLimit && rawSkew[i] > lowerLimit)) { 203 n++; 204 cumSum += rawSkew[i]; 205 x += n; 206 x2 += n * n; 207 y += cumSum; 208 xy += n * cumSum; 209 } 210 } 211 212 if (n == 0) { 213 return -1; 214 } 215 assert(n > 0); 216 xAvg = x / n; 217 denom = x2 - xAvg * x; 218 219 if (denom != 0) { 220 skew = (xy - xAvg * y) / denom; 221 } 222 223 *skewEst = skew; 224 return 0; 225 } 226