int Speech_Encode_Frame_First ( Speech_Encode_FrameState *st, /* i/o : post filter states */ Word16 *new_speech) /* i : speech input */ { #if !defined(NO13BIT) Word16 i; #endif setCounter(st->complexityCounter); #if !defined(NO13BIT) /* Delete the 3 LSBs (13-bit input) */ for (i = 0; i < L_NEXT; i++) { new_speech[i] = new_speech[i] & 0xfff8; move16 (); logic16 (); } #endif /* filter + downscaling */ Pre_Process (st->pre_state, new_speech, L_NEXT); cod_amr_first(st->cod_amr_state, new_speech); Init_WMOPS_counter (); /* reset WMOPS counter for the new frame */ return 0; }
static void compress_code ( Word16 sign_indx[], /* i : signs of 4 pulses (signs only) */ Word16 pos_indx[], /* i : position index of 8 pulses (position only) */ Word16 indx[]) /* o : position and sign of 8 pulses (compressed) */ { Word16 i, ia, ib, ic; for (i = 0; i < NB_TRACK_MR102; i++) { indx[i] = sign_indx[i]; move16 (); } /* First index indx[NB_TRACK] = (ia/2+(ib/2)*5 +(ic/2)*25)*8 + ia%2 + (ib%2)*2 + (ic%2)*4; */ move16 (); indx[NB_TRACK_MR102] = compress10(pos_indx[0],pos_indx[4],pos_indx[1]); /* Second index indx[NB_TRACK+1] = (ia/2+(ib/2)*5 +(ic/2)*25)*8 + ia%2 + (ib%2)*2 + (ic%2)*4; */ move16 (); indx[NB_TRACK_MR102+1]= compress10(pos_indx[2],pos_indx[6],pos_indx[5]); /* Third index if ((ib/2)%2 == 1) indx[NB_TRACK+2] = ((((4-ia/2) + (ib/2)*5)*32+12)/25)*4 + ia%2 + (ib%2)*2; else indx[NB_TRACK+2] = ((((ia/2) + (ib/2)*5)*32+12)/25)*4 + ia%2 + (ib%2)*2; */ ib = shr(pos_indx[7], 1) & 1; logic16 (); test (); if (sub(ib, 1) == 0) ia = sub(4, shr(pos_indx[3], 1)); else ia = shr(pos_indx[3], 1); ib = extract_l(L_shr(L_mult(shr(pos_indx[7], 1), 5), 1)); ib = add(shl(add(ia, ib), 5), 12); ic = shl(mult(ib, 1311), 2); ia = pos_indx[3] & 1; logic16 (); ib = shl((pos_indx[7] & 1), 1); logic16 (); indx[NB_TRACK_MR102+2] = add(ia, add(ib, ic)); }
static Word16 compress10 ( Word16 pos_indxA, /* i : signs of 4 pulses (signs only) */ Word16 pos_indxB, /* i : position index of 8 pulses (pos only) */ Word16 pos_indxC) /* i : position and sign of 8 pulses (compressed) */ { Word16 indx, ia,ib,ic; ia = shr(pos_indxA, 1); ib = extract_l(L_shr(L_mult(shr(pos_indxB, 1), 5), 1)); ic = extract_l(L_shr(L_mult(shr(pos_indxC, 1), 25), 1)); indx = shl(add(ia, add(ib, ic)), 3); ia = pos_indxA & 1; logic16 (); ib = shl((pos_indxB & 1), 1); logic16 (); ic = shl((pos_indxC & 1), 2); logic16 (); indx = add(indx , add(ia, add(ib, ic))); return indx; }
void decode_4i40_17bits( Word16 sign, /* i : signs of 4 pulses. */ Word16 index, /* i : Positions of the 4 pulses. */ Word16 cod[] /* o : algebraic (fixed) codebook excitation */ ) { Word16 i, j; Word16 pos[NB_PULSE]; /* Decode the positions */ i = index & 7; logic16 (); i = dgray[i]; move16 (); pos[0] = add(i, shl(i, 2)); /* pos0 =i*5 */ move16 (); index = shr(index, 3); i = index & 7; logic16 (); i = dgray[i]; move16 (); i = add(i, shl(i, 2)); /* pos1 =i*5+1 */ pos[1] = add(i, 1); move16 (); index = shr(index, 3); i = index & 7; logic16 (); i = dgray[i]; move16 (); i = add(i, shl(i, 2)); /* pos2 =i*5+1 */ pos[2] = add(i, 2); move16 (); index = shr(index, 3); j = index & 1; logic16 (); index = shr(index, 1); i = index & 7; logic16 (); i = dgray[i]; move16 (); i = add(i, shl(i, 2)); /* pos3 =i*5+3+j */ i = add(i, 3); pos[3] = add(i, j); move16 (); /* decode the signs and build the codeword */ for (i = 0; i < L_SUBFR; i++) { cod[i] = 0; move16 (); } for (j = 0; j < NB_PULSE; j++) { i = sign & 1; logic16 (); sign = shr(sign, 1); test (); if (i != 0) { cod[pos[j]] = 8191; move16 (); } else { cod[pos[j]] = -8192; move16 (); } } return; }
int Speech_Encode_Frame ( Speech_Encode_FrameState *st, /* i/o : post filter states */ enum Mode mode, /* i : speech coder mode */ Word16 *new_speech, /* i : speech input */ Word16 *serial, /* o : serial bit stream */ enum Mode *usedMode /* o : used speech coder mode */ ) { Word16 prm[MAX_PRM_SIZE]; /* Analysis parameters. */ Word16 syn[L_FRAME]; /* Buffer for synthesis speech */ Word16 i; setCounter(st->complexityCounter); Reset_WMOPS_counter (); /* reset WMOPS counter for the new frame */ /* initialize the serial output frame to zero */ for (i = 0; i < MAX_SERIAL_SIZE; i++) { serial[i] = 0; move16 (); } #if !defined(NO13BIT) /* Delete the 3 LSBs (13-bit input) */ for (i = 0; i < L_FRAME; i++) { new_speech[i] = new_speech[i] & 0xfff8; move16 (); logic16 (); } #endif /* filter + downscaling */ Pre_Process (st->pre_state, new_speech, L_FRAME); /* Call the speech encoder */ cod_amr(st->cod_amr_state, mode, new_speech, prm, usedMode, syn); /* Parameters to serial bits */ Prm2bits (*usedMode, prm, &serial[0]); fwc(); setCounter(0); /* set counter to global counter */ return 0; }
static void build_code ( Word16 codvec[], /* i : position of pulses */ Word16 sign[], /* i : sign of d[n] */ Word16 cod[], /* o : innovative code vector */ Word16 h[], /* i : impulse response of weighted synthesis filter*/ Word16 y[], /* o : filtered innovative code */ Word16 sign_indx[], /* o : signs of 4 pulses (signs only) */ Word16 pos_indx[] /* o : position index of 8 pulses(position only) */ ) { Word16 i, j, k, track, sign_index, pos_index, _sign[NB_PULSE]; Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7; Word32 s; for (i = 0; i < L_CODE; i++) { cod[i] = 0; move16 (); } for (i = 0; i < NB_TRACK_MR102; i++) { pos_indx[i] = -1; move16 (); sign_indx[i] = -1; move16 (); } for (k = 0; k < NB_PULSE; k++) { /* read pulse position */ i = codvec[k]; move16 (); /* read sign */ j = sign[i]; move16 (); pos_index = shr(i, 2); /* index = pos/4 */ track = i & 3; logic16 (); /* track = pos%4 */ test (); if (j > 0) { cod[i] = add (cod[i], POS_CODE); move16 (); _sign[k] = POS_SIGN; move16 (); sign_index = 0; /* bit=0 -> positive pulse */ move16 (); } else { cod[i] = sub (cod[i], NEG_CODE); move16 (); _sign[k] = NEG_SIGN; move16 (); sign_index = 1; move16 (); /* bit=1 => negative pulse */ /* index = add (index, 8); 1 = negative old code */ } test (); move16 (); if (pos_indx[track] < 0) { /* first set first NB_TRACK pulses */ pos_indx[track] = pos_index; move16 (); sign_indx[track] = sign_index; move16 (); } else { /* 2nd row of pulses , test if positions needs to be switched */ test (); logic16 (); logic16 (); if (((sign_index ^ sign_indx[track]) & 1) == 0) { /* sign of 1st pulse == sign of 2nd pulse */ test (); if (sub (pos_indx[track], pos_index) <= 0) { /* no swap */ pos_indx[track + NB_TRACK_MR102] = pos_index; move16 (); } else { /* swap*/ pos_indx[track + NB_TRACK_MR102] = pos_indx[track]; move16 (); pos_indx[track] = pos_index; move16 (); sign_indx[track] = sign_index; move16 (); } } else { /* sign of 1st pulse != sign of 2nd pulse */ test (); if (sub (pos_indx[track], pos_index) <= 0) { /*swap*/ pos_indx[track + NB_TRACK_MR102] = pos_indx[track]; move16 (); pos_indx[track] = pos_index; move16 (); sign_indx[track] = sign_index; move16 (); } else { /*no swap */ pos_indx[track + NB_TRACK_MR102] = pos_index; move16 (); } } } } p0 = h - codvec[0]; move16 (); p1 = h - codvec[1]; move16 (); p2 = h - codvec[2]; move16 (); p3 = h - codvec[3]; move16 (); p4 = h - codvec[4]; move16 (); p5 = h - codvec[5]; move16 (); p6 = h - codvec[6]; move16 (); p7 = h - codvec[7]; move16 (); for (i = 0; i < L_CODE; i++) { s = 0; move32 (); s = L_mac (s, *p0++, _sign[0]); s = L_mac (s, *p1++, _sign[1]); s = L_mac (s, *p2++, _sign[2]); s = L_mac (s, *p3++, _sign[3]); s = L_mac (s, *p4++, _sign[4]); s = L_mac (s, *p5++, _sign[5]); s = L_mac (s, *p6++, _sign[6]); s = L_mac (s, *p7++, _sign[7]); y[i] = round (s); move16 (); } }
void vector_quantize_mlts(Word16 number_of_available_bits, Word16 number_of_regions, Word16 num_categorization_control_possibilities, Word16 *mlt_coefs, Word16 *absolute_region_power_index, Word16 *power_categories, Word16 *category_balances, Word16 *p_categorization_control, Word16 *region_mlt_bit_counts, UWord32 *region_mlt_bits) { Word16 *raw_mlt_ptr; Word16 region; Word16 category; Word16 total_mlt_bits = 0; Word16 temp; Word16 temp1; Word16 temp2; /* Start in the middle of the categorization control range. */ temp = shr_nocheck(num_categorization_control_possibilities,1); temp = sub(temp,1); for (*p_categorization_control = 0; *p_categorization_control < temp; (*p_categorization_control)++) { region = category_balances[*p_categorization_control]; move16(); power_categories[region] = add(power_categories[region],1); move16(); } for (region=0; region<number_of_regions; region++) { category = power_categories[region]; move16(); temp = extract_l(L_mult0(region,REGION_SIZE)); raw_mlt_ptr = &mlt_coefs[temp]; move16(); temp = sub(category,(NUM_CATEGORIES-1)); test(); if (temp < 0) { region_mlt_bit_counts[region] = vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, ®ion_mlt_bits[shl_nocheck(region,2)]); } else { region_mlt_bit_counts[region] = 0; move16(); } total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); } /* If too few bits... */ temp = sub(total_mlt_bits,number_of_available_bits); test(); test(); logic16(); while ((temp < 0) && (*p_categorization_control > 0)) { test(); test(); logic16(); (*p_categorization_control)--; region = category_balances[*p_categorization_control]; move16(); power_categories[region] = sub(power_categories[region],1); move16(); total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]); category = power_categories[region]; move16(); raw_mlt_ptr = &mlt_coefs[region*REGION_SIZE]; move16(); temp = sub(category,(NUM_CATEGORIES-1)); test(); if (temp < 0) { region_mlt_bit_counts[region] = vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, ®ion_mlt_bits[shl_nocheck(region,2)]); } else { region_mlt_bit_counts[region] = 0; move16(); } total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); temp = sub(total_mlt_bits,number_of_available_bits); } /* If too many bits... */ /* Set up for while loop test */ temp1 = sub(total_mlt_bits,number_of_available_bits); temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1)); test(); test(); logic16(); while ((temp1 > 0) && (temp2 < 0)) { /* operations for while contitions */ test(); test(); logic16(); region = category_balances[*p_categorization_control]; move16(); power_categories[region] = add(power_categories[region],1); move16(); total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]); category = power_categories[region]; move16(); temp = extract_l(L_mult0(region,REGION_SIZE)); raw_mlt_ptr = &mlt_coefs[temp]; move16(); temp = sub(category,(NUM_CATEGORIES-1)); test(); if (temp < 0) { region_mlt_bit_counts[region] = vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, ®ion_mlt_bits[shl_nocheck(region,2)]); } else { region_mlt_bit_counts[region] = 0; move16(); } total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); (*p_categorization_control)++; temp1 = sub(total_mlt_bits,number_of_available_bits); temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1)); } }
Word16 compute_region_powers(Word16 *mlt_coefs, Word16 mag_shift, Word16 *drp_num_bits, UWord16 *drp_code_bits, Word16 *absolute_region_power_index, Word16 number_of_regions) { Word16 *input_ptr; Word32 long_accumulator; Word16 itemp1; Word16 power_shift; Word16 region; Word16 j; Word16 differential_region_power_index[MAX_NUMBER_OF_REGIONS]; Word16 number_of_bits; Word32 acca; Word16 temp; Word16 temp1; Word16 temp2; input_ptr = mlt_coefs; for (region=0; region<number_of_regions; region++) { long_accumulator = L_deposit_l(0); for (j=0; j<REGION_SIZE; j++) { itemp1 = *input_ptr++; move16(); long_accumulator = L_mac0(long_accumulator,itemp1,itemp1); } power_shift = 0; move16(); acca = (long_accumulator & 0x7fff0000L); logic32(); test(); while (acca > 0) { test(); long_accumulator = L_shr_nocheck(long_accumulator,1); acca = (long_accumulator & 0x7fff0000L); logic32(); power_shift = add(power_shift,1); } acca = L_sub(long_accumulator,32767); temp = add(power_shift,15); test(); test(); logic16(); while ((acca <= 0) && (temp >= 0)) { test(); test(); logic16(); long_accumulator = L_shl_nocheck(long_accumulator,1); acca = L_sub(long_accumulator,32767); power_shift--; temp = add(power_shift,15); } long_accumulator = L_shr_nocheck(long_accumulator,1); /* 28963 corresponds to square root of 2 times REGION_SIZE(20). */ acca = L_sub(long_accumulator,28963); test(); if (acca >= 0) power_shift = add(power_shift,1); acca = L_deposit_l(mag_shift); acca = L_shl_nocheck(acca,1); acca = L_sub(power_shift,acca); acca = L_add(35,acca); acca = L_sub(acca,REGION_POWER_TABLE_NUM_NEGATIVES); absolute_region_power_index[region] = extract_l(acca); } /* Before we differentially encode the quantized region powers, adjust upward the valleys to make sure all the peaks can be accurately represented. */ temp = sub(number_of_regions,2); for (region = temp; region >= 0; region--) { temp1 = sub(absolute_region_power_index[region+1],DRP_DIFF_MAX); temp2 = sub(absolute_region_power_index[region],temp1); test(); if (temp2 < 0) { absolute_region_power_index[region] = temp1; move16(); } } /* The MLT is currently scaled too low by the factor ENCODER_SCALE_FACTOR(=18318)/32768 * (1./sqrt(160). This is the ninth power of 1 over the square root of 2. So later we will add ESF_ADJUSTMENT_TO_RMS_INDEX (now 9) to drp_code_bits[0]. */ /* drp_code_bits[0] can range from 1 to 31. 0 will be used only as an escape sequence. */ temp1 = sub(1,ESF_ADJUSTMENT_TO_RMS_INDEX); temp2 = sub(absolute_region_power_index[0],temp1); test(); if (temp2 < 0) { absolute_region_power_index[0] = temp1; move16(); } temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX); /* * The next line was corrected in Release 1.2 */ temp2 = sub(absolute_region_power_index[0], temp1); test(); if (temp2 > 0) { absolute_region_power_index[0] = temp1; move16(); } differential_region_power_index[0] = absolute_region_power_index[0]; move16(); number_of_bits = 5; move16(); drp_num_bits[0] = 5; move16(); drp_code_bits[0] = (UWord16)add(absolute_region_power_index[0],ESF_ADJUSTMENT_TO_RMS_INDEX); move16(); /* Lower limit the absolute region power indices to -8 and upper limit them to 31. Such extremes may be mathematically impossible anyway.*/ for (region=1; region<number_of_regions; region++) { temp1 = sub(-8,ESF_ADJUSTMENT_TO_RMS_INDEX); temp2 = sub(absolute_region_power_index[region],temp1); test(); if (temp2 < 0) { absolute_region_power_index[region] = temp1; move16(); } temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX); temp2 = sub(absolute_region_power_index[region],temp1); test(); if (temp2 > 0) { absolute_region_power_index[region] = temp1; move16(); } } for (region=1; region<number_of_regions; region++) { j = sub(absolute_region_power_index[region],absolute_region_power_index[region-1]); temp = sub(j,DRP_DIFF_MIN); test(); if (temp < 0) { j = DRP_DIFF_MIN; } j = sub(j,DRP_DIFF_MIN); move16(); differential_region_power_index[region] = j; move16(); temp = add(absolute_region_power_index[region-1],differential_region_power_index[region]); temp = add(temp,DRP_DIFF_MIN); absolute_region_power_index[region] = temp; move16(); number_of_bits = add(number_of_bits,differential_region_power_bits[region][j]); drp_num_bits[region] = differential_region_power_bits[region][j]; move16(); drp_code_bits[region] = differential_region_power_codes[region][j]; move16(); } return (number_of_bits); }
/*************************************************************************** Function: bits_to_words Syntax: bits_to_words(UWord32 *region_mlt_bits, Word16 *region_mlt_bit_counts, Word16 *drp_num_bits, UWord16 *drp_code_bits, Word16 *out_words, Word16 categorization_control, Word16 number_of_regions, Word16 num_categorization_control_bits, Word16 number_of_bits_per_frame) Description: Stuffs the bits into words for output WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.09 | 0.12 -------|--------------|---------------- MAX | 0.10 | 0.13 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.12 | 0.15 | 0.19 -------|--------------|----------------|---------------- MAX | 0.14 | 0.17 | 0.21 -------|--------------|----------------|---------------- ***************************************************************************/ void bits_to_words(UWord32 *region_mlt_bits, Word16 *region_mlt_bit_counts, Word16 *drp_num_bits, UWord16 *drp_code_bits, Word16 *out_words, Word16 categorization_control, Word16 number_of_regions, Word16 num_categorization_control_bits, Word16 number_of_bits_per_frame) { Word16 out_word_index = 0; Word16 j; Word16 region; Word16 out_word; Word16 region_bit_count; Word16 current_word_bits_left; UWord16 slice; Word16 out_word_bits_free = 16; UWord32 *in_word_ptr; UWord32 current_word; Word32 acca = 0; Word32 accb; Word16 temp; /* First set up the categorization control bits to look like one more set of region power bits. */ out_word = 0; move16(); drp_num_bits[number_of_regions] = num_categorization_control_bits; move16(); drp_code_bits[number_of_regions] = (UWord16)categorization_control; move16(); /* These code bits are right justified. */ for (region=0; region <= number_of_regions; region++) { current_word_bits_left = drp_num_bits[region]; move16(); current_word = (UWord32)drp_code_bits[region]; move16(); j = sub(current_word_bits_left,out_word_bits_free); test(); if (j >= 0) { temp = extract_l(L_shr_nocheck(current_word,j)); out_word = add(out_word,temp); out_words[out_word_index++] = out_word; move16(); out_word_bits_free = 16; move16(); out_word_bits_free = sub(out_word_bits_free,j); acca = (current_word << out_word_bits_free); out_word = extract_l(acca); } else { j = negate(j); acca = (current_word << j); accb = L_deposit_l(out_word); acca = L_add(accb,acca); out_word = extract_l(acca); out_word_bits_free = sub(out_word_bits_free,current_word_bits_left); } } /* These code bits are left justified. */ for (region=0;region<number_of_regions; region++) { accb = L_deposit_l(out_word_index); accb = L_shl_nocheck(accb,4); accb = L_sub(accb,number_of_bits_per_frame); test(); if(accb < 0) { temp = shl_nocheck(region,2); in_word_ptr = ®ion_mlt_bits[temp]; region_bit_count = region_mlt_bit_counts[region]; move16(); temp = sub(32,region_bit_count); test(); if(temp > 0) current_word_bits_left = region_bit_count; else current_word_bits_left = 32; current_word = *in_word_ptr++; acca = L_deposit_l(out_word_index); acca = L_shl_nocheck(acca,4); acca = L_sub(acca,number_of_bits_per_frame); /* from while loop */ test(); test(); logic16(); while ((region_bit_count > 0) && (acca < 0)) { /* from while loop */ test(); test(); logic16(); temp = sub(current_word_bits_left,out_word_bits_free); test(); if (temp >= 0) { temp = sub(32,out_word_bits_free); accb = LU_shr(current_word,temp); slice = (UWord16)extract_l(accb); out_word = add(out_word,slice); test(); current_word <<= out_word_bits_free; current_word_bits_left = sub(current_word_bits_left,out_word_bits_free); out_words[out_word_index++] = extract_l(out_word); move16(); out_word = 0; move16(); out_word_bits_free = 16; move16(); } else { temp = sub(32,current_word_bits_left); accb = LU_shr(current_word,temp); slice = (UWord16)extract_l(accb); temp = sub(out_word_bits_free,current_word_bits_left); test(); accb = slice << temp; acca = L_deposit_l(out_word); acca = L_add(acca,accb); out_word = extract_l(acca); out_word_bits_free = sub(out_word_bits_free,current_word_bits_left); current_word_bits_left = 0; move16(); } test(); if (current_word_bits_left == 0) { current_word = *in_word_ptr++; region_bit_count = sub(region_bit_count,32); /* current_word_bits_left = MIN(32,region_bit_count); */ temp = sub(32,region_bit_count); test(); if(temp > 0) current_word_bits_left = region_bit_count; else current_word_bits_left = 32; } acca = L_deposit_l(out_word_index); acca = L_shl_nocheck(acca,4); acca = L_sub(acca,number_of_bits_per_frame); } accb = L_deposit_l(out_word_index); accb = L_shl_nocheck(accb,4); accb = L_sub(accb,number_of_bits_per_frame); } } /* Fill out with 1's. */ test(); while (acca < 0) { test(); current_word = 0x0000ffff; move32(); temp = sub(16,out_word_bits_free); acca = LU_shr(current_word,temp); slice = (UWord16)extract_l(acca); out_word = add(out_word,slice); out_words[out_word_index++] = out_word; move16(); out_word = 0; move16(); out_word_bits_free = 16; move16(); acca = L_deposit_l(out_word_index); acca = L_shl_nocheck(acca,4); acca = L_sub(acca,number_of_bits_per_frame); } }
Word16 vad2 (Word16 * farray_ptr, vadState2 * st) { /* * The channel table is defined below. In this table, the * lower and higher frequency coefficients for each of the 16 * channels are specified. The table excludes the coefficients * with numbers 0 (DC), 1, and 64 (Foldover frequency). */ const static Word16 ch_tbl[NUM_CHAN][2] = { {2, 3}, {4, 5}, {6, 7}, {8, 9}, {10, 11}, {12, 13}, {14, 16}, {17, 19}, {20, 22}, {23, 26}, {27, 30}, {31, 35}, {36, 41}, {42, 48}, {49, 55}, {56, 63} }; /* channel energy scaling table - allows efficient division by number * of DFT bins in the channel: 1/2, 1/3, 1/4, etc. */ const static Word16 ch_tbl_sh[NUM_CHAN] = { 16384, 16384, 16384, 16384, 16384, 16384, 10923, 10923, 10923, 8192, 8192, 6554, 5461, 4681, 4681, 4096 }; /* * The voice metric table is defined below. It is a non- * linear table with a deadband near zero. It maps the SNR * index (quantized SNR value) to a number that is a measure * of voice quality. */ const static Word16 vm_tbl[90] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 23, 24, 24, 25, 26, 27, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50 }; /* hangover as a function of peak SNR (3 dB steps) */ const static Word16 hangover_table[20] = { 30, 30, 30, 30, 30, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 8, 8, 8 }; /* burst sensitivity as a function of peak SNR (3 dB steps) */ const static Word16 burstcount_table[20] = { 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; /* voice metric sensitivity as a function of peak SNR (3 dB steps) */ const static Word16 vm_threshold_table[20] = { 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 40, 51, 71, 100, 139, 191, 257, 337, 432 }; /* State tables that use 22,9 or 27,4 scaling for ch_enrg[] */ const static Word16 noise_floor_chan[2] = {NOISE_FLOOR_CHAN_0, NOISE_FLOOR_CHAN_1}; const static Word16 min_chan_enrg[2] = {MIN_CHAN_ENRG_0, MIN_CHAN_ENRG_1}; const static Word16 ine_noise[2] = {INE_NOISE_0, INE_NOISE_1}; const static Word16 fbits[2] = {FRACTIONAL_BITS_0, FRACTIONAL_BITS_1}; const static Word16 state_change_shift_r[2] = {STATE_1_TO_0_SHIFT_R, STATE_0_TO_1_SHIFT_R}; /* Energy scale table given 30,1 input scaling (also account for -6 dB shift on input) */ const static Word16 enrg_norm_shift[2] = {(FRACTIONAL_BITS_0-1+2), (FRACTIONAL_BITS_1-1+2)}; /* Automatic variables */ Word32 Lenrg; /* scaled as 30,1 */ Word32 Ltne; /* scaled as 22,9 */ Word32 Ltce; /* scaled as 22,9 or 27,4 */ Word16 tne_db; /* scaled as 7,8 */ Word16 tce_db; /* scaled as 7,8 */ Word16 input_buffer[FRM_LEN]; /* used for block normalising input data */ Word16 data_buffer[FFT_LEN]; /* used for in-place FFT */ Word16 ch_snr[NUM_CHAN]; /* scaled as 7,8 */ Word16 ch_snrq; /* scaled as 15,0 (in 0.375 dB steps) */ Word16 vm_sum; /* scaled as 15,0 */ Word16 ch_enrg_dev; /* scaled as 7,8 */ Word32 Lpeak; /* maximum channel energy */ Word16 p2a_flag; /* flag to indicate spectral peak-to-average ratio > 10 dB */ Word16 ch_enrg_db[NUM_CHAN]; /* scaled as 7,8 */ Word16 ch_noise_db; /* scaled as 7,8 */ Word16 alpha; /* scaled as 0,15 */ Word16 one_m_alpha; /* scaled as 0,15 */ Word16 update_flag; /* set to indicate a background noise estimate update */ Word16 i, j, j1, j2; /* Scratch variables */ Word16 hi1, lo1; Word32 Ltmp, Ltmp1, Ltmp2; Word16 tmp; Word16 normb_shift; /* block norm shift count */ Word16 ivad; /* intermediate VAD decision (return value) */ Word16 tsnrq; /* total signal-to-noise ratio (quantized 3 dB steps) scaled as 15,0 */ Word16 xt; /* instantaneous frame SNR in dB, scaled as 7,8 */ Word16 state_change; /* Increment frame counter */ st->Lframe_cnt = L_add(st->Lframe_cnt, 1); /* Block normalize the input */ normb_shift = block_norm(farray_ptr, input_buffer, FRM_LEN, FFT_HEADROOM); /* Pre-emphasize the input data and store in the data buffer with the appropriate offset */ for (i = 0; i < DELAY; i++) { data_buffer[i] = 0; move16(); } st->pre_emp_mem = shr_r(st->pre_emp_mem, sub(st->last_normb_shift, normb_shift)); st->last_normb_shift = normb_shift; move16(); data_buffer[DELAY] = add(input_buffer[0], mult(PRE_EMP_FAC, st->pre_emp_mem)); move16(); for (i = DELAY + 1, j = 1; i < DELAY + FRM_LEN; i++, j++) { data_buffer[i] = add(input_buffer[j], mult(PRE_EMP_FAC, input_buffer[j-1])); move16(); } st->pre_emp_mem = input_buffer[FRM_LEN-1]; move16(); for (i = DELAY + FRM_LEN; i < FFT_LEN; i++) { data_buffer[i] = 0; move16(); } /* Perform FFT on the data buffer */ r_fft(data_buffer); /* Use normb_shift factor to determine the scaling of the energy estimates */ state_change = 0; move16(); test(); if (st->shift_state == 0) { test(); if (sub(normb_shift, -FFT_HEADROOM+2) <= 0) { state_change = 1; move16(); st->shift_state = 1; move16(); } } else { test(); if (sub(normb_shift, -FFT_HEADROOM+5) >= 0) { state_change = 1; move16(); st->shift_state = 0; move16(); } } /* Scale channel energy estimate */ test(); if (state_change) { for (i = LO_CHAN; i <= HI_CHAN; i++) { st->Lch_enrg[i] = L_shr(st->Lch_enrg[i], state_change_shift_r[st->shift_state]); move32(); } } /* Estimate the energy in each channel */ test(); if (L_sub(st->Lframe_cnt, 1) == 0) { alpha = 32767; move16(); one_m_alpha = 0; move16(); } else { alpha = CEE_SM_FAC; move16(); one_m_alpha = ONE_MINUS_CEE_SM_FAC; move16(); } for (i = LO_CHAN; i <= HI_CHAN; i++) { Lenrg = 0; move16(); j1 = ch_tbl[i][0]; move16(); j2 = ch_tbl[i][1]; move16(); for (j = j1; j <= j2; j++) { Lenrg = L_mac(Lenrg, data_buffer[2 * j], data_buffer[2 * j]); Lenrg = L_mac(Lenrg, data_buffer[2 * j + 1], data_buffer[2 * j + 1]); } /* Denorm energy & scale 30,1 according to the state */ Lenrg = L_shr_r(Lenrg, sub(shl(normb_shift, 1), enrg_norm_shift[st->shift_state])); /* integrate over time: e[i] = (1-alpha)*e[i] + alpha*enrg/num_bins_in_chan */ tmp = mult(alpha, ch_tbl_sh[i]); L_Extract (Lenrg, &hi1, &lo1); Ltmp = Mpy_32_16(hi1, lo1, tmp); L_Extract (st->Lch_enrg[i], &hi1, &lo1); st->Lch_enrg[i] = L_add(Ltmp, Mpy_32_16(hi1, lo1, one_m_alpha)); move32(); test(); if (L_sub(st->Lch_enrg[i], min_chan_enrg[st->shift_state]) < 0) { st->Lch_enrg[i] = min_chan_enrg[st->shift_state]; move32(); } } /* Compute the total channel energy estimate (Ltce) */ Ltce = 0; move16(); for (i = LO_CHAN; i <= HI_CHAN; i++) { Ltce = L_add(Ltce, st->Lch_enrg[i]); } /* Calculate spectral peak-to-average ratio, set flag if p2a > 10 dB */ Lpeak = 0; move32(); for (i = LO_CHAN+2; i <= HI_CHAN; i++) /* Sine waves not valid for low frequencies */ { test(); if (L_sub(st->Lch_enrg [i], Lpeak) > 0) { Lpeak = st->Lch_enrg [i]; move32(); } } /* Set p2a_flag if peak (dB) > average channel energy (dB) + 10 dB */ /* Lpeak > Ltce/num_channels * 10^(10/10) */ /* Lpeak > (10/16)*Ltce */ L_Extract (Ltce, &hi1, &lo1); Ltmp = Mpy_32_16(hi1, lo1, 20480); test(); if (L_sub(Lpeak, Ltmp) > 0) { p2a_flag = TRUE; move16(); } else { p2a_flag = FALSE; move16(); } /* Initialize channel noise estimate to either the channel energy or fixed level */ /* Scale the energy appropriately to yield state 0 (22,9) scaling for noise */ test(); if (L_sub(st->Lframe_cnt, 4) <= 0) { test(); if (p2a_flag == TRUE) { for (i = LO_CHAN; i <= HI_CHAN; i++) { st->Lch_noise[i] = INE_NOISE_0; move32(); } } else { for (i = LO_CHAN; i <= HI_CHAN; i++) { test(); if (L_sub(st->Lch_enrg[i], ine_noise[st->shift_state]) < 0) { st->Lch_noise[i] = INE_NOISE_0; move32(); } else { test(); if (st->shift_state == 1) { st->Lch_noise[i] = L_shr(st->Lch_enrg[i], state_change_shift_r[0]); move32(); } else { st->Lch_noise[i] = st->Lch_enrg[i]; move32(); } } } } } /* Compute the channel energy (in dB), the channel SNRs, and the sum of voice metrics */ vm_sum = 0; move16(); for (i = LO_CHAN; i <= HI_CHAN; i++) { ch_enrg_db[i] = fn10Log10(st->Lch_enrg[i], fbits[st->shift_state]); move16(); ch_noise_db = fn10Log10(st->Lch_noise[i], FRACTIONAL_BITS_0); ch_snr[i] = sub(ch_enrg_db[i], ch_noise_db); move16(); /* quantize channel SNR in 3/8 dB steps (scaled 7,8 => 15,0) */ /* ch_snr = round((snr/(3/8))>>8) */ /* = round(((0.6667*snr)<<2)>>8) */ /* = round((0.6667*snr)>>6) */ ch_snrq = shr_r(mult(21845, ch_snr[i]), 6); /* Accumulate the sum of voice metrics */ test(); if (sub(ch_snrq, 89) < 0) { test(); if (ch_snrq > 0) { j = ch_snrq; move16(); } else { j = 0; move16(); } } else { j = 89; move16(); } vm_sum = add(vm_sum, vm_tbl[j]); } /* Initialize NOMINAL peak voice energy and average noise energy, calculate instantaneous SNR */ test(),test(),logic16(); if (L_sub(st->Lframe_cnt, 4) <= 0 || st->fupdate_flag == TRUE) { /* tce_db = (96 - 22 - 10*log10(64) (due to FFT)) scaled as 7,8 */ tce_db = 14320; move16(); st->negSNRvar = 0; move16(); st->negSNRbias = 0; move16(); /* Compute the total noise estimate (Ltne) */ Ltne = 0; move32(); for (i = LO_CHAN; i <= HI_CHAN; i++) { Ltne = L_add(Ltne, st->Lch_noise[i]); } /* Get total noise in dB */ tne_db = fn10Log10(Ltne, FRACTIONAL_BITS_0); /* Initialise instantaneous and long-term peak signal-to-noise ratios */ xt = sub(tce_db, tne_db); st->tsnr = xt; move16(); } else { /* Calculate instantaneous frame signal-to-noise ratio */ /* xt = 10*log10( sum(2.^(ch_snr*0.1*log2(10)))/length(ch_snr) ) */ Ltmp1 = 0; move32(); for (i=LO_CHAN; i<=HI_CHAN; i++) { /* Ltmp2 = ch_snr[i] * 0.1 * log2(10); (ch_snr scaled as 7,8) */ Ltmp2 = L_shr(L_mult(ch_snr[i], 10885), 8); L_Extract(Ltmp2, &hi1, &lo1); hi1 = add(hi1, 3); /* 2^3 to compensate for negative SNR */ Ltmp1 = L_add(Ltmp1, Pow2(hi1, lo1)); } xt = fn10Log10(Ltmp1, 4+3); /* average by 16, inverse compensation 2^3 */ /* Estimate long-term "peak" SNR */ test(),test(); if (sub(xt, st->tsnr) > 0) { /* tsnr = 0.9*tsnr + 0.1*xt; */ st->tsnr = round(L_add(L_mult(29491, st->tsnr), L_mult(3277, xt))); } /* else if (xt > 0.625*tsnr) */ else if (sub(xt, mult(20480, st->tsnr)) > 0) { /* tsnr = 0.998*tsnr + 0.002*xt; */ st->tsnr = round(L_add(L_mult(32702, st->tsnr), L_mult(66, xt))); } } /* Quantize the long-term SNR in 3 dB steps, limit to 0 <= tsnrq <= 19 */ tsnrq = shr(mult(st->tsnr, 10923), 8); /* tsnrq = min(19, max(0, tsnrq)); */ test(),test(); if (sub(tsnrq, 19) > 0) { tsnrq = 19; move16(); } else if (tsnrq < 0) { tsnrq = 0; move16(); } /* Calculate the negative SNR sensitivity bias */ test(); if (xt < 0) { /* negSNRvar = 0.99*negSNRvar + 0.01*xt*xt; */ /* xt scaled as 7,8 => xt*xt scaled as 14,17, shift to 7,8 and round */ tmp = round(L_shl(L_mult(xt, xt), 7)); st->negSNRvar = round(L_add(L_mult(32440, st->negSNRvar), L_mult(328, tmp))); /* if (negSNRvar > 4.0) negSNRvar = 4.0; */ test(); if (sub(st->negSNRvar, 1024) > 0) { st->negSNRvar = 1024; move16(); } /* negSNRbias = max(12.0*(negSNRvar - 0.65), 0.0); */ tmp = mult_r(shl(sub(st->negSNRvar, 166), 4), 24576); test(); if (tmp < 0) { st->negSNRbias = 0; move16(); } else { st->negSNRbias = shr(tmp, 8); } } /* Determine VAD as a function of the voice metric sum and quantized SNR */ tmp = add(vm_threshold_table[tsnrq], st->negSNRbias); test(); if (sub(vm_sum, tmp) > 0) { ivad = 1; move16(); st->burstcount = add(st->burstcount, 1); test(); if (sub(st->burstcount, burstcount_table[tsnrq]) > 0) { st->hangover = hangover_table[tsnrq]; move16(); } } else { st->burstcount = 0; move16(); st->hangover = sub(st->hangover, 1); test(); if (st->hangover <= 0) { ivad = 0; move16(); st->hangover = 0; move16(); } else { ivad = 1; move16(); } } /* Calculate log spectral deviation */ ch_enrg_dev = 0; move16(); test(); if (L_sub(st->Lframe_cnt, 1) == 0) { for (i = LO_CHAN; i <= HI_CHAN; i++) { st->ch_enrg_long_db[i] = ch_enrg_db[i]; move16(); } } else { for (i = LO_CHAN; i <= HI_CHAN; i++) { tmp = abs_s(sub(st->ch_enrg_long_db[i], ch_enrg_db[i])); ch_enrg_dev = add(ch_enrg_dev, tmp); } } /* * Calculate long term integration constant as a function of instantaneous SNR * (i.e., high SNR (tsnr dB) -> slower integration (alpha = HIGH_ALPHA), * low SNR (0 dB) -> faster integration (alpha = LOW_ALPHA) */ /* alpha = HIGH_ALPHA - ALPHA_RANGE * (tsnr - xt) / tsnr, low <= alpha <= high */ tmp = sub(st->tsnr, xt); test(),logic16(),test(),test(); if (tmp <= 0 || st->tsnr <= 0) { alpha = HIGH_ALPHA; move16(); one_m_alpha = 32768L-HIGH_ALPHA; move16(); } else if (sub(tmp, st->tsnr) > 0) { alpha = LOW_ALPHA; move16(); one_m_alpha = 32768L-LOW_ALPHA; move16(); } else { tmp = div_s(tmp, st->tsnr); alpha = sub(HIGH_ALPHA, mult(ALPHA_RANGE, tmp)); one_m_alpha = sub(32767, alpha); } /* Calc long term log spectral energy */ for (i = LO_CHAN; i <= HI_CHAN; i++) { Ltmp1 = L_mult(one_m_alpha, ch_enrg_db[i]); Ltmp2 = L_mult(alpha, st->ch_enrg_long_db[i]); st->ch_enrg_long_db[i] = round(L_add(Ltmp1, Ltmp2)); } /* Set or clear the noise update flags */ update_flag = FALSE; move16(); st->fupdate_flag = FALSE; move16(); test(),test(); if (sub(vm_sum, UPDATE_THLD) <= 0) { test(); if (st->burstcount == 0) { update_flag = TRUE; move16(); st->update_cnt = 0; move16(); } } else if (L_sub(Ltce, noise_floor_chan[st->shift_state]) > 0) { test(); if (sub(ch_enrg_dev, DEV_THLD) < 0) { test(); if (p2a_flag == FALSE) { test(); if (st->LTP_flag == FALSE) { st->update_cnt = add(st->update_cnt, 1); test(); if (sub(st->update_cnt, UPDATE_CNT_THLD) >= 0) { update_flag = TRUE; move16(); st->fupdate_flag = TRUE; move16(); } } } } } test(); if (sub(st->update_cnt, st->last_update_cnt) == 0) { st->hyster_cnt = add(st->hyster_cnt, 1); } else { st->hyster_cnt = 0; move16(); } st->last_update_cnt = st->update_cnt; move16(); test(); if (sub(st->hyster_cnt, HYSTER_CNT_THLD) > 0) { st->update_cnt = 0; move16(); } /* Conditionally update the channel noise estimates */ test(); if (update_flag == TRUE) { /* Check shift state */ test(); if (st->shift_state == 1) { /* get factor to shift ch_enrg[] from state 1 to 0 (noise always state 0) */ tmp = state_change_shift_r[0]; move16(); } else { /* No shift if already state 0 */ tmp = 0; move16(); } /* Update noise energy estimate */ for (i = LO_CHAN; i <= HI_CHAN; i++) { test(); /* integrate over time: en[i] = (1-alpha)*en[i] + alpha*e[n] */ /* (extract with shift compensation for state 1) */ L_Extract (L_shr(st->Lch_enrg[i], tmp), &hi1, &lo1); Ltmp = Mpy_32_16(hi1, lo1, CNE_SM_FAC); L_Extract (st->Lch_noise[i], &hi1, &lo1); st->Lch_noise[i] = L_add(Ltmp, Mpy_32_16(hi1, lo1, ONE_MINUS_CNE_SM_FAC)); move32(); /* Limit low level noise */ test(); if (L_sub(st->Lch_noise[i], MIN_NOISE_ENRG_0) < 0) { st->Lch_noise[i] = MIN_NOISE_ENRG_0; move32(); } } } return(ivad); } /* end of vad2 () */
/*************************************************************************** * FUNCTION: cod_amr * * PURPOSE: Main encoder routine. * * DESCRIPTION: This function is called every 20 ms speech frame, * operating on the newly read 160 speech samples. It performs the * principle encoding functions to produce the set of encoded parameters * which include the LSP, adaptive codebook, and fixed codebook * quantization indices (addresses and gains). * * INPUTS: * No input argument are passed to this function. However, before * calling this function, 160 new speech data should be copied to the * vector new_speech[]. This is a global pointer which is declared in * this file (it points to the end of speech buffer minus 160). * * OUTPUTS: * * ana[]: vector of analysis parameters. * synth[]: Local synthesis speech (for debugging purposes) * ***************************************************************************/ int cod_amr( cod_amrState *st, /* i/o : State struct */ enum Mode mode, /* i : AMR mode */ Word16 new_speech[], /* i : speech input (L_FRAME) */ Word16 ana[], /* o : Analysis parameters */ enum Mode *usedMode, /* o : used mode */ Word16 synth[] /* o : Local synthesis */ ) { /* LPC coefficients */ Word16 A_t[(MP1) * 4]; /* A(z) unquantized for the 4 subframes */ Word16 Aq_t[(MP1) * 4]; /* A(z) quantized for the 4 subframes */ Word16 *A, *Aq; /* Pointer on A_t and Aq_t */ Word16 lsp_new[M]; /* Other vectors */ Word16 xn[L_SUBFR]; /* Target vector for pitch search */ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ Word16 code[L_SUBFR]; /* Fixed codebook excitation */ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ Word16 y2[L_SUBFR]; /* Filtered fixed codebook excitation */ Word16 gCoeff[6]; /* Correlations between xn, y1, & y2: */ Word16 res[L_SUBFR]; /* Short term (LPC) prediction residual */ Word16 res2[L_SUBFR]; /* Long term (LTP) prediction residual */ /* Vector and scalars needed for the MR475 */ Word16 xn_sf0[L_SUBFR]; /* Target vector for pitch search */ Word16 y2_sf0[L_SUBFR]; /* Filtered codebook innovation */ Word16 code_sf0[L_SUBFR]; /* Fixed codebook excitation */ Word16 h1_sf0[L_SUBFR]; /* The impulse response of sf0 */ Word16 mem_syn_save[M]; /* Filter memory */ Word16 mem_w0_save[M]; /* Filter memory */ Word16 mem_err_save[M]; /* Filter memory */ Word16 sharp_save; /* Sharpening */ Word16 evenSubfr; /* Even subframe indicator */ Word16 T0_sf0 = 0; /* Integer pitch lag of sf0 */ Word16 T0_frac_sf0 = 0; /* Fractional pitch lag of sf0 */ Word16 i_subfr_sf0 = 0; /* Position in exc[] for sf0 */ Word16 gain_pit_sf0; /* Quantized pitch gain for sf0 */ Word16 gain_code_sf0; /* Quantized codebook gain for sf0 */ /* Scalars */ Word16 i_subfr, subfrNr; Word16 T_op[L_FRAME/L_FRAME_BY2]; Word16 T0, T0_frac; Word16 gain_pit, gain_code; /* Flags */ Word16 lsp_flag = 0; /* indicates resonance in LPC filter */ Word16 gp_limit; /* pitch gain limit value */ Word16 vad_flag; /* VAD decision flag */ Word16 compute_sid_flag; /* SID analysis flag */ Copy(new_speech, st->new_speech, L_FRAME); *usedMode = mode; move16 (); /* DTX processing */ if (st->dtx) { /* no test() call since this if is only in simulation env */ /* Find VAD decision */ #ifdef VAD2 vad_flag = vad2 (st->new_speech, st->vadSt); vad_flag = vad2 (st->new_speech+80, st->vadSt) || vad_flag; logic16(); #else vad_flag = vad1(st->vadSt, st->new_speech); #endif fwc (); /* function worst case */ /* NB! usedMode may change here */ compute_sid_flag = tx_dtx_handler(st->dtx_encSt, vad_flag, usedMode); } else { compute_sid_flag = 0; move16 (); } /*------------------------------------------------------------------------* * - Perform LPC analysis: * * * autocorrelation + lag windowing * * * Levinson-durbin algorithm to find a[] * * * convert a[] to lsp[] * * * quantize and code the LSPs * * * find the interpolated LSPs and convert to a[] for all * * subframes (both quantized and unquantized) * *------------------------------------------------------------------------*/ /* LP analysis */ lpc(st->lpcSt, mode, st->p_window, st->p_window_12k2, A_t); fwc (); /* function worst case */ /* From A(z) to lsp. LSP quantization and interpolation */ lsp(st->lspSt, mode, *usedMode, A_t, Aq_t, lsp_new, &ana); fwc (); /* function worst case */ /* Buffer lsp's and energy */ dtx_buffer(st->dtx_encSt, lsp_new, st->new_speech); /* Check if in DTX mode */ test(); if (sub(*usedMode, MRDTX) == 0) { dtx_enc(st->dtx_encSt, compute_sid_flag, st->lspSt->qSt, st->gainQuantSt->gc_predSt, &ana); Set_zero(st->old_exc, PIT_MAX + L_INTERPOL); Set_zero(st->mem_w0, M); Set_zero(st->mem_err, M); Set_zero(st->zero, L_SUBFR); Set_zero(st->hvec, L_SUBFR); /* set to zero "h1[-L_SUBFR..-1]" */ /* Reset lsp states */ lsp_reset(st->lspSt); Copy(lsp_new, st->lspSt->lsp_old, M); Copy(lsp_new, st->lspSt->lsp_old_q, M); /* Reset clLtp states */ cl_ltp_reset(st->clLtpSt); st->sharp = SHARPMIN; move16 (); } else { /* check resonance in the filter */ lsp_flag = check_lsp(st->tonStabSt, st->lspSt->lsp_old); move16 (); } /*----------------------------------------------------------------------* * - Find the weighted input speech w_sp[] for the whole speech frame * * - Find the open-loop pitch delay for first 2 subframes * * - Set the range for searching closed-loop pitch in 1st subframe * * - Find the open-loop pitch delay for last 2 subframes * *----------------------------------------------------------------------*/ #ifdef VAD2 if (st->dtx) { /* no test() call since this if is only in simulation env */ st->vadSt->L_Rmax = 0; move32 (); st->vadSt->L_R0 = 0; move32 (); } #endif for(subfrNr = 0, i_subfr = 0; subfrNr < L_FRAME/L_FRAME_BY2; subfrNr++, i_subfr += L_FRAME_BY2) { /* Pre-processing on 80 samples */ pre_big(mode, gamma1, gamma1_12k2, gamma2, A_t, i_subfr, st->speech, st->mem_w, st->wsp); test (); test (); if ((sub(mode, MR475) != 0) && (sub(mode, MR515) != 0)) { /* Find open loop pitch lag for two subframes */ ol_ltp(st->pitchOLWghtSt, st->vadSt, mode, &st->wsp[i_subfr], &T_op[subfrNr], st->old_lags, st->ol_gain_flg, subfrNr, st->dtx); } } fwc (); /* function worst case */ test (); test(); if ((sub(mode, MR475) == 0) || (sub(mode, MR515) == 0)) { /* Find open loop pitch lag for ONE FRAME ONLY */ /* search on 160 samples */ ol_ltp(st->pitchOLWghtSt, st->vadSt, mode, &st->wsp[0], &T_op[0], st->old_lags, st->ol_gain_flg, 1, st->dtx); T_op[1] = T_op[0]; move16 (); } fwc (); /* function worst case */ #ifdef VAD2 if (st->dtx) { /* no test() call since this if is only in simulation env */ LTP_flag_update(st->vadSt, mode); } #endif #ifndef VAD2 /* run VAD pitch detection */ if (st->dtx) { /* no test() call since this if is only in simulation env */ vad_pitch_detection(st->vadSt, T_op); } #endif fwc (); /* function worst case */ if (sub(*usedMode, MRDTX) == 0) { goto the_end; } /*------------------------------------------------------------------------* * Loop for every subframe in the analysis frame * *------------------------------------------------------------------------* * To find the pitch and innovation parameters. The subframe size is * * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. * * - find the weighted LPC coefficients * * - find the LPC residual signal res[] * * - compute the target signal for pitch search * * - compute impulse response of weighted synthesis filter (h1[]) * * - find the closed-loop pitch parameters * * - encode the pitch dealy * * - update the impulse response h1[] by including fixed-gain pitch * * - find target vector for codebook search * * - codebook search * * - encode codebook address * * - VQ of pitch and codebook gains * * - find synthesis speech * * - update states of weighting filter * *------------------------------------------------------------------------*/ A = A_t; /* pointer to interpolated LPC parameters */ Aq = Aq_t; /* pointer to interpolated quantized LPC parameters */ evenSubfr = 0; move16 (); subfrNr = -1; move16 (); for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { subfrNr = add(subfrNr, 1); evenSubfr = sub(1, evenSubfr); /* Save states for the MR475 mode */ test(); test(); if ((evenSubfr != 0) && (sub(*usedMode, MR475) == 0)) { Copy(st->mem_syn, mem_syn_save, M); Copy(st->mem_w0, mem_w0_save, M); Copy(st->mem_err, mem_err_save, M); sharp_save = st->sharp; } /*-----------------------------------------------------------------* * - Preprocessing of subframe * *-----------------------------------------------------------------*/ test(); if (sub(*usedMode, MR475) != 0) { subframePreProc(*usedMode, gamma1, gamma1_12k2, gamma2, A, Aq, &st->speech[i_subfr], st->mem_err, st->mem_w0, st->zero, st->ai_zero, &st->exc[i_subfr], st->h1, xn, res, st->error); } else { /* MR475 */ subframePreProc(*usedMode, gamma1, gamma1_12k2, gamma2, A, Aq, &st->speech[i_subfr], st->mem_err, mem_w0_save, st->zero, st->ai_zero, &st->exc[i_subfr], st->h1, xn, res, st->error); /* save impulse response (modified in cbsearch) */ test (); if (evenSubfr != 0) { Copy (st->h1, h1_sf0, L_SUBFR); } } /* copy the LP residual (res2 is modified in the CL LTP search) */ Copy (res, res2, L_SUBFR); fwc (); /* function worst case */ /*-----------------------------------------------------------------* * - Closed-loop LTP search * *-----------------------------------------------------------------*/ cl_ltp(st->clLtpSt, st->tonStabSt, *usedMode, i_subfr, T_op, st->h1, &st->exc[i_subfr], res2, xn, lsp_flag, xn2, y1, &T0, &T0_frac, &gain_pit, gCoeff, &ana, &gp_limit); /* update LTP lag history */ move16 (); test(); test (); if ((subfrNr == 0) && (st->ol_gain_flg[0] > 0)) { st->old_lags[1] = T0; move16 (); } move16 (); test(); test (); if ((sub(subfrNr, 3) == 0) && (st->ol_gain_flg[1] > 0)) { st->old_lags[0] = T0; move16 (); } fwc (); /* function worst case */ /*-----------------------------------------------------------------* * - Inovative codebook search (find index and gain) * *-----------------------------------------------------------------*/ cbsearch(xn2, st->h1, T0, st->sharp, gain_pit, res2, code, y2, &ana, *usedMode, subfrNr); fwc (); /* function worst case */ /*------------------------------------------------------* * - Quantization of gains. * *------------------------------------------------------*/ gainQuant(st->gainQuantSt, *usedMode, res, &st->exc[i_subfr], code, xn, xn2, y1, y2, gCoeff, evenSubfr, gp_limit, &gain_pit_sf0, &gain_code_sf0, &gain_pit, &gain_code, &ana); fwc (); /* function worst case */ /* update gain history */ update_gp_clipping(st->tonStabSt, gain_pit); test(); if (sub(*usedMode, MR475) != 0) { /* Subframe Post Porcessing */ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit, gain_code, Aq, synth, xn, code, y1, y2, st->mem_syn, st->mem_err, st->mem_w0, st->exc, &st->sharp); } else { test(); if (evenSubfr != 0) { i_subfr_sf0 = i_subfr; move16 (); Copy(xn, xn_sf0, L_SUBFR); Copy(y2, y2_sf0, L_SUBFR); Copy(code, code_sf0, L_SUBFR); T0_sf0 = T0; move16 (); T0_frac_sf0 = T0_frac; move16 (); /* Subframe Post Porcessing */ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit, gain_code, Aq, synth, xn, code, y1, y2, mem_syn_save, st->mem_err, mem_w0_save, st->exc, &st->sharp); st->sharp = sharp_save; move16(); } else { /* update both subframes for the MR475 */ /* Restore states for the MR475 mode */ Copy(mem_err_save, st->mem_err, M); /* re-build excitation for sf 0 */ Pred_lt_3or6(&st->exc[i_subfr_sf0], T0_sf0, T0_frac_sf0, L_SUBFR, 1); Convolve(&st->exc[i_subfr_sf0], h1_sf0, y1, L_SUBFR); Aq -= MP1; subframePostProc(st->speech, *usedMode, i_subfr_sf0, gain_pit_sf0, gain_code_sf0, Aq, synth, xn_sf0, code_sf0, y1, y2_sf0, st->mem_syn, st->mem_err, st->mem_w0, st->exc, &sharp_save); /* overwrites sharp_save */ Aq += MP1; /* re-run pre-processing to get xn right (needed by postproc) */ /* (this also reconstructs the unsharpened h1 for sf 1) */ subframePreProc(*usedMode, gamma1, gamma1_12k2, gamma2, A, Aq, &st->speech[i_subfr], st->mem_err, st->mem_w0, st->zero, st->ai_zero, &st->exc[i_subfr], st->h1, xn, res, st->error); /* re-build excitation sf 1 (changed if lag < L_SUBFR) */ Pred_lt_3or6(&st->exc[i_subfr], T0, T0_frac, L_SUBFR, 1); Convolve(&st->exc[i_subfr], st->h1, y1, L_SUBFR); subframePostProc(st->speech, *usedMode, i_subfr, gain_pit, gain_code, Aq, synth, xn, code, y1, y2, st->mem_syn, st->mem_err, st->mem_w0, st->exc, &st->sharp); } } fwc (); /* function worst case */ A += MP1; /* interpolated LPC parameters for next subframe */ Aq += MP1; } Copy(&st->old_exc[L_FRAME], &st->old_exc[0], PIT_MAX + L_INTERPOL); the_end: /*--------------------------------------------------* * Update signal for next frame. * *--------------------------------------------------*/ Copy(&st->old_wsp[L_FRAME], &st->old_wsp[0], PIT_MAX); Copy(&st->old_speech[L_FRAME], &st->old_speech[0], L_TOTAL - L_FRAME); fwc (); /* function worst case */ return 0; }
/************************************************************************* * * FUNCTION: G_pitch * * PURPOSE: Compute the pitch (adaptive codebook) gain. * Result in Q14 (NOTE: 12.2 bit exact using Q12) * * DESCRIPTION: * The adaptive codebook gain is given by * * g = <x[], y[]> / <y[], y[]> * * where x[] is the target vector, y[] is the filtered adaptive * codevector, and <> denotes dot product. * The gain is limited to the range [0,1.2] (=0..19661 Q14) * *************************************************************************/ Word16 G_pitch ( /* o : Gain of pitch lag saturated to 1.2 */ enum Mode mode, /* i : AMR mode */ Word16 xn[], /* i : Pitch target. */ Word16 y1[], /* i : Filtered adaptive codebook. */ Word16 g_coeff[], /* i : Correlations need for gain quantization */ Word16 L_subfr /* i : Length of subframe. */ ) { Word16 i; Word16 xy, yy, exp_xy, exp_yy, gain; Word32 s; Word16 scaled_y1[L_SUBFR]; /* Usually dynamic allocation of (L_subfr) */ /* divide "y1[]" by 4 to avoid overflow */ for (i = 0; i < L_subfr; i++) { scaled_y1[i] = shr (y1[i], 2); move16 (); } /* Compute scalar product <y1[],y1[]> */ /* Q12 scaling / MR122 */ Overflow = 0; move16 (); s = 1L; move32 (); /* Avoid case of all zeros */ for (i = 0; i < L_subfr; i++) { s = L_mac (s, y1[i], y1[i]); } test (); if (Overflow == 0) /* Test for overflow */ { exp_yy = norm_l (s); yy = round (L_shl (s, exp_yy)); } else { s = 1L; move32 (); /* Avoid case of all zeros */ for (i = 0; i < L_subfr; i++) { s = L_mac (s, scaled_y1[i], scaled_y1[i]); } exp_yy = norm_l (s); yy = round (L_shl (s, exp_yy)); exp_yy = sub (exp_yy, 4); } /* Compute scalar product <xn[],y1[]> */ Overflow = 0; move16 (); s = 1L; move32 (); /* Avoid case of all zeros */ for (i = 0; i < L_subfr; i++) { s = L_mac(s, xn[i], y1[i]); } test (); if (Overflow == 0) { exp_xy = norm_l (s); xy = round (L_shl (s, exp_xy)); } else { s = 1L; move32 (); /* Avoid case of all zeros */ for (i = 0; i < L_subfr; i++) { s = L_mac (s, xn[i], scaled_y1[i]); } exp_xy = norm_l (s); xy = round (L_shl (s, exp_xy)); exp_xy = sub (exp_xy, 2); } g_coeff[0] = yy; move16 (); g_coeff[1] = sub (15, exp_yy); move16 (); g_coeff[2] = xy; move16 (); g_coeff[3] = sub (15, exp_xy); move16 (); /* If (xy < 4) gain = 0 */ i = sub (xy, 4); test (); if (i < 0) return ((Word16) 0); /* compute gain = xy/yy */ xy = shr (xy, 1); /* Be sure xy < yy */ gain = div_s (xy, yy); i = sub (exp_xy, exp_yy); /* Denormalization of division */ gain = shr (gain, i); /* if(gain >1.2) gain = 1.2 */ test (); if (sub (gain, 19661) > 0) { gain = 19661; move16 (); } test (); if (sub(mode, MR122) == 0) { /* clear 2 LSBits */ gain = gain & 0xfffC; logic16 (); } return (gain); }
enum DTXStateType rx_dtx_handler( dtx_decState *st, /* i/o : State struct */ enum RXFrameType frame_type /* i : Frame type */ ) { enum DTXStateType newState; enum DTXStateType encState; /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */ test(); test(); test(); test(); test(); test(); test(); test(); if ((sub(frame_type, RX_SID_FIRST) == 0) || (sub(frame_type, RX_SID_UPDATE) == 0) || (sub(frame_type, RX_SID_BAD) == 0) || (((sub(st->dtxGlobalState, DTX) == 0) || (sub(st->dtxGlobalState, DTX_MUTE) == 0)) && ((sub(frame_type, RX_NO_DATA) == 0) || (sub(frame_type, RX_SPEECH_BAD) == 0) || (sub(frame_type, RX_ONSET) == 0)))) { newState = DTX; move16(); /* stay in mute for these input types */ test(); test(); test(); test(); test(); if ((sub(st->dtxGlobalState, DTX_MUTE) == 0) && ((sub(frame_type, RX_SID_BAD) == 0) || (sub(frame_type, RX_SID_FIRST) == 0) || (sub(frame_type, RX_ONSET) == 0) || (sub(frame_type, RX_NO_DATA) == 0))) { newState = DTX_MUTE; move16(); } /* evaluate if noise parameters are too old */ /* since_last_sid is reset when CN parameters have been updated */ st->since_last_sid = add(st->since_last_sid, 1); move16(); /* no update of sid parameters in DTX for a long while */ /* Due to the delayed update of st->since_last_sid counter SID_UPDATE frames need to be handled separately to avoid entering DTX_MUTE for late SID_UPDATE frames */ test(); test(); logic16(); if((sub(frame_type, RX_SID_UPDATE) != 0) && (sub(st->since_last_sid, DTX_MAX_EMPTY_THRESH) > 0)) { newState = DTX_MUTE; move16(); } } else { newState = SPEECH; move16(); st->since_last_sid = 0; move16(); } /* reset the decAnaElapsed Counter when receiving CNI data the first time, to robustify counter missmatch after handover this might delay the bwd CNI analysis in the new decoder slightly. */ test(); test(); if ((st->data_updated == 0) && (sub(frame_type, RX_SID_UPDATE) == 0)) { st->decAnaElapsedCount = 0; move16(); } /* update the SPE-SPD DTX hangover synchronization */ /* to know when SPE has added dtx hangover */ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); move16(); st->dtxHangoverAdded = 0; move16(); test(); test(); test(); test(); test(); if ((sub(frame_type, RX_SID_FIRST) == 0) || (sub(frame_type, RX_SID_UPDATE) == 0) || (sub(frame_type, RX_SID_BAD) == 0) || (sub(frame_type, RX_ONSET) == 0) || (sub(frame_type, RX_NO_DATA) == 0)) { encState = DTX; move16(); /* In frame errors simulations RX_NO_DATA may occasionally mean that a speech packet was probably sent by the encoder, the assumed _encoder_ state should be SPEECH in such cases. */ test(); logic16(); if((sub(frame_type, RX_NO_DATA) == 0) && (sub(newState, SPEECH) == 0)) { encState = SPEECH; move16(); } /* Note on RX_ONSET operation differing from RX_NO_DATA operation: If a RX_ONSET is received in the decoder (by "accident") it is still most likely that the encoder state for the "ONSET frame" was DTX. */ } else { encState = SPEECH; move16(); } test(); if (sub(encState, SPEECH) == 0) { st->dtxHangoverCount = DTX_HANG_CONST; move16(); } else { test(); if (sub(st->decAnaElapsedCount, DTX_ELAPSED_FRAMES_THRESH) > 0) { st->dtxHangoverAdded = 1; move16(); st->decAnaElapsedCount = 0; move16(); st->dtxHangoverCount = 0; move16(); } else if (test(), st->dtxHangoverCount == 0) { st->decAnaElapsedCount = 0; move16(); } else { st->dtxHangoverCount = sub(st->dtxHangoverCount, 1); move16(); } } if (sub(newState, SPEECH) != 0) { /* DTX or DTX_MUTE * CN data is not in a first SID, first SIDs are marked as SID_BAD * but will do backwards analysis if a hangover period has been added * according to the state machine above */ st->sid_frame = 0; move16(); st->valid_data = 0; move16(); test(); if (sub(frame_type, RX_SID_FIRST) == 0) { st->sid_frame = 1; move16(); } else if (test(), sub(frame_type, RX_SID_UPDATE) == 0) { st->sid_frame = 1; move16(); st->valid_data = 1; move16(); } else if (test(), sub(frame_type, RX_SID_BAD) == 0) { st->sid_frame = 1; move16(); st->dtxHangoverAdded = 0; /* use old data */ move16(); } } return newState; /* newState is used by both SPEECH AND DTX synthesis routines */ }
/* ************************************************************************** * * Function : D_plsf_5 * Purpose : Decodes the 2 sets of LSP parameters in a frame * using the received quantization indices. * ************************************************************************** */ int D_plsf_5 ( D_plsfState *st, /* i/o: State variables */ Word16 bfi, /* i : bad frame indicator (set to 1 if a bad frame is received) */ Word16 *indice, /* i : quantization indices of 5 submatrices, Q0 */ Word16 *lsp1_q, /* o : quantized 1st LSP vector (M), Q15 */ Word16 *lsp2_q /* o : quantized 2nd LSP vector (M), Q15 */ ) { Word16 i; const Word16 *p_dico; Word16 temp, sign; Word16 lsf1_r[M], lsf2_r[M]; Word16 lsf1_q[M], lsf2_q[M]; test (); if (bfi != 0) /* if bad frame */ { /* use the past LSFs slightly shifted towards their mean */ for (i = 0; i < M; i++) { /* lsfi_q[i] = ALPHA*st->past_lsf_q[i] + ONE_ALPHA*mean_lsf[i]; */ lsf1_q[i] = add (mult (st->past_lsf_q[i], ALPHA), mult (mean_lsf[i], ONE_ALPHA)); move16 (); lsf2_q[i] = lsf1_q[i]; move16 (); } /* estimate past quantized residual to be used in next frame */ for (i = 0; i < M; i++) { /* temp = mean_lsf[i] + st->past_r_q[i] * LSP_PRED_FAC_MR122; */ temp = add (mean_lsf[i], mult (st->past_r_q[i], LSP_PRED_FAC_MR122)); st->past_r_q[i] = sub (lsf2_q[i], temp); move16 (); } } else /* if good LSFs received */ { /* decode prediction residuals from 5 received indices */ p_dico = &dico1_lsf[shl (indice[0], 2)];move16 (); lsf1_r[0] = *p_dico++; move16 (); lsf1_r[1] = *p_dico++; move16 (); lsf2_r[0] = *p_dico++; move16 (); lsf2_r[1] = *p_dico++; move16 (); p_dico = &dico2_lsf[shl (indice[1], 2)];move16 (); lsf1_r[2] = *p_dico++; move16 (); lsf1_r[3] = *p_dico++; move16 (); lsf2_r[2] = *p_dico++; move16 (); lsf2_r[3] = *p_dico++; move16 (); sign = indice[2] & 1; logic16 (); i = shr (indice[2], 1); p_dico = &dico3_lsf[shl (i, 2)]; move16 (); test (); if (sign == 0) { lsf1_r[4] = *p_dico++; move16 (); lsf1_r[5] = *p_dico++; move16 (); lsf2_r[4] = *p_dico++; move16 (); lsf2_r[5] = *p_dico++; move16 (); } else { lsf1_r[4] = negate (*p_dico++); move16 (); lsf1_r[5] = negate (*p_dico++); move16 (); lsf2_r[4] = negate (*p_dico++); move16 (); lsf2_r[5] = negate (*p_dico++); move16 (); } p_dico = &dico4_lsf[shl (indice[3], 2)];move16 (); lsf1_r[6] = *p_dico++; move16 (); lsf1_r[7] = *p_dico++; move16 (); lsf2_r[6] = *p_dico++; move16 (); lsf2_r[7] = *p_dico++; move16 (); p_dico = &dico5_lsf[shl (indice[4], 2)];move16 (); lsf1_r[8] = *p_dico++; move16 (); lsf1_r[9] = *p_dico++; move16 (); lsf2_r[8] = *p_dico++; move16 (); lsf2_r[9] = *p_dico++; move16 (); /* Compute quantized LSFs and update the past quantized residual */ for (i = 0; i < M; i++) { temp = add (mean_lsf[i], mult (st->past_r_q[i], LSP_PRED_FAC_MR122)); lsf1_q[i] = add (lsf1_r[i], temp); move16 (); lsf2_q[i] = add (lsf2_r[i], temp); move16 (); st->past_r_q[i] = lsf2_r[i]; move16 (); } } /* verification that LSFs have minimum distance of LSF_GAP Hz */ Reorder_lsf (lsf1_q, LSF_GAP, M); Reorder_lsf (lsf2_q, LSF_GAP, M); Copy (lsf2_q, st->past_lsf_q, M); /* convert LSFs to the cosine domain */ Lsf_lsp (lsf1_q, lsp1_q, M); Lsf_lsp (lsf2_q, lsp2_q, M); return 0; }
/************************************************************************* * * FUNCTION: dec_10i40_35bits() * * PURPOSE: Builds the innovative codevector from the received * index of algebraic codebook. * * See c1035pf.c for more details about the algebraic codebook structure. * *************************************************************************/ void dec_10i40_35bits ( Word16 index[], /* (i) : index of 10 pulses (sign+position) */ Word16 cod[] /* (o) : algebraic (fixed) codebook excitation */ ) { Word16 i, j, pos1, pos2, sign, tmp; for (i = 0; i < L_CODE; i++) { cod[i] = 0; move16 (); } /* decode the positions and signs of pulses and build the codeword */ for (j = 0; j < NB_TRACK; j++) { /* compute index i */ tmp = index[j]; move16 (); i = tmp & 7; logic16 (); i = dgray[i]; move16 (); i = extract_l (L_shr (L_mult (i, 5), 1)); pos1 = add (i, j); /* position of pulse "j" */ i = shr (tmp, 3) & 1; logic16 (); test (); if (i == 0) { sign = 4096; move16 (); /* +1.0 */ } else { sign = -4096; move16 (); /* -1.0 */ } cod[pos1] = sign; move16 (); /* compute index i */ i = index[add (j, 5)] & 7; logic16 (); i = dgray[i]; move16 (); i = extract_l (L_shr (L_mult (i, 5), 1)); pos2 = add (i, j); /* position of pulse "j+5" */ test (); if (sub (pos2, pos1) < 0) { sign = negate (sign); } cod[pos2] = add (cod[pos2], sign); move16 (); } return; }