| Index: webrtc/modules/audio_processing/aec/aec_core.c
 | 
| diff --git a/webrtc/modules/audio_processing/aec/aec_core.c b/webrtc/modules/audio_processing/aec/aec_core.c
 | 
| index b1b2448da5fdc06347e26c9b489cba3ec70c7c2f..468532644b6cca720c826a21fd0e39c2da42ca19 100644
 | 
| --- a/webrtc/modules/audio_processing/aec/aec_core.c
 | 
| +++ b/webrtc/modules/audio_processing/aec/aec_core.c
 | 
| @@ -44,7 +44,6 @@ static const int countLen = 50;
 | 
|  static const int kDelayMetricsAggregationWindow = 1250;  // 5 seconds at 16 kHz.
 | 
|  
 | 
|  // Quantities to control H band scaling for SWB input
 | 
| -static const int flagHbandCn = 1;  // flag for adding comfort noise in H band
 | 
|  static const float cnScaleHband =
 | 
|      (float)0.4;  // scale for comfort noise in H band
 | 
|  // Initial bin for averaging nlp gain in low band
 | 
| @@ -483,7 +482,7 @@ static void ComfortNoise(AecCore* aec,
 | 
|    noiseAvg = 0.0;
 | 
|    tmpAvg = 0.0;
 | 
|    num = 0;
 | 
| -  if (aec->num_bands > 1 && flagHbandCn == 1) {
 | 
| +  if (aec->num_bands > 1) {
 | 
|  
 | 
|      // average noise scale
 | 
|      // average over second half of freq spectrum (i.e., 4->8khz)
 | 
| @@ -814,15 +813,18 @@ static void UpdateDelayMetrics(AecCore* self) {
 | 
|    return;
 | 
|  }
 | 
|  
 | 
| -static void InverseFft(float freq_data[2][PART_LEN1],
 | 
| -                       float time_data[PART_LEN2]) {
 | 
| +static void ScaledInverseFft(float freq_data[2][PART_LEN1],
 | 
| +                             float time_data[PART_LEN2],
 | 
| +                             float scale,
 | 
| +                             int conjugate) {
 | 
|    int i;
 | 
| -  const float scale = 1.0f / PART_LEN2;
 | 
| -  time_data[0] = freq_data[0][0] * scale;
 | 
| -  time_data[1] = freq_data[0][PART_LEN] * scale;
 | 
| +  const float normalization = scale / ((float)PART_LEN2);
 | 
| +  const float sign = (conjugate ? -1 : 1);
 | 
| +  time_data[0] = freq_data[0][0] * normalization;
 | 
| +  time_data[1] = freq_data[0][PART_LEN] * normalization;
 | 
|    for (i = 1; i < PART_LEN; i++) {
 | 
| -    time_data[2 * i] = freq_data[0][i] * scale;
 | 
| -    time_data[2 * i + 1] = freq_data[1][i] * scale;
 | 
| +    time_data[2 * i] = freq_data[0][i] * normalization;
 | 
| +    time_data[2 * i + 1] = sign * freq_data[1][i] * normalization;
 | 
|    }
 | 
|    aec_rdft_inverse_128(time_data);
 | 
|  }
 | 
| @@ -963,11 +965,8 @@ static void EchoSubtraction(
 | 
|                        s_fft);
 | 
|  
 | 
|    // Compute the time-domain echo estimate s.
 | 
| -  InverseFft(s_fft, s_extended);
 | 
| +  ScaledInverseFft(s_fft, s_extended, 2.0f, 0);
 | 
|    s = &s_extended[PART_LEN];
 | 
| -  for (i = 0; i < PART_LEN; ++i) {
 | 
| -    s[i] *= 2.0f;
 | 
| -  }
 | 
|  
 | 
|    // Compute the time-domain echo prediction error.
 | 
|    for (i = 0; i < PART_LEN; ++i) {
 | 
| @@ -1014,7 +1013,6 @@ static void EchoSuppression(AecCore* aec,
 | 
|    float dfw[2][PART_LEN1];
 | 
|    float comfortNoiseHband[2][PART_LEN1];
 | 
|    float fft[PART_LEN2];
 | 
| -  float scale, dtmp;
 | 
|    float nlpGainHband;
 | 
|    int i;
 | 
|    size_t j;
 | 
| @@ -1054,11 +1052,6 @@ static void EchoSuppression(AecCore* aec,
 | 
|    aec_rdft_forward_128(fft);
 | 
|    StoreAsComplex(fft, efw);
 | 
|  
 | 
| -  aec->delayEstCtr++;
 | 
| -  if (aec->delayEstCtr == delayEstInterval) {
 | 
| -    aec->delayEstCtr = 0;
 | 
| -  }
 | 
| -
 | 
|    // We should always have at least one element stored in |far_buf|.
 | 
|    assert(WebRtc_available_read(aec->far_buf_windowed) > 0);
 | 
|    // NLP
 | 
| @@ -1069,8 +1062,11 @@ static void EchoSuppression(AecCore* aec,
 | 
|    // Buffer far.
 | 
|    memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1);
 | 
|  
 | 
| -  if (aec->delayEstCtr == 0)
 | 
| +  aec->delayEstCtr++;
 | 
| +  if (aec->delayEstCtr == delayEstInterval) {
 | 
| +    aec->delayEstCtr = 0;
 | 
|      aec->delayIdx = WebRtcAec_PartitionDelay(aec);
 | 
| +  }
 | 
|  
 | 
|    // Use delayed far.
 | 
|    memcpy(xfw,
 | 
| @@ -1190,67 +1186,51 @@ static void EchoSuppression(AecCore* aec,
 | 
|      // scaling only in UpdateMetrics().
 | 
|      UpdateLevel(&aec->nlpoutlevel, efw);
 | 
|    }
 | 
| +
 | 
|    // Inverse error fft.
 | 
| -  fft[0] = efw[0][0];
 | 
| -  fft[1] = efw[0][PART_LEN];
 | 
| -  for (i = 1; i < PART_LEN; i++) {
 | 
| -    fft[2 * i] = efw[0][i];
 | 
| -    // Sign change required by Ooura fft.
 | 
| -    fft[2 * i + 1] = -efw[1][i];
 | 
| -  }
 | 
| -  aec_rdft_inverse_128(fft);
 | 
| +  ScaledInverseFft(efw, fft, 2.0f, 1);
 | 
|  
 | 
|    // Overlap and add to obtain output.
 | 
| -  scale = 2.0f / PART_LEN2;
 | 
|    for (i = 0; i < PART_LEN; i++) {
 | 
| -    fft[i] *= scale;  // fft scaling
 | 
| -    fft[i] = fft[i] * WebRtcAec_sqrtHanning[i] + aec->outBuf[i];
 | 
| -
 | 
| -    fft[PART_LEN + i] *= scale;  // fft scaling
 | 
| -    aec->outBuf[i] = fft[PART_LEN + i] * WebRtcAec_sqrtHanning[PART_LEN - i];
 | 
| +    output[i] = (fft[i] * WebRtcAec_sqrtHanning[i] +
 | 
| +                 aec->outBuf[i] * WebRtcAec_sqrtHanning[PART_LEN - i]);
 | 
|  
 | 
|      // Saturate output to keep it in the allowed range.
 | 
|      output[i] = WEBRTC_SPL_SAT(
 | 
| -        WEBRTC_SPL_WORD16_MAX, fft[i], WEBRTC_SPL_WORD16_MIN);
 | 
| +        WEBRTC_SPL_WORD16_MAX, output[i], WEBRTC_SPL_WORD16_MIN);
 | 
|    }
 | 
| +  memcpy(aec->outBuf, &fft[PART_LEN], PART_LEN * sizeof(aec->outBuf[0]));
 | 
|  
 | 
|    // For H band
 | 
|    if (aec->num_bands > 1) {
 | 
| -
 | 
|      // H band gain
 | 
|      // average nlp over low band: average over second half of freq spectrum
 | 
|      // (4->8khz)
 | 
|      GetHighbandGain(hNl, &nlpGainHband);
 | 
|  
 | 
|      // Inverse comfort_noise
 | 
| -    if (flagHbandCn == 1) {
 | 
| -      fft[0] = comfortNoiseHband[0][0];
 | 
| -      fft[1] = comfortNoiseHband[0][PART_LEN];
 | 
| -      for (i = 1; i < PART_LEN; i++) {
 | 
| -        fft[2 * i] = comfortNoiseHband[0][i];
 | 
| -        fft[2 * i + 1] = comfortNoiseHband[1][i];
 | 
| -      }
 | 
| -      aec_rdft_inverse_128(fft);
 | 
| -      scale = 2.0f / PART_LEN2;
 | 
| -    }
 | 
| +    ScaledInverseFft(comfortNoiseHband, fft, 2.0f, 0);
 | 
|  
 | 
|      // compute gain factor
 | 
|      for (j = 0; j < aec->num_bands - 1; ++j) {
 | 
|        for (i = 0; i < PART_LEN; i++) {
 | 
| -        dtmp = aec->dBufH[j][i];
 | 
| -        dtmp = dtmp * nlpGainHband;  // for variable gain
 | 
| +        outputH[j][i] = aec->dBufH[j][i] * nlpGainHband;
 | 
| +      }
 | 
| +    }
 | 
|  
 | 
| -        // add some comfort noise where Hband is attenuated
 | 
| -        if (flagHbandCn == 1 && j == 0) {
 | 
| -          fft[i] *= scale;  // fft scaling
 | 
| -          dtmp += cnScaleHband * fft[i];
 | 
| -        }
 | 
| +    // Add some comfort noise where Hband is attenuated.
 | 
| +    for (i = 0; i < PART_LEN; i++) {
 | 
| +      outputH[0][i] += cnScaleHband * fft[i];
 | 
| +    }
 | 
|  
 | 
| -        // Saturate output to keep it in the allowed range.
 | 
| +    // Saturate output to keep it in the allowed range.
 | 
| +    for (j = 0; j < aec->num_bands - 1; ++j) {
 | 
| +      for (i = 0; i < PART_LEN; i++) {
 | 
|          outputH[j][i] = WEBRTC_SPL_SAT(
 | 
| -            WEBRTC_SPL_WORD16_MAX, dtmp, WEBRTC_SPL_WORD16_MIN);
 | 
| +            WEBRTC_SPL_WORD16_MAX, outputH[j][i], WEBRTC_SPL_WORD16_MIN);
 | 
|        }
 | 
|      }
 | 
| +
 | 
|    }
 | 
|  
 | 
|    // Copy the current block to the old position.
 | 
| 
 |