1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 112f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org/* Resamples a signal to an arbitrary rate. Used by the AEC to compensate for 12127d8ad377534ca58125bf65ffaf843f73ac36a5andrew@webrtc.org * clock skew by resampling the farend signal. 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 159fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/aec/aec_resampler.h" 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <assert.h> 189fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include <math.h> 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdlib.h> 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h> 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 229fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/aec/aec_core.h" 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 242f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.orgenum { 252f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org kEstimateLengthFrames = 400 262f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org}; 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgtypedef struct { 2938a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org float buffer[kResamplerBufferSize]; 302f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float position; 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 322f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int deviceSampleRateHz; 332f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int skewData[kEstimateLengthFrames]; 342f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int skewDataIndex; 352f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float skewEstimate; 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} resampler_t; 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic int EstimateSkew(const int* rawSkew, 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int size, 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int absLimit, 412f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float* skewEst); 422f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 432f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.orgint WebRtcAec_CreateResampler(void** resampInst) { 442f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org resampler_t* obj = malloc(sizeof(resampler_t)); 452f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org *resampInst = obj; 462f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if (obj == NULL) { 472f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return -1; 482f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 502f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return 0; 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 532f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.orgint WebRtcAec_InitResampler(void* resampInst, int deviceSampleRateHz) { 542f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org resampler_t* obj = (resampler_t*)resampInst; 552f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org memset(obj->buffer, 0, sizeof(obj->buffer)); 562f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->position = 0.0; 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 582f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->deviceSampleRateHz = deviceSampleRateHz; 592f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org memset(obj->skewData, 0, sizeof(obj->skewData)); 602f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewDataIndex = 0; 612f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewEstimate = 0.0; 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 632f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return 0; 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 662f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.orgint WebRtcAec_FreeResampler(void* resampInst) { 672f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org resampler_t* obj = (resampler_t*)resampInst; 682f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org free(obj); 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 702f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return 0; 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 732f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.orgvoid WebRtcAec_ResampleLinear(void* resampInst, 7438a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org const float* inspeech, 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int size, 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float skew, 7738a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org float* outspeech, 782f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int* size_out) { 792f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org resampler_t* obj = (resampler_t*)resampInst; 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8138a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org float* y; 8238a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org float be, tnew; 832f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int tn, mm; 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 852f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(!(size < 0 || size > 2 * FRAME_LEN)); 862f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(resampInst != NULL); 872f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(inspeech != NULL); 882f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(outspeech != NULL); 892f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(size_out != NULL); 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 912f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org // Add new frame data in lookahead 922f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay], 932f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org inspeech, 9438a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org size * sizeof(inspeech[0])); 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 962f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org // Sample rate ratio 972f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org be = 1 + skew; 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 992f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org // Loop over input frame 1002f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org mm = 0; 1012f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org y = &obj->buffer[FRAME_LEN]; // Point at current frame 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1032f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org tnew = be * mm + obj->position; 1042f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org tn = (int)tnew; 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1062f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org while (tn < size) { 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1082f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org // Interpolation 10938a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org outspeech[mm] = y[tn] + (tnew - tn) * (y[tn + 1] - y[tn]); 1102f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org mm++; 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1122f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org tnew = be * mm + obj->position; 1132f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org tn = (int)tnew; 1142f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1162f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org *size_out = mm; 1172f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->position += (*size_out) * be - size; 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1192f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org // Shift buffer 1202f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org memmove(obj->buffer, 1212f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org &obj->buffer[size], 12238a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org (kResamplerBufferSize - size) * sizeof(obj->buffer[0])); 1232f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org} 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1252f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.orgint WebRtcAec_GetSkew(void* resampInst, int rawSkew, float* skewEst) { 1262f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org resampler_t* obj = (resampler_t*)resampInst; 1272f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int err = 0; 1282f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 1292f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if (obj->skewDataIndex < kEstimateLengthFrames) { 1302f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewData[obj->skewDataIndex] = rawSkew; 1312f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewDataIndex++; 1322f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } else if (obj->skewDataIndex == kEstimateLengthFrames) { 1332f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org err = EstimateSkew( 1342f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewData, kEstimateLengthFrames, obj->deviceSampleRateHz, skewEst); 1352f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewEstimate = *skewEst; 1362f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org obj->skewDataIndex++; 1372f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } else { 1382f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org *skewEst = obj->skewEstimate; 1392f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 1402f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 1412f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return err; 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EstimateSkew(const int* rawSkew, 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int size, 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int deviceSampleRateHz, 1472f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float* skewEst) { 1482f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org const int absLimitOuter = (int)(0.04f * deviceSampleRateHz); 1492f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org const int absLimitInner = (int)(0.0025f * deviceSampleRateHz); 1502f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int i = 0; 1512f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int n = 0; 1522f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float rawAvg = 0; 1532f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float err = 0; 1542f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float rawAbsDev = 0; 1552f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int upperLimit = 0; 1562f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org int lowerLimit = 0; 1572f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float cumSum = 0; 1582f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float x = 0; 1592f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float x2 = 0; 1602f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float y = 0; 1612f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float xy = 0; 1622f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float xAvg = 0; 1632f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float denom = 0; 1642f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org float skew = 0; 1652f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 1662f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org *skewEst = 0; // Set in case of error below. 1672f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org for (i = 0; i < size; i++) { 1682f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) { 1692f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org n++; 1702f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org rawAvg += rawSkew[i]; 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1722f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 1732f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 1742f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if (n == 0) { 1752f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return -1; 1762f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 1772f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(n > 0); 1782f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org rawAvg /= n; 1792f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 1802f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org for (i = 0; i < size; i++) { 1812f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) { 1822f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org err = rawSkew[i] - rawAvg; 1832f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org rawAbsDev += err >= 0 ? err : -err; 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1852f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 1862f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(n > 0); 1872f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org rawAbsDev /= n; 1882f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org upperLimit = (int)(rawAvg + 5 * rawAbsDev + 1); // +1 for ceiling. 1892f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org lowerLimit = (int)(rawAvg - 5 * rawAbsDev - 1); // -1 for floor. 1902f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org 1912f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org n = 0; 1922f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org for (i = 0; i < size; i++) { 1932f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if ((rawSkew[i] < absLimitInner && rawSkew[i] > -absLimitInner) || 1942f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org (rawSkew[i] < upperLimit && rawSkew[i] > lowerLimit)) { 1952f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org n++; 1962f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org cumSum += rawSkew[i]; 1972f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org x += n; 1982f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org x2 += n * n; 1992f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org y += cumSum; 2002f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org xy += n * cumSum; 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 2022f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2042f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if (n == 0) { 2052f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return -1; 2062f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 2072f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org assert(n > 0); 2082f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org xAvg = x / n; 2092f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org denom = x2 - xAvg * x; 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2112f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org if (denom != 0) { 2122f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org skew = (xy - xAvg * y) / denom; 2132f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org } 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2152f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org *skewEst = skew; 2162f40af3ae55077b771fe301e19750984348d3eafandrew@webrtc.org return 0; 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 218