This CL adds guards against division by zero, that should fix http://b/issue?id=5278531

In addition a read outside memory event has been detected and removed.
Also an improper noise weighting has been corrected.
Review URL: http://webrtc-codereview.appspot.com/152001

git-svn-id: http://webrtc.googlecode.com/svn/trunk@640 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
bjornv@google.com 2011-09-23 12:39:47 +00:00
parent 9e7774f163
commit 8e9e83b530
2 changed files with 169 additions and 136 deletions

View File

@ -14,16 +14,13 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "nsx_core.h" #include "nsx_core.h"
// Skip first frequency bins during estimation. (0 <= value < 64) // Skip first frequency bins during estimation. (0 <= value < 64)
static const int kStartBand = 5; static const int kStartBand = 5;
// Rounding
static const WebRtc_Word16 kRoundTable[16] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
2048, 4096, 8192, 16384};
// Constants to compensate for shifting signal log(2^shifts). // Constants to compensate for shifting signal log(2^shifts).
const WebRtc_Word16 WebRtcNsx_kLogTable[9] = {0, 177, 355, 532, 710, 887, 1065, 1242, 1420}; const WebRtc_Word16 WebRtcNsx_kLogTable[9] = {0, 177, 355, 532, 710, 887, 1065, 1242, 1420};
@ -246,7 +243,16 @@ static const WebRtc_Word16 kBlocks160w256x[256] = {
2139, 1872, 1606, 1339, 1072, 804, 536, 268 2139, 1872, 1606, 1339, 1072, 804, 536, 268
}; };
// Gain factor table: Input value in Q8 and output value in Q13 // Gain factor1 table: Input value in Q8 and output value in Q13
// original floating point code
// if (gain > blim) {
// factor1 = 1.0 + 1.3 * (gain - blim);
// if (gain * factor1 > 1.0) {
// factor1 = 1.0 / gain;
// }
// } else {
// factor1 = 1.0;
// }
static const WebRtc_Word16 kFactor1Table[257] = { static const WebRtc_Word16 kFactor1Table[257] = {
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
@ -270,6 +276,17 @@ static const WebRtc_Word16 kFactor1Table[257] = {
8306, 8289, 8273, 8256, 8240, 8224, 8208, 8192 8306, 8289, 8273, 8256, 8240, 8224, 8208, 8192
}; };
// For Factor2 tables
// original floating point code
// if (gain > blim) {
// factor2 = 1.0;
// } else {
// factor2 = 1.0 - 0.3 * (blim - gain);
// if (gain <= inst->denoiseBound) {
// factor2 = 1.0 - 0.3 * (blim - inst->denoiseBound);
// }
// }
//
// Gain factor table: Input value in Q8 and output value in Q13 // Gain factor table: Input value in Q8 and output value in Q13
static const WebRtc_Word16 kFactor2Aggressiveness1[257] = { static const WebRtc_Word16 kFactor2Aggressiveness1[257] = {
7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577,
@ -403,39 +420,44 @@ static const WebRtc_Word16 kDeterminantEstMatrix[66] = {
355, 330 355, 330
}; };
void WebRtcNsx_UpdateNoiseEstimate(NsxInst_t *inst, int offset) void WebRtcNsx_UpdateNoiseEstimate(NsxInst_t *inst, int offset) {
{
WebRtc_Word32 tmp32no1 = 0; WebRtc_Word32 tmp32no1 = 0;
WebRtc_Word32 tmp32no2 = 0; WebRtc_Word32 tmp32no2 = 0;
WebRtc_Word16 tmp16no1 = 0; WebRtc_Word16 tmp16no1 = 0;
WebRtc_Word16 tmp16no2 = 0; WebRtc_Word16 tmp16no2 = 0;
WebRtc_Word16 exp2Const = 11819; // Q13 const WebRtc_Word16 kExp2Const = 11819; // Q13
int i = 0; int i = 0;
tmp16no2 = WebRtcSpl_MaxValueW16(inst->noiseEstLogQuantile + offset, inst->magnLen); tmp16no2 = WebRtcSpl_MaxValueW16(inst->noiseEstLogQuantile + offset,
inst->qNoise = 14 inst->magnLen);
- (int)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(exp2Const, tmp16no2, 21); // Guarantee a Q-domain as high as possible and still fit in int16
for (i = 0; i < inst->magnLen; i++) inst->qNoise = 14 - (int) WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2Const,
{ tmp16no2,
21);
for (i = 0; i < inst->magnLen; i++) {
// inst->quantile[i]=exp(inst->lquantile[offset+i]); // inst->quantile[i]=exp(inst->lquantile[offset+i]);
// in Q21 // in Q21
tmp32no2 = WEBRTC_SPL_MUL_16_16(exp2Const, inst->noiseEstLogQuantile[offset + i]); tmp32no2 = WEBRTC_SPL_MUL_16_16(kExp2Const,
tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); inst->noiseEstLogQuantile[offset + i]);
tmp16no1 = -(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32no2, 21); tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac
tmp16no1 = -(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmp32no2, 21);
tmp16no1 += 21;// shift 21 to get result in Q0 tmp16no1 += 21;// shift 21 to get result in Q0
tmp16no1 -= (WebRtc_Word16)inst->qNoise; //shift to get result in Q(qNoise) tmp16no1 -= (WebRtc_Word16) inst->qNoise; //shift to get result in Q(qNoise)
if (tmp16no1 > 0) if (tmp16no1 > 0) {
{ tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no1, tmp16no1);
inst->noiseEstQuantile[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32no1 + } else {
kRoundTable[tmp16no1], tmp16no1); tmp32no1 = WEBRTC_SPL_LSHIFT_W32(tmp32no1, -tmp16no1);
} }
else // TODO(bjornv): Replace with WebRtcSpl_SatW32ToW16(...) when available.
{ if (tmp32no1 > 32767) {
inst->noiseEstQuantile[i] = (WebRtc_Word16)WEBRTC_SPL_LSHIFT_W32(tmp32no1, tmp32no1 = 32767;
-tmp16no1); } else if (tmp32no1 < -32768) {
tmp32no1 = -32768;
} }
tmp16no1 = (WebRtc_Word16) tmp32no1;
inst->noiseEstQuantile[i] = tmp16no1;
} }
} }
@ -454,7 +476,8 @@ void WebRtcNsx_CalcParametricNoiseEstimate(NsxInst_t *inst,
// Use pink noise estimate // Use pink noise estimate
// noise_estimate = 2^(pinkNoiseNumerator + pinkNoiseExp * log2(j)) // noise_estimate = 2^(pinkNoiseNumerator + pinkNoiseExp * log2(j))
assert(freq_index > 0); assert(freq_index >= 0);
assert(freq_index < 129);
tmp32no2 = WEBRTC_SPL_MUL_16_16(pink_noise_exp_avg, kLogIndex[freq_index]); // Q26 tmp32no2 = WEBRTC_SPL_MUL_16_16(pink_noise_exp_avg, kLogIndex[freq_index]); // Q26
tmp32no2 = WEBRTC_SPL_RSHIFT_W32(tmp32no2, 15); // Q11 tmp32no2 = WEBRTC_SPL_RSHIFT_W32(tmp32no2, 15); // Q11
tmp32no1 = pink_noise_num_avg - tmp32no2; // Q11 tmp32no1 = pink_noise_num_avg - tmp32no2; // Q11
@ -469,16 +492,16 @@ void WebRtcNsx_CalcParametricNoiseEstimate(NsxInst_t *inst,
// Piecewise linear approximation of 'b' in // Piecewise linear approximation of 'b' in
// 2^(int_part+frac_part) = 2^int_part * (1 + b) // 2^(int_part+frac_part) = 2^int_part * (1 + b)
// 'b' is given in Q11 and below stored in frac_part. // 'b' is given in Q11 and below stored in frac_part.
if (WEBRTC_SPL_RSHIFT_W32(frac_part, 10)) if (WEBRTC_SPL_RSHIFT_W16(frac_part, 10))
{ {
// Upper fractional part // Upper fractional part
tmp32no2 = WEBRTC_SPL_MUL_32_16(2048 - frac_part, 1244); // Q21 tmp32no2 = WEBRTC_SPL_MUL_16_16(2048 - frac_part, 1244); // Q21
tmp32no2 = 2048 - WEBRTC_SPL_RSHIFT_W32(tmp32no2, 10); tmp32no2 = 2048 - WEBRTC_SPL_RSHIFT_W32(tmp32no2, 10);
} }
else else
{ {
// Lower fractional part // Lower fractional part
tmp32no2 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_32_16(frac_part, 804), 10); tmp32no2 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(frac_part, 804), 10);
} }
// Shift fractional part to Q(minNorm-stages) // Shift fractional part to Q(minNorm-stages)
tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, int_part - 11); tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, int_part - 11);
@ -684,11 +707,11 @@ void WebRtcNsx_NoiseEstimation(NsxInst_t *inst, WebRtc_UWord16 *magn, WebRtc_UWo
numerator = FACTOR_Q16; numerator = FACTOR_Q16;
tabind = inst->stages - inst->normData; tabind = inst->stages - inst->normData;
if (tabind < 0) assert(tabind < 9);
{ assert(tabind > -9);
if (tabind < 0) {
logval = -WebRtcNsx_kLogTable[-tabind]; logval = -WebRtcNsx_kLogTable[-tabind];
} else } else {
{
logval = WebRtcNsx_kLogTable[tabind]; logval = WebRtcNsx_kLogTable[tabind];
} }
@ -703,6 +726,7 @@ void WebRtcNsx_NoiseEstimation(NsxInst_t *inst, WebRtc_UWord16 *magn, WebRtc_UWo
zeros = WebRtcSpl_NormU32((WebRtc_UWord32)magn[i]); zeros = WebRtcSpl_NormU32((WebRtc_UWord32)magn[i]);
frac = (WebRtc_Word16)((((WebRtc_UWord32)magn[i] << zeros) & 0x7FFFFFFF) >> 23); frac = (WebRtc_Word16)((((WebRtc_UWord32)magn[i] << zeros) & 0x7FFFFFFF) >> 23);
// log2(magn(i)) // log2(magn(i))
assert(frac < 256);
log2 = (WebRtc_Word16)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); log2 = (WebRtc_Word16)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]);
// log2(magn(i))*log(2) // log2(magn(i))*log(2)
lmagn[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(log2, log2Const, 15); lmagn[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(log2, log2Const, 15);
@ -721,6 +745,7 @@ void WebRtcNsx_NoiseEstimation(NsxInst_t *inst, WebRtc_UWord16 *magn, WebRtc_UWo
// Get counter values from state // Get counter values from state
counter = inst->noiseEstCounter[s]; counter = inst->noiseEstCounter[s];
assert(counter < 201);
countDiv = WebRtcNsx_kCounterDiv[counter]; countDiv = WebRtcNsx_kCounterDiv[counter];
countProd = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(counter, countDiv); countProd = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(counter, countDiv);
@ -728,13 +753,16 @@ void WebRtcNsx_NoiseEstimation(NsxInst_t *inst, WebRtc_UWord16 *magn, WebRtc_UWo
for (i = 0; i < inst->magnLen; i++) for (i = 0; i < inst->magnLen; i++)
{ {
// compute delta // compute delta
if (inst->noiseEstDensity[offset + i] > 512) if (inst->noiseEstDensity[offset + i] > 512) {
{
delta = WebRtcSpl_DivW32W16ResW16(numerator, delta = WebRtcSpl_DivW32W16ResW16(numerator,
inst->noiseEstDensity[offset + i]); inst->noiseEstDensity[offset + i]);
} else } else {
{
delta = FACTOR_Q7; delta = FACTOR_Q7;
if (inst->blockIndex < END_STARTUP_LONG) {
// Smaller step size during startup. This prevents from using
// unrealistic values causing overflow.
delta = FACTOR_Q7_STARTUP;
}
} }
// update log quantile estimate // update log quantile estimate
@ -742,7 +770,7 @@ void WebRtcNsx_NoiseEstimation(NsxInst_t *inst, WebRtc_UWord16 *magn, WebRtc_UWo
if (lmagn[i] > inst->noiseEstLogQuantile[offset + i]) if (lmagn[i] > inst->noiseEstLogQuantile[offset + i])
{ {
// +=QUANTILE*delta/(inst->counter[s]+1) QUANTILE=0.25, =1 in Q2 // +=QUANTILE*delta/(inst->counter[s]+1) QUANTILE=0.25, =1 in Q2
// CounterDiv=1/inst->counter[s] in Q15 // CounterDiv=1/(inst->counter[s]+1) in Q15
tmp16 += 2; tmp16 += 2;
tmp16no1 = WEBRTC_SPL_RSHIFT_W16(tmp16, 2); tmp16no1 = WEBRTC_SPL_RSHIFT_W16(tmp16, 2);
inst->noiseEstLogQuantile[offset + i] += tmp16no1; inst->noiseEstLogQuantile[offset + i] += tmp16no1;
@ -753,6 +781,11 @@ void WebRtcNsx_NoiseEstimation(NsxInst_t *inst, WebRtc_UWord16 *magn, WebRtc_UWo
// *(1-QUANTILE), in Q2 QUANTILE=0.25, 1-0.25=0.75=3 in Q2 // *(1-QUANTILE), in Q2 QUANTILE=0.25, 1-0.25=0.75=3 in Q2
tmp16no2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, 3, 1); tmp16no2 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, 3, 1);
inst->noiseEstLogQuantile[offset + i] -= tmp16no2; inst->noiseEstLogQuantile[offset + i] -= tmp16no2;
if (inst->noiseEstLogQuantile[offset + i] < logval) {
// This is the smallest fixed point representation we can
// have, hence we limit the output.
inst->noiseEstLogQuantile[offset + i] = logval;
}
} }
// update density estimate // update density estimate
@ -838,16 +871,14 @@ void WebRtcNsx_FeatureParameterExtraction(NsxInst_t *inst, int flag)
} }
// Spectral difference // Spectral difference
histIndex = HIST_PAR_EST; histIndex = HIST_PAR_EST;
if (inst->timeAvgMagnEnergy) if (inst->timeAvgMagnEnergy > 0) {
{
// Guard against division by zero // Guard against division by zero
// If timeAvgMagnEnergy == 0 we have no normalizing statistics and therefore can't // If timeAvgMagnEnergy == 0 we have no normalizing statistics and
// update the histogram // therefore can't update the histogram
histIndex = WEBRTC_SPL_UDIV((inst->featureSpecDiff * 5) >> inst->stages, histIndex = WEBRTC_SPL_UDIV((inst->featureSpecDiff * 5) >> inst->stages,
inst->timeAvgMagnEnergy); inst->timeAvgMagnEnergy);
} }
if (histIndex < HIST_PAR_EST) if (histIndex < HIST_PAR_EST) {
{
inst->histSpecDiff[histIndex]++; inst->histSpecDiff[histIndex]++;
} }
} }
@ -882,15 +913,17 @@ void WebRtcNsx_FeatureParameterExtraction(NsxInst_t *inst, int flag)
thresFluctLrtFX = THRES_FLUCT_LRT * numHistLrt; thresFluctLrtFX = THRES_FLUCT_LRT * numHistLrt;
// get threshold for LRT feature: // get threshold for LRT feature:
tmpU32 = (FACTOR_1_LRT_DIFF * (WebRtc_UWord32)avgHistLrtFX); tmpU32 = (FACTOR_1_LRT_DIFF * (WebRtc_UWord32)avgHistLrtFX);
if ((fluctLrtFX < thresFluctLrtFX) || (numHistLrt == 0) || (tmpU32 if ((fluctLrtFX < thresFluctLrtFX) || (numHistLrt == 0) ||
> (WebRtc_UWord32)(100 * numHistLrt))) (tmpU32 > (WebRtc_UWord32)(100 * numHistLrt))) {
{ //very low fluctuation, so likely noise
inst->thresholdLogLrt = inst->maxLrt; //very low fluctuation, so likely noise inst->thresholdLogLrt = inst->maxLrt;
} else } else {
{ tmp32 = (WebRtc_Word32)((tmpU32 << (9 + inst->stages)) / numHistLrt /
tmp32 = (WebRtc_Word32)((tmpU32 << (9 + inst->stages)) / numHistLrt / 25); 25);
// check if value is within min/max range // check if value is within min/max range
inst->thresholdLogLrt = WEBRTC_SPL_SAT(inst->maxLrt, tmp32, inst->minLrt); inst->thresholdLogLrt = WEBRTC_SPL_SAT(inst->maxLrt,
tmp32,
inst->minLrt);
} }
if (fluctLrtFX < thresFluctLrtFX) if (fluctLrtFX < thresFluctLrtFX)
{ {
@ -1047,6 +1080,7 @@ void WebRtcNsx_ComputeSpectralFlatness(NsxInst_t *inst, WebRtc_UWord16 *magn)
frac = (WebRtc_Word16)(((WebRtc_UWord32)((WebRtc_UWord32)(magn[i]) << zeros) frac = (WebRtc_Word16)(((WebRtc_UWord32)((WebRtc_UWord32)(magn[i]) << zeros)
& 0x7FFFFFFF) >> 23); & 0x7FFFFFFF) >> 23);
// log2(magn(i)) // log2(magn(i))
assert(frac < 256);
tmpU32 = (WebRtc_UWord32)(((31 - zeros) << 8) tmpU32 = (WebRtc_UWord32)(((31 - zeros) << 8)
+ WebRtcNsx_kLogTableFrac[frac]); // Q8 + WebRtcNsx_kLogTableFrac[frac]); // Q8
avgSpectralFlatnessNum += tmpU32; // Q8 avgSpectralFlatnessNum += tmpU32; // Q8
@ -1062,6 +1096,7 @@ void WebRtcNsx_ComputeSpectralFlatness(NsxInst_t *inst, WebRtc_UWord16 *magn)
zeros = WebRtcSpl_NormU32(avgSpectralFlatnessDen); zeros = WebRtcSpl_NormU32(avgSpectralFlatnessDen);
frac = (WebRtc_Word16)(((avgSpectralFlatnessDen << zeros) & 0x7FFFFFFF) >> 23); frac = (WebRtc_Word16)(((avgSpectralFlatnessDen << zeros) & 0x7FFFFFFF) >> 23);
// log2(avgSpectralFlatnessDen) // log2(avgSpectralFlatnessDen)
assert(frac < 256);
tmp32 = (WebRtc_Word32)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); // Q8 tmp32 = (WebRtc_Word32)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); // Q8
logCurSpectralFlatness = (WebRtc_Word32)avgSpectralFlatnessNum; logCurSpectralFlatness = (WebRtc_Word32)avgSpectralFlatnessNum;
logCurSpectralFlatness += ((WebRtc_Word32)(inst->stages - 1) << (inst->stages + 7)); // Q(8+stages-1) logCurSpectralFlatness += ((WebRtc_Word32)(inst->stages - 1) << (inst->stages + 7)); // Q(8+stages-1)
@ -1166,10 +1201,16 @@ void WebRtcNsx_ComputeSpectralDifference(NsxInst_t *inst, WebRtc_UWord16 *magnIn
varPauseUFX >>= (-nShifts); // Q(2*(qMagn+norm32+minPause)) varPauseUFX >>= (-nShifts); // Q(2*(qMagn+norm32+minPause))
nShifts = 0; nShifts = 0;
} }
tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no2, varPauseUFX); // Q(2*(qMagn+norm32-16+minPause)) if (varPauseUFX > 0) {
// Q(2*(qMagn+norm32-16+minPause))
tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no2, varPauseUFX);
tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, nShifts); tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, nShifts);
avgDiffNormMagnUFX -= WEBRTC_SPL_MIN(avgDiffNormMagnUFX, tmpU32no1); // Q(2*qMagn) // Q(2*qMagn)
avgDiffNormMagnUFX -= WEBRTC_SPL_MIN(avgDiffNormMagnUFX, tmpU32no1);
} else {
avgDiffNormMagnUFX = 0;
}
} }
//normalize and compute time average update of difference feature //normalize and compute time average update of difference feature
tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(avgDiffNormMagnUFX, 2 * inst->normData); tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(avgDiffNormMagnUFX, 2 * inst->normData);
@ -1219,7 +1260,11 @@ void WebRtcNsx_SpeechNoiseProb(NsxInst_t *inst, WebRtc_UWord16 *nonSpeechProbFin
{ {
den = WEBRTC_SPL_RSHIFT_U32(priorLocSnr[i], 11 - normTmp); // Q(normTmp) den = WEBRTC_SPL_RSHIFT_U32(priorLocSnr[i], 11 - normTmp); // Q(normTmp)
} }
if (den > 0) {
besselTmpFX32 -= WEBRTC_SPL_UDIV(num, den); // Q11 besselTmpFX32 -= WEBRTC_SPL_UDIV(num, den); // Q11
} else {
besselTmpFX32 -= num; // Q11
}
// inst->logLrtTimeAvg[i] += LRT_TAVG * (besselTmp - log(snrLocPrior) - inst->logLrtTimeAvg[i]); // inst->logLrtTimeAvg[i] += LRT_TAVG * (besselTmp - log(snrLocPrior) - inst->logLrtTimeAvg[i]);
// Here, LRT_TAVG = 0.5 // Here, LRT_TAVG = 0.5
@ -1327,11 +1372,10 @@ void WebRtcNsx_SpeechNoiseProb(NsxInst_t *inst, WebRtc_UWord16 *nonSpeechProbFin
tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(inst->featureSpecDiff, normTmp); // Q(normTmp-2*stages) tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(inst->featureSpecDiff, normTmp); // Q(normTmp-2*stages)
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->timeAvgMagnEnergy, 20 - inst->stages tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->timeAvgMagnEnergy, 20 - inst->stages
- normTmp); - normTmp);
if (tmpU32no2) if (tmpU32no2 > 0) {
{ // Q(20 - inst->stages)
tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); // Q14?? Q(20 - inst->stages) tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2);
} else } else {
{
tmpU32no1 = (WebRtc_UWord32)(0x7fffffff); tmpU32no1 = (WebRtc_UWord32)(0x7fffffff);
} }
} }
@ -1554,6 +1598,7 @@ void WebRtcNsx_DataAnalysis(NsxInst_t *inst, short *speechFrame, WebRtc_UWord16
frac = (WebRtc_Word16)((((WebRtc_UWord32)magnU16[inst->anaLen2] << zeros) & frac = (WebRtc_Word16)((((WebRtc_UWord32)magnU16[inst->anaLen2] << zeros) &
0x7FFFFFFF) >> 23); // Q8 0x7FFFFFFF) >> 23); // Q8
// log2(magnU16(i)) in Q8 // log2(magnU16(i)) in Q8
assert(frac < 256);
log2 = (WebRtc_Word16)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); log2 = (WebRtc_Word16)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]);
} }
@ -1597,6 +1642,7 @@ void WebRtcNsx_DataAnalysis(NsxInst_t *inst, short *speechFrame, WebRtc_UWord16
frac = (WebRtc_Word16)((((WebRtc_UWord32)magnU16[i] << zeros) & frac = (WebRtc_Word16)((((WebRtc_UWord32)magnU16[i] << zeros) &
0x7FFFFFFF) >> 23); 0x7FFFFFFF) >> 23);
// log2(magnU16(i)) in Q8 // log2(magnU16(i)) in Q8
assert(frac < 256);
log2 = (WebRtc_Word16)(((31 - zeros) << 8) log2 = (WebRtc_Word16)(((31 - zeros) << 8)
+ WebRtcNsx_kLogTableFrac[frac]); + WebRtcNsx_kLogTableFrac[frac]);
} }
@ -1630,6 +1676,7 @@ void WebRtcNsx_DataAnalysis(NsxInst_t *inst, short *speechFrame, WebRtc_UWord16
// Denominator used in both parameter estimates. // Denominator used in both parameter estimates.
// The value is only dependent on the size of the frequency band (kStartBand) // The value is only dependent on the size of the frequency band (kStartBand)
// and to reduce computational complexity stored in a table (kDeterminantEstMatrix[]) // and to reduce computational complexity stored in a table (kDeterminantEstMatrix[])
assert(kStartBand < 66);
matrix_determinant = kDeterminantEstMatrix[kStartBand]; // Q0 matrix_determinant = kDeterminantEstMatrix[kStartBand]; // Q0
sum_log_i = kSumLogIndex[kStartBand]; // Q5 sum_log_i = kSumLogIndex[kStartBand]; // Q5
sum_log_i_square = kSumSquareLogIndex[kStartBand]; // Q2 sum_log_i_square = kSumSquareLogIndex[kStartBand]; // Q2
@ -1727,8 +1774,7 @@ void WebRtcNsx_DataSynthesis(NsxInst_t *inst, short *outFrame)
return; return;
} }
// Filter the data in the frequency domain // Filter the data in the frequency domain
for (i = 0; i < inst->magnLen; i++) for (i = 0; i < inst->magnLen; i++) {
{
inst->real[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->real[i], inst->real[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->real[i],
(WebRtc_Word16)(inst->noiseSupFilter[i]), 14); // Q(normData-stages) (WebRtc_Word16)(inst->noiseSupFilter[i]), 14); // Q(normData-stages)
inst->imag[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->imag[i], inst->imag[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->imag[i],
@ -1754,11 +1800,12 @@ void WebRtcNsx_DataSynthesis(NsxInst_t *inst, short *outFrame)
WebRtcSpl_ComplexBitReverse(realImag, inst->stages); WebRtcSpl_ComplexBitReverse(realImag, inst->stages);
outCIFFT = WebRtcSpl_ComplexIFFT(realImag, inst->stages, 1); outCIFFT = WebRtcSpl_ComplexIFFT(realImag, inst->stages, 1);
for (i = 0; i < inst->anaLen; i++) for (i = 0; i < inst->anaLen; i++) {
{
j = WEBRTC_SPL_LSHIFT_W16(i, 1); j = WEBRTC_SPL_LSHIFT_W16(i, 1);
tmp32no1 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32)realImag[j], outCIFFT - inst->normData); tmp32no1 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32)realImag[j],
inst->real[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, tmp32no1, outCIFFT - inst->normData);
inst->real[i] = (WebRtc_Word16)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX,
tmp32no1,
WEBRTC_SPL_WORD16_MIN); WEBRTC_SPL_WORD16_MIN);
} }
@ -1782,30 +1829,11 @@ void WebRtcNsx_DataSynthesis(NsxInst_t *inst, short *outFrame)
assert(inst->energyIn > 0); assert(inst->energyIn > 0);
energyRatio = (WebRtc_Word16)WEBRTC_SPL_DIV(energyOut energyRatio = (WebRtc_Word16)WEBRTC_SPL_DIV(energyOut
+ WEBRTC_SPL_RSHIFT_W32(inst->energyIn, 1), inst->energyIn); // Q8 + WEBRTC_SPL_RSHIFT_W32(inst->energyIn, 1), inst->energyIn); // Q8
// Limit the ratio to [0, 1] in Q8, i.e., [0, 256]
// // original FLOAT code energyRatio = WEBRTC_SPL_SAT(256, energyRatio, 0);
// if (gain > blim) {
// factor1=1.0+1.3*(gain-blim);
// if (gain*factor1 > 1.0) { // FLOAT
// factor1 = 1.0/gain; // FLOAT
// }
// }
// else {
// factor1=1.0; // FLOAT
// }
//
// if (gain > blim) {
// factor2=1.0; //FLOAT
// }
// else {
// //don't reduce scale too much for pause regions: attenuation here should be controlled by flooring
// factor2=1.0-0.3*(blim-gain); // FLOAT
// if (gain <= inst->denoiseBound) {
// factor2=1.0-0.3*(blim-inst->denoiseBound); // FLOAT
// }
// }
// all done in lookup tables now // all done in lookup tables now
assert(energyRatio < 257);
gainFactor1 = kFactor1Table[energyRatio]; // Q8 gainFactor1 = kFactor1Table[energyRatio]; // Q8
gainFactor2 = inst->factor2Table[energyRatio]; // Q8 gainFactor2 = inst->factor2Table[energyRatio]; // Q8
@ -2005,6 +2033,11 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
// Shift denominator to Q(nShifts-6+minNorm-stages) // Shift denominator to Q(nShifts-6+minNorm-stages)
tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(inst->initMagnEst[i], 6 - nShifts); tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(inst->initMagnEst[i], 6 - nShifts);
if (tmpU32no1 == 0) {
// This is only possible if numerator = 0, in which case
// we don't need any division.
tmpU32no1 = 1;
}
tmpU32no2 = WEBRTC_SPL_UDIV(numerator, tmpU32no1); // Q14 tmpU32no2 = WEBRTC_SPL_UDIV(numerator, tmpU32no1); // Q14
noiseSupFilterTmp[i] = (WebRtc_UWord16)WEBRTC_SPL_SAT(16384, tmpU32no2, noiseSupFilterTmp[i] = (WebRtc_UWord16)WEBRTC_SPL_SAT(16384, tmpU32no2,
(WebRtc_UWord32)(inst->denoiseBound)); // Q14 (WebRtc_UWord32)(inst->denoiseBound)); // Q14
@ -2030,6 +2063,8 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, 6); tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, 6);
nShifts = 6; nShifts = 6;
} }
tmpU32no1 *= inst->blockIndex;
tmpU32no2 *= (END_STARTUP_SHORT - inst->blockIndex);
// Add them together and divide by startup length // Add them together and divide by startup length
noiseU32[i] = WebRtcSpl_DivU32U16(tmpU32no1 + tmpU32no2, END_STARTUP_SHORT); noiseU32[i] = WebRtcSpl_DivU32U16(tmpU32no1 + tmpU32no2, END_STARTUP_SHORT);
// Shift back if necessary // Shift back if necessary
@ -2090,12 +2125,10 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
{ {
// Current magnitude larger than noise // Current magnitude larger than noise
tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(tmpU32no1, 11); // Q(17+qMagn) tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(tmpU32no1, 11); // Q(17+qMagn)
if (tmpU32no2) if (tmpU32no2 > 0) {
{
tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); // Q11 tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); // Q11
postLocSnr[i] = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 postLocSnr[i] = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11
} else } else {
{
postLocSnr[i] = satMax; postLocSnr[i] = satMax;
} }
} }
@ -2105,12 +2138,10 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(nearMagnEst, 3); // Q(prevQMagn+17) tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(nearMagnEst, 3); // Q(prevQMagn+17)
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->prevNoiseU32[i], nShifts); // Q(prevQMagn+6) tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->prevNoiseU32[i], nShifts); // Q(prevQMagn+6)
if (tmpU32no2) if (tmpU32no2 > 0) {
{ tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); // Q11
tmpU32no1 = WEBRTC_SPL_DIV(tmpU32no1, tmpU32no2); // Q11
tmpU32no1 = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 tmpU32no1 = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11
} else } else {
{
tmpU32no1 = satMax; // Q11 tmpU32no1 = satMax; // Q11
} }
prevNearSnr[i] = tmpU32no1; // Q11 prevNearSnr[i] = tmpU32no1; // Q11
@ -2147,7 +2178,8 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
tmpU32no1 = (inst->curAvgMagnEnergy + inst->timeAvgMagnEnergy + 1) >> 1; //Q(-2*stages) tmpU32no1 = (inst->curAvgMagnEnergy + inst->timeAvgMagnEnergy + 1) >> 1; //Q(-2*stages)
// Update featureSpecDiff // Update featureSpecDiff
if ((tmpU32no1 != inst->timeAvgMagnEnergy) && (inst->featureSpecDiff)) if ((tmpU32no1 != inst->timeAvgMagnEnergy) && (inst->featureSpecDiff) &&
(inst->timeAvgMagnEnergy > 0))
{ {
norm32no1 = 0; norm32no1 = 0;
tmpU32no3 = tmpU32no1; tmpU32no3 = tmpU32no1;
@ -2355,8 +2387,7 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
norm32no2 = WEBRTC_SPL_MIN(11, WebRtcSpl_NormU32(tmpU32no1)); norm32no2 = WEBRTC_SPL_MIN(11, WebRtcSpl_NormU32(tmpU32no1));
tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(tmpU32no1, norm32no2); // Q(qCur+norm32no2) tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(tmpU32no1, norm32no2); // Q(qCur+norm32no2)
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpNoiseU32, 11 - norm32no2); // Q(qCur+norm32no2-11) tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpNoiseU32, 11 - norm32no2); // Q(qCur+norm32no2-11)
if (tmpU32no2) if (tmpU32no2 > 0) {
{
tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); // Q11 tmpU32no1 = WEBRTC_SPL_UDIV(tmpU32no1, tmpU32no2); // Q11
} }
curNearSnr = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 curNearSnr = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11
@ -2373,6 +2404,7 @@ int WebRtcNsx_ProcessCore(NsxInst_t *inst, short *speechFrame, short *speechFram
//gain filter //gain filter
tmpU32no1 = (WebRtc_UWord32)(inst->overdrive) tmpU32no1 = (WebRtc_UWord32)(inst->overdrive)
+ WEBRTC_SPL_RSHIFT_U32(priorSnr + 8192, 14); // Q8 + WEBRTC_SPL_RSHIFT_U32(priorSnr + 8192, 14); // Q8
assert(inst->overdrive > 0);
tmpU16no1 = (WebRtc_UWord16)WEBRTC_SPL_UDIV(priorSnr + (tmpU32no1 >> 1), tmpU32no1); // Q14 tmpU16no1 = (WebRtc_UWord16)WEBRTC_SPL_UDIV(priorSnr + (tmpU32no1 >> 1), tmpU32no1); // Q14
inst->noiseSupFilter[i] = WEBRTC_SPL_SAT(16384, tmpU16no1, inst->denoiseBound); // 16384 = Q14(1.0) // Q14 inst->noiseSupFilter[i] = WEBRTC_SPL_SAT(16384, tmpU16no1, inst->denoiseBound); // 16384 = Q14(1.0) // Q14

View File

@ -18,6 +18,7 @@
#define END_STARTUP_SHORT 50 #define END_STARTUP_SHORT 50
#define FACTOR_Q16 (WebRtc_Word32)2621440 // 40 in Q16 #define FACTOR_Q16 (WebRtc_Word32)2621440 // 40 in Q16
#define FACTOR_Q7 (WebRtc_Word16)5120 // 40 in Q7 #define FACTOR_Q7 (WebRtc_Word16)5120 // 40 in Q7
#define FACTOR_Q7_STARTUP (WebRtc_Word16)1024 // 8 in Q7
#define WIDTH_Q8 3 // 0.01 in Q8 (or 25 ) #define WIDTH_Q8 3 // 0.01 in Q8 (or 25 )
//PARAMETERS FOR NEW METHOD //PARAMETERS FOR NEW METHOD
#define DD_PR_SNR_Q11 2007 // ~= Q11(0.98) DD update of prior SNR #define DD_PR_SNR_Q11 2007 // ~= Q11(0.98) DD update of prior SNR