📄 smooth.c
字号:
/* Copyright 2001,2002,2003 NAH6
* All Rights Reserved
*
* Parts Copyright DoD, Parts Copyright Starium
*
*/
/***************************************************************************
ROUTINE
Smooth
FUNCTION
Smooth parameters when error conditions indicate it is necessary
SYNOPSIS
Smooth(assure, frame, subframe, parameters)
formal
data I/O
name type type function
-------------------------------------------------------------------
assure int i EDAC assurance levels
frame int i frame number
subframe int i subframe number
prameters TX_PARAM i/o array of parameters to be smoothed
==========================================================================
DESCRIPTION
Smooth parameters based on error level indications. If edac is set
then smoothing is done according to the edac design. If edac is not set
then smoothing is done according to channel estimates received from the
Hamming decoder. A running average of the number of times the Hamming
codeword has received an error. If this number is above a given threshold
then smoothing is performed.
**************************************************************************/
#include "main.h"
#include "smooth.h"
#include "variance.h"
#include "rint.h"
#define SYNDRUN 100.0
#define SYNDERR 0.01
#define HISTORY 4
#define SGAINHIGH 64.0
#define SGAINLOW -64.0
#define FRAME_MARK 4
void Smooth(
int assure,
int frame,
int subframe,
TX_PARAM *parameters)
{ float syndrome;
static float *AdaptGains;
static float PDelay3;
static float *gains;
static float syndavg;
if (subframe == 0) {
if (assure == 0)
syndrome = 0.0;
else
syndrome = 1.0;
syndavg = ((1.0 - SYNDERR) * syndavg) + (SYNDERR * syndrome);
}
PDelay3 = parameters->AdaptiveDelay[2];
AdaptGains = parameters->AdaptiveGain;
gains = parameters->StochasticGain;
smoothPDelay(¶meters->AdaptiveDelay[subframe], syndavg, PDelay3, frame, subframe+1);
smoothAdaptGain(¶meters->AdaptiveGain[subframe], syndavg, AdaptGains, frame, subframe+1);
smoothStochGain(¶meters->StochasticGain[subframe], syndavg, gains, frame, subframe+1);
}
/*
**************************************************************************
ROUTINE
smoothPDelay
FUNCTION
smooth PDelay values
SYNOPSIS
smoothPDelay(PDelay,syndavg,PDelay3,subframe,frame)
formal
data I/O
name type type function
-------------------------------------------------------------------
PDelay real i/o input PDelay
syndavg real i error rate estimation parameter
PDelay3 float i third PDelay value
frame int i frame number
subframe int i subframe number
==========================================================================
DESCRIPTION
Routine to smooth PDelay (pitch lag) when errors are detected:
If the variance of past PDelay values is within the range VARLIMIT
(indicating voiced speech) the validity of the current PDelay value
is tested. If the current value of PDelay is within the range
PDELAYLIMIT, PDELAY is passed. If PDELAY is not within the range
PDELAYLIMIT, PDELAY is reset to the average value of PDelays.
The array OLDPDELAY contains past values of PDelay. The array VECTOR
is constructed from the array OLDPDELAY and PDELAY3 for subframes 1
and 2 (PDELAY3 is a future absolute PDelay value). For subframes 3
and 4 there are no valid future values (since delta PDelays in the
future are not valid), therefore the array VECTOR is constructed
entirely from the array OLDPDELAY. Decisions concering smoothing of
a particular PDelay are made on the variance of the array VECTOR and
the PDelay in question (PDELAY).
If the value of PDelay is smoothed in subframe 3, smoothing is disabled
for subframe 4 of the same frame since the PDelay value in subframe 4
is a delta based on subframe 3.
Note: The smoothing parameters should be capable of adapting to
various bit error rate estimates. For example, different values
of SYNDAVG should select different levels of PDELAYLIMIT and VARLIMIT.
**************************************************************************/
#define PDLIMIT 15
#define PDVARLIMIT 15
#define SYNDLIMIT 0.01
void smoothPDelay(
float *PDelay,
float syndavg,
float PDelay3,
int frame,
int subframe)
{ int i;
static int enable;
float avg, var, vector[4];
static float oldPDelay[HISTORY];
if (subframe != 4) enable = 1;
if ((syndavg > SYNDLIMIT) && enable) {
switch (subframe) {
case 1: case 2:
vector[0]=oldPDelay[0]; vector[1]=oldPDelay[1];
vector[2]=oldPDelay[2]; vector[3]=PDelay3;
break;
case 3: case 4:
vector[0]=oldPDelay[0]; vector[1]=oldPDelay[1];
vector[2]=oldPDelay[2]; vector[3]=oldPDelay[3];
break;
default:
fprintf(stderr,"smoothPDelay: Error in subframe number: %d\n", subframe);
break;
}
variance(vector, 4, &var, &avg);
if ((var < PDVARLIMIT)&&((*PDelay>(avg+PDLIMIT))||(*PDelay<(avg-PDLIMIT)))) {
*PDelay = rint(avg);
fprintf(stderr,"smoothPDelay: Pitch Delay value set to %g. frame %d subframe %d\n",
avg, frame, subframe);
if (subframe == 3) {
enable = 0;
fprintf(stderr,"smoothPDelay: Pitch Delay smoothing disabled for subframe 4\n");
}
} /** if var and *PDelay **/
} /** if (syndavg > SYNDLIMIT) && enable **/
for (i = HISTORY-1; i > 0; i--)
oldPDelay[i] = oldPDelay[i-i];
oldPDelay[0] = *PDelay;
}
/*
**************************************************************************
ROUTINE
smoothStochGain
FUNCTION
smooth StochGain values
SYNOPSIS
smoothStochGain(StochGain,syndavg,gains,frame,subframe)
formal
data I/O
name type type function
-------------------------------------------------------------------
StochGain real i/o input StochGain
syndavg real i error rate estimation parameter
gains real i vector of gains to calculate variance
frame int i frame number
subframe int i subframe number
==========================================================================
DESCRIPTION
Smoothing routine to smooth StochGain when errors are detected:
If the variance of past StochGain values is within the range VARLIMIT,
the validity of the current StochGain value is tested. If the current
value of StochGain is within the range STOCHGAINLIMIT, STOCHGAIN is
passed. If STOCHGAIN is not within the range STOCHGAINLIMIT it is
reset to the average value of the surrounding StochGain values.
The array OLDSTOCHGAIN contains past values of StochGain. The array
GAINS contains current and future values of StochGain. The array
VECTOR is constructed from the arrays OLDSTOCHGAIN and GAINS
depending on the current subframe. STOCHGAIN is smoothed based on
the statistics of VECTOR, which contains the nearest four
surrounding StochGain values, both past and future values, except
where future values are not available (subframes 3 and 4).
Note: The smoothing parameters should be capable of adapting to
various bit error rate estimates. For example, different values of
SYNDAVG should select different levels of STOCHGAINLIMIT, VARLIMIT,
and SYNDLIMIT.
**************************************************************************/
#define STOCHGAINLIMIT 300.0
#define CBVARLIMIT 30000.0
#define SGAINLIMIT 9.0
#define SVARLIMIT 10.0
#define AVGLIMIT 6.0
#define SYNDLIMIT 0.01
void smoothStochGain(
float *StochGain,
float syndavg,
float *gains,
int frame,
int subframe)
{ int i;
float avg, var,sign, absStochGain, vector[4];
static int enable;
static float oldStochGain[HISTORY];
absStochGain = fabs(*StochGain);
if (subframe != 4) enable = 1;
if ((syndavg > SYNDLIMIT) && enable) {
switch (subframe) {
case 1:
vector[0]=oldStochGain[1]; vector[1]=oldStochGain[0];
vector[2]=fabs(gains[1]); vector[3]=fabs(gains[2]);
break;
case 2:
vector[0]=oldStochGain[1]; vector[1]=oldStochGain[0];
vector[2]=fabs(gains[2]); vector[3]=fabs(gains[3]);
break;
case 3:
vector[0]=oldStochGain[2]; vector[1]=oldStochGain[1];
vector[2]=oldStochGain[0]; vector[3]=fabs(gains[3]);
break;
case 4:
vector[0]=oldStochGain[3]; vector[1]=oldStochGain[2];
vector[2]=oldStochGain[1]; vector[3]=oldStochGain[0];
break;
default:
fprintf(stderr,"smoothStochGain: Error in subframe number: %d\n", subframe);
break;
} /** end switch on subframe **/
variance(vector, 4, &var, &avg);
if (*StochGain < 0) sign = -1.0;
else sign = 1.0;
if ((var < CBVARLIMIT) && ((absStochGain > (avg+STOCHGAINLIMIT)) || (absStochGain < (avg-STOCHGAINLIMIT)))) {
absStochGain = avg;
fprintf(stderr,"smoothStochGain: StochGain value reset to %g StochGains at frame %d subframe %d\n", avg, frame, subframe);
*StochGain = sign * absStochGain;
if (subframe == 2) {
enable = 0;
fprintf(stderr,"smoothStochGain: smoothing disabled for subframe 3\n");
}
}
if ((var < SVARLIMIT) && (absStochGain > SGAINLIMIT) && (avg < AVGLIMIT) && enable) {
absStochGain = avg;
*StochGain = sign * absStochGain;
fprintf(stderr,"smoothStochGain: StochGain value reset to %g (silence?) at frame %d subframe %d\n", avg, frame, subframe);
if (subframe == 3) {
enable = 0;
fprintf(stderr,"smoothStochGain: smoothing disabled for subframe 4\n");
} /** end if subframe 3 **/
} /** end if var < ... **/
} /** end if syndavg > && enable **/
for (i = HISTORY-1; i >= 1; i--)
oldStochGain[i] = oldStochGain[i-1];
oldStochGain[0] = *StochGain; /** was absStochGain **/
}
/*
**************************************************************************
ROUTINE
smoothAdaptGain
FUNCTION
smooth AdaptGain value
SYNOPSIS
smoothAdaptGain(AdaptGain,syndavg,AdaptGains,frame,subframe)
formal
data I/O
name type type function
-------------------------------------------------------------------
AdaptGain float i/o AdaptGain for current subframe
syndavg float i error rate estimation parameter
AdaptGains float i AdaptGains for current frame
frame int i frame number
subframe int i subframe number
==========================================================================
DESCRIPTION
Routine to smooth AdaptGain (alpha) when errors are detected:
Due to the range of ADAPTGAIN, statistical variance is not appropriate.
Pseudovariance is used and calculated as:
sum of delta oldAdaptGains/# of deltas
If this variance of past AdaptGain values is within the range VARLIMIT,
the validity of the current AdaptGain value is tested. If the current
value of AdaptGain is within the range ADAPTGAINLIMIT, ADAPTGAIN is
passed. If ADAPTGAIN is not within that range it is reset to the
average value of surrounding AdaptGain values.
The array OLDADAPTGAIN contains past values of AdaptGain. The array
ADAPTGAINS contains current and future values of AdaptGain. The array
VECTOR is constructed from the arrays OLDADAPTGAIN and ADAPTGAINS
depending on the current subframe. ADAPTGAIN is smoothed based on
the statistics of VECTOR, which contains the nearest four
surrounding AdaptGain values, both past and future values, except
where future values are not available (subframes 3 and 4).
Absolute values of AdaptGain are used in averaging and reassigning
AdaptGain. All reassigned AdaptGains are limited to the range 0.0-1.0.
Note: The smoothing parameters should be capable of adapting to
various bit error rate estimates. For example, different values of
SYNDAVG should select different levels of ADAPTGAINLIMIT, VARLIMIT,
and SYNDLIMIT.
**************************************************************************/
#define AGLIMIT 0.9
#define AGVARLIMIT 0.2
#define SYNDLIMIT 0.01
void smoothAdaptGain(
float *AdaptGain,
float syndavg,
float *AdaptGains,
int frame,
int subframe)
{ int i;
float AGain, avg, var, sum1 = 0.0, sum2 = 0.0, vector[4];
static float oldAdaptGain[HISTORY];
static int enable;
AGain = *AdaptGain;
if (subframe != 4) enable = 1;
if ((syndavg > SYNDLIMIT) && enable) {
switch (subframe) {
case 1:
vector[0] = oldAdaptGain[1]; vector[1] = oldAdaptGain[0];
vector[2] = AdaptGains[1]; vector[3] = AdaptGains[2];
break;
case 2:
vector[0] = oldAdaptGain[1]; vector[1] = oldAdaptGain[0];
vector[2] = AdaptGains[2]; vector[3] = AdaptGains[3];
break;
case 3:
vector[0] = oldAdaptGain[2]; vector[1] = oldAdaptGain[1];
vector[2] = oldAdaptGain[0]; vector[3] = AdaptGains[3];
break;
case 4:
vector[0] = oldAdaptGain[3]; vector[1] = oldAdaptGain[2];
vector[2] = oldAdaptGain[1]; vector[3] = oldAdaptGain[0];
break;
default:
fprintf(stderr,"smoothAdaptGain: Error in subframe numbering: %d\n",
subframe);
break;
}
for (i=0; i < HISTORY; i++)
sum1 += vector[i];
for (i = 0; i < HISTORY-1; i++)
sum2 += fabs(vector[i] - vector[i+1]);
avg = sum1 / (float) HISTORY;
var = sum2 / (float) (HISTORY-1);
/**
fprintf(stderr,"\t%d\t%2.4f\t%2.4f\n", subframe, avg, var);
**/
if ((var < AGVARLIMIT) && enable) {
if ((AGain > (avg + AGLIMIT)) || (AGain < (avg - AGLIMIT))) {
if (avg > 1.0) avg = 1.0; /* clip avg if: avg > 1.0 */
else if (avg < 0.0) avg = 0.0; /* or 0 < avg */
*AdaptGain = avg;
fprintf(stderr,"smoothAdaptGain: AdaptGain value set to %g. frame %d subframe %d\n",
avg, frame, subframe);
if (subframe == 3) {
enable = 0;
fprintf(stderr,"smoothAdaptGain: smoothing disabled for subframe 4\n");
} /** subframe next to last and updated **/
} /** end absAdaptGain not within ADAPTGAINLIMIT of avg **/
} /** end (var < PGVARLIMIT) && enable **/
} /** end (syndavg > SYNDLIMIT) && enable **/
for (i = HISTORY-1; i > 0; i--)
oldAdaptGain[i] = oldAdaptGain[i-1];
oldAdaptGain[0] = *AdaptGain; /** was absAdaptGain **/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -