LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_processing/aec - aec_resampler.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 106 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13