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