📄 chan_dec.c
字号:
if ((rbits <= bit_class[0]+8) || (SpeechCodecMode == 2)) {
/* Allocate all redundancy to class 0 */
if (SpeechCodecMode < 2) {
bit_class[3] = bit_class[3]-4;
}else{
bit_class[0] = bit_class[0]-4;
}
r[0] = GetRate(rbits,(Word16)(-32768),bit_class[0]+4,inv_b0p4,0);
if (r[0] == 12) {
for (i=0;i<4;i++) {
bit_class[4] = bit_class[4] + bit_class[i];
bit_class[i] = 0;
}
}else{
bit_class[0] = bit_class[0] + 4;
}
for (j=0;j<3;j++) punctur[0][j] = PuncturTable[r[0]-12][j];
}else{
r[0] = GetRate(rbits,weight[0],bit_class[0],inv_bit_class[0],1);
if (r[0] < 24) r[0] = 24;
if (r[0] > 36) r[0] = 36;
for (j=0;j<3;j++) punctur[0][j] = PuncturTable[r[0]-12][j];
bit_class[3] = bit_class[3] - 4;
bit_class[0] = bit_class[0] + 4;
for (i=1;i<4;i++) {
abits = bitrate_test (bit_class,punctur,i-1);
if (abits < cbits) {
r[i] = GetRate(rbits,weight[i],bit_class[i],inv_bit_class[i],1);
if (r[i] < 18) r[i] = 18;
if (r[i] > 36) r[i] = 36;
if (r[i] > r[0]) r[i] = r[0];
for (j=0;j<3;j++) punctur[i][j] = PuncturTable[r[i]-12][j];
bit_class[i-1] = bit_class[i-1] - 4;
bit_class[i] = bit_class[i] + 4;
}else {
break;
}
}
}
}
}
/* Determine which class is the last protected one */
/* ----------------------------------------------- */
last=0;
for (i=1;i<5;i++){
if (r[i] > 12) last=i;
}
/* Determine channel bitrate with these settings */
/* --------------------------------------------- */
abits = bitrate_test (bit_class,punctur,last);
if (abits > cbits) {
/* too many bits are used: shift bits from high to low protection */
/* -------------------------------------------------------------- */
if (SpeechCodecMode < 2){
bitrate_adapt_high (bit_class,punctur,cbits,r,last);
}else{
r[0]--;
for (j=0;j<3;j++) punctur[0][j] = PuncturTable[r[0]-12][j];
if (r[0] == 12) bit_class[0]=bit_class[0]-4;
}
}
if ((abits < cbits) && (r[0]>12) && (rbits < limit) && (SpeechCodecMode < 2)) {
/* too few bits are used:: shift bits from low to high protection */
/* -------------------------------------------------------------- */
bitrate_adapt_low (bit_class,punctur,cbits,r,last);
}
return;
}
/*_________________________________________________________________________________
| |
| Determine rate for one bit class |
| (section 2.5.1) |
|_________________________________________________________________________________|
*/
static Word16 GetRate (Word16 rbits, Word16 weight, Word16 bit_class, Word16 inv_bit_class, Word16 rnd)
{
Word16 tmp;
Word32 L_tmp1, L_tmp2;
/* Calculate 12*(rbits*weight+bit_class) */
/* ------------------------------------- */
L_tmp1 = - L_mult(rbits,weight);
L_tmp2 = - L_mult(bit_class,(Word16)(-32768));
L_tmp1 = L_add(L_tmp1,L_tmp2);
/* Multiply by 12 */
/* -------------- */
L_tmp2 = L_shl(L_tmp1,3);
L_tmp1 = L_shl(L_tmp1,2);
L_tmp1 = L_add(L_tmp1,L_tmp2);
tmp = (Word16) L_shr(L_tmp1,12);
/* Multiply by inv_bit_class and round */
/* ----------------------------------- */
L_tmp1 = L_mult(tmp,inv_bit_class);
tmp = (Word16) L_shr(L_tmp1,24);
tmp = add(tmp,rnd);
tmp = shr (tmp,1);
return(tmp);
}
/*_________________________________________________________________________________
| |
| Adaptation of bit allocation to meet channel bitrate requirement |
| (section 2.5.1) |
|_________________________________________________________________________________|
*/
static void bitrate_adapt_low (Word16 bit_class[],Word16 punctur[5][3],
Word16 cbits, Word16 r[], Word16 last)
{
Word16 abits,src,dest;
src = last+1;
dest = last;
for (;;) {
if (bit_class[src] == 0) {
if (src == last) return;
src = last;
dest = last-1;
if (r[src] == r[dest]) return;
}
/* shift one bit from bit_class[src] to bit_class[dest] */
/* ---------------------------------------------------- */
bit_class[src]--;
bit_class[dest]++;
abits = bitrate_test (bit_class,punctur,last);
if (abits >= cbits) break;
}
if (abits > cbits) bitrate_adapt_high (bit_class,punctur,cbits,r,last);
return;
}
/*_________________________________________________________________________________
| |
| Adaptation of bit allocation to meet channel bitrate requirement |
| (section 2.5.1) |
|_________________________________________________________________________________|
*/
static void bitrate_adapt_high (Word16 bit_class[],Word16 punctur[5][3],
Word16 cbits, Word16 r[], Word16 last)
{
Word16 abits,i;
if (r[3] > 21) {
/* The number of bits in the unprotected class may not be increased */
/* ---------------------------------------------------------------- */
for (;;) {
for (i=2;i>0;i--){
/* shift one bit of bit_class[i] to bit_class[i+1] */
/* ----------------------------------------------- */
if (bit_class[i] == 0) return;
bit_class[i]--;
bit_class[i+1]++;
abits = bitrate_test (bit_class,punctur,last);
if (abits <= cbits) break;
}
if (abits <= cbits) break;
}
}else{
for (;;) {
/* shift one bit of bit_class[last] to bit_class[last+1] */
/* ----------------------------------------------------- */
if (bit_class[last] == 0) {
printf ("\n\n Error in bitrate_adapt_high\n\n");
exit(1);
}
bit_class[last]--;
bit_class[last+1]++;
abits = bitrate_test (bit_class,punctur,last);
if (abits <= cbits) break;
}
}
return;
}
/*_______________________________________________________________________
| |
| Determination of required channel bitrate |
| (section 2.5.1) |
|______________________________________________________________________|
*/
static bitrate_test( Word16 nbit_class[], Word16 punctur[5][3], Word16 last )
{
Word16 i, j, k, ptr0, cnt;
static const Word16 mask[16] = { 0X0001, 0X0002, 0X0004, 0X0008,
0X0010, 0X0020, 0X0040, 0X0080,
0X0100, 0X0200, 0X0400, 0X0800,
0X1000, 0X2000, 0X4000, -32768 };
/* Encode the protected classes: */
/* ----------------------------- */
ptr0 = 0;
cnt = 0;
for( k = 0; k <= last; ++k ) {
for( i = 0; i < nbit_class[k]; ++i ) {
for( j = 0; j < 3; ++j ) {
if(( punctur[k][j] & mask[cnt] ) != 0 ) ptr0++;
}
cnt = ++cnt % 12;
}
}
/* Determine channel bitrate */
/* ------------------------- */
for (i=last+1;i<5;i++) ptr0 = ptr0 + nbit_class[i];
ptr0 += BCHLen;
return(ptr0);
}
static void hamming_distance( Word16 chan_bit_np[], Word16 metric[], Word16 temp[] )
{
#define SCALE 2
static const Word16 code_word[16][3] = {
{ 16384/SCALE, 16384/SCALE, 16384/SCALE },
{ -16384/SCALE, -16384/SCALE, -16384/SCALE },
{ -16384/SCALE, 16384/SCALE, -16384/SCALE },
{ 16384/SCALE, -16384/SCALE, 16384/SCALE },
{ 16384/SCALE, -16384/SCALE, -16384/SCALE },
{ -16384/SCALE, 16384/SCALE, 16384/SCALE },
{ -16384/SCALE, -16384/SCALE, 16384/SCALE },
{ 16384/SCALE, 16384/SCALE, -16384/SCALE },
{ 16384/SCALE, -16384/SCALE, 16384/SCALE },
{ -16384/SCALE, 16384/SCALE, -16384/SCALE },
{ -16384/SCALE, -16384/SCALE, -16384/SCALE },
{ 16384/SCALE, 16384/SCALE, 16384/SCALE },
{ 16384/SCALE, 16384/SCALE, -16384/SCALE },
{ -16384/SCALE, -16384/SCALE, 16384/SCALE },
{ -16384/SCALE, 16384/SCALE, 16384/SCALE },
{ 16384/SCALE, -16384/SCALE, -16384/SCALE }};
Word16 ham_dist, i, j;
Word32 acc;
for( i = 0, j = 0; i < 8; ++i ) {
acc = L_mac( 0, code_word[j][0], chan_bit_np[0] );
acc = L_mac( acc, code_word[j][1], chan_bit_np[1] );
acc = L_mac( acc, code_word[j][2], chan_bit_np[2] );
ham_dist = extract_h( acc );
temp[j] = add( metric[i], ham_dist );
temp[j+17] = add( metric[i+8], ham_dist );
++j;
acc = L_mac( 0, code_word[j][0], chan_bit_np[0] );
acc = L_mac( acc, code_word[j][1], chan_bit_np[1] );
acc = L_mac( acc, code_word[j][2], chan_bit_np[2] );
ham_dist = extract_h( acc );
temp[j] = add( metric[i], ham_dist );
temp[j+15] = add( metric[i+8], ham_dist );
++j;
}
}
static void metric_update( Word16 chan_bit_np[], Word16 metric[], Word16 *surv_mem )
{
Word16 temp[32], j;
hamming_distance( chan_bit_np, metric, temp );
for( j = 0; j < 16; ++j ) {
if( sub( temp[j], temp[j+16] ) >= 0 ) {
metric[j] = temp[j];
if (metric[j] > 32760) printf("metric problem 1 %d\n",metric[j]);
if (metric[j] < -32760) printf("metric problem 1 %d\n",metric[j]);
clrbit( *surv_mem, j );
} else {
metric[j] = temp[j+16];
setbit( *surv_mem, j );
if (metric[j] > 32760) printf("metric problem 2 %d\n",metric[j]);
if (metric[j] < -32760) printf("metric problem 2 %d\n",metric[j]);
}
}
}
static Word16 metric_difference( Word16 chan_bit_np[], Word16 metric[], Word16 adr )
{
Word16 delta, temp[32], j;
hamming_distance( chan_bit_np, metric, temp );
for( j = 0; j < 16; ++j )
metric[j] = ( sub( temp[j], temp[j+16] ) >= 0 ) ? temp[j] : temp[j+16];
/* Compute difference metric: */
/* -------------------------- */
delta = abs_s( sub( temp[adr], temp[adr+16] ));
/* Scale difference metric: */
/* ------------------------ */
return( shr( delta, 1 ));
}
static void metric_update_delta( Word16 chan_bit_np[], Word16 metric[],
Word16 *surv_mem, Word16 delta_soft[] )
{
Word16 temp[32], j;
hamming_distance( chan_bit_np, metric, temp );
for( j = 0; j < 16; ++j ) {
/* Compute difference metric: */
/* -------------------------- */
delta_soft[j] = sub( temp[j], temp[j+16] );
if( delta_soft[j] >= 0 ) {
metric[j] = temp[j];
clrbit( *surv_mem, j );
} else {
metric[j] = temp[j+16];
setbit( *surv_mem, j );
}
}
}
static void viterbi( Word16 nbit_class[], Word16 punctur[5][3],
Word16 chan_bit_r[], Word16 info_bit_r[],
Word16 info_bit_r_soft[])
{
Word16 chan_bit_np[1500][3], surv[200], surv_mem[200];
Word16 ninfo_conv, metric[16];
Word16 ptr0, ptr1, adr, cnt12, i, j, k, last, n0;
static const Word16 mask[16] = { 0X0001, 0X0002, 0X0004, 0X0008,
0X0010, 0X0020, 0X0040, 0X0080,
0X0100, 0X0200, 0X0400, 0X0800,
0X1000, 0X2000, 0X4000, -32768 };
if (punctur[0][0] != 0) {
/* Check which class is the last protected one */
last=0;
for (i=1;i<5;i++){
if (punctur[i][0] != 0) last=i;
}
for (ninfo_conv=0,i=0;i<=last;i++) ninfo_conv += nbit_class[i];
for (n0=0,i=last+1;i<5;i++) n0 += nbit_class[i];
/* Initialise metrics: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -