6 Computational details
3GPP46.032Full rate speechRelease 17TSVoice Activity Detector (VAD) for full rate speech traffic channels
In the next paragraphs, the detailed description of the VAD algorithm follows the preceding high level description. This detailed description is divided in ten clauses related to the blocks of figure 2.1 (except periodicity updating) in the high level description of the VAD algorithm.
Those clauses are:
1) adaptive filtering and energy computation;
2) ACF averaging;
3) predictor values computation;
4) spectral comparison;
5) periodicity detection;
6) threshold adaptation;
7) VAD decision;
8) VAD hangover addition;
9) periodicity updating;
10) information tone detection.
The VAD algorithm takes as input the following variables of the RPE‑LTP encoder (see the detailed description of the RPE‑LTP encoder GSM 06.10):
‑ L_ACF[0..8], auto‑correlation function (GSM 06.10/4.2.4);
‑ scalauto, scaling factor to compute the L_ACF[0..8] (GSM 06.10/4.2.4);
‑ Nc, LTP lag (one for each sub‑segment, GSM 06.10/4.2.11);
‑ sof, offset compensated signal frame (GSM 06.10/4.2.2).
So four Nc values are needed for the VAD algorithm.
The VAD computation can start as soon as the L_ACF[0..8] and scalauto variables are known. This means that the VAD computation can take place after part 4.2.4 of GSM 06.10 (Auto‑correlation) of the LPC analysis clause of the RPE‑LTP encoder. This scheme will reduce the delay to yield the VAD information. The periodicity updating (included in subclause 2.2.5) and information tone detection, are done after the processing of the current speech encoder frame.
All the arithmetic operations and names of the variables follow the RPE‑LTP detailed description. To increase the precision within the fixed point implementation, a pseudo‑floating point representation of some variables is used. This stands for the following variables (and related constants) of the VAD algorithm:
pvad: Energy of filtered signal;
thvad: Threshold of the VAD decision;
acf0: Energy of input signal.
For the representation of these variables, two integers (16 bits) are needed:
‑ one for the exponent (e_pvad, e_thvad, e_acf0);
‑ one for the mantissa (m_pvad, m_thvad, m_acf0).
The value e_pvad represents the lowest power of 2 just greater or equal to the actual value of pvad and the m_pvad value represents a integer which is always greater or equal to 16384 (normalized mantissa). It means that the pvad value is equal to:
This scheme guarantees a large dynamic range for the pvad value and always keeps a precision of 16 bits. All the comparisons are easy to make by comparing the exponents of two variables and the VAD algorithm needs only one pseudo‑floating point addition. All the computations related to the pseudo‑floating point variables require very simple 16 or 32 bits arithmetic operations defined in the detailed description of the RPE‑LTP encoder. This pseudo‑floating point arithmetic is only used in subclauses 3.1 and 3.6.
Table 3.1 gives a list of all the variables of the VAD algorithm that must be initialized in the reset procedure and kept in memory for processing the subsequent frame of the RPE‑ LTP encoder. The types (16 or 32 bits) and initial values of all these variables are clearly indicated and their related subclause is also mentioned. The bit exact implementation uses other temporary variables that are introduced in the detailed description whenever it is needed.
Table 3.1: Initial values for variables to be stored in memory
Names of variables: |
type (# of bits): |
Initialization: |
Subclause: |
Adaptive filter coefficients: |
|||
rvad[0] |
16 |
24 576 |
3.1, 3.6 |
rvad[1] |
16 |
‑16 384 |
3.1, 3.6 |
rvad[2] |
16 |
4 096 |
3.1, 3.6 |
rvad[3..8] |
16 |
0 |
3.1, 3.6 |
Scaling factor of ravd[0..8]: |
|||
normrvad |
16 |
7 |
3.1, 3.6 |
Delay line of the auto‑correlation coefficients: |
|||
L_sacf[0..26] |
32 |
0 |
3.2 |
L_sav0[0..35] |
32 |
0 |
3.2 |
Pointers on the delay lines: |
|||
pt_sacf |
16 |
0 |
3.2 |
pt_sav0 |
16 |
0 |
3.2 |
Distance measure: |
|||
L_lastdm |
32 |
0 |
3.4 |
Periodicity counters: |
|||
oldlagcount |
16 |
0 |
3.5, 3.9 |
veryoldlagcount |
16 |
0 |
3.5, 3.9 |
Adaptive threshold: |
|||
e_thvad (exponent) |
16 |
20 |
3.6 |
m_thvad (mantissa) |
16 |
31 250 |
3.6 |
Counter for adaptation: |
|||
adaptcount |
16 |
0 |
3.6 |
Hangover flags: |
|||
burstcount |
16 |
0 |
3.8 |
hangcount |
16 |
‑1 |
3.8 |
LTP lag memory: |
|||
oldlag |
16 |
40 |
3.9 |
Tone Detection |
|||
tone |
16 |
0 |
3.10 |
6.1 Adaptive filtering and energy computation
This subclause computes the e_pvad and m_pvad variables which represent the pvad value. It needs the L_ACF[0..8] and scalauto variables of the RPE‑LTP algorithm and the rvad[0..8] and normrvad variables produced by subclause 3.6 of the VAD algorithm. It also computes a floating point representation of L_ACF[0] (e_acf0 and m_acf0) used in subclause 3.6.
Test if L_ACF[0] is equal to 0:
IF ( scalauto < 0 ) THEN scalvad = 0;
ELSE scalvad = scalauto; / keep scalvad for use in subclause 3.2 /
IF ( L_ACF[0] == 0 ) THEN
| e_pvad = ‑32768;
| m_pvad = 0;
| e_acf0 = ‑32768;
| m_acf0 = 0;
| EXIT /continue with subclause 3.2/
Re‑normalization of the L_ACF[0..8]:
normacf = norm( L_ACF[0] );
| FOR i = 0 to 8:
| sacf[i] = ( L_ACF[i] << normacf ) >> 19;
| NEXT i:
Computation of e_acf0 and m_acf0:
e_acf0 = add( 32, (scalvad << 1 ) );
e_acf0 = sub( e_acf0, normacf);
m_acf0 = sacf[0] << 3;
Computation of e_pvad and m_pvad:
e_pvad = add( e_acf0, 14 );
e_pvad = sub( e_pvad, normrvad );
L_temp = 0;
| FOR i = 1 to 8:
| L_temp = L_add( L_temp, L_mult( sacf[i], rvad[i] ) );
| NEXT i:
L_temp = L_add( L_temp, L_mult( sacf[0], rvad[0] ) >> 1 );
IF ( L_temp <= 0 ) THEN L_temp = 1;
normprod = norm( L_temp );
e_pvad = sub( e_pvad, normprod );
m_pvad = ( L_temp << normprod ) >> 16;
6.2 ACF averaging
This subclause uses the L_ACF[0..8] and the scalvad variables to compute the array L_av0[0..8] and L_av1[0..8] used in subclause 3.3 and 3.4.
Computation of the scaling factor:
scal = sub( 10, (scalvad << 1) );
Computation of the arrays L_av0[0..8] and L_av1[0..8]:
| FOR i = 0 to 8:
| L_temp = L_ACF[i] >> scal;
| L_av0[i] = L_add( L_sacf[i], L_temp );
| L_av0[i] = L_add( L_sacf[i+9], L_av0[i] );
| L_av0[i] = L_add( L_sacf[i+18], L_av0[i] );
| L_sacf[ pt_sacf + i ] = L_temp;
| L_av1[i] = L_sav0[ pt_sav0 + i ];
| L_sav0[ pt_sav0 + i] = L_av0[i];
| NEXT i:
Update of the array pointers:
IF ( pt_sacf == 18 ) THEN pt_sacf = 0;
ELSE pt_sacf = add( pt_sacf, 9);
IF ( pt_sav0 == 27 ) THEN pt_sav0 = 0;
ELSE pt_sav0 = add( pt_sav0, 9);
6.3 Predictor values computation
This subclause computes the array rav1[0..8] needed for the spectral comparison and the threshold adaptation. It uses the L_av1[0..8] computed in subclause 3.2, and is divided in the three following subclauses:
‑ Schur recursion to compute reflection coefficients.
‑ Step up procedure to obtain the aav1[0..8].
‑ Computation of the rav1[0..8].
6.3.1 Schur recursion to compute reflection coefficients
This subclause is identical to the one used in the RPE‑LTP algorithm. The array vpar[1..8] is computed with the array L_av1[0..8] as an input.
Schur recursion with 16 bits arithmetic:
IF( L_av1[0] == 0 ) THEN
|== FOR i = 1 to 8:
| vpar[i] = 0;
|== NEXT i:
| EXIT; /continue with subclause 3.3.2/
temp = norm( L_av1[0] );
|== FOR k=0 to 8:
| sacf[k] = ( L_av1[k] << temp ) >> 16;
|== NEXT k:
Initialize array P[..] and K[..] for the recursion:
|== FOR i=1 to 7:
| K[9‑i] = sacf[i];
|== NEXT i:
|== FOR i=0 to 8:
| P[i] = sacf[i];
|== NEXT i:
Compute reflection coefficients:
|== FOR n=1 to 8:
| IF( P[0] < abs( P[1] ) ) THEN
| |== FOR i = n to 8:
| | vpar[i] = 0;
| |== NEXT i:
| | EXIT; /continue with
| | subclause 3.3.2/
| vpar[n] = div( abs( P[1] ), P[0] );
| IF ( P[1] > 0 ) THEN vpar[n] = sub( 0, vpar[n] );
| IF ( n == 8 ) THEN EXIT; /continue with subclause 3.3.2/
|
| Schur recursion:
|
| P[0] = add( P[0], mult_r( P[1], vpar[n] ) );
|==== FOR m=1 to 8‑n:
| P[m] = add( P[m+1], mult_r( K[9‑m], vpar[n] ) );
| K[9‑m] = add( K[9‑m], mult_r( P[m+1], vpar[n] ) );
|==== NEXT m:
|
|== NEXT n:
6.3.2 Step‑up procedure to obtain the aav1[0..8]
Initialization of the step‑up recursion:
L_coef[0] = 16384 << 15;
L_coef[1] = vpar[1] << 14;
Loop on the LPC analysis order:
|= FOR m = 2 to 8:
|== FOR i = 1 to m‑1:
|== temp = L_coef[m‑i] >> 16; / takes the msb /
|== L_work[i] = L_add( L_coef[i], L_mult( vpar[m], temp ) );
|== NEXT i
|=
|== FOR i = 1 to m‑1:
|== L_coef[i] = L_work[i];
|== NEXT i
|=
|= L_coef[m] = vpar[m] << 14;
|= NEXT m:
Keep the aav1[0..8] on 13 bits for next clause:
| FOR i = 0 to 8:
| aav1[i] = L_coef[i] >> 19;
| NEXT i:
6.3.3 Computation of the rav1[0..8]
|= FOR i= 0 to 8:
|= L_work[i] = 0;
|== FOR k = 0 to 8‑i:
|== L_work[i] = L_add( L_work[i], L_mult( aav1[k], aav1[k+i] ) );
|== NEXT k:
|= NEXT i:
IF ( L_work[0] == 0 ) THEN normrav1 =0;
ELSE normrav1 = norm( L_work[0] );
|= FOR i= 0 to 8:
|= rav1[i] = ( L_work[i] << normrav1 ) >> 16;
|= NEXT i:
Keep the normrav1 for use in subclause 3.4 and 3.6.
6.4 Spectral comparison
This subclause computes the variable stat needed for the threshold adaptation. It uses the array L_av0[0..8] computed in subclause 3.2 and the array rav1[0..8] computed in subclause 3.3.3.
Re‑normalize L_av0[0..8]:
IF ( L_av0[0] == 0 ) THEN
| FOR i = 0 to 8:
| sav0[i] = 4095;
| NEXT i:
ELSE
| shift = norm( L_av0[0] );
|= FOR i = 0 to 8:
|= sav0[i] = ( L_av0[i] << shift‑3 ) >> 16;
|= NEXT i:
Compute partial of dm:
L_ p = 0;
|= FOR i = 1 to 8:
|= L_ p = L_add( L_ p, L_mult( rav1[i], sav0[i] ) );
|= NEXT i:
Compute the division of partial by sav0[0]:
IF ( L_ p < 0 ) THEN L_temp = L_sub( 0, L_ p );
ELSE L_temp = L_ p;
IF ( L_temp == 0 ) THEN
| L_dm = 0;
| shift = 0;
ELSE
| sav0[0] = sav0[0] << 3;
| shift = norm( L_temp );
| temp = ( L_temp << shift ) >> 16;
| IF ( sav0[0] >= temp ) THEN
| | divshift = 0;
| | temp = div( temp, sav0[0] );
| ELSE
| | divshift = 1;
| | temp = sub( temp, sav0[0] );
| | temp = div( temp, sav0[0] );
|
| IF( divshift == 1 ) THEN L_dm = 32768;
| ELSE L_dm = 0;
|
| L_dm = L_add( L_dm, temp) << 1;
| IF( L_ p < 0 ) THEN L_dm = L_sub( 0, L_dm);
Re‑normalization and final computation of L_dm:
L_dm = ( L_dm << 14 );
L_dm = L_dm >> shift;
L_dm = L_add( L_dm, ( rav1[0] << 11 ) );
L_dm = L_dm >> normrav1;
Compute the difference and save L_dm:
L_temp = L_sub( L_dm, L_lastdm );
L_lastdm = L_dm;
IF ( L_temp < 0 ) THEN L_temp = L_sub( 0, L_temp );
L_temp = L_sub( L_temp, 3277 );
Evaluation of the stat flag:
IF ( L_temp < 0 ) THEN stat = 1;
ELSE stat = 0;
6.5 Periodicity detection
This subclause just sets the ptch flag needed for the threshold adaptation.
temp = add( oldlagcount, veryoldlagcount );
IF ( temp >= 4 ) THEN ptch = 1;
ELSE ptch = 0;
6.6 Threshold adaptation
This subclause uses the variables e_pvad, m_pvad, e_acf0 and m_acf0 computed in subclause 3.1. It also uses the flags stat (see subclause 3.4) and ptch (see subclause 3.5). It follows the flowchart represented on figure 2.2.
Some constants, represented by a floating point format, are needed and a symbolic name (in capital letter) for their exponent and mantissa is used; table 3.2 lists all these constants with the symbolic names associated and their numerical constant values.
Table 3.2: List of constants
Constant |
Exponent |
Mantissa |
pth |
E_PTH = 19 |
M_PTH = 18 750 |
NOTE: Floating point representation of constants used in subclause 3.6:
pth = 2(E_PTH)x(M_PTH/32768).
margin = 2(E_MARGIN)x(M_MARGIN/32768).
plev = 2(E_PLEV)x(M_PLEV/32768).
Test if acf0 < pth; if yes set thvad to plev:
comp = 0;
IF ( e_acf0 < E_PTH ) THEN comp = 1;
IF ( e_acf0 == E_PTH ) THEN IF ( m_acf0 < M_PTH ) THEN comp =1;
IF ( comp == 1 ) THEN
| e_thvad = E_PLEV;
| m_thvad = M_PLEV;
| EXIT; /continue with subclause 3.7/
Test if an adaptation is needed:
comp = 0;
IF ( ptch == 1 ) THEN comp = 1;
IF ( stat == 0 ) THEN comp = 1;
IF ( tone == 1 ) THEN comp = 1;
IF ( comp == 1 ) THEN
| adaptcount = 0;
| EXIT; /continue with subclause 3.7/
Incrementation of adaptcount:
adaptcount = add( adaptcount, 1 );
IF ( adaptcount <= 8 ) THEN EXIT; /continue with subclause 3.7/
Computation of thvad‑(thvad/dec):
m_thvad = sub( m_thvad, (m_thvad >> 5 ) );
IF ( m_thvad < 16384) THEN
| m_thvad = m_thvad << 1;
| e_thvad = sub( e_thvad, 1 );
Computation of pvad*fac:
L_temp = L_add( m_pvad, m_pvad );
L_temp = L_add( L_temp, m_pvad );
L_temp = L_temp >> 1;
e_temp = add( e_pvad, 1 );
IF ( L_temp > 32767 ) THEN
| L_temp = L_temp >> 1;
| e_temp = add( e_temp, 1 );
m_temp = L_temp;
Test if thvad < pvad*fac:
comp = 0;
IF ( e_thvad < e_temp) THEN comp = 1;
IF (e_thvad == e_temp) THEN IF (m_thvad < m_temp) THEN comp =1;
Computation of minimum (thvad+(thvad/inc), pvad*fac) if comp = 1:
IF ( comp == 1 ) THEN
| Compute thvad +(thvad/inc).
| L_temp = L_add( m_thvad, (m_thvad >> 4 ) );
| IF ( L_temp > 32767 ) THEN
| | m_thvad = L_temp >> 1;
| | e_thvad = add( e_thvad,1 );
| ELSE m_thvad = L_temp;
| comp2 = 0;
| IF ( e_temp < e_thvad) THEN comp2 = 1;
| IF (e_temp == e__hvad) THEN IF (m_temp<m_thvad) THEN comp2 = 1;
| IF ( comp2 == 1 ) THEN
| | e_thvad = e_temp;
| | m_thvad = m_temp;
Computation of pvad + margin:
IF ( e_pvad == E_MARGIN ) THEN
| L_temp = L_add(m_pvad, M_MARGIN);
| m_temp = L_temp >> 1;
| e_temp = add( e_pvad, 1 );
ELSE
| IF ( e_pvad > E_MARGIN ) THEN
| | temp = sub( e_pvad, E_MARGIN );
| | temp = M_MARGIN >> temp;
| | L_temp = L_add( m_pvad, temp );
| | IF ( L_temp > 32767) THEN
| | | e_temp = add( e_pvad, 1 );
| | | m_temp = L_temp >> 1;
| | ELSE
| | | e_temp = e_pvad;
| | | m_temp = L_temp;
| ELSE
| | temp = sub( E_MARGIN, e_pvad );
| | temp = m_pvad >> temp;
| | L_temp = L_add( M_MARGIN, temp );
| | IF (L_temp > 32767) THEN
| | | e_temp = add( E_MARGIN, 1);
| | | m_temp = L_temp >> 1;
| | ELSE
| | | e_temp = E_MARGIN;
| | | m_temp = L_temp;
Test if thvad > pvad + margin:
comp = 0;
IF ( e_thvad > e_temp) THEN comp = 1;
IF (e_thvad == e_temp) THEN IF (m_thvad > m_temp) THEN comp =1;
IF ( comp == 1 ) THEN
| e_thvad = e_temp;
| m_thvad = m_temp;
Initialize new rvad[0..8] in memory:
normrvad = normrav1;
|= FOR i = 0 to 8:
|= rvad[i] = rav1[i];
|= NEXT i:
Set adaptcount to adp + 1:
adaptcount = 9;
6.7 VAD decision
This subclause only outputs the result of the comparison between pvad and thvad using the pseudo‑floating point representation of thvad and pvad. The values e_pvad and m_pvad are computed in subclause 3.1 and the values e_thvad and m_thvad are computed in subclause 3.6.
vvad = 0;
IF (e_pvad > e_thvad) THEN vvad = 1;
IF (e_pvad == e_thvad) THEN IF (m_pvad > m_thvad) THEN vvad =1;
6.8 VAD hangover addition
This subclause finally sets the vad decision for the current frame to be processed.
IF ( vvad == 1 ) THEN burstcount = add( burstcount, 1 );
ELSE burstcount = 0;
IF ( burstcount >= 3 ) THEN
| hangcount = 5;
| burstcount = 3;
vad = vvad;
IF ( hangcount >= 0 ) THEN
| vad = 1;
| hangcount = sub( hangcount, 1 );
6.9 Periodicity updating
This subclause must be delayed until the LTP lags are computed by the RPE‑LTP algorithm. The LTP lags called Nc in the speech encoder are renamed lags[0..3] (index 0 for the first sub‑ segment of the frame, 1 for the second and so on).
Loop on sub‑segments for the frame:
lagcount = 0;
|= FOR i = 0 to 3:
|= Search the maximum and minimum of consecutive lags.
|= IF ( oldlag > lags[i] ) THEN
|= | minlag = lags[i];
|= | maxlag = oldlag;
|= ELSE
|= | minlag = oldlag;
|= | maxlag = lags[i] ;
|=
|= Compute smallag (modulo operation not defined ):
|=
|= smallag = maxlag;
|== | FOR j = 0 to 2:
|== | IF (smallag >= minlag) THEN smallag =sub( smallag, minlag);
|== | NEXT j;
|=
|= Minimum of smallag and minlag ‑ smallag:
|=
|= temp = sub( minlag, smallag );
|= IF ( temp < smallag ) THEN smallag = temp;
|= IF ( smallag < 2 ) THEN lagcount = add( lagcount, 1 );
|= Save the current LTP lag.
|= oldlag = lags[i];
|= NEXT i:
Update the veryoldlagcount and oldlagcount:
veryoldlagcount = oldlagcount;
oldlagcount = lagcount;
6.10 Tone detection
This subclause computes the tone variable needed for the threshold adaptation. Tone is only calculated for the VAD in the downlink. In the uplink VAD tone=0.
To reduce delay, this subclause should be calculated after the processing of the current speech encoder frame.
6.10.1 Windowing
This subclause applies a Hanning window to the input frame sof[0..159] to form the output frame sofh[0..159]. The input frame is the current offset compensated signal frame calculated in the RPE‑LTP codec. The array of constants hann[i] is defined in table 3.2.
Multiply signal frame by Hanning window:
|== FOR i = 0 to 79:
| sofh[i] = mult_r( sof[i], hann[i] );
| sofh[159‑i] = mult_r( sof[159‑i], hann[i] );
|== NEXT i;
6.10.2 Auto‑correlation
This subclause computes the auto‑correlation vector L_acfh[0..5] from the windowed input frame sofh[0..159]. The input frame must be scaled in order to avoid an overflow situation. This subclause is identical to the one used in the RPE‑LTP algorithm, with the exception that only five auto‑correlation values are calculated.
Dynamic scaling of the array sofh[0..159]:
Search for the maximum:
smax = 0;
|== FOR k = 0 to 159:
| temp = abs( sofh[k] );
| IF ( temp > smax ) THEN smax = temp;
|== NEXT k;
Computation of the scaling factor:
IF ( smax == 0 ) THEN scalauto = 0;
ELSE scalauto = sub( 4, norm( smax << 16));
Scaling of the array sofh[0..159]:
IF ( scalauto > 0 ) THEN
| temp = 16384 >> sub( scalauto,1);
|== FOR k = 0 to 159:
| sofh[k] = mult_r( sofh[k], temp);
|== NEXT k:
Compute the L_ACF[..]:
|== FOR k=0 to 4:
| L_acfh[k] = 0;
|==== FOR i=k to 159:
| L_temp = L_mult( sofh[i], sofh[i‑k] );
| L_acfh[k] = L_add( L_acfh[k], L_temp );
|==== NEXT i:
|== NEXT k:
6.10.3 Computation of the reflection coefficients
This subclause calculates the reflection coefficients rc[1..4] from the input array L_acfh[0..4]. This procedure is identical to the one in subclause 3.3.1 and the RPE‑LTP codec, with the exception that only four reflection coefficients are calculated.
Schur recursion with 16 bits arithmetic:
IF( L_acfh[0] == 0 ) THEN
|== FOR i = 1 to 4:
| rc[i] = 0;
|== NEXT i:
| EXIT; /continue with subclause 3.10.4/
temp = norm( L_acfh[0] );
|== FOR k=0 to 4:
| sacf[k] = ( L_acfh[k] << temp ) >> 16;
|== NEXT k:
Initialize array P[..] and K[..] for the recursion:
|== FOR i=1 to 3:
| K[5‑i] = sacf[i];
|== NEXT i:
|== FOR i=0 to 4:
| P[i] = sacf[i];
|== NEXT i:
Compute reflection coefficients:
|== FOR n=1 to 4:
| IF( P[0] < abs( P[1] ) ) THEN
| |== FOR i = n to 4:
| | rc[i] = 0;
| |== NEXT i:
| | EXIT; /continue with subclause 3.10.4/
| rc[n] = div( abs( P[1] ), P[0] );
| IF ( P[1] > 0 ) THEN rc[n] = sub( 0, rc[n] );
| IF ( n == 4 ) THEN EXIT; /continue with subclause 3.10.4/
|
Schur recursion:
| P[0] = add( P[0], mult_r( P[1], rc[n] ) );
|==== FOR m=1 to 4‑n:
| P[m] = add( P[m+1], mult_r( K[5‑m], rc[n] ) );
| K[5‑m] = add( K[5‑m], mult_r( P[m+1], rc[n] ) );
|==== NEXT m:
|
|== NEXT n:
6.10.4 Filter coefficient calculation
This subclause calculates the direct form filter coefficients a[1..2] from the reflection coefficients rc[1..4].
Step‑up procedure to obtain the a[1..2]:
temp = rc[1] >> 2;
a[1] = add( temp, mult_r( rc[2], temp ) );
a[2] = rc[2] >> 2;
6.10.5 Pole Frequency Test
This subclause uses the direct form filter coefficients a[1..2] to determine the pole frequency of the second order LPC analysis. If the pole frequency is less than 385 Hz tone is set to 0 and clause 3 terminates.
L_den = L_mult ( a[1], a[1] );
L_temp = a[2] << 16;
L_num = L_sub ( L_temp, L_den );
If pole is not complex then exit:
IF ( L_num <= 0 ) THEN
| tone = 0;
| EXIT; /clause 3 complete/
If pole frequency is less than 385 Hz then exit:
IF ( a[1] < 0) THEN
| temp = L_den >> 16;
| L_den = L_mult ( temp, 3189 );
| L_temp = L_sub ( L_num, L_den );
| IF ( L_temp < 0 ) THEN
| tone = 0;
| EXIT; /clause 3 complete/
6.10.6 Prediction gain test
This subclause uses the reflection coefficients rc[1..4] to calculate the prediction gain. If the prediction gain is greater than 13,5 dB then tone is set to 1 otherwise tone is set to 0.
Calculate normalized prediction error:
prederr = 32767;
|== FOR i=1 to 4
| temp = mult ( rc[i], rc[i] );
| temp = sub ( 32767, temp);
| prederr = mult( prederr, temp );
|== NEXT i;
Test if prediction error is smaller than threshold:
temp = sub ( prederr, 1464 );
IF ( temp < 0 ) THEN tone = 1;
ELSE tone = 0;
Table 3.2: Values of the Hanning window array hann[i]
i |
hann |
i |
hann |
i |
hann |
i |
hann |
0 |
0 |
20 |
4856 |
40 |
16545 |
60 |
28139 |
1 |
12 |
21 |
5325 |
41 |
17192 |
61 |
28581 |
2 |
51 |
22 |
5811 |
42 |
17838 |
62 |
29003 |
3 |
114 |
23 |
6314 |
43 |
18482 |
63 |
29406 |
4 |
204 |
24 |
6832 |
44 |
19122 |
64 |
29789 |
5 |
318 |
25 |
7365 |
45 |
19758 |
65 |
30151 |
6 |
458 |
26 |
7913 |
46 |
20389 |
66 |
30491 |
7 |
622 |
27 |
8473 |
47 |
21014 |
67 |
30809 |
8 |
811 |
28 |
9046 |
48 |
21631 |
68 |
31105 |
9 |
1025 |
29 |
9631 |
49 |
22240 |
69 |
31377 |
10 |
1262 |
30 |
10226 |
50 |
22840 |
70 |
31626 |
11 |
1523 |
31 |
10831 |
51 |
23430 |
71 |
31852 |
12 |
1807 |
32 |
11444 |
52 |
24009 |
72 |
32053 |
13 |
2114 |
33 |
12065 |
53 |
24575 |
73 |
32230 |
14 |
2444 |
34 |
12693 |
54 |
25130 |
74 |
32382 |
15 |
2795 |
35 |
13326 |
55 |
25670 |
75 |
32509 |
16 |
3167 |
36 |
13964 |
56 |
26196 |
76 |
32611 |
17 |
3560 |
37 |
14607 |
57 |
26707 |
77 |
32688 |
18 |
3972 |
38 |
15251 |
58 |
27201 |
78 |
32739 |
19 |
4405 |
39 |
15898 |
59 |
27679 |
79 |
32764 |