Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_processing / ns / ns_core.c
index 285e404..e026c29 100644 (file)
@@ -8,6 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <assert.h>
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
 #include "webrtc/modules/audio_processing/ns/windows_private.h"
 #include "webrtc/modules/audio_processing/utility/fft4g.h"
 
-// Set Feature Extraction Parameters
-void WebRtcNs_set_feature_extraction_parameters(NSinst_t* inst) {
-  // bin size of histogram
-  inst->featureExtractionParams.binSizeLrt = (float)0.1;
-  inst->featureExtractionParams.binSizeSpecFlat = (float)0.05;
-  inst->featureExtractionParams.binSizeSpecDiff = (float)0.1;
-
-  // range of histogram over which lrt threshold is computed
-  inst->featureExtractionParams.rangeAvgHistLrt = (float)1.0;
-
-  // scale parameters: multiply dominant peaks of the histograms by scale factor
-  // to obtain thresholds for prior model
-  inst->featureExtractionParams.factor1ModelPars =
-      (float)1.20;  // for lrt and spectral diff
-  inst->featureExtractionParams.factor2ModelPars =
-      (float)0.9;  // for spectral_flatness:
-  // used when noise is flatter than speech
-
-  // peak limit for spectral flatness (varies between 0 and 1)
-  inst->featureExtractionParams.thresPosSpecFlat = (float)0.6;
-
-  // limit on spacing of two highest peaks in histogram: spacing determined by
-  // bin size
-  inst->featureExtractionParams.limitPeakSpacingSpecFlat =
-      2 * inst->featureExtractionParams.binSizeSpecFlat;
-  inst->featureExtractionParams.limitPeakSpacingSpecDiff =
-      2 * inst->featureExtractionParams.binSizeSpecDiff;
-
-  // limit on relevance of second peak:
-  inst->featureExtractionParams.limitPeakWeightsSpecFlat = (float)0.5;
-  inst->featureExtractionParams.limitPeakWeightsSpecDiff = (float)0.5;
-
-  // fluctuation limit of lrt feature
-  inst->featureExtractionParams.thresFluctLrt = (float)0.05;
-
-  // limit on the max and min values for the feature thresholds
-  inst->featureExtractionParams.maxLrt = (float)1.0;
-  inst->featureExtractionParams.minLrt = (float)0.20;
-
-  inst->featureExtractionParams.maxSpecFlat = (float)0.95;
-  inst->featureExtractionParams.minSpecFlat = (float)0.10;
-
-  inst->featureExtractionParams.maxSpecDiff = (float)1.0;
-  inst->featureExtractionParams.minSpecDiff = (float)0.16;
-
-  // criteria of weight of histogram peak  to accept/reject feature
-  inst->featureExtractionParams.thresWeightSpecFlat =
-      (int)(0.3 * (inst->modelUpdatePars[1]));  // for spectral flatness
-  inst->featureExtractionParams.thresWeightSpecDiff =
-      (int)(0.3 * (inst->modelUpdatePars[1]));  // for spectral difference
+// Set Feature Extraction Parameters.
+static void set_feature_extraction_parameters(NSinst_t* self) {
+  // Bin size of histogram.
+  self->featureExtractionParams.binSizeLrt = 0.1f;
+  self->featureExtractionParams.binSizeSpecFlat = 0.05f;
+  self->featureExtractionParams.binSizeSpecDiff = 0.1f;
+
+  // Range of histogram over which LRT threshold is computed.
+  self->featureExtractionParams.rangeAvgHistLrt = 1.f;
+
+  // Scale parameters: multiply dominant peaks of the histograms by scale factor
+  // to obtain thresholds for prior model.
+  // For LRT and spectral difference.
+  self->featureExtractionParams.factor1ModelPars = 1.2f;
+  // For spectral_flatness: used when noise is flatter than speech.
+  self->featureExtractionParams.factor2ModelPars = 0.9f;
+
+  // Peak limit for spectral flatness (varies between 0 and 1).
+  self->featureExtractionParams.thresPosSpecFlat = 0.6f;
+
+  // Limit on spacing of two highest peaks in histogram: spacing determined by
+  // bin size.
+  self->featureExtractionParams.limitPeakSpacingSpecFlat =
+      2 * self->featureExtractionParams.binSizeSpecFlat;
+  self->featureExtractionParams.limitPeakSpacingSpecDiff =
+      2 * self->featureExtractionParams.binSizeSpecDiff;
+
+  // Limit on relevance of second peak.
+  self->featureExtractionParams.limitPeakWeightsSpecFlat = 0.5f;
+  self->featureExtractionParams.limitPeakWeightsSpecDiff = 0.5f;
+
+  // Fluctuation limit of LRT feature.
+  self->featureExtractionParams.thresFluctLrt = 0.05f;
+
+  // Limit on the max and min values for the feature thresholds.
+  self->featureExtractionParams.maxLrt = 1.f;
+  self->featureExtractionParams.minLrt = 0.2f;
+
+  self->featureExtractionParams.maxSpecFlat = 0.95f;
+  self->featureExtractionParams.minSpecFlat = 0.1f;
+
+  self->featureExtractionParams.maxSpecDiff = 1.f;
+  self->featureExtractionParams.minSpecDiff = 0.16f;
+
+  // Criteria of weight of histogram peak to accept/reject feature.
+  self->featureExtractionParams.thresWeightSpecFlat =
+      (int)(0.3 * (self->modelUpdatePars[1]));  // For spectral flatness.
+  self->featureExtractionParams.thresWeightSpecDiff =
+      (int)(0.3 * (self->modelUpdatePars[1]));  // For spectral difference.
 }
 
-// Initialize state
-int WebRtcNs_InitCore(NSinst_t* inst, uint32_t fs) {
+// Initialize state.
+int WebRtcNs_InitCore(NSinst_t* self, uint32_t fs) {
   int i;
-  // We only support 10ms frames
-
-  // check for valid pointer
-  if (inst == NULL) {
+  // Check for valid pointer.
+  if (self == NULL) {
     return -1;
   }
 
-  // Initialization of struct
+  // Initialization of struct.
   if (fs == 8000 || fs == 16000 || fs == 32000) {
-    inst->fs = fs;
+    self->fs = fs;
   } else {
     return -1;
   }
-  inst->windShift = 0;
+  self->windShift = 0;
   if (fs == 8000) {
-    // We only support 10ms frames
-    inst->blockLen = 80;
-    inst->blockLen10ms = 80;
-    inst->anaLen = 128;
-    inst->window = kBlocks80w128;
-    inst->outLen = 0;
+    // We only support 10ms frames.
+    self->blockLen = 80;
+    self->anaLen = 128;
+    self->window = kBlocks80w128;
   } else if (fs == 16000) {
-    // We only support 10ms frames
-    inst->blockLen = 160;
-    inst->blockLen10ms = 160;
-    inst->anaLen = 256;
-    inst->window = kBlocks160w256;
-    inst->outLen = 0;
+    // We only support 10ms frames.
+    self->blockLen = 160;
+    self->anaLen = 256;
+    self->window = kBlocks160w256;
   } else if (fs == 32000) {
-    // We only support 10ms frames
-    inst->blockLen = 160;
-    inst->blockLen10ms = 160;
-    inst->anaLen = 256;
-    inst->window = kBlocks160w256;
-    inst->outLen = 0;
+    // We only support 10ms frames.
+    self->blockLen = 160;
+    self->anaLen = 256;
+    self->window = kBlocks160w256;
   }
-  inst->magnLen = inst->anaLen / 2 + 1;  // Number of frequency bins
+  self->magnLen = self->anaLen / 2 + 1;  // Number of frequency bins.
 
-  // Initialize fft work arrays.
-  inst->ip[0] = 0;  // Setting this triggers initialization.
-  memset(inst->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
-  WebRtc_rdft(inst->anaLen, 1, inst->dataBuf, inst->ip, inst->wfft);
+  // Initialize FFT work arrays.
+  self->ip[0] = 0;  // Setting this triggers initialization.
+  memset(self->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
+  WebRtc_rdft(self->anaLen, 1, self->dataBuf, self->ip, self->wfft);
 
-  memset(inst->analyzeBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
-  memset(inst->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
-  memset(inst->syntBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
+  memset(self->analyzeBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
+  memset(self->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
+  memset(self->syntBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX);
 
-  // for HB processing
-  memset(inst->dataBufHB, 0, sizeof(float) * ANAL_BLOCKL_MAX);
+  // For HB processing.
+  memset(self->dataBufHB, 0, sizeof(float) * ANAL_BLOCKL_MAX);
 
-  // for quantile noise estimation
-  memset(inst->quantile, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // For quantile noise estimation.
+  memset(self->quantile, 0, sizeof(float) * HALF_ANAL_BLOCKL);
   for (i = 0; i < SIMULT * HALF_ANAL_BLOCKL; i++) {
-    inst->lquantile[i] = (float)8.0;
-    inst->density[i] = (float)0.3;
+    self->lquantile[i] = 8.f;
+    self->density[i] = 0.3f;
   }
 
   for (i = 0; i < SIMULT; i++) {
-    inst->counter[i] =
+    self->counter[i] =
         (int)floor((float)(END_STARTUP_LONG * (i + 1)) / (float)SIMULT);
   }
 
-  inst->updates = 0;
+  self->updates = 0;
 
-  // Wiener filter initialization
+  // Wiener filter initialization.
   for (i = 0; i < HALF_ANAL_BLOCKL; i++) {
-    inst->smooth[i] = (float)1.0;
+    self->smooth[i] = 1.f;
   }
 
-  // Set the aggressiveness: default
-  inst->aggrMode = 0;
-
-  // initialize variables for new method
-  inst->priorSpeechProb = (float)0.5;  // prior prob for speech/noise
+  // Set the aggressiveness: default.
+  self->aggrMode = 0;
+
+  // Initialize variables for new method.
+  self->priorSpeechProb = 0.5f;  // Prior prob for speech/noise.
+  // Previous analyze mag spectrum.
+  memset(self->magnPrevAnalyze, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // Previous process mag spectrum.
+  memset(self->magnPrevProcess, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // Current noise-spectrum.
+  memset(self->noise, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // Previous noise-spectrum.
+  memset(self->noisePrev, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // Conservative noise spectrum estimate.
+  memset(self->magnAvgPause, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // For estimation of HB in second pass.
+  memset(self->speechProb, 0, sizeof(float) * HALF_ANAL_BLOCKL);
+  // Initial average magnitude spectrum.
+  memset(self->initMagnEst, 0, sizeof(float) * HALF_ANAL_BLOCKL);
   for (i = 0; i < HALF_ANAL_BLOCKL; i++) {
-    inst->magnPrev[i] = (float)0.0;  // previous mag spectrum
-    inst->noisePrev[i] = (float)0.0;  // previous noise-spectrum
-    inst->logLrtTimeAvg[i] =
-        LRT_FEATURE_THR;  // smooth LR ratio (same as threshold)
-    inst->magnAvgPause[i] = (float)0.0;  // conservative noise spectrum estimate
-    inst->speechProb[i] = (float)0.0;  // for estimation of HB in second pass
-    inst->initMagnEst[i] = (float)0.0;  // initial average mag spectrum
-  }
-
-  // feature quantities
-  inst->featureData[0] =
-      SF_FEATURE_THR;  // spectral flatness (start on threshold)
-  inst->featureData[1] =
-      (float)0.0;  // spectral entropy: not used in this version
-  inst->featureData[2] =
-      (float)0.0;  // spectral variance: not used in this version
-  inst->featureData[3] =
-      LRT_FEATURE_THR;  // average lrt factor (start on threshold)
-  inst->featureData[4] =
-      SF_FEATURE_THR;  // spectral template diff (start on threshold)
-  inst->featureData[5] = (float)0.0;  // normalization for spectral-diff
-  inst->featureData[6] =
-      (float)0.0;  // window time-average of input magnitude spectrum
-
-  // histogram quantities: used to estimate/update thresholds for features
-  for (i = 0; i < HIST_PAR_EST; i++) {
-    inst->histLrt[i] = 0;
-    inst->histSpecFlat[i] = 0;
-    inst->histSpecDiff[i] = 0;
-  }
-
-  inst->blockInd = -1;  // frame counter
-  inst->priorModelPars[0] =
-      LRT_FEATURE_THR;                   // default threshold for lrt feature
-  inst->priorModelPars[1] = (float)0.5;  // threshold for spectral flatness:
-  // determined on-line
-  inst->priorModelPars[2] = (float)1.0;  // sgn_map par for spectral measure:
-  // 1 for flatness measure
-  inst->priorModelPars[3] =
-      (float)0.5;  // threshold for template-difference feature:
-  // determined on-line
-  inst->priorModelPars[4] =
-      (float)1.0;  // default weighting parameter for lrt feature
-  inst->priorModelPars[5] = (float)0.0;  // default weighting parameter for
-  // spectral flatness feature
-  inst->priorModelPars[6] = (float)0.0;  // default weighting parameter for
-  // spectral difference feature
-
-  inst->modelUpdatePars[0] = 2;  // update flag for parameters:
-  // 0 no update, 1=update once, 2=update every window
-  inst->modelUpdatePars[1] = 500;  // window for update
-  inst->modelUpdatePars[2] =
-      0;  // counter for update of conservative noise spectrum
-  // counter if the feature thresholds are updated during the sequence
-  inst->modelUpdatePars[3] = inst->modelUpdatePars[1];
-
-  inst->signalEnergy = 0.0;
-  inst->sumMagn = 0.0;
-  inst->whiteNoiseLevel = 0.0;
-  inst->pinkNoiseNumerator = 0.0;
-  inst->pinkNoiseExp = 0.0;
-
-  WebRtcNs_set_feature_extraction_parameters(inst);
-
-  // default mode
-  WebRtcNs_set_policy_core(inst, 0);
-
-  memset(inst->outBuf, 0, sizeof(float) * 3 * BLOCKL_MAX);
-
-  inst->initFlag = 1;
-  return 0;
-}
-
-int WebRtcNs_set_policy_core(NSinst_t* inst, int mode) {
-  // allow for modes:0,1,2,3
-  if (mode < 0 || mode > 3) {
-    return (-1);
+    // Smooth LR (same as threshold).
+    self->logLrtTimeAvg[i] = LRT_FEATURE_THR;
   }
 
-  inst->aggrMode = mode;
-  if (mode == 0) {
-    inst->overdrive = (float)1.0;
-    inst->denoiseBound = (float)0.5;
-    inst->gainmap = 0;
-  } else if (mode == 1) {
-    // inst->overdrive = (float)1.25;
-    inst->overdrive = (float)1.0;
-    inst->denoiseBound = (float)0.25;
-    inst->gainmap = 1;
-  } else if (mode == 2) {
-    // inst->overdrive = (float)1.25;
-    inst->overdrive = (float)1.1;
-    inst->denoiseBound = (float)0.125;
-    inst->gainmap = 1;
-  } else if (mode == 3) {
-    // inst->overdrive = (float)1.30;
-    inst->overdrive = (float)1.25;
-    inst->denoiseBound = (float)0.09;
-    inst->gainmap = 1;
-  }
+  // Feature quantities.
+  // Spectral flatness (start on threshold).
+  self->featureData[0] = SF_FEATURE_THR;
+  self->featureData[1] = 0.f;  // Spectral entropy: not used in this version.
+  self->featureData[2] = 0.f;  // Spectral variance: not used in this version.
+  // Average LRT factor (start on threshold).
+  self->featureData[3] = LRT_FEATURE_THR;
+  // Spectral template diff (start on threshold).
+  self->featureData[4] = SF_FEATURE_THR;
+  self->featureData[5] = 0.f;  // Normalization for spectral difference.
+  // Window time-average of input magnitude spectrum.
+  self->featureData[6] = 0.f;
+
+  // Histogram quantities: used to estimate/update thresholds for features.
+  memset(self->histLrt, 0, sizeof(int) * HIST_PAR_EST);
+  memset(self->histSpecFlat, 0, sizeof(int) * HIST_PAR_EST);
+  memset(self->histSpecDiff, 0, sizeof(int) * HIST_PAR_EST);
+
+
+  self->blockInd = -1;  // Frame counter.
+  // Default threshold for LRT feature.
+  self->priorModelPars[0] = LRT_FEATURE_THR;
+  // Threshold for spectral flatness: determined on-line.
+  self->priorModelPars[1] = 0.5f;
+  // sgn_map par for spectral measure: 1 for flatness measure.
+  self->priorModelPars[2] = 1.f;
+  // Threshold for template-difference feature: determined on-line.
+  self->priorModelPars[3] = 0.5f;
+  // Default weighting parameter for LRT feature.
+  self->priorModelPars[4] = 1.f;
+  // Default weighting parameter for spectral flatness feature.
+  self->priorModelPars[5] = 0.f;
+  // Default weighting parameter for spectral difference feature.
+  self->priorModelPars[6] = 0.f;
+
+  // Update flag for parameters:
+  // 0 no update, 1 = update once, 2 = update every window.
+  self->modelUpdatePars[0] = 2;
+  self->modelUpdatePars[1] = 500;  // Window for update.
+  // Counter for update of conservative noise spectrum.
+  self->modelUpdatePars[2] = 0;
+  // Counter if the feature thresholds are updated during the sequence.
+  self->modelUpdatePars[3] = self->modelUpdatePars[1];
+
+  self->signalEnergy = 0.0;
+  self->sumMagn = 0.0;
+  self->whiteNoiseLevel = 0.0;
+  self->pinkNoiseNumerator = 0.0;
+  self->pinkNoiseExp = 0.0;
+
+  set_feature_extraction_parameters(self);
+
+  // Default mode.
+  WebRtcNs_set_policy_core(self, 0);
+
+  self->initFlag = 1;
   return 0;
 }
 
-// Estimate noise
-void WebRtcNs_NoiseEstimation(NSinst_t* inst, float* magn, float* noise) {
+// Estimate noise.
+static void NoiseEstimation(NSinst_t* self, float* magn, float* noise) {
   int i, s, offset;
   float lmagn[HALF_ANAL_BLOCKL], delta;
 
-  if (inst->updates < END_STARTUP_LONG) {
-    inst->updates++;
+  if (self->updates < END_STARTUP_LONG) {
+    self->updates++;
   }
 
-  for (i = 0; i < inst->magnLen; i++) {
+  for (i = 0; i < self->magnLen; i++) {
     lmagn[i] = (float)log(magn[i]);
   }
 
-  // loop over simultaneous estimates
+  // Loop over simultaneous estimates.
   for (s = 0; s < SIMULT; s++) {
-    offset = s * inst->magnLen;
+    offset = s * self->magnLen;
 
     // newquantest(...)
-    for (i = 0; i < inst->magnLen; i++) {
-      // compute delta
-      if (inst->density[offset + i] > 1.0) {
-        delta = FACTOR * (float)1.0 / inst->density[offset + i];
+    for (i = 0; i < self->magnLen; i++) {
+      // Compute delta.
+      if (self->density[offset + i] > 1.0) {
+        delta = FACTOR * 1.f / self->density[offset + i];
       } else {
         delta = FACTOR;
       }
 
-      // update log quantile estimate
-      if (lmagn[i] > inst->lquantile[offset + i]) {
-        inst->lquantile[offset + i] +=
-            QUANTILE * delta / (float)(inst->counter[s] + 1);
+      // Update log quantile estimate.
+      if (lmagn[i] > self->lquantile[offset + i]) {
+        self->lquantile[offset + i] +=
+            QUANTILE * delta / (float)(self->counter[s] + 1);
       } else {
-        inst->lquantile[offset + i] -=
-            ((float)1.0 - QUANTILE) * delta / (float)(inst->counter[s] + 1);
+        self->lquantile[offset + i] -=
+            (1.f - QUANTILE) * delta / (float)(self->counter[s] + 1);
       }
 
-      // update density estimate
-      if (fabs(lmagn[i] - inst->lquantile[offset + i]) < WIDTH) {
-        inst->density[offset + i] =
-            ((float)inst->counter[s] * inst->density[offset + i] +
-             (float)1.0 / ((float)2.0 * WIDTH)) /
-            (float)(inst->counter[s] + 1);
+      // Update density estimate.
+      if (fabs(lmagn[i] - self->lquantile[offset + i]) < WIDTH) {
+        self->density[offset + i] =
+            ((float)self->counter[s] * self->density[offset + i] +
+             1.f / (2.f * WIDTH)) /
+            (float)(self->counter[s] + 1);
       }
-    }  // end loop over magnitude spectrum
+    }  // End loop over magnitude spectrum.
 
-    if (inst->counter[s] >= END_STARTUP_LONG) {
-      inst->counter[s] = 0;
-      if (inst->updates >= END_STARTUP_LONG) {
-        for (i = 0; i < inst->magnLen; i++) {
-          inst->quantile[i] = (float)exp(inst->lquantile[offset + i]);
+    if (self->counter[s] >= END_STARTUP_LONG) {
+      self->counter[s] = 0;
+      if (self->updates >= END_STARTUP_LONG) {
+        for (i = 0; i < self->magnLen; i++) {
+          self->quantile[i] = (float)exp(self->lquantile[offset + i]);
         }
       }
     }
 
-    inst->counter[s]++;
-  }  // end loop over simultaneous estimates
+    self->counter[s]++;
+  }  // End loop over simultaneous estimates.
 
-  // Sequentially update the noise during startup
-  if (inst->updates < END_STARTUP_LONG) {
+  // Sequentially update the noise during startup.
+  if (self->updates < END_STARTUP_LONG) {
     // Use the last "s" to get noise during startup that differ from zero.
-    for (i = 0; i < inst->magnLen; i++) {
-      inst->quantile[i] = (float)exp(inst->lquantile[offset + i]);
+    for (i = 0; i < self->magnLen; i++) {
+      self->quantile[i] = (float)exp(self->lquantile[offset + i]);
     }
   }
 
-  for (i = 0; i < inst->magnLen; i++) {
-    noise[i] = inst->quantile[i];
+  for (i = 0; i < self->magnLen; i++) {
+    noise[i] = self->quantile[i];
   }
 }
 
-// Extract thresholds for feature parameters
-// histograms are computed over some window_size (given by
-// inst->modelUpdatePars[1])
-// thresholds and weights are extracted every window
-// flag 0 means update histogram only, flag 1 means compute the
-// thresholds/weights
-// threshold and weights are returned in: inst->priorModelPars
-void WebRtcNs_FeatureParameterExtraction(NSinst_t* inst, int flag) {
+// Extract thresholds for feature parameters.
+// Histograms are computed over some window size (given by
+// self->modelUpdatePars[1]).
+// Thresholds and weights are extracted every window.
+// |flag| = 0 updates histogram only, |flag| = 1 computes the threshold/weights.
+// Threshold and weights are returned in: self->priorModelPars.
+static void FeatureParameterExtraction(NSinst_t* self, int flag) {
   int i, useFeatureSpecFlat, useFeatureSpecDiff, numHistLrt;
   int maxPeak1, maxPeak2;
   int weightPeak1SpecFlat, weightPeak2SpecFlat, weightPeak1SpecDiff,
@@ -337,82 +302,81 @@ void WebRtcNs_FeatureParameterExtraction(NSinst_t* inst, int flag) {
   float posPeak1SpecFlat, posPeak2SpecFlat, posPeak1SpecDiff, posPeak2SpecDiff;
   float fluctLrt, avgHistLrt, avgSquareHistLrt, avgHistLrtCompl;
 
-  // 3 features: lrt, flatness, difference
-  // lrt_feature = inst->featureData[3];
-  // flat_feature = inst->featureData[0];
-  // diff_feature = inst->featureData[4];
+  // 3 features: LRT, flatness, difference.
+  // lrt_feature = self->featureData[3];
+  // flat_feature = self->featureData[0];
+  // diff_feature = self->featureData[4];
 
-  // update histograms
+  // Update histograms.
   if (flag == 0) {
     // LRT
-    if ((inst->featureData[3] <
-         HIST_PAR_EST * inst->featureExtractionParams.binSizeLrt) &&
-        (inst->featureData[3] >= 0.0)) {
-      i = (int)(inst->featureData[3] /
-                inst->featureExtractionParams.binSizeLrt);
-      inst->histLrt[i]++;
+    if ((self->featureData[3] <
+         HIST_PAR_EST * self->featureExtractionParams.binSizeLrt) &&
+        (self->featureData[3] >= 0.0)) {
+      i = (int)(self->featureData[3] /
+                self->featureExtractionParams.binSizeLrt);
+      self->histLrt[i]++;
     }
-    // Spectral flatness
-    if ((inst->featureData[0] <
-         HIST_PAR_EST * inst->featureExtractionParams.binSizeSpecFlat) &&
-        (inst->featureData[0] >= 0.0)) {
-      i = (int)(inst->featureData[0] /
-                inst->featureExtractionParams.binSizeSpecFlat);
-      inst->histSpecFlat[i]++;
+    // Spectral flatness.
+    if ((self->featureData[0] <
+         HIST_PAR_EST * self->featureExtractionParams.binSizeSpecFlat) &&
+        (self->featureData[0] >= 0.0)) {
+      i = (int)(self->featureData[0] /
+                self->featureExtractionParams.binSizeSpecFlat);
+      self->histSpecFlat[i]++;
     }
-    // Spectral difference
-    if ((inst->featureData[4] <
-         HIST_PAR_EST * inst->featureExtractionParams.binSizeSpecDiff) &&
-        (inst->featureData[4] >= 0.0)) {
-      i = (int)(inst->featureData[4] /
-                inst->featureExtractionParams.binSizeSpecDiff);
-      inst->histSpecDiff[i]++;
+    // Spectral difference.
+    if ((self->featureData[4] <
+         HIST_PAR_EST * self->featureExtractionParams.binSizeSpecDiff) &&
+        (self->featureData[4] >= 0.0)) {
+      i = (int)(self->featureData[4] /
+                self->featureExtractionParams.binSizeSpecDiff);
+      self->histSpecDiff[i]++;
     }
   }
 
-  // extract parameters for speech/noise probability
+  // Extract parameters for speech/noise probability.
   if (flag == 1) {
-    // lrt feature: compute the average over
-    // inst->featureExtractionParams.rangeAvgHistLrt
+    // LRT feature: compute the average over
+    // self->featureExtractionParams.rangeAvgHistLrt.
     avgHistLrt = 0.0;
     avgHistLrtCompl = 0.0;
     avgSquareHistLrt = 0.0;
     numHistLrt = 0;
     for (i = 0; i < HIST_PAR_EST; i++) {
-      binMid =
-          ((float)i + (float)0.5) * inst->featureExtractionParams.binSizeLrt;
-      if (binMid <= inst->featureExtractionParams.rangeAvgHistLrt) {
-        avgHistLrt += inst->histLrt[i] * binMid;
-        numHistLrt += inst->histLrt[i];
+      binMid = ((float)i + 0.5f) * self->featureExtractionParams.binSizeLrt;
+      if (binMid <= self->featureExtractionParams.rangeAvgHistLrt) {
+        avgHistLrt += self->histLrt[i] * binMid;
+        numHistLrt += self->histLrt[i];
       }
-      avgSquareHistLrt += inst->histLrt[i] * binMid * binMid;
-      avgHistLrtCompl += inst->histLrt[i] * binMid;
+      avgSquareHistLrt += self->histLrt[i] * binMid * binMid;
+      avgHistLrtCompl += self->histLrt[i] * binMid;
     }
     if (numHistLrt > 0) {
       avgHistLrt = avgHistLrt / ((float)numHistLrt);
     }
-    avgHistLrtCompl = avgHistLrtCompl / ((float)inst->modelUpdatePars[1]);
-    avgSquareHistLrt = avgSquareHistLrt / ((float)inst->modelUpdatePars[1]);
+    avgHistLrtCompl = avgHistLrtCompl / ((float)self->modelUpdatePars[1]);
+    avgSquareHistLrt = avgSquareHistLrt / ((float)self->modelUpdatePars[1]);
     fluctLrt = avgSquareHistLrt - avgHistLrt * avgHistLrtCompl;
-    // get threshold for lrt feature:
-    if (fluctLrt < inst->featureExtractionParams.thresFluctLrt) {
-      // very low fluct, so likely noise
-      inst->priorModelPars[0] = inst->featureExtractionParams.maxLrt;
+    // Get threshold for LRT feature.
+    if (fluctLrt < self->featureExtractionParams.thresFluctLrt) {
+      // Very low fluctuation, so likely noise.
+      self->priorModelPars[0] = self->featureExtractionParams.maxLrt;
     } else {
-      inst->priorModelPars[0] =
-          inst->featureExtractionParams.factor1ModelPars * avgHistLrt;
-      // check if value is within min/max range
-      if (inst->priorModelPars[0] < inst->featureExtractionParams.minLrt) {
-        inst->priorModelPars[0] = inst->featureExtractionParams.minLrt;
+      self->priorModelPars[0] =
+          self->featureExtractionParams.factor1ModelPars * avgHistLrt;
+      // Check if value is within min/max range.
+      if (self->priorModelPars[0] < self->featureExtractionParams.minLrt) {
+        self->priorModelPars[0] = self->featureExtractionParams.minLrt;
       }
-      if (inst->priorModelPars[0] > inst->featureExtractionParams.maxLrt) {
-        inst->priorModelPars[0] = inst->featureExtractionParams.maxLrt;
+      if (self->priorModelPars[0] > self->featureExtractionParams.maxLrt) {
+        self->priorModelPars[0] = self->featureExtractionParams.maxLrt;
       }
     }
-    // done with lrt feature
+    // Done with LRT feature.
 
-    // for spectral flatness and spectral difference: compute the main peaks of
-    // histogram
+    // For spectral flatness and spectral difference: compute the main peaks of
+    // histogram.
     maxPeak1 = 0;
     maxPeak2 = 0;
     posPeak1SpecFlat = 0.0;
@@ -420,234 +384,266 @@ void WebRtcNs_FeatureParameterExtraction(NSinst_t* inst, int flag) {
     weightPeak1SpecFlat = 0;
     weightPeak2SpecFlat = 0;
 
-    // peaks for flatness
+    // Peaks for flatness.
     for (i = 0; i < HIST_PAR_EST; i++) {
-      binMid = ((float)i + (float)0.5) *
-               inst->featureExtractionParams.binSizeSpecFlat;
-      if (inst->histSpecFlat[i] > maxPeak1) {
-        // Found new "first" peak
+      binMid =
+          (i + 0.5f) * self->featureExtractionParams.binSizeSpecFlat;
+      if (self->histSpecFlat[i] > maxPeak1) {
+        // Found new "first" peak.
         maxPeak2 = maxPeak1;
         weightPeak2SpecFlat = weightPeak1SpecFlat;
         posPeak2SpecFlat = posPeak1SpecFlat;
 
-        maxPeak1 = inst->histSpecFlat[i];
-        weightPeak1SpecFlat = inst->histSpecFlat[i];
+        maxPeak1 = self->histSpecFlat[i];
+        weightPeak1SpecFlat = self->histSpecFlat[i];
         posPeak1SpecFlat = binMid;
-      } else if (inst->histSpecFlat[i] > maxPeak2) {
-        // Found new "second" peak
-        maxPeak2 = inst->histSpecFlat[i];
-        weightPeak2SpecFlat = inst->histSpecFlat[i];
+      } else if (self->histSpecFlat[i] > maxPeak2) {
+        // Found new "second" peak.
+        maxPeak2 = self->histSpecFlat[i];
+        weightPeak2SpecFlat = self->histSpecFlat[i];
         posPeak2SpecFlat = binMid;
       }
     }
 
-    // compute two peaks for spectral difference
+    // Compute two peaks for spectral difference.
     maxPeak1 = 0;
     maxPeak2 = 0;
     posPeak1SpecDiff = 0.0;
     posPeak2SpecDiff = 0.0;
     weightPeak1SpecDiff = 0;
     weightPeak2SpecDiff = 0;
-    // peaks for spectral difference
+    // Peaks for spectral difference.
     for (i = 0; i < HIST_PAR_EST; i++) {
-      binMid = ((float)i + (float)0.5) *
-               inst->featureExtractionParams.binSizeSpecDiff;
-      if (inst->histSpecDiff[i] > maxPeak1) {
-        // Found new "first" peak
+      binMid =
+          ((float)i + 0.5f) * self->featureExtractionParams.binSizeSpecDiff;
+      if (self->histSpecDiff[i] > maxPeak1) {
+        // Found new "first" peak.
         maxPeak2 = maxPeak1;
         weightPeak2SpecDiff = weightPeak1SpecDiff;
         posPeak2SpecDiff = posPeak1SpecDiff;
 
-        maxPeak1 = inst->histSpecDiff[i];
-        weightPeak1SpecDiff = inst->histSpecDiff[i];
+        maxPeak1 = self->histSpecDiff[i];
+        weightPeak1SpecDiff = self->histSpecDiff[i];
         posPeak1SpecDiff = binMid;
-      } else if (inst->histSpecDiff[i] > maxPeak2) {
-        // Found new "second" peak
-        maxPeak2 = inst->histSpecDiff[i];
-        weightPeak2SpecDiff = inst->histSpecDiff[i];
+      } else if (self->histSpecDiff[i] > maxPeak2) {
+        // Found new "second" peak.
+        maxPeak2 = self->histSpecDiff[i];
+        weightPeak2SpecDiff = self->histSpecDiff[i];
         posPeak2SpecDiff = binMid;
       }
     }
 
-    // for spectrum flatness feature
+    // For spectrum flatness feature.
     useFeatureSpecFlat = 1;
-    // merge the two peaks if they are close
+    // Merge the two peaks if they are close.
     if ((fabs(posPeak2SpecFlat - posPeak1SpecFlat) <
-         inst->featureExtractionParams.limitPeakSpacingSpecFlat) &&
+         self->featureExtractionParams.limitPeakSpacingSpecFlat) &&
         (weightPeak2SpecFlat >
-         inst->featureExtractionParams.limitPeakWeightsSpecFlat *
+         self->featureExtractionParams.limitPeakWeightsSpecFlat *
              weightPeak1SpecFlat)) {
       weightPeak1SpecFlat += weightPeak2SpecFlat;
-      posPeak1SpecFlat = (float)0.5 * (posPeak1SpecFlat + posPeak2SpecFlat);
+      posPeak1SpecFlat = 0.5f * (posPeak1SpecFlat + posPeak2SpecFlat);
     }
-    // reject if weight of peaks is not large enough, or peak value too small
+    // Reject if weight of peaks is not large enough, or peak value too small.
     if (weightPeak1SpecFlat <
-            inst->featureExtractionParams.thresWeightSpecFlat ||
-        posPeak1SpecFlat < inst->featureExtractionParams.thresPosSpecFlat) {
+            self->featureExtractionParams.thresWeightSpecFlat ||
+        posPeak1SpecFlat < self->featureExtractionParams.thresPosSpecFlat) {
       useFeatureSpecFlat = 0;
     }
-    // if selected, get the threshold
+    // If selected, get the threshold.
     if (useFeatureSpecFlat == 1) {
-      // compute the threshold
-      inst->priorModelPars[1] =
-          inst->featureExtractionParams.factor2ModelPars * posPeak1SpecFlat;
-      // check if value is within min/max range
-      if (inst->priorModelPars[1] < inst->featureExtractionParams.minSpecFlat) {
-        inst->priorModelPars[1] = inst->featureExtractionParams.minSpecFlat;
+      // Compute the threshold.
+      self->priorModelPars[1] =
+          self->featureExtractionParams.factor2ModelPars * posPeak1SpecFlat;
+      // Check if value is within min/max range.
+      if (self->priorModelPars[1] < self->featureExtractionParams.minSpecFlat) {
+        self->priorModelPars[1] = self->featureExtractionParams.minSpecFlat;
       }
-      if (inst->priorModelPars[1] > inst->featureExtractionParams.maxSpecFlat) {
-        inst->priorModelPars[1] = inst->featureExtractionParams.maxSpecFlat;
+      if (self->priorModelPars[1] > self->featureExtractionParams.maxSpecFlat) {
+        self->priorModelPars[1] = self->featureExtractionParams.maxSpecFlat;
       }
     }
-    // done with flatness feature
+    // Done with flatness feature.
 
-    // for template feature
+    // For template feature.
     useFeatureSpecDiff = 1;
-    // merge the two peaks if they are close
+    // Merge the two peaks if they are close.
     if ((fabs(posPeak2SpecDiff - posPeak1SpecDiff) <
-         inst->featureExtractionParams.limitPeakSpacingSpecDiff) &&
+         self->featureExtractionParams.limitPeakSpacingSpecDiff) &&
         (weightPeak2SpecDiff >
-         inst->featureExtractionParams.limitPeakWeightsSpecDiff *
+         self->featureExtractionParams.limitPeakWeightsSpecDiff *
              weightPeak1SpecDiff)) {
       weightPeak1SpecDiff += weightPeak2SpecDiff;
-      posPeak1SpecDiff = (float)0.5 * (posPeak1SpecDiff + posPeak2SpecDiff);
+      posPeak1SpecDiff = 0.5f * (posPeak1SpecDiff + posPeak2SpecDiff);
     }
-    // get the threshold value
-    inst->priorModelPars[3] =
-        inst->featureExtractionParams.factor1ModelPars * posPeak1SpecDiff;
-    // reject if weight of peaks is not large enough
+    // Get the threshold value.
+    self->priorModelPars[3] =
+        self->featureExtractionParams.factor1ModelPars * posPeak1SpecDiff;
+    // Reject if weight of peaks is not large enough.
     if (weightPeak1SpecDiff <
-        inst->featureExtractionParams.thresWeightSpecDiff) {
+        self->featureExtractionParams.thresWeightSpecDiff) {
       useFeatureSpecDiff = 0;
     }
-    // check if value is within min/max range
-    if (inst->priorModelPars[3] < inst->featureExtractionParams.minSpecDiff) {
-      inst->priorModelPars[3] = inst->featureExtractionParams.minSpecDiff;
+    // Check if value is within min/max range.
+    if (self->priorModelPars[3] < self->featureExtractionParams.minSpecDiff) {
+      self->priorModelPars[3] = self->featureExtractionParams.minSpecDiff;
     }
-    if (inst->priorModelPars[3] > inst->featureExtractionParams.maxSpecDiff) {
-      inst->priorModelPars[3] = inst->featureExtractionParams.maxSpecDiff;
+    if (self->priorModelPars[3] > self->featureExtractionParams.maxSpecDiff) {
+      self->priorModelPars[3] = self->featureExtractionParams.maxSpecDiff;
     }
-    // done with spectral difference feature
+    // Done with spectral difference feature.
 
-    // don't use template feature if fluctuation of lrt feature is very low:
-    //  most likely just noise state
-    if (fluctLrt < inst->featureExtractionParams.thresFluctLrt) {
+    // Don't use template feature if fluctuation of LRT feature is very low:
+    // most likely just noise state.
+    if (fluctLrt < self->featureExtractionParams.thresFluctLrt) {
       useFeatureSpecDiff = 0;
     }
 
-    // select the weights between the features
-    // inst->priorModelPars[4] is weight for lrt: always selected
-    // inst->priorModelPars[5] is weight for spectral flatness
-    // inst->priorModelPars[6] is weight for spectral difference
+    // Select the weights between the features.
+    // self->priorModelPars[4] is weight for LRT: always selected.
+    // self->priorModelPars[5] is weight for spectral flatness.
+    // self->priorModelPars[6] is weight for spectral difference.
     featureSum = (float)(1 + useFeatureSpecFlat + useFeatureSpecDiff);
-    inst->priorModelPars[4] = (float)1.0 / featureSum;
-    inst->priorModelPars[5] = ((float)useFeatureSpecFlat) / featureSum;
-    inst->priorModelPars[6] = ((float)useFeatureSpecDiff) / featureSum;
+    self->priorModelPars[4] = 1.f / featureSum;
+    self->priorModelPars[5] = ((float)useFeatureSpecFlat) / featureSum;
+    self->priorModelPars[6] = ((float)useFeatureSpecDiff) / featureSum;
 
-    // set hists to zero for next update
-    if (inst->modelUpdatePars[0] >= 1) {
+    // Set hists to zero for next update.
+    if (self->modelUpdatePars[0] >= 1) {
       for (i = 0; i < HIST_PAR_EST; i++) {
-        inst->histLrt[i] = 0;
-        inst->histSpecFlat[i] = 0;
-        inst->histSpecDiff[i] = 0;
+        self->histLrt[i] = 0;
+        self->histSpecFlat[i] = 0;
+        self->histSpecDiff[i] = 0;
       }
     }
-  }  // end of flag == 1
+  }  // End of flag == 1.
 }
 
-// Compute spectral flatness on input spectrum
-// magnIn is the magnitude spectrum
-// spectral flatness is returned in inst->featureData[0]
-void WebRtcNs_ComputeSpectralFlatness(NSinst_t* inst, float* magnIn) {
+// Compute spectral flatness on input spectrum.
+// |magnIn| is the magnitude spectrum.
+// Spectral flatness is returned in self->featureData[0].
+static void ComputeSpectralFlatness(NSinst_t* self, const float* magnIn) {
   int i;
-  int shiftLP = 1;  // option to remove first bin(s) from spectral measures
+  int shiftLP = 1;  // Option to remove first bin(s) from spectral measures.
   float avgSpectralFlatnessNum, avgSpectralFlatnessDen, spectralTmp;
 
-  // comute spectral measures
-  // for flatness
+  // Compute spectral measures.
+  // For flatness.
   avgSpectralFlatnessNum = 0.0;
-  avgSpectralFlatnessDen = inst->sumMagn;
+  avgSpectralFlatnessDen = self->sumMagn;
   for (i = 0; i < shiftLP; i++) {
     avgSpectralFlatnessDen -= magnIn[i];
   }
-  // compute log of ratio of the geometric to arithmetic mean: check for log(0)
-  // case
-  for (i = shiftLP; i < inst->magnLen; i++) {
+  // Compute log of ratio of the geometric to arithmetic mean: check for log(0)
+  // case.
+  for (i = shiftLP; i < self->magnLen; i++) {
     if (magnIn[i] > 0.0) {
       avgSpectralFlatnessNum += (float)log(magnIn[i]);
     } else {
-      inst->featureData[0] -= SPECT_FL_TAVG * inst->featureData[0];
+      self->featureData[0] -= SPECT_FL_TAVG * self->featureData[0];
       return;
     }
   }
-  // normalize
-  avgSpectralFlatnessDen = avgSpectralFlatnessDen / inst->magnLen;
-  avgSpectralFlatnessNum = avgSpectralFlatnessNum / inst->magnLen;
+  // Normalize.
+  avgSpectralFlatnessDen = avgSpectralFlatnessDen / self->magnLen;
+  avgSpectralFlatnessNum = avgSpectralFlatnessNum / self->magnLen;
 
-  // ratio and inverse log: check for case of log(0)
+  // Ratio and inverse log: check for case of log(0).
   spectralTmp = (float)exp(avgSpectralFlatnessNum) / avgSpectralFlatnessDen;
 
-  // time-avg update of spectral flatness feature
-  inst->featureData[0] += SPECT_FL_TAVG * (spectralTmp - inst->featureData[0]);
-  // done with flatness feature
+  // Time-avg update of spectral flatness feature.
+  self->featureData[0] += SPECT_FL_TAVG * (spectralTmp - self->featureData[0]);
+  // Done with flatness feature.
+}
+
+// Compute prior and post SNR based on quantile noise estimation.
+// Compute DD estimate of prior SNR.
+// Inputs:
+//   * |magn| is the signal magnitude spectrum estimate.
+//   * |noise| is the magnitude noise spectrum estimate.
+// Outputs:
+//   * |snrLocPrior| is the computed prior SNR.
+//   * |snrLocPost| is the computed post SNR.
+static void ComputeSnr(const NSinst_t* self,
+                       const float* magn,
+                       const float* noise,
+                       float* snrLocPrior,
+                       float* snrLocPost) {
+  int i;
+
+  for (i = 0; i < self->magnLen; i++) {
+    // Previous post SNR.
+    // Previous estimate: based on previous frame with gain filter.
+    float previousEstimateStsa = self->magnPrevAnalyze[i] /
+        (self->noisePrev[i] + 0.0001f) * self->smooth[i];
+    // Post SNR.
+    snrLocPost[i] = 0.f;
+    if (magn[i] > noise[i]) {
+      snrLocPost[i] = magn[i] / (noise[i] + 0.0001f) - 1.f;
+    }
+    // DD estimate is sum of two terms: current estimate and previous estimate.
+    // Directed decision update of snrPrior.
+    snrLocPrior[i] =
+        DD_PR_SNR * previousEstimateStsa + (1.f - DD_PR_SNR) * snrLocPost[i];
+  }  // End of loop over frequencies.
 }
 
 // Compute the difference measure between input spectrum and a template/learned
-// noise spectrum
-// magnIn is the input spectrum
-// the reference/template spectrum is inst->magnAvgPause[i]
-// returns (normalized) spectral difference in inst->featureData[4]
-void WebRtcNs_ComputeSpectralDifference(NSinst_t* inst, float* magnIn) {
+// noise spectrum.
+// |magnIn| is the input spectrum.
+// The reference/template spectrum is self->magnAvgPause[i].
+// Returns (normalized) spectral difference in self->featureData[4].
+static void ComputeSpectralDifference(NSinst_t* self,
+                                      const float* magnIn) {
   // avgDiffNormMagn = var(magnIn) - cov(magnIn, magnAvgPause)^2 /
   // var(magnAvgPause)
   int i;
   float avgPause, avgMagn, covMagnPause, varPause, varMagn, avgDiffNormMagn;
 
   avgPause = 0.0;
-  avgMagn = inst->sumMagn;
-  // compute average quantities
-  for (i = 0; i < inst->magnLen; i++) {
-    // conservative smooth noise spectrum from pause frames
-    avgPause += inst->magnAvgPause[i];
+  avgMagn = self->sumMagn;
+  // Compute average quantities.
+  for (i = 0; i < self->magnLen; i++) {
+    // Conservative smooth noise spectrum from pause frames.
+    avgPause += self->magnAvgPause[i];
   }
-  avgPause = avgPause / ((float)inst->magnLen);
-  avgMagn = avgMagn / ((float)inst->magnLen);
+  avgPause = avgPause / ((float)self->magnLen);
+  avgMagn = avgMagn / ((float)self->magnLen);
 
   covMagnPause = 0.0;
   varPause = 0.0;
   varMagn = 0.0;
-  // compute variance and covariance quantities
-  for (i = 0; i < inst->magnLen; i++) {
-    covMagnPause += (magnIn[i] - avgMagn) * (inst->magnAvgPause[i] - avgPause);
+  // Compute variance and covariance quantities.
+  for (i = 0; i < self->magnLen; i++) {
+    covMagnPause += (magnIn[i] - avgMagn) * (self->magnAvgPause[i] - avgPause);
     varPause +=
-        (inst->magnAvgPause[i] - avgPause) * (inst->magnAvgPause[i] - avgPause);
+        (self->magnAvgPause[i] - avgPause) * (self->magnAvgPause[i] - avgPause);
     varMagn += (magnIn[i] - avgMagn) * (magnIn[i] - avgMagn);
   }
-  covMagnPause = covMagnPause / ((float)inst->magnLen);
-  varPause = varPause / ((float)inst->magnLen);
-  varMagn = varMagn / ((float)inst->magnLen);
-  // update of average magnitude spectrum
-  inst->featureData[6] += inst->signalEnergy;
+  covMagnPause = covMagnPause / ((float)self->magnLen);
+  varPause = varPause / ((float)self->magnLen);
+  varMagn = varMagn / ((float)self->magnLen);
+  // Update of average magnitude spectrum.
+  self->featureData[6] += self->signalEnergy;
 
   avgDiffNormMagn =
-      varMagn - (covMagnPause * covMagnPause) / (varPause + (float)0.0001);
-  // normalize and compute time-avg update of difference feature
-  avgDiffNormMagn =
-      (float)(avgDiffNormMagn / (inst->featureData[5] + (float)0.0001));
-  inst->featureData[4] +=
-      SPECT_DIFF_TAVG * (avgDiffNormMagn - inst->featureData[4]);
+      varMagn - (covMagnPause * covMagnPause) / (varPause + 0.0001f);
+  // Normalize and compute time-avg update of difference feature.
+  avgDiffNormMagn = (float)(avgDiffNormMagn / (self->featureData[5] + 0.0001f));
+  self->featureData[4] +=
+      SPECT_DIFF_TAVG * (avgDiffNormMagn - self->featureData[4]);
 }
 
-// Compute speech/noise probability
-// speech/noise probability is returned in: probSpeechFinal
-// magn is the input magnitude spectrum
-// noise is the noise spectrum
-// snrLocPrior is the prior snr for each freq.
-// snr loc_post is the post snr for each freq.
-void WebRtcNs_SpeechNoiseProb(NSinst_t* inst,
-                              float* probSpeechFinal,
-                              float* snrLocPrior,
-                              float* snrLocPost) {
+// Compute speech/noise probability.
+// Speech/noise probability is returned in |probSpeechFinal|.
+// |magn| is the input magnitude spectrum.
+// |noise| is the noise spectrum.
+// |snrLocPrior| is the prior SNR for each frequency.
+// |snrLocPost| is the post SNR for each frequency.
+static void SpeechNoiseProb(NSinst_t* self,
+                            float* probSpeechFinal,
+                            const float* snrLocPrior,
+                            const float* snrLocPost) {
   int i, sgnMap;
   float invLrt, gainPrior, indPrior;
   float logLrtTimeAvgKsum, besselTmp;
@@ -658,120 +654,406 @@ void WebRtcNs_SpeechNoiseProb(NSinst_t* inst,
   float widthPrior, widthPrior0, widthPrior1, widthPrior2;
 
   widthPrior0 = WIDTH_PR_MAP;
-  widthPrior1 = (float)2.0 * WIDTH_PR_MAP;  // width for pause region:
-  // lower range, so increase width in tanh map
-  widthPrior2 = (float)2.0 * WIDTH_PR_MAP;  // for spectral-difference measure
+  // Width for pause region: lower range, so increase width in tanh map.
+  widthPrior1 = 2.f * WIDTH_PR_MAP;
+  widthPrior2 = 2.f * WIDTH_PR_MAP;  // For spectral-difference measure.
 
-  // threshold parameters for features
-  threshPrior0 = inst->priorModelPars[0];
-  threshPrior1 = inst->priorModelPars[1];
-  threshPrior2 = inst->priorModelPars[3];
+  // Threshold parameters for features.
+  threshPrior0 = self->priorModelPars[0];
+  threshPrior1 = self->priorModelPars[1];
+  threshPrior2 = self->priorModelPars[3];
 
-  // sign for flatness feature
-  sgnMap = (int)(inst->priorModelPars[2]);
+  // Sign for flatness feature.
+  sgnMap = (int)(self->priorModelPars[2]);
 
-  // weight parameters for features
-  weightIndPrior0 = inst->priorModelPars[4];
-  weightIndPrior1 = inst->priorModelPars[5];
-  weightIndPrior2 = inst->priorModelPars[6];
+  // Weight parameters for features.
+  weightIndPrior0 = self->priorModelPars[4];
+  weightIndPrior1 = self->priorModelPars[5];
+  weightIndPrior2 = self->priorModelPars[6];
 
-  // compute feature based on average LR factor
-  // this is the average over all frequencies of the smooth log lrt
+  // Compute feature based on average LR factor.
+  // This is the average over all frequencies of the smooth log LRT.
   logLrtTimeAvgKsum = 0.0;
-  for (i = 0; i < inst->magnLen; i++) {
-    tmpFloat1 = (float)1.0 + (float)2.0 * snrLocPrior[i];
-    tmpFloat2 = (float)2.0 * snrLocPrior[i] / (tmpFloat1 + (float)0.0001);
-    besselTmp = (snrLocPost[i] + (float)1.0) * tmpFloat2;
-    inst->logLrtTimeAvg[i] +=
-        LRT_TAVG * (besselTmp - (float)log(tmpFloat1) - inst->logLrtTimeAvg[i]);
-    logLrtTimeAvgKsum += inst->logLrtTimeAvg[i];
+  for (i = 0; i < self->magnLen; i++) {
+    tmpFloat1 = 1.f + 2.f * snrLocPrior[i];
+    tmpFloat2 = 2.f * snrLocPrior[i] / (tmpFloat1 + 0.0001f);
+    besselTmp = (snrLocPost[i] + 1.f) * tmpFloat2;
+    self->logLrtTimeAvg[i] +=
+        LRT_TAVG * (besselTmp - (float)log(tmpFloat1) - self->logLrtTimeAvg[i]);
+    logLrtTimeAvgKsum += self->logLrtTimeAvg[i];
   }
-  logLrtTimeAvgKsum = (float)logLrtTimeAvgKsum / (inst->magnLen);
-  inst->featureData[3] = logLrtTimeAvgKsum;
-  // done with computation of LR factor
+  logLrtTimeAvgKsum = (float)logLrtTimeAvgKsum / (self->magnLen);
+  self->featureData[3] = logLrtTimeAvgKsum;
+  // Done with computation of LR factor.
 
-  //
-  // compute the indicator functions
-  //
-
-  // average lrt feature
+  // Compute the indicator functions.
+  // Average LRT feature.
   widthPrior = widthPrior0;
-  // use larger width in tanh map for pause regions
+  // Use larger width in tanh map for pause regions.
   if (logLrtTimeAvgKsum < threshPrior0) {
     widthPrior = widthPrior1;
   }
-  // compute indicator function: sigmoid map
-  indicator0 = (float)0.5 *
-               ((float)tanh(widthPrior * (logLrtTimeAvgKsum - threshPrior0)) +
-                (float)1.0);
+  // Compute indicator function: sigmoid map.
+  indicator0 =
+      0.5f *
+      ((float)tanh(widthPrior * (logLrtTimeAvgKsum - threshPrior0)) + 1.f);
 
-  // spectral flatness feature
-  tmpFloat1 = inst->featureData[0];
+  // Spectral flatness feature.
+  tmpFloat1 = self->featureData[0];
   widthPrior = widthPrior0;
-  // use larger width in tanh map for pause regions
+  // Use larger width in tanh map for pause regions.
   if (sgnMap == 1 && (tmpFloat1 > threshPrior1)) {
     widthPrior = widthPrior1;
   }
   if (sgnMap == -1 && (tmpFloat1 < threshPrior1)) {
     widthPrior = widthPrior1;
   }
-  // compute indicator function: sigmoid map
+  // Compute indicator function: sigmoid map.
   indicator1 =
-      (float)0.5 *
+      0.5f *
       ((float)tanh((float)sgnMap * widthPrior * (threshPrior1 - tmpFloat1)) +
-       (float)1.0);
+       1.f);
 
-  // for template spectrum-difference
-  tmpFloat1 = inst->featureData[4];
+  // For template spectrum-difference.
+  tmpFloat1 = self->featureData[4];
   widthPrior = widthPrior0;
-  // use larger width in tanh map for pause regions
+  // Use larger width in tanh map for pause regions.
   if (tmpFloat1 < threshPrior2) {
     widthPrior = widthPrior2;
   }
-  // compute indicator function: sigmoid map
+  // Compute indicator function: sigmoid map.
   indicator2 =
-      (float)0.5 *
-      ((float)tanh(widthPrior * (tmpFloat1 - threshPrior2)) + (float)1.0);
+      0.5f * ((float)tanh(widthPrior * (tmpFloat1 - threshPrior2)) + 1.f);
 
-  // combine the indicator function with the feature weights
+  // Combine the indicator function with the feature weights.
   indPrior = weightIndPrior0 * indicator0 + weightIndPrior1 * indicator1 +
              weightIndPrior2 * indicator2;
-  // done with computing indicator function
+  // Done with computing indicator function.
 
-  // compute the prior probability
-  inst->priorSpeechProb += PRIOR_UPDATE * (indPrior - inst->priorSpeechProb);
-  // make sure probabilities are within range: keep floor to 0.01
-  if (inst->priorSpeechProb > 1.0) {
-    inst->priorSpeechProb = (float)1.0;
+  // Compute the prior probability.
+  self->priorSpeechProb += PRIOR_UPDATE * (indPrior - self->priorSpeechProb);
+  // Make sure probabilities are within range: keep floor to 0.01.
+  if (self->priorSpeechProb > 1.f) {
+    self->priorSpeechProb = 1.f;
   }
-  if (inst->priorSpeechProb < 0.01) {
-    inst->priorSpeechProb = (float)0.01;
+  if (self->priorSpeechProb < 0.01f) {
+    self->priorSpeechProb = 0.01f;
   }
 
-  // final speech probability: combine prior model with LR factor:
-  gainPrior = ((float)1.0 - inst->priorSpeechProb) /
-              (inst->priorSpeechProb + (float)0.0001);
-  for (i = 0; i < inst->magnLen; i++) {
-    invLrt = (float)exp(-inst->logLrtTimeAvg[i]);
+  // Final speech probability: combine prior model with LR factor:.
+  gainPrior = (1.f - self->priorSpeechProb) / (self->priorSpeechProb + 0.0001f);
+  for (i = 0; i < self->magnLen; i++) {
+    invLrt = (float)exp(-self->logLrtTimeAvg[i]);
     invLrt = (float)gainPrior * invLrt;
-    probSpeechFinal[i] = (float)1.0 / ((float)1.0 + invLrt);
+    probSpeechFinal[i] = 1.f / (1.f + invLrt);
   }
 }
 
-int WebRtcNs_AnalyzeCore(NSinst_t* inst, float* speechFrame) {
+// Update the noise features.
+// Inputs:
+//   * |magn| is the signal magnitude spectrum estimate.
+//   * |updateParsFlag| is an update flag for parameters.
+static void FeatureUpdate(NSinst_t* self,
+                          const float* magn,
+                          int updateParsFlag) {
+  // Compute spectral flatness on input spectrum.
+  ComputeSpectralFlatness(self, magn);
+  // Compute difference of input spectrum with learned/estimated noise spectrum.
+  ComputeSpectralDifference(self, magn);
+  // Compute histograms for parameter decisions (thresholds and weights for
+  // features).
+  // Parameters are extracted once every window time.
+  // (=self->modelUpdatePars[1])
+  if (updateParsFlag >= 1) {
+    // Counter update.
+    self->modelUpdatePars[3]--;
+    // Update histogram.
+    if (self->modelUpdatePars[3] > 0) {
+      FeatureParameterExtraction(self, 0);
+    }
+    // Compute model parameters.
+    if (self->modelUpdatePars[3] == 0) {
+      FeatureParameterExtraction(self, 1);
+      self->modelUpdatePars[3] = self->modelUpdatePars[1];
+      // If wish to update only once, set flag to zero.
+      if (updateParsFlag == 1) {
+        self->modelUpdatePars[0] = 0;
+      } else {
+        // Update every window:
+        // Get normalization for spectral difference for next window estimate.
+        self->featureData[6] =
+            self->featureData[6] / ((float)self->modelUpdatePars[1]);
+        self->featureData[5] =
+            0.5f * (self->featureData[6] + self->featureData[5]);
+        self->featureData[6] = 0.f;
+      }
+    }
+  }
+}
+
+// Update the noise estimate.
+// Inputs:
+//   * |magn| is the signal magnitude spectrum estimate.
+//   * |snrLocPrior| is the prior SNR.
+//   * |snrLocPost| is the post SNR.
+// Output:
+//   * |noise| is the updated noise magnitude spectrum estimate.
+static void UpdateNoiseEstimate(NSinst_t* self,
+                                const float* magn,
+                                const float* snrLocPrior,
+                                const float* snrLocPost,
+                                float* noise) {
+  int i;
+  float probSpeech, probNonSpeech;
+  // Time-avg parameter for noise update.
+  float gammaNoiseTmp = NOISE_UPDATE;
+  float gammaNoiseOld;
+  float noiseUpdateTmp;
+
+  for (i = 0; i < self->magnLen; i++) {
+    probSpeech = self->speechProb[i];
+    probNonSpeech = 1.f - probSpeech;
+    // Temporary noise update:
+    // Use it for speech frames if update value is less than previous.
+    noiseUpdateTmp = gammaNoiseTmp * self->noisePrev[i] +
+                     (1.f - gammaNoiseTmp) * (probNonSpeech * magn[i] +
+                                              probSpeech * self->noisePrev[i]);
+    // Time-constant based on speech/noise state.
+    gammaNoiseOld = gammaNoiseTmp;
+    gammaNoiseTmp = NOISE_UPDATE;
+    // Increase gamma (i.e., less noise update) for frame likely to be speech.
+    if (probSpeech > PROB_RANGE) {
+      gammaNoiseTmp = SPEECH_UPDATE;
+    }
+    // Conservative noise update.
+    if (probSpeech < PROB_RANGE) {
+      self->magnAvgPause[i] += GAMMA_PAUSE * (magn[i] - self->magnAvgPause[i]);
+    }
+    // Noise update.
+    if (gammaNoiseTmp == gammaNoiseOld) {
+      noise[i] = noiseUpdateTmp;
+    } else {
+      noise[i] = gammaNoiseTmp * self->noisePrev[i] +
+                 (1.f - gammaNoiseTmp) * (probNonSpeech * magn[i] +
+                                          probSpeech * self->noisePrev[i]);
+      // Allow for noise update downwards:
+      // If noise update decreases the noise, it is safe, so allow it to
+      // happen.
+      if (noiseUpdateTmp < noise[i]) {
+        noise[i] = noiseUpdateTmp;
+      }
+    }
+  }  // End of freq loop.
+}
+
+// Updates |buffer| with a new |frame|.
+// Inputs:
+//   * |frame| is a new speech frame or NULL for setting to zero.
+//   * |frame_length| is the length of the new frame.
+//   * |buffer_length| is the length of the buffer.
+// Output:
+//   * |buffer| is the updated buffer.
+static void UpdateBuffer(const float* frame,
+                         int frame_length,
+                         int buffer_length,
+                         float* buffer) {
+  assert(buffer_length < 2 * frame_length);
+
+  memcpy(buffer,
+         buffer + frame_length,
+         sizeof(*buffer) * (buffer_length - frame_length));
+  if (frame) {
+    memcpy(buffer + buffer_length - frame_length,
+           frame,
+           sizeof(*buffer) * frame_length);
+  } else {
+    memset(buffer + buffer_length - frame_length,
+           0,
+           sizeof(*buffer) * frame_length);
+  }
+}
+
+// Transforms the signal from time to frequency domain.
+// Inputs:
+//   * |time_data| is the signal in the time domain.
+//   * |time_data_length| is the length of the analysis buffer.
+//   * |magnitude_length| is the length of the spectrum magnitude, which equals
+//     the length of both |real| and |imag| (time_data_length / 2 + 1).
+// Outputs:
+//   * |time_data| is the signal in the frequency domain.
+//   * |real| is the real part of the frequency domain.
+//   * |imag| is the imaginary part of the frequency domain.
+//   * |magn| is the calculated signal magnitude in the frequency domain.
+static void FFT(NSinst_t* self,
+                float* time_data,
+                int time_data_length,
+                int magnitude_length,
+                float* real,
+                float* imag,
+                float* magn) {
+  int i;
+
+  assert(magnitude_length == time_data_length / 2 + 1);
+
+  WebRtc_rdft(time_data_length, 1, time_data, self->ip, self->wfft);
+
+  imag[0] = 0;
+  real[0] = time_data[0];
+  magn[0] = fabs(real[0]) + 1.f;
+  imag[magnitude_length - 1] = 0;
+  real[magnitude_length - 1] = time_data[1];
+  magn[magnitude_length - 1] = fabs(real[magnitude_length - 1]) + 1.f;
+  for (i = 1; i < magnitude_length - 1; ++i) {
+    real[i] = time_data[2 * i];
+    imag[i] = time_data[2 * i + 1];
+    // Magnitude spectrum.
+    magn[i] = sqrtf(real[i] * real[i] + imag[i] * imag[i]) + 1.f;
+  }
+}
+
+// Transforms the signal from frequency to time domain.
+// Inputs:
+//   * |real| is the real part of the frequency domain.
+//   * |imag| is the imaginary part of the frequency domain.
+//   * |magnitude_length| is the length of the spectrum magnitude, which equals
+//     the length of both |real| and |imag|.
+//   * |time_data_length| is the length of the analysis buffer
+//     (2 * (magnitude_length - 1)).
+// Output:
+//   * |time_data| is the signal in the time domain.
+static void IFFT(NSinst_t* self,
+                 const float* real,
+                 const float* imag,
+                 int magnitude_length,
+                 int time_data_length,
+                 float* time_data) {
+  int i;
+
+  assert(time_data_length == 2 * (magnitude_length - 1));
+
+  time_data[0] = real[0];
+  time_data[1] = real[magnitude_length - 1];
+  for (i = 1; i < magnitude_length - 1; ++i) {
+    time_data[2 * i] = real[i];
+    time_data[2 * i + 1] = imag[i];
+  }
+  WebRtc_rdft(time_data_length, -1, time_data, self->ip, self->wfft);
+
+  for (i = 0; i < time_data_length; ++i) {
+    time_data[i] *= 2.f / time_data_length;  // FFT scaling.
+  }
+}
+
+// Calculates the energy of a buffer.
+// Inputs:
+//   * |buffer| is the buffer over which the energy is calculated.
+//   * |length| is the length of the buffer.
+// Returns the calculated energy.
+static float Energy(const float* buffer, int length) {
+  int i;
+  float energy = 0.f;
+
+  for (i = 0; i < length; ++i) {
+    energy += buffer[i] * buffer[i];
+  }
+
+  return energy;
+}
+
+// Windows a buffer.
+// Inputs:
+//   * |window| is the window by which to multiply.
+//   * |data| is the data without windowing.
+//   * |length| is the length of the window and data.
+// Output:
+//   * |data_windowed| is the windowed data.
+static void Windowing(const float* window,
+                      const float* data,
+                      int length,
+                      float* data_windowed) {
+  int i;
+
+  for (i = 0; i < length; ++i) {
+    data_windowed[i] = window[i] * data[i];
+  }
+}
+
+// Estimate prior SNR decision-directed and compute DD based Wiener Filter.
+// Input:
+//   * |magn| is the signal magnitude spectrum estimate.
+// Output:
+//   * |theFilter| is the frequency response of the computed Wiener filter.
+static void ComputeDdBasedWienerFilter(const NSinst_t* self,
+                                       const float* magn,
+                                       float* theFilter) {
+  int i;
+  float snrPrior, previousEstimateStsa, currentEstimateStsa;
+
+  for (i = 0; i < self->magnLen; i++) {
+    // Previous estimate: based on previous frame with gain filter.
+    previousEstimateStsa = self->magnPrevProcess[i] /
+                           (self->noisePrev[i] + 0.0001f) * self->smooth[i];
+    // Post and prior SNR.
+    currentEstimateStsa = 0.f;
+    if (magn[i] > self->noise[i]) {
+      currentEstimateStsa = magn[i] / (self->noise[i] + 0.0001f) - 1.f;
+    }
+    // DD estimate is sum of two terms: current estimate and previous estimate.
+    // Directed decision update of |snrPrior|.
+    snrPrior = DD_PR_SNR * previousEstimateStsa +
+               (1.f - DD_PR_SNR) * currentEstimateStsa;
+    // Gain filter.
+    theFilter[i] = snrPrior / (self->overdrive + snrPrior);
+  }  // End of loop over frequencies.
+}
+
+// Changes the aggressiveness of the noise suppression method.
+// |mode| = 0 is mild (6dB), |mode| = 1 is medium (10dB) and |mode| = 2 is
+// aggressive (15dB).
+// Returns 0 on success and -1 otherwise.
+int WebRtcNs_set_policy_core(NSinst_t* self, int mode) {
+  // Allow for modes: 0, 1, 2, 3.
+  if (mode < 0 || mode > 3) {
+    return (-1);
+  }
+
+  self->aggrMode = mode;
+  if (mode == 0) {
+    self->overdrive = 1.f;
+    self->denoiseBound = 0.5f;
+    self->gainmap = 0;
+  } else if (mode == 1) {
+    // self->overdrive = 1.25f;
+    self->overdrive = 1.f;
+    self->denoiseBound = 0.25f;
+    self->gainmap = 1;
+  } else if (mode == 2) {
+    // self->overdrive = 1.25f;
+    self->overdrive = 1.1f;
+    self->denoiseBound = 0.125f;
+    self->gainmap = 1;
+  } else if (mode == 3) {
+    // self->overdrive = 1.3f;
+    self->overdrive = 1.25f;
+    self->denoiseBound = 0.09f;
+    self->gainmap = 1;
+  }
+  return 0;
+}
+
+int WebRtcNs_AnalyzeCore(NSinst_t* self, float* speechFrame) {
   int i;
   const int kStartBand = 5;  // Skip first frequency bins during estimation.
   int updateParsFlag;
   float energy;
-  float signalEnergy, sumMagn;
-  float tmpFloat1, tmpFloat2, tmpFloat3, probSpeech, probNonSpeech;
-  float gammaNoiseTmp, gammaNoiseOld;
-  float noiseUpdateTmp, fTmp;
+  float signalEnergy = 0.f;
+  float sumMagn = 0.f;
+  float tmpFloat1, tmpFloat2, tmpFloat3;
   float winData[ANAL_BLOCKL_MAX];
   float magn[HALF_ANAL_BLOCKL], noise[HALF_ANAL_BLOCKL];
   float snrLocPost[HALF_ANAL_BLOCKL], snrLocPrior[HALF_ANAL_BLOCKL];
   float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL];
-  // Variables during startup
+  // Variables during startup.
   float sum_log_i = 0.0;
   float sum_log_i_square = 0.0;
   float sum_log_magn = 0.0;
@@ -779,577 +1061,348 @@ int WebRtcNs_AnalyzeCore(NSinst_t* inst, float* speechFrame) {
   float parametric_exp = 0.0;
   float parametric_num = 0.0;
 
-  // Check that initiation has been done
-  if (inst->initFlag != 1) {
+  // Check that initiation has been done.
+  if (self->initFlag != 1) {
     return (-1);
   }
-  //
-  updateParsFlag = inst->modelUpdatePars[0];
-  //
-
-  // update analysis buffer for L band
-  memcpy(inst->analyzeBuf,
-         inst->analyzeBuf + inst->blockLen10ms,
-         sizeof(float) * (inst->anaLen - inst->blockLen10ms));
-  memcpy(inst->analyzeBuf + inst->anaLen - inst->blockLen10ms,
-         speechFrame,
-         sizeof(float) * inst->blockLen10ms);
-
-  // check if processing needed
-  if (inst->outLen == 0) {
-    // windowing
-    energy = 0.0;
-    for (i = 0; i < inst->anaLen; i++) {
-      winData[i] = inst->window[i] * inst->analyzeBuf[i];
-      energy += winData[i] * winData[i];
-    }
-    if (energy == 0.0) {
-      // we want to avoid updating statistics in this case:
-      // Updating feature statistics when we have zeros only will cause
-      // thresholds to move towards zero signal situations. This in turn has the
-      // effect that once the signal is "turned on" (non-zero values) everything
-      // will be treated as speech and there is no noise suppression effect.
-      // Depending on the duration of the inactive signal it takes a
-      // considerable amount of time for the system to learn what is noise and
-      // what is speech.
-      return 0;
-    }
+  updateParsFlag = self->modelUpdatePars[0];
+
+  // Update analysis buffer for L band.
+  UpdateBuffer(speechFrame, self->blockLen, self->anaLen, self->analyzeBuf);
+
+  Windowing(self->window, self->analyzeBuf, self->anaLen, winData);
+  energy = Energy(winData, self->anaLen);
+  if (energy == 0.0) {
+    // We want to avoid updating statistics in this case:
+    // Updating feature statistics when we have zeros only will cause
+    // thresholds to move towards zero signal situations. This in turn has the
+    // effect that once the signal is "turned on" (non-zero values) everything
+    // will be treated as speech and there is no noise suppression effect.
+    // Depending on the duration of the inactive signal it takes a
+    // considerable amount of time for the system to learn what is noise and
+    // what is speech.
+    return 0;
+  }
 
-    //
-    inst->blockInd++;  // Update the block index only when we process a block.
-    // FFT
-    WebRtc_rdft(inst->anaLen, 1, winData, inst->ip, inst->wfft);
-
-    imag[0] = 0;
-    real[0] = winData[0];
-    magn[0] = (float)(fabs(real[0]) + 1.0f);
-    imag[inst->magnLen - 1] = 0;
-    real[inst->magnLen - 1] = winData[1];
-    magn[inst->magnLen - 1] = (float)(fabs(real[inst->magnLen - 1]) + 1.0f);
-    signalEnergy = (float)(real[0] * real[0]) +
-                   (float)(real[inst->magnLen - 1] * real[inst->magnLen - 1]);
-    sumMagn = magn[0] + magn[inst->magnLen - 1];
-    if (inst->blockInd < END_STARTUP_SHORT) {
-      tmpFloat2 = log((float)(inst->magnLen - 1));
-      sum_log_i = tmpFloat2;
-      sum_log_i_square = tmpFloat2 * tmpFloat2;
-      tmpFloat1 = log(magn[inst->magnLen - 1]);
-      sum_log_magn = tmpFloat1;
-      sum_log_i_log_magn = tmpFloat2 * tmpFloat1;
-    }
-    for (i = 1; i < inst->magnLen - 1; i++) {
-      real[i] = winData[2 * i];
-      imag[i] = winData[2 * i + 1];
-      // magnitude spectrum
-      fTmp = real[i] * real[i];
-      fTmp += imag[i] * imag[i];
-      signalEnergy += fTmp;
-      magn[i] = ((float)sqrt(fTmp)) + 1.0f;
-      sumMagn += magn[i];
-      if (inst->blockInd < END_STARTUP_SHORT) {
-        if (i >= kStartBand) {
-          tmpFloat2 = log((float)i);
-          sum_log_i += tmpFloat2;
-          sum_log_i_square += tmpFloat2 * tmpFloat2;
-          tmpFloat1 = log(magn[i]);
-          sum_log_magn += tmpFloat1;
-          sum_log_i_log_magn += tmpFloat2 * tmpFloat1;
-        }
+  self->blockInd++;  // Update the block index only when we process a block.
+
+  FFT(self, winData, self->anaLen, self->magnLen, real, imag, magn);
+
+  for (i = 0; i < self->magnLen; i++) {
+    signalEnergy += real[i] * real[i] + imag[i] * imag[i];
+    sumMagn += magn[i];
+    if (self->blockInd < END_STARTUP_SHORT) {
+      if (i >= kStartBand) {
+        tmpFloat2 = log((float)i);
+        sum_log_i += tmpFloat2;
+        sum_log_i_square += tmpFloat2 * tmpFloat2;
+        tmpFloat1 = log(magn[i]);
+        sum_log_magn += tmpFloat1;
+        sum_log_i_log_magn += tmpFloat2 * tmpFloat1;
       }
     }
-    signalEnergy = signalEnergy / ((float)inst->magnLen);
-    inst->signalEnergy = signalEnergy;
-    inst->sumMagn = sumMagn;
-
-    // compute spectral flatness on input spectrum
-    WebRtcNs_ComputeSpectralFlatness(inst, magn);
-    // quantile noise estimate
-    WebRtcNs_NoiseEstimation(inst, magn, noise);
-    // compute simplified noise model during startup
-    if (inst->blockInd < END_STARTUP_SHORT) {
-      // Estimate White noise
-      inst->whiteNoiseLevel +=
-          sumMagn / ((float)inst->magnLen) * inst->overdrive;
-      // Estimate Pink noise parameters
-      tmpFloat1 = sum_log_i_square * ((float)(inst->magnLen - kStartBand));
-      tmpFloat1 -= (sum_log_i * sum_log_i);
-      tmpFloat2 =
-          (sum_log_i_square * sum_log_magn - sum_log_i * sum_log_i_log_magn);
-      tmpFloat3 = tmpFloat2 / tmpFloat1;
-      // Constrain the estimated spectrum to be positive
-      if (tmpFloat3 < 0.0f) {
-        tmpFloat3 = 0.0f;
-      }
-      inst->pinkNoiseNumerator += tmpFloat3;
-      tmpFloat2 = (sum_log_i * sum_log_magn);
-      tmpFloat2 -= ((float)(inst->magnLen - kStartBand)) * sum_log_i_log_magn;
-      tmpFloat3 = tmpFloat2 / tmpFloat1;
-      // Constrain the pink noise power to be in the interval [0, 1];
-      if (tmpFloat3 < 0.0f) {
-        tmpFloat3 = 0.0f;
-      }
-      if (tmpFloat3 > 1.0f) {
-        tmpFloat3 = 1.0f;
-      }
-      inst->pinkNoiseExp += tmpFloat3;
-
-      // Calculate frequency independent parts of parametric noise estimate.
-      if (inst->pinkNoiseExp > 0.0f) {
-        // Use pink noise estimate
-        parametric_num =
-            exp(inst->pinkNoiseNumerator / (float)(inst->blockInd + 1));
-        parametric_num *= (float)(inst->blockInd + 1);
-        parametric_exp = inst->pinkNoiseExp / (float)(inst->blockInd + 1);
-      }
-      for (i = 0; i < inst->magnLen; i++) {
-        // Estimate the background noise using the white and pink noise
-        // parameters
-        if (inst->pinkNoiseExp == 0.0f) {
-          // Use white noise estimate
-          inst->parametricNoise[i] = inst->whiteNoiseLevel;
-        } else {
-          // Use pink noise estimate
-          float use_band = (float)(i < kStartBand ? kStartBand : i);
-          inst->parametricNoise[i] =
-              parametric_num / pow(use_band, parametric_exp);
-        }
-        // Weight quantile noise with modeled noise
-        noise[i] *= (inst->blockInd);
-        tmpFloat2 =
-            inst->parametricNoise[i] * (END_STARTUP_SHORT - inst->blockInd);
-        noise[i] += (tmpFloat2 / (float)(inst->blockInd + 1));
-        noise[i] /= END_STARTUP_SHORT;
-      }
+  }
+  signalEnergy = signalEnergy / ((float)self->magnLen);
+  self->signalEnergy = signalEnergy;
+  self->sumMagn = sumMagn;
+
+  // Quantile noise estimate.
+  NoiseEstimation(self, magn, noise);
+  // Compute simplified noise model during startup.
+  if (self->blockInd < END_STARTUP_SHORT) {
+    // Estimate White noise.
+    self->whiteNoiseLevel += sumMagn / ((float)self->magnLen) * self->overdrive;
+    // Estimate Pink noise parameters.
+    tmpFloat1 = sum_log_i_square * ((float)(self->magnLen - kStartBand));
+    tmpFloat1 -= (sum_log_i * sum_log_i);
+    tmpFloat2 =
+        (sum_log_i_square * sum_log_magn - sum_log_i * sum_log_i_log_magn);
+    tmpFloat3 = tmpFloat2 / tmpFloat1;
+    // Constrain the estimated spectrum to be positive.
+    if (tmpFloat3 < 0.f) {
+      tmpFloat3 = 0.f;
     }
-    // compute average signal during END_STARTUP_LONG time:
-    // used to normalize spectral difference measure
-    if (inst->blockInd < END_STARTUP_LONG) {
-      inst->featureData[5] *= inst->blockInd;
-      inst->featureData[5] += signalEnergy;
-      inst->featureData[5] /= (inst->blockInd + 1);
+    self->pinkNoiseNumerator += tmpFloat3;
+    tmpFloat2 = (sum_log_i * sum_log_magn);
+    tmpFloat2 -= ((float)(self->magnLen - kStartBand)) * sum_log_i_log_magn;
+    tmpFloat3 = tmpFloat2 / tmpFloat1;
+    // Constrain the pink noise power to be in the interval [0, 1].
+    if (tmpFloat3 < 0.f) {
+      tmpFloat3 = 0.f;
     }
-
-    // start processing at frames == converged+1
-    // STEP 1: compute  prior and post snr based on quantile noise est
-    // compute DD estimate of prior SNR: needed for new method
-    for (i = 0; i < inst->magnLen; i++) {
-      // post snr
-      snrLocPost[i] = (float)0.0;
-      if (magn[i] > noise[i]) {
-        snrLocPost[i] = magn[i] / (noise[i] + (float)0.0001) - (float)1.0;
-      }
-      // previous post snr
-      // previous estimate: based on previous frame with gain filter
-      inst->previousEstimateStsa[i] = inst->magnPrev[i] /
-                                (inst->noisePrev[i] + (float)0.0001) *
-                                (inst->smooth[i]);
-      // DD estimate is sum of two terms: current estimate and previous estimate
-      // directed decision update of snrPrior
-      snrLocPrior[i] = DD_PR_SNR * inst->previousEstimateStsa[i] +
-                       ((float)1.0 - DD_PR_SNR) * snrLocPost[i];
-      // post and prior snr needed for step 2
-    }  // end of loop over freqs
-       // done with step 1: dd computation of prior and post snr
-
-    // STEP 2: compute speech/noise likelihood
-    // compute difference of input spectrum with learned/estimated noise
-    // spectrum
-    WebRtcNs_ComputeSpectralDifference(inst, magn);
-    // compute histograms for parameter decisions (thresholds and weights for
-    // features)
-    // parameters are extracted once every window time
-    // (=inst->modelUpdatePars[1])
-    if (updateParsFlag >= 1) {
-      // counter update
-      inst->modelUpdatePars[3]--;
-      // update histogram
-      if (inst->modelUpdatePars[3] > 0) {
-        WebRtcNs_FeatureParameterExtraction(inst, 0);
-      }
-      // compute model parameters
-      if (inst->modelUpdatePars[3] == 0) {
-        WebRtcNs_FeatureParameterExtraction(inst, 1);
-        inst->modelUpdatePars[3] = inst->modelUpdatePars[1];
-        // if wish to update only once, set flag to zero
-        if (updateParsFlag == 1) {
-          inst->modelUpdatePars[0] = 0;
-        } else {
-          // update every window:
-          // get normalization for spectral difference for next window estimate
-          inst->featureData[6] =
-              inst->featureData[6] / ((float)inst->modelUpdatePars[1]);
-          inst->featureData[5] =
-              (float)0.5 * (inst->featureData[6] + inst->featureData[5]);
-          inst->featureData[6] = (float)0.0;
-        }
-      }
+    if (tmpFloat3 > 1.f) {
+      tmpFloat3 = 1.f;
     }
-    // compute speech/noise probability
-    WebRtcNs_SpeechNoiseProb(inst, inst->speechProb, snrLocPrior, snrLocPost);
-    // time-avg parameter for noise update
-    gammaNoiseTmp = NOISE_UPDATE;
-    for (i = 0; i < inst->magnLen; i++) {
-      probSpeech = inst->speechProb[i];
-      probNonSpeech = (float)1.0 - probSpeech;
-      // temporary noise update:
-      // use it for speech frames if update value is less than previous
-      noiseUpdateTmp =
-          gammaNoiseTmp * inst->noisePrev[i] +
-          ((float)1.0 - gammaNoiseTmp) *
-              (probNonSpeech * magn[i] + probSpeech * inst->noisePrev[i]);
-      //
-      // time-constant based on speech/noise state
-      gammaNoiseOld = gammaNoiseTmp;
-      gammaNoiseTmp = NOISE_UPDATE;
-      // increase gamma (i.e., less noise update) for frame likely to be speech
-      if (probSpeech > PROB_RANGE) {
-        gammaNoiseTmp = SPEECH_UPDATE;
-      }
-      // conservative noise update
-      if (probSpeech < PROB_RANGE) {
-        inst->magnAvgPause[i] +=
-            GAMMA_PAUSE * (magn[i] - inst->magnAvgPause[i]);
-      }
-      // noise update
-      if (gammaNoiseTmp == gammaNoiseOld) {
-        noise[i] = noiseUpdateTmp;
+    self->pinkNoiseExp += tmpFloat3;
+
+    // Calculate frequency independent parts of parametric noise estimate.
+    if (self->pinkNoiseExp > 0.f) {
+      // Use pink noise estimate.
+      parametric_num =
+          exp(self->pinkNoiseNumerator / (float)(self->blockInd + 1));
+      parametric_num *= (float)(self->blockInd + 1);
+      parametric_exp = self->pinkNoiseExp / (float)(self->blockInd + 1);
+    }
+    for (i = 0; i < self->magnLen; i++) {
+      // Estimate the background noise using the white and pink noise
+      // parameters.
+      if (self->pinkNoiseExp == 0.f) {
+        // Use white noise estimate.
+        self->parametricNoise[i] = self->whiteNoiseLevel;
       } else {
-        noise[i] =
-            gammaNoiseTmp * inst->noisePrev[i] +
-            ((float)1.0 - gammaNoiseTmp) *
-                (probNonSpeech * magn[i] + probSpeech * inst->noisePrev[i]);
-        // allow for noise update downwards:
-        // if noise update decreases the noise, it is safe, so allow it to
-        // happen
-        if (noiseUpdateTmp < noise[i]) {
-          noise[i] = noiseUpdateTmp;
-        }
+        // Use pink noise estimate.
+        float use_band = (float)(i < kStartBand ? kStartBand : i);
+        self->parametricNoise[i] =
+            parametric_num / pow(use_band, parametric_exp);
       }
-    }  // end of freq loop
-    // done with step 2: noise update
-
-    // keep track of noise spectrum for next frame
-    for (i = 0; i < inst->magnLen; i++) {
-      inst->noisePrev[i] = noise[i];
+      // Weight quantile noise with modeled noise.
+      noise[i] *= (self->blockInd);
+      tmpFloat2 =
+          self->parametricNoise[i] * (END_STARTUP_SHORT - self->blockInd);
+      noise[i] += (tmpFloat2 / (float)(self->blockInd + 1));
+      noise[i] /= END_STARTUP_SHORT;
     }
-  }  // end of if inst->outLen == 0
+  }
+  // Compute average signal during END_STARTUP_LONG time:
+  // used to normalize spectral difference measure.
+  if (self->blockInd < END_STARTUP_LONG) {
+    self->featureData[5] *= self->blockInd;
+    self->featureData[5] += signalEnergy;
+    self->featureData[5] /= (self->blockInd + 1);
+  }
+
+  // Post and prior SNR needed for SpeechNoiseProb.
+  ComputeSnr(self, magn, noise, snrLocPrior, snrLocPost);
+
+  FeatureUpdate(self, magn, updateParsFlag);
+  SpeechNoiseProb(self, self->speechProb, snrLocPrior, snrLocPost);
+  UpdateNoiseEstimate(self, magn, snrLocPrior, snrLocPost, noise);
+
+  // Keep track of noise spectrum for next frame.
+  memcpy(self->noise, noise, sizeof(*noise) * self->magnLen);
+  memcpy(self->magnPrevAnalyze, magn, sizeof(*magn) * self->magnLen);
 
   return 0;
 }
 
-int WebRtcNs_ProcessCore(NSinst_t* inst,
+int WebRtcNs_ProcessCore(NSinst_t* self,
                          float* speechFrame,
                          float* speechFrameHB,
                          float* outFrame,
                          float* outFrameHB) {
-  // main routine for noise reduction
+  // Main routine for noise reduction.
   int flagHB = 0;
   int i;
 
   float energy1, energy2, gain, factor, factor1, factor2;
-  float snrPrior, currentEstimateStsa;
-  float tmpFloat1, tmpFloat2;
-  float fTmp;
   float fout[BLOCKL_MAX];
   float winData[ANAL_BLOCKL_MAX];
   float magn[HALF_ANAL_BLOCKL];
   float theFilter[HALF_ANAL_BLOCKL], theFilterTmp[HALF_ANAL_BLOCKL];
   float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL];
 
-  // SWB variables
+  // SWB variables.
   int deltaBweHB = 1;
   int deltaGainHB = 1;
   float decayBweHB = 1.0;
   float gainMapParHB = 1.0;
   float gainTimeDomainHB = 1.0;
   float avgProbSpeechHB, avgProbSpeechHBTmp, avgFilterGainHB, gainModHB;
+  float sumMagnAnalyze, sumMagnProcess;
 
-  // Check that initiation has been done
-  if (inst->initFlag != 1) {
+  // Check that initiation has been done.
+  if (self->initFlag != 1) {
     return (-1);
   }
-  // Check for valid pointers based on sampling rate
-  if (inst->fs == 32000) {
+  // Check for valid pointers based on sampling rate.
+  if (self->fs == 32000) {
     if (speechFrameHB == NULL) {
       return -1;
     }
     flagHB = 1;
-    // range for averaging low band quantities for H band gain
-    deltaBweHB = (int)inst->magnLen / 4;
+    // Range for averaging low band quantities for H band gain.
+    deltaBweHB = (int)self->magnLen / 4;
     deltaGainHB = deltaBweHB;
   }
 
-  // update analysis buffer for L band
-  memcpy(inst->dataBuf,
-         inst->dataBuf + inst->blockLen10ms,
-         sizeof(float) * (inst->anaLen - inst->blockLen10ms));
-  memcpy(inst->dataBuf + inst->anaLen - inst->blockLen10ms,
-         speechFrame,
-         sizeof(float) * inst->blockLen10ms);
+  // Update analysis buffer for L band.
+  UpdateBuffer(speechFrame, self->blockLen, self->anaLen, self->dataBuf);
 
   if (flagHB == 1) {
-    // update analysis buffer for H band
-    memcpy(inst->dataBufHB,
-           inst->dataBufHB + inst->blockLen10ms,
-           sizeof(float) * (inst->anaLen - inst->blockLen10ms));
-    memcpy(inst->dataBufHB + inst->anaLen - inst->blockLen10ms,
-           speechFrameHB,
-           sizeof(float) * inst->blockLen10ms);
+    // Update analysis buffer for H band.
+    UpdateBuffer(speechFrameHB, self->blockLen, self->anaLen, self->dataBufHB);
   }
 
-  // check if processing needed
-  if (inst->outLen == 0) {
-    // windowing
-    energy1 = 0.0;
-    for (i = 0; i < inst->anaLen; i++) {
-      winData[i] = inst->window[i] * inst->dataBuf[i];
-      energy1 += winData[i] * winData[i];
+  Windowing(self->window, self->dataBuf, self->anaLen, winData);
+  energy1 = Energy(winData, self->anaLen);
+  if (energy1 == 0.0) {
+    // Synthesize the special case of zero input.
+    // Read out fully processed segment.
+    for (i = self->windShift; i < self->blockLen + self->windShift; i++) {
+      fout[i - self->windShift] = self->syntBuf[i];
     }
-    if (energy1 == 0.0) {
-      // synthesize the special case of zero input
-      // read out fully processed segment
-      for (i = inst->windShift; i < inst->blockLen + inst->windShift; i++) {
-        fout[i - inst->windShift] = inst->syntBuf[i];
-      }
-      // update synthesis buffer
-      memcpy(inst->syntBuf,
-             inst->syntBuf + inst->blockLen,
-             sizeof(float) * (inst->anaLen - inst->blockLen));
-      memset(inst->syntBuf + inst->anaLen - inst->blockLen,
-             0,
-             sizeof(float) * inst->blockLen);
-
-      // out buffer
-      inst->outLen = inst->blockLen - inst->blockLen10ms;
-      if (inst->blockLen > inst->blockLen10ms) {
-        for (i = 0; i < inst->outLen; i++) {
-          inst->outBuf[i] = fout[i + inst->blockLen10ms];
-        }
-      }
-      for (i = 0; i < inst->blockLen10ms; ++i)
-        outFrame[i] = WEBRTC_SPL_SAT(
-            WEBRTC_SPL_WORD16_MAX, fout[i], WEBRTC_SPL_WORD16_MIN);
+    // Update synthesis buffer.
+    UpdateBuffer(NULL, self->blockLen, self->anaLen, self->syntBuf);
 
-      // for time-domain gain of HB
-      if (flagHB == 1)
-        for (i = 0; i < inst->blockLen10ms; ++i)
-          outFrameHB[i] = WEBRTC_SPL_SAT(
-              WEBRTC_SPL_WORD16_MAX, inst->dataBufHB[i], WEBRTC_SPL_WORD16_MIN);
+    for (i = 0; i < self->blockLen; ++i)
+      outFrame[i] =
+          WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, fout[i], WEBRTC_SPL_WORD16_MIN);
 
-      return 0;
-    }
+    // For time-domain gain of HB.
+    if (flagHB == 1)
+      for (i = 0; i < self->blockLen; ++i)
+        outFrameHB[i] = WEBRTC_SPL_SAT(
+            WEBRTC_SPL_WORD16_MAX, self->dataBufHB[i], WEBRTC_SPL_WORD16_MIN);
 
-    // FFT
-    WebRtc_rdft(inst->anaLen, 1, winData, inst->ip, inst->wfft);
-
-    imag[0] = 0;
-    real[0] = winData[0];
-    magn[0] = (float)(fabs(real[0]) + 1.0f);
-    imag[inst->magnLen - 1] = 0;
-    real[inst->magnLen - 1] = winData[1];
-    magn[inst->magnLen - 1] = (float)(fabs(real[inst->magnLen - 1]) + 1.0f);
-    if (inst->blockInd < END_STARTUP_SHORT) {
-      inst->initMagnEst[0] += magn[0];
-      inst->initMagnEst[inst->magnLen - 1] += magn[inst->magnLen - 1];
-    }
-    for (i = 1; i < inst->magnLen - 1; i++) {
-      real[i] = winData[2 * i];
-      imag[i] = winData[2 * i + 1];
-      // magnitude spectrum
-      fTmp = real[i] * real[i];
-      fTmp += imag[i] * imag[i];
-      magn[i] = ((float)sqrt(fTmp)) + 1.0f;
-      if (inst->blockInd < END_STARTUP_SHORT) {
-        inst->initMagnEst[i] += magn[i];
-      }
-    }
+    return 0;
+  }
 
-    // Compute dd update of prior snr and post snr based on new noise estimate
-    for (i = 0; i < inst->magnLen; i++) {
-      // post and prior snr
-      currentEstimateStsa = (float)0.0;
-      if (magn[i] > inst->noisePrev[i]) {
-        currentEstimateStsa =
-            magn[i] / (inst->noisePrev[i] + (float)0.0001) - (float)1.0;
-      }
-      // DD estimate is sume of two terms: current estimate and previous
-      // estimate
-      // directed decision update of snrPrior
-      snrPrior = DD_PR_SNR * inst->previousEstimateStsa[i] +
-                 ((float)1.0 - DD_PR_SNR) * currentEstimateStsa;
-      // gain filter
-      tmpFloat1 = inst->overdrive + snrPrior;
-      tmpFloat2 = (float)snrPrior / tmpFloat1;
-      theFilter[i] = (float)tmpFloat2;
-    }  // end of loop over freqs
-
-    for (i = 0; i < inst->magnLen; i++) {
-      // flooring bottom
-      if (theFilter[i] < inst->denoiseBound) {
-        theFilter[i] = inst->denoiseBound;
-      }
-      // flooring top
-      if (theFilter[i] > (float)1.0) {
-        theFilter[i] = 1.0;
-      }
-      if (inst->blockInd < END_STARTUP_SHORT) {
-        theFilterTmp[i] =
-            (inst->initMagnEst[i] - inst->overdrive * inst->parametricNoise[i]);
-        theFilterTmp[i] /= (inst->initMagnEst[i] + (float)0.0001);
-        // flooring bottom
-        if (theFilterTmp[i] < inst->denoiseBound) {
-          theFilterTmp[i] = inst->denoiseBound;
-        }
-        // flooring top
-        if (theFilterTmp[i] > (float)1.0) {
-          theFilterTmp[i] = 1.0;
-        }
-        // Weight the two suppression filters
-        theFilter[i] *= (inst->blockInd);
-        theFilterTmp[i] *= (END_STARTUP_SHORT - inst->blockInd);
-        theFilter[i] += theFilterTmp[i];
-        theFilter[i] /= (END_STARTUP_SHORT);
-      }
-      // smoothing
-      inst->smooth[i] = theFilter[i];
-      real[i] *= inst->smooth[i];
-      imag[i] *= inst->smooth[i];
-    }
-    // keep track of magn spectrum for next frame
-    for (i = 0; i < inst->magnLen; i++) {
-      inst->magnPrev[i] = magn[i];
-    }
-    // back to time domain
-    winData[0] = real[0];
-    winData[1] = real[inst->magnLen - 1];
-    for (i = 1; i < inst->magnLen - 1; i++) {
-      winData[2 * i] = real[i];
-      winData[2 * i + 1] = imag[i];
-    }
-    WebRtc_rdft(inst->anaLen, -1, winData, inst->ip, inst->wfft);
+  FFT(self, winData, self->anaLen, self->magnLen, real, imag, magn);
 
-    for (i = 0; i < inst->anaLen; i++) {
-      real[i] = 2.0f * winData[i] / inst->anaLen;  // fft scaling
+  if (self->blockInd < END_STARTUP_SHORT) {
+    for (i = 0; i < self->magnLen; i++) {
+      self->initMagnEst[i] += magn[i];
     }
+  }
 
-    // scale factor: only do it after END_STARTUP_LONG time
-    factor = (float)1.0;
-    if (inst->gainmap == 1 && inst->blockInd > END_STARTUP_LONG) {
-      factor1 = (float)1.0;
-      factor2 = (float)1.0;
-
-      energy2 = 0.0;
-      for (i = 0; i < inst->anaLen; i++) {
-        energy2 += (float)real[i] * (float)real[i];
-      }
-      gain = (float)sqrt(energy2 / (energy1 + (float)1.0));
+  ComputeDdBasedWienerFilter(self, magn, theFilter);
 
-      // scaling for new version
-      if (gain > B_LIM) {
-        factor1 = (float)1.0 + (float)1.3 * (gain - B_LIM);
-        if (gain * factor1 > (float)1.0) {
-          factor1 = (float)1.0 / gain;
-        }
+  for (i = 0; i < self->magnLen; i++) {
+    // Flooring bottom.
+    if (theFilter[i] < self->denoiseBound) {
+      theFilter[i] = self->denoiseBound;
+    }
+    // Flooring top.
+    if (theFilter[i] > 1.f) {
+      theFilter[i] = 1.f;
+    }
+    if (self->blockInd < END_STARTUP_SHORT) {
+      theFilterTmp[i] =
+          (self->initMagnEst[i] - self->overdrive * self->parametricNoise[i]);
+      theFilterTmp[i] /= (self->initMagnEst[i] + 0.0001f);
+      // Flooring bottom.
+      if (theFilterTmp[i] < self->denoiseBound) {
+        theFilterTmp[i] = self->denoiseBound;
       }
-      if (gain < B_LIM) {
-        // don't reduce scale too much for pause regions:
-        // attenuation here should be controlled by flooring
-        if (gain <= inst->denoiseBound) {
-          gain = inst->denoiseBound;
-        }
-        factor2 = (float)1.0 - (float)0.3 * (B_LIM - gain);
+      // Flooring top.
+      if (theFilterTmp[i] > 1.f) {
+        theFilterTmp[i] = 1.f;
       }
-      // combine both scales with speech/noise prob:
-      // note prior (priorSpeechProb) is not frequency dependent
-      factor = inst->priorSpeechProb * factor1 +
-               ((float)1.0 - inst->priorSpeechProb) * factor2;
-    }  // out of inst->gainmap==1
-
-    // synthesis
-    for (i = 0; i < inst->anaLen; i++) {
-      inst->syntBuf[i] += factor * inst->window[i] * (float)real[i];
+      // Weight the two suppression filters.
+      theFilter[i] *= (self->blockInd);
+      theFilterTmp[i] *= (END_STARTUP_SHORT - self->blockInd);
+      theFilter[i] += theFilterTmp[i];
+      theFilter[i] /= (END_STARTUP_SHORT);
     }
-    // read out fully processed segment
-    for (i = inst->windShift; i < inst->blockLen + inst->windShift; i++) {
-      fout[i - inst->windShift] = inst->syntBuf[i];
-    }
-    // update synthesis buffer
-    memcpy(inst->syntBuf,
-           inst->syntBuf + inst->blockLen,
-           sizeof(float) * (inst->anaLen - inst->blockLen));
-    memset(inst->syntBuf + inst->anaLen - inst->blockLen,
-           0,
-           sizeof(float) * inst->blockLen);
 
-    // out buffer
-    inst->outLen = inst->blockLen - inst->blockLen10ms;
-    if (inst->blockLen > inst->blockLen10ms) {
-      for (i = 0; i < inst->outLen; i++) {
-        inst->outBuf[i] = fout[i + inst->blockLen10ms];
+    self->smooth[i] = theFilter[i];
+    real[i] *= self->smooth[i];
+    imag[i] *= self->smooth[i];
+  }
+  // Keep track of |magn| spectrum for next frame.
+  memcpy(self->magnPrevProcess, magn, sizeof(*magn) * self->magnLen);
+  memcpy(self->noisePrev, self->noise, sizeof(self->noise[0]) * self->magnLen);
+  // Back to time domain.
+  IFFT(self, real, imag, self->magnLen, self->anaLen, winData);
+
+  // Scale factor: only do it after END_STARTUP_LONG time.
+  factor = 1.f;
+  if (self->gainmap == 1 && self->blockInd > END_STARTUP_LONG) {
+    factor1 = 1.f;
+    factor2 = 1.f;
+
+    energy2 = Energy(winData, self->anaLen);
+    gain = (float)sqrt(energy2 / (energy1 + 1.f));
+
+    // Scaling for new version.
+    if (gain > B_LIM) {
+      factor1 = 1.f + 1.3f * (gain - B_LIM);
+      if (gain * factor1 > 1.f) {
+        factor1 = 1.f / gain;
       }
     }
-  }  // end of if out.len==0
-  else {
-    for (i = 0; i < inst->blockLen10ms; i++) {
-      fout[i] = inst->outBuf[i];
+    if (gain < B_LIM) {
+      // Don't reduce scale too much for pause regions:
+      // attenuation here should be controlled by flooring.
+      if (gain <= self->denoiseBound) {
+        gain = self->denoiseBound;
+      }
+      factor2 = 1.f - 0.3f * (B_LIM - gain);
     }
-    memcpy(inst->outBuf,
-           inst->outBuf + inst->blockLen10ms,
-           sizeof(float) * (inst->outLen - inst->blockLen10ms));
-    memset(inst->outBuf + inst->outLen - inst->blockLen10ms,
-           0,
-           sizeof(float) * inst->blockLen10ms);
-    inst->outLen -= inst->blockLen10ms;
+    // Combine both scales with speech/noise prob:
+    // note prior (priorSpeechProb) is not frequency dependent.
+    factor = self->priorSpeechProb * factor1 +
+             (1.f - self->priorSpeechProb) * factor2;
+  }  // Out of self->gainmap == 1.
+
+  Windowing(self->window, winData, self->anaLen, winData);
+
+  // Synthesis.
+  for (i = 0; i < self->anaLen; i++) {
+    self->syntBuf[i] += factor * winData[i];
   }
+  // Read out fully processed segment.
+  for (i = self->windShift; i < self->blockLen + self->windShift; i++) {
+    fout[i - self->windShift] = self->syntBuf[i];
+  }
+  // Update synthesis buffer.
+  UpdateBuffer(NULL, self->blockLen, self->anaLen, self->syntBuf);
 
-  for (i = 0; i < inst->blockLen10ms; ++i)
+  for (i = 0; i < self->blockLen; ++i)
     outFrame[i] =
         WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, fout[i], WEBRTC_SPL_WORD16_MIN);
 
-  // for time-domain gain of HB
+  // For time-domain gain of HB.
   if (flagHB == 1) {
-    // average speech prob from low band
-    // avg over second half (i.e., 4->8kHz) of freq. spectrum
+    // Average speech prob from low band.
+    // Average over second half (i.e., 4->8kHz) of frequencies spectrum.
     avgProbSpeechHB = 0.0;
-    for (i = inst->magnLen - deltaBweHB - 1; i < inst->magnLen - 1; i++) {
-      avgProbSpeechHB += inst->speechProb[i];
+    for (i = self->magnLen - deltaBweHB - 1; i < self->magnLen - 1; i++) {
+      avgProbSpeechHB += self->speechProb[i];
     }
     avgProbSpeechHB = avgProbSpeechHB / ((float)deltaBweHB);
-    // average filter gain from low band
-    // average over second half (i.e., 4->8kHz) of freq. spectrum
+    // If the speech was suppressed by a component between Analyze and
+    // Process, for example the AEC, then it should not be considered speech
+    // for high band suppression purposes.
+    sumMagnAnalyze = 0;
+    sumMagnProcess = 0;
+    for (i = 0; i < self->magnLen; ++i) {
+      sumMagnAnalyze += self->magnPrevAnalyze[i];
+      sumMagnProcess += self->magnPrevProcess[i];
+    }
+    avgProbSpeechHB *= sumMagnProcess / sumMagnAnalyze;
+    // Average filter gain from low band.
+    // Average over second half (i.e., 4->8kHz) of frequencies spectrum.
     avgFilterGainHB = 0.0;
-    for (i = inst->magnLen - deltaGainHB - 1; i < inst->magnLen - 1; i++) {
-      avgFilterGainHB += inst->smooth[i];
+    for (i = self->magnLen - deltaGainHB - 1; i < self->magnLen - 1; i++) {
+      avgFilterGainHB += self->smooth[i];
     }
     avgFilterGainHB = avgFilterGainHB / ((float)(deltaGainHB));
-    avgProbSpeechHBTmp = (float)2.0 * avgProbSpeechHB - (float)1.0;
-    // gain based on speech prob:
-    gainModHB = (float)0.5 *
-                ((float)1.0 + (float)tanh(gainMapParHB * avgProbSpeechHBTmp));
-    // combine gain with low band gain
-    gainTimeDomainHB = (float)0.5 * gainModHB + (float)0.5 * avgFilterGainHB;
-    if (avgProbSpeechHB >= (float)0.5) {
-      gainTimeDomainHB =
-          (float)0.25 * gainModHB + (float)0.75 * avgFilterGainHB;
+    avgProbSpeechHBTmp = 2.f * avgProbSpeechHB - 1.f;
+    // Gain based on speech probability.
+    gainModHB = 0.5f * (1.f + (float)tanh(gainMapParHB * avgProbSpeechHBTmp));
+    // Combine gain with low band gain.
+    gainTimeDomainHB = 0.5f * gainModHB + 0.5f * avgFilterGainHB;
+    if (avgProbSpeechHB >= 0.5f) {
+      gainTimeDomainHB = 0.25f * gainModHB + 0.75f * avgFilterGainHB;
     }
     gainTimeDomainHB = gainTimeDomainHB * decayBweHB;
-    // make sure gain is within flooring range
-    // flooring bottom
-    if (gainTimeDomainHB < inst->denoiseBound) {
-      gainTimeDomainHB = inst->denoiseBound;
+    // Make sure gain is within flooring range.
+    // Flooring bottom.
+    if (gainTimeDomainHB < self->denoiseBound) {
+      gainTimeDomainHB = self->denoiseBound;
     }
-    // flooring top
-    if (gainTimeDomainHB > (float)1.0) {
-      gainTimeDomainHB = 1.0;
+    // Flooring top.
+    if (gainTimeDomainHB > 1.f) {
+      gainTimeDomainHB = 1.f;
     }
-    // apply gain
-    for (i = 0; i < inst->blockLen10ms; i++) {
-      float o = gainTimeDomainHB * inst->dataBufHB[i];
+    // Apply gain.
+    for (i = 0; i < self->blockLen; i++) {
+      float o = gainTimeDomainHB * self->dataBufHB[i];
       outFrameHB[i] =
           WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, o, WEBRTC_SPL_WORD16_MIN);
     }
-  }  // end of H band gain computation
-  //
+  }  // End of H band gain computation.
 
   return 0;
 }