diff options
Diffstat (limited to 'src/modules/audio_processing/ns/main/source/ns_core.c')
-rw-r--r-- | src/modules/audio_processing/ns/main/source/ns_core.c | 1500 |
1 files changed, 0 insertions, 1500 deletions
diff --git a/src/modules/audio_processing/ns/main/source/ns_core.c b/src/modules/audio_processing/ns/main/source/ns_core.c deleted file mode 100644 index 10a1b831f7..0000000000 --- a/src/modules/audio_processing/ns/main/source/ns_core.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include <string.h> -#include <math.h> -//#include <stdio.h> -#include <stdlib.h> -#include "noise_suppression.h" -#include "ns_core.h" -#include "windows_private.h" -#include "fft4g.h" -#include "signal_processing_library.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 -} - -// Initialize state -int WebRtcNs_InitCore(NSinst_t *inst, WebRtc_UWord32 fs) -{ - int i; - //We only support 10ms frames - - //check for valid pointer - if (inst == NULL) - { - return -1; - } - - // Initialization of struct - if (fs == 8000 || fs == 16000 || fs == 32000) - { - inst->fs = fs; - } - else - { - return -1; - } - inst->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; - } - else if (fs == 16000) - { - // We only support 10ms frames - inst->blockLen = 160; - inst->blockLen10ms = 160; - inst->anaLen = 256; - inst->window = kBlocks160w256; - inst->outLen = 0; - } - else if (fs==32000) - { - // We only support 10ms frames - inst->blockLen = 160; - inst->blockLen10ms = 160; - inst->anaLen = 256; - inst->window = kBlocks160w256; - inst->outLen = 0; - } - inst->magnLen = inst->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); - rdft(inst->anaLen, 1, inst->dataBuf, inst->ip, inst->wfft); - - memset(inst->dataBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); - memset(inst->syntBuf, 0, sizeof(float) * ANAL_BLOCKL_MAX); - - //for HB processing - memset(inst->dataBufHB, 0, sizeof(float) * ANAL_BLOCKL_MAX); - - //for quantile noise estimation - memset(inst->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; - } - - for (i = 0; i < SIMULT; i++) - { - inst->counter[i] = (int)floor((float)(END_STARTUP_LONG * (i + 1)) / (float)SIMULT); - } - - inst->updates = 0; - - // Wiener filter initialization - for (i = 0; i < HALF_ANAL_BLOCKL; i++) - { - inst->smooth[i] = (float)1.0; - } - - // Set the aggressiveness: default - inst->aggrMode = 0; - - //initialize variables for new method - inst->priorSpeechProb = (float)0.5; //prior prob for speech/noise - 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->speechProbHB[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); // Set feature configuration - - //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); - } - - 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; - } - return 0; -} - -// Estimate noise -void WebRtcNs_NoiseEstimation(NSinst_t *inst, float *magn, float *noise) -{ - int i, s, offset; - float lmagn[HALF_ANAL_BLOCKL], delta; - - if (inst->updates < END_STARTUP_LONG) - { - inst->updates++; - } - - for (i = 0; i < inst->magnLen; i++) - { - lmagn[i] = (float)log(magn[i]); - } - - // loop over simultaneous estimates - for (s = 0; s < SIMULT; s++) - { - offset = s * inst->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]; - } - 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); - } - else - { - inst->lquantile[offset + i] -= ((float)1.0 - QUANTILE) * delta - / (float)(inst->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); - } - } // 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]); - } - } - } - - inst->counter[s]++; - } // end loop over simultaneous estimates - - // Sequentially update the noise during startup - if (inst->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 < inst->magnLen; i++) - { - noise[i] = inst->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) -{ - int i, useFeatureSpecFlat, useFeatureSpecDiff, numHistLrt; - int maxPeak1, maxPeak2; - int weightPeak1SpecFlat, weightPeak2SpecFlat, weightPeak1SpecDiff, weightPeak2SpecDiff; - - float binMid, featureSum; - 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]; - - //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]++; - } - // 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 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]++; - } - } - - // extract parameters for speech/noise probability - if (flag == 1) - { - //lrt feature: compute the average over inst->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]; - } - avgSquareHistLrt += inst->histLrt[i] * binMid * binMid; - avgHistLrtCompl += inst->histLrt[i] * binMid; - } - if (numHistLrt > 0) - { - avgHistLrt = avgHistLrt / ((float)numHistLrt); - } - avgHistLrtCompl = avgHistLrtCompl / ((float)inst->modelUpdatePars[1]); - avgSquareHistLrt = avgSquareHistLrt / ((float)inst->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; - } - 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; - } - if (inst->priorModelPars[0] > inst->featureExtractionParams.maxLrt) - { - inst->priorModelPars[0] = inst->featureExtractionParams.maxLrt; - } - } - // done with lrt feature - - // - // for spectral flatness and spectral difference: compute the main peaks of histogram - maxPeak1 = 0; - maxPeak2 = 0; - posPeak1SpecFlat = 0.0; - posPeak2SpecFlat = 0.0; - weightPeak1SpecFlat = 0; - weightPeak2SpecFlat = 0; - - // 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 - maxPeak2 = maxPeak1; - weightPeak2SpecFlat = weightPeak1SpecFlat; - posPeak2SpecFlat = posPeak1SpecFlat; - - maxPeak1 = inst->histSpecFlat[i]; - weightPeak1SpecFlat = inst->histSpecFlat[i]; - posPeak1SpecFlat = binMid; - } - else if (inst->histSpecFlat[i] > maxPeak2) - { - // Found new "second" peak - maxPeak2 = inst->histSpecFlat[i]; - weightPeak2SpecFlat = inst->histSpecFlat[i]; - posPeak2SpecFlat = binMid; - } - } - - //compute two peaks for spectral difference - maxPeak1 = 0; - maxPeak2 = 0; - posPeak1SpecDiff = 0.0; - posPeak2SpecDiff = 0.0; - weightPeak1SpecDiff = 0; - weightPeak2SpecDiff = 0; - // 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 - maxPeak2 = maxPeak1; - weightPeak2SpecDiff = weightPeak1SpecDiff; - posPeak2SpecDiff = posPeak1SpecDiff; - - maxPeak1 = inst->histSpecDiff[i]; - weightPeak1SpecDiff = inst->histSpecDiff[i]; - posPeak1SpecDiff = binMid; - } - else if (inst->histSpecDiff[i] > maxPeak2) - { - // Found new "second" peak - maxPeak2 = inst->histSpecDiff[i]; - weightPeak2SpecDiff = inst->histSpecDiff[i]; - posPeak2SpecDiff = binMid; - } - } - - // for spectrum flatness feature - useFeatureSpecFlat = 1; - // merge the two peaks if they are close - if ((fabs(posPeak2SpecFlat - posPeak1SpecFlat) - < inst->featureExtractionParams.limitPeakSpacingSpecFlat) - && (weightPeak2SpecFlat - > inst->featureExtractionParams.limitPeakWeightsSpecFlat - * weightPeak1SpecFlat)) - { - weightPeak1SpecFlat += weightPeak2SpecFlat; - posPeak1SpecFlat = (float)0.5 * (posPeak1SpecFlat + posPeak2SpecFlat); - } - //reject if weight of peaks is not large enough, or peak value too small - if (weightPeak1SpecFlat < inst->featureExtractionParams.thresWeightSpecFlat - || posPeak1SpecFlat < inst->featureExtractionParams.thresPosSpecFlat) - { - useFeatureSpecFlat = 0; - } - // 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; - } - if (inst->priorModelPars[1] > inst->featureExtractionParams.maxSpecFlat) - { - inst->priorModelPars[1] = inst->featureExtractionParams.maxSpecFlat; - } - } - // done with flatness feature - - // for template feature - useFeatureSpecDiff = 1; - // merge the two peaks if they are close - if ((fabs(posPeak2SpecDiff - posPeak1SpecDiff) - < inst->featureExtractionParams.limitPeakSpacingSpecDiff) - && (weightPeak2SpecDiff - > inst->featureExtractionParams.limitPeakWeightsSpecDiff - * weightPeak1SpecDiff)) - { - weightPeak1SpecDiff += weightPeak2SpecDiff; - posPeak1SpecDiff = (float)0.5 * (posPeak1SpecDiff + posPeak2SpecDiff); - } - // get the threshold value - inst->priorModelPars[3] = inst->featureExtractionParams.factor1ModelPars - * posPeak1SpecDiff; - //reject if weight of peaks is not large enough - if (weightPeak1SpecDiff < inst->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; - } - if (inst->priorModelPars[3] > inst->featureExtractionParams.maxSpecDiff) - { - inst->priorModelPars[3] = inst->featureExtractionParams.maxSpecDiff; - } - // 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) - { - 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 - featureSum = (float)(1 + useFeatureSpecFlat + useFeatureSpecDiff); - inst->priorModelPars[4] = (float)1.0 / featureSum; - inst->priorModelPars[5] = ((float)useFeatureSpecFlat) / featureSum; - inst->priorModelPars[6] = ((float)useFeatureSpecDiff) / featureSum; - - // set hists to zero for next update - if (inst->modelUpdatePars[0] >= 1) - { - for (i = 0; i < HIST_PAR_EST; i++) - { - inst->histLrt[i] = 0; - inst->histSpecFlat[i] = 0; - inst->histSpecDiff[i] = 0; - } - } - } // 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) -{ - int i; - int shiftLP = 1; //option to remove first bin(s) from spectral measures - float avgSpectralFlatnessNum, avgSpectralFlatnessDen, spectralTmp; - - // comute spectral measures - // for flatness - avgSpectralFlatnessNum = 0.0; - avgSpectralFlatnessDen = inst->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++) - { - if (magnIn[i] > 0.0) - { - avgSpectralFlatnessNum += (float)log(magnIn[i]); - } - else - { - inst->featureData[0] -= SPECT_FL_TAVG * inst->featureData[0]; - return; - } - } - //normalize - avgSpectralFlatnessDen = avgSpectralFlatnessDen / inst->magnLen; - avgSpectralFlatnessNum = avgSpectralFlatnessNum / inst->magnLen; - - //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 -} - -// 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) -{ - // 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]; - } - avgPause = avgPause / ((float)inst->magnLen); - avgMagn = avgMagn / ((float)inst->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); - varPause += (inst->magnAvgPause[i] - avgPause) * (inst->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; - - 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]); -} - -// 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) -{ - int i, sgnMap; - float invLrt, gainPrior, indPrior; - float logLrtTimeAvgKsum, besselTmp; - float indicator0, indicator1, indicator2; - float tmpFloat1, tmpFloat2; - float weightIndPrior0, weightIndPrior1, weightIndPrior2; - float threshPrior0, threshPrior1, threshPrior2; - 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 - - //threshold parameters for features - threshPrior0 = inst->priorModelPars[0]; - threshPrior1 = inst->priorModelPars[1]; - threshPrior2 = inst->priorModelPars[3]; - - //sign for flatness feature - sgnMap = (int)(inst->priorModelPars[2]); - - //weight parameters for features - weightIndPrior0 = inst->priorModelPars[4]; - weightIndPrior1 = inst->priorModelPars[5]; - weightIndPrior2 = inst->priorModelPars[6]; - - // 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]; - } - logLrtTimeAvgKsum = (float)logLrtTimeAvgKsum / (inst->magnLen); - inst->featureData[3] = logLrtTimeAvgKsum; - // done with computation of LR factor - - // - //compute the indicator functions - // - - // average lrt feature - widthPrior = widthPrior0; - //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); - - //spectral flatness feature - tmpFloat1 = inst->featureData[0]; - widthPrior = widthPrior0; - //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 - indicator1 = (float)0.5 * ((float)tanh( - (float)sgnMap * widthPrior * (threshPrior1 - - tmpFloat1)) + (float)1.0); - - //for template spectrum-difference - tmpFloat1 = inst->featureData[4]; - widthPrior = widthPrior0; - //use larger width in tanh map for pause regions - if (tmpFloat1 < threshPrior2) - { - widthPrior = widthPrior2; - } - // compute indicator function: sigmoid map - indicator2 = (float)0.5 * ((float)tanh(widthPrior * (tmpFloat1 - threshPrior2)) - + (float)1.0); - - //combine the indicator function with the feature weights - indPrior = weightIndPrior0 * indicator0 + weightIndPrior1 * indicator1 + weightIndPrior2 - * indicator2; - // 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; - } - if (inst->priorSpeechProb < 0.01) - { - inst->priorSpeechProb = (float)0.01; - } - - //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]); - invLrt = (float)gainPrior * invLrt; - probSpeechFinal[i] = (float)1.0 / ((float)1.0 + invLrt); - } -} - -int WebRtcNs_ProcessCore(NSinst_t *inst, - short *speechFrame, - short *speechFrameHB, - short *outFrame, - short *outFrameHB) -{ - // main routine for noise reduction - - int flagHB = 0; - int i; - const int kStartBand = 5; // Skip first frequency bins during estimation. - int updateParsFlag; - - float energy1, energy2, gain, factor, factor1, factor2; - float signalEnergy, sumMagn; - float snrPrior, currentEstimateStsa; - float tmpFloat1, tmpFloat2, tmpFloat3, probSpeech, probNonSpeech; - float gammaNoiseTmp, gammaNoiseOld; - float noiseUpdateTmp, fTmp, dTmp; - float fin[BLOCKL_MAX], fout[BLOCKL_MAX]; - float winData[ANAL_BLOCKL_MAX]; - float magn[HALF_ANAL_BLOCKL], noise[HALF_ANAL_BLOCKL]; - float theFilter[HALF_ANAL_BLOCKL], theFilterTmp[HALF_ANAL_BLOCKL]; - float snrLocPost[HALF_ANAL_BLOCKL], snrLocPrior[HALF_ANAL_BLOCKL]; - float probSpeechFinal[HALF_ANAL_BLOCKL], previousEstimateStsa[HALF_ANAL_BLOCKL]; - float real[ANAL_BLOCKL_MAX], imag[HALF_ANAL_BLOCKL]; - // Variables during startup - float sum_log_i = 0.0; - float sum_log_i_square = 0.0; - float sum_log_magn = 0.0; - float sum_log_i_log_magn = 0.0; - float parametric_noise = 0.0; - float parametric_exp = 0.0; - float parametric_num = 0.0; - - // 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; - - // Check that initiation has been done - if (inst->initFlag != 1) - { - return (-1); - } - // Check for valid pointers based on sampling rate - if (inst->fs == 32000) - { - if (speechFrameHB == NULL) - { - return -1; - } - flagHB = 1; - // range for averaging low band quantities for H band gain - deltaBweHB = (int)inst->magnLen / 4; - deltaGainHB = deltaBweHB; - } - // - updateParsFlag = inst->modelUpdatePars[0]; - // - - //for LB do all processing - // convert to float - for (i = 0; i < inst->blockLen10ms; i++) - { - fin[i] = (float)speechFrame[i]; - } - // 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, fin, - sizeof(float) * inst->blockLen10ms); - - if (flagHB == 1) - { - // convert to float - for (i = 0; i < inst->blockLen10ms; i++) - { - fin[i] = (float)speechFrameHB[i]; - } - // 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, fin, - sizeof(float) * inst->blockLen10ms); - } - - // 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]; - } - if (energy1 == 0.0) - { - // synthesize the special case of zero input - // 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. - - // 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]; - } - } - // convert to short - for (i = 0; i < inst->blockLen10ms; i++) - { - dTmp = fout[i]; - if (dTmp < WEBRTC_SPL_WORD16_MIN) - { - dTmp = WEBRTC_SPL_WORD16_MIN; - } - else if (dTmp > WEBRTC_SPL_WORD16_MAX) - { - dTmp = WEBRTC_SPL_WORD16_MAX; - } - outFrame[i] = (short)dTmp; - } - - // for time-domain gain of HB - if (flagHB == 1) - { - for (i = 0; i < inst->blockLen10ms; i++) - { - dTmp = inst->dataBufHB[i]; - if (dTmp < WEBRTC_SPL_WORD16_MIN) - { - dTmp = WEBRTC_SPL_WORD16_MIN; - } - else if (dTmp > WEBRTC_SPL_WORD16_MAX) - { - dTmp = WEBRTC_SPL_WORD16_MAX; - } - outFrameHB[i] = (short)dTmp; - } - } // end of H band gain computation - // - return 0; - } - - // - inst->blockInd++; // Update the block index only when we process a block. - // FFT - 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) - { - inst->initMagnEst[0] += magn[0]; - inst->initMagnEst[inst->magnLen - 1] += magn[inst->magnLen - 1]; - 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) - { - inst->initMagnEst[i] += magn[i]; - 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 white noise estimate - parametric_noise = inst->whiteNoiseLevel; - } - else - { - // 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); - parametric_noise = parametric_num / pow((float)kStartBand, parametric_exp); - } - for (i = 0; i < inst->magnLen; i++) - { - // Estimate the background noise using the white and pink noise parameters - if ((inst->pinkNoiseExp > 0.0f) && (i >= kStartBand)) - { - // Use pink noise estimate - parametric_noise = parametric_num / pow((float)i, parametric_exp); - } - theFilterTmp[i] = (inst->initMagnEst[i] - inst->overdrive * parametric_noise); - theFilterTmp[i] /= (inst->initMagnEst[i] + (float)0.0001); - // Weight quantile noise with modeled noise - noise[i] *= (inst->blockInd); - tmpFloat2 = parametric_noise * (END_STARTUP_SHORT - inst->blockInd); - noise[i] += (tmpFloat2 / (float)(inst->blockInd + 1)); - noise[i] /= END_STARTUP_SHORT; - } - } - //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); - } - -#ifdef PROCESS_FLOW_0 - if (inst->blockInd > END_STARTUP_LONG) - { - //option: average the quantile noise: for check with AEC2 - for (i = 0; i < inst->magnLen; i++) - { - noise[i] = (float)0.6 * inst->noisePrev[i] + (float)0.4 * noise[i]; - } - for (i = 0; i < inst->magnLen; i++) - { - // Wiener with over sub-substraction: - theFilter[i] = (magn[i] - inst->overdrive * noise[i]) / (magn[i] + (float)0.0001); - } - } -#else - //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 - 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 * previousEstimateStsa[i] + ((float)1.0 - DD_PR_SNR) - * snrLocPost[i]; - // post and prior snr needed for step 2 - } // end of loop over freqs -#ifdef PROCESS_FLOW_1 - for (i = 0; i < inst->magnLen; i++) - { - // gain filter - tmpFloat1 = inst->overdrive + snrLocPrior[i]; - tmpFloat2 = (float)snrLocPrior[i] / tmpFloat1; - theFilter[i] = (float)tmpFloat2; - } // end of loop over freqs -#endif - // done with step 1: dd computation of prior and post snr - - // - //STEP 2: compute speech/noise likelihood - // -#ifdef PROCESS_FLOW_2 - // 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; - } - } - } - // compute speech/noise probability - WebRtcNs_SpeechNoiseProb(inst, probSpeechFinal, snrLocPrior, snrLocPost); - // time-avg parameter for noise update - gammaNoiseTmp = NOISE_UPDATE; - for (i = 0; i < inst->magnLen; i++) - { - probSpeech = probSpeechFinal[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; - } - 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; - } - } - } // end of freq loop - // done with step 2: noise update - - // - // STEP 3: 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] > noise[i]) - { - currentEstimateStsa = magn[i] / (noise[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 * 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 - // done with step3 -#endif -#endif - - 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) - { - // 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 -#ifdef PROCESS_FLOW_0 - inst->smooth[i] *= SMOOTH; // value set to 0.7 in define.h file - inst->smooth[i] += ((float)1.0 - SMOOTH) * theFilter[i]; -#else - inst->smooth[i] = theFilter[i]; -#endif - real[i] *= inst->smooth[i]; - imag[i] *= inst->smooth[i]; - } - // keep track of noise and magn spectrum for next frame - for (i = 0; i < inst->magnLen; i++) - { - inst->noisePrev[i] = noise[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]; - } - rdft(inst->anaLen, -1, winData, inst->ip, inst->wfft); - - for (i = 0; i < inst->anaLen; i++) - { - real[i] = 2.0f * winData[i] / inst->anaLen; // fft scaling - } - - //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)); - -#ifdef PROCESS_FLOW_2 - // 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; - } - } - 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); - } - //combine both scales with speech/noise prob: - // note prior (priorSpeechProb) is not frequency dependent - factor = inst->priorSpeechProb * factor1 + ((float)1.0 - inst->priorSpeechProb) - * factor2; -#else - if (gain > B_LIM) - { - factor = (float)1.0 + (float)1.3 * (gain - B_LIM); - } - else - { - factor = (float)1.0 + (float)2.0 * (gain - B_LIM); - } - if (gain * factor > (float)1.0) - { - factor = (float)1.0 / gain; - } -#endif - } // out of inst->gainmap==1 - - // synthesis - for (i = 0; i < inst->anaLen; i++) - { - inst->syntBuf[i] += factor * inst->window[i] * (float)real[i]; - } - // 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]; - } - } - } // end of if out.len==0 - else - { - for (i = 0; i < inst->blockLen10ms; i++) - { - fout[i] = inst->outBuf[i]; - } - 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; - } - - // convert to short - for (i = 0; i < inst->blockLen10ms; i++) - { - dTmp = fout[i]; - if (dTmp < WEBRTC_SPL_WORD16_MIN) - { - dTmp = WEBRTC_SPL_WORD16_MIN; - } - else if (dTmp > WEBRTC_SPL_WORD16_MAX) - { - dTmp = WEBRTC_SPL_WORD16_MAX; - } - outFrame[i] = (short)dTmp; - } - - // for time-domain gain of HB - if (flagHB == 1) - { - for (i = 0; i < inst->magnLen; i++) - { - inst->speechProbHB[i] = probSpeechFinal[i]; - } - if (inst->blockInd > END_STARTUP_LONG) - { - // average speech prob from low band - // avg over second half (i.e., 4->8kHz) of freq. spectrum - avgProbSpeechHB = 0.0; - for (i = inst->magnLen - deltaBweHB - 1; i < inst->magnLen - 1; i++) - { - avgProbSpeechHB += inst->speechProbHB[i]; - } - avgProbSpeechHB = avgProbSpeechHB / ((float)deltaBweHB); - // average filter gain from low band - // average over second half (i.e., 4->8kHz) of freq. spectrum - avgFilterGainHB = 0.0; - for (i = inst->magnLen - deltaGainHB - 1; i < inst->magnLen - 1; i++) - { - avgFilterGainHB += inst->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; - } - gainTimeDomainHB = gainTimeDomainHB * decayBweHB; - } // end of converged - //make sure gain is within flooring range - // flooring bottom - if (gainTimeDomainHB < inst->denoiseBound) - { - gainTimeDomainHB = inst->denoiseBound; - } - // flooring top - if (gainTimeDomainHB > (float)1.0) - { - gainTimeDomainHB = 1.0; - } - //apply gain - for (i = 0; i < inst->blockLen10ms; i++) - { - dTmp = gainTimeDomainHB * inst->dataBufHB[i]; - if (dTmp < WEBRTC_SPL_WORD16_MIN) - { - dTmp = WEBRTC_SPL_WORD16_MIN; - } - else if (dTmp > WEBRTC_SPL_WORD16_MAX) - { - dTmp = WEBRTC_SPL_WORD16_MAX; - } - outFrameHB[i] = (short)dTmp; - } - } // end of H band gain computation - // - - return 0; -} |