rtphone/src/libs/libevs/lib_com/hvq_pvq_bitalloc_fx.cpp

190 lines
6.3 KiB
C++
Executable File

/*====================================================================================
EVS Codec 3GPP TS26.442 Apr 03, 2018. Version 12.11.0 / 13.6.0 / 14.2.0
====================================================================================*/
#include "options.h" /* Compilation switches */
#include "stl.h" /* required by wmc_tool */
#include "rom_com_fx.h"
#include "prot_fx.h" /* Function prototypes */
#include "cnst_fx.h" /* Common constants */
/*--------------------------------------------------------------------------*/
/* Function hvq_pvq_bitalloc */
/* ~~~~~~~~~~~~~~~~~~~~~~~~ */
/* */
/* Calculate the number of PVQ bands to code and allocate bits based on */
/* the number of available bits. */
/*--------------------------------------------------------------------------*/
Word16 hvq_pvq_bitalloc_fx(
Word16 num_bits, /* i/o: Number of available bits (including gain bits) */
const Word32 brate, /* i : bitrate */
const Word16 bwidth_fx, /* i : Encoded bandwidth */
const Word16 *ynrm, /* i : Envelope coefficients */
const Word32 manE_peak, /* i : Peak energy mantissa */
const Word16 expE_peak, /* i : Peak energy exponent */
Word16 *Rk, /* o : bit allocation for concatenated vector */
Word16 *R, /* i/o: Global bit allocation */
Word16 *sel_bands, /* o : Selected bands for encoding */
Word16 *n_sel_bands /* o : No. of selected bands for encoding */
)
{
Word16 num_bands, band_max_bits;
Word16 one_over_band_max_bits;
Word16 k;
Word16 reciprocal, envSum, expo, align, m, n, indx;
Word16 k_max;
Word16 k_start;
Word32 E_max, E_max5;
Word32 tmp, acc;
Word32 env_mean;
UWord16 lsb;
Word16 num_sfm;
IF (sub(bwidth_fx, FB) == 0)
{
num_sfm = SFM_N_HARM_FB;
}
ELSE
{
num_sfm = SFM_N_HARM;
}
IF ( L_sub(brate, HQ_24k40) == 0 )
{
band_max_bits = HVQ_BAND_MAX_BITS_24k;
move16();
one_over_band_max_bits = ONE_OVER_HVQ_BAND_MAX_BITS_24k_FX;
move16();
k_start = HVQ_THRES_SFM_24k;
move16();
IF (sub(bwidth_fx, FB) == 0)
{
reciprocal = 2731; /* Q15, 1/(SFM_N_HARM_FB + 1 - k_start) */ move16();
}
ELSE
{
reciprocal = 3277; /* Q15, 1/(SFM_N_HARM + 1 - k_start) */ move16();
}
}
ELSE
{
band_max_bits = HVQ_BAND_MAX_BITS_32k;
move16();
one_over_band_max_bits = ONE_OVER_HVQ_BAND_MAX_BITS_32k_FX;
move16();
k_start = HVQ_THRES_SFM_32k;
move16();
IF (sub(bwidth_fx, FB) == 0)
{
reciprocal = 3641; /* Q15, 1/(SFM_N_HARM_FB + 1 - k_start) */ move16();
}
ELSE
{
reciprocal = 4681; /* Q15, 1/(SFM_N_HARM + 1 - k_start) */ move16();
}
}
num_bands = mult( num_bits, one_over_band_max_bits ); /* Q0 */
num_bits = sub( num_bits, i_mult(num_bands, band_max_bits) ); /* Q0 */
IF ( sub(num_bits, HVQ_NEW_BAND_BIT_THR) >= 0 )
{
num_bands = add(num_bands, 1);
}
ELSE
{
num_bits = add(num_bits, band_max_bits);
}
/* safety check in case of bit errors */
if (sub(num_bands, 1) < 0)
{
return 0;
}
*n_sel_bands = 0;
move16();
envSum = 0;
move16();
E_max = L_deposit_l(0);
k_max = k_start;
move16();
FOR ( k = k_start; k < num_sfm; k++ )
{
indx = ynrm[k];
move16();
tmp = L_add(0,dicn_fx[indx]); /* Q14 */
envSum = add(envSum, indx); /* Since the size of dicn_fx = 40, ynrm[k] must be less than 41. 16 bits are enough for envSum.*/
IF (L_sub(tmp, E_max) > 0)
{
E_max = L_add(0,tmp);
k_max = k;
move16();
}
}
env_mean = L_mult(envSum, reciprocal); /* env_mean in Q16 */
IF (L_sub(L_sub(env_mean, L_deposit_h(ynrm[k_max])), 0x30000L) > 0) /* condition: env_mean - ynrm[k_max] > 3 */
{
expo = norm_l(E_max);
E_max = L_shl(E_max, expo);
Mpy_32_16_ss(E_max, 0x7a12, &E_max5, &lsb); /* NB: 5.0e5 = 0x7a12(Q15) x 2^19. */
/* True floating point value of E_max*5e5 = E_max5 x 2^(19 - expo - 14).
* In this context, the 32-bit E_max5 is in Q0, and
* -14 is due to Emax in Q14.
* True floating point value of E_peak = manE_peak x 2^(31 - expE_peak - 2*12). See peak_vq_enc_fx().
*/
/* Align the Q-points of the floating point Emax*5e5 and E_peak. */
align = sub(expo, expE_peak);
align = add(align, (19 - 14) - (31 - 2*12));
IF (align < 0)
{
acc = L_sub(E_max5, L_shl(manE_peak, align));
}
ELSE
{
acc = L_sub(L_shr(E_max5, align), manE_peak);
}
IF (acc > 0) /* condition: E_max*5.e5 > E_peak */
{
IF ( sub(band_len_harm[k_max], 96) == 0 )
{
n = 61;
}
ELSE
{
QuantaPerDsDirac_fx(band_len_harm[k_max], 1, hBitsN, &n);
}
m = shl(sub(num_bits, HVQ_PVQ_GAIN_BITS), 3);
IF (sub(m, n) >= 0)
{
IF (sub(num_bands, 1) > 0) /* condition: num_bands > 1 */
{
sel_bands[*n_sel_bands] = k_max;
move16();
*n_sel_bands = add(*n_sel_bands, 1);
R[k_max] = 1; /* Mark that the band has been encoded for fill_spectrum */ move16();
}
}
}
}
/* Allocate bits */
tmp = sub(num_bands,1);
FOR (k = 0; k < tmp; k++)
{
Rk[k] = shl(sub(band_max_bits, HVQ_PVQ_GAIN_BITS), 3);
move16();
}
/* NB: When it exits the above loop, k = num_bands - 1. */
Rk[k] = shl(sub(num_bits, HVQ_PVQ_GAIN_BITS), 3);
move16();
return num_bands;
}