void LTP_flag_update (vadState2 * st, Word16 mode) { Word16 thresh; Word16 hi1; Word16 lo1; Word32 Ltmp; test(); test(); if ((sub(mode, MR475) == 0) || (sub(mode, MR515) == 0)) { thresh = (Word16)(32768.0*0.55); move16(); } else if (sub(mode, MR102) == 0) { thresh = (Word16)(32768.0*0.60); move16(); } else { thresh = (Word16)(32768.0*0.65); move16(); } L_Extract (st->L_R0, &hi1, &lo1); Ltmp = Mpy_32_16(hi1, lo1, thresh); test(); if (L_sub(st->L_Rmax, Ltmp) > 0) { st->LTP_flag = TRUE; move16(); } else { st->LTP_flag = FALSE; move16(); } return; }
/*************************************************************************** Function: compute_raw_pow_categories Syntax: void compute_raw_pow_categories(Word16 *power_categories, Word16 *rms_index, Word16 number_of_regions, Word16 offset) inputs: *rms_index number_of_regions offset outputs: *power_categories Description: This function computes the power categories given the offset This is kind of redundant since they were already computed in calc_offset to determine the offset. WMOPS: | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.01 | 0.01 -------|--------------|---------------- MAX | 0.01 | 0.01 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.01 | 0.01 | 0.01 -------|--------------|----------------|---------------- MAX | 0.01 | 0.01 | 0.01 -------|--------------|----------------|---------------- ***************************************************************************/ void compute_raw_pow_categories(Word16 *power_categories,Word16 *rms_index,Word16 number_of_regions,Word16 offset) { Word16 region; Word16 j; Word16 temp; for (region=0; region<number_of_regions; region++) { j = sub(offset,rms_index[region]); j = shr(j,1); /* make sure j is between 0 and NUM_CAT-1 */ test(); if (j < 0) { j = 0; move16(); } temp = sub(j,(NUM_CATEGORIES-1)); test(); if (temp > 0) j = sub(NUM_CATEGORIES,1); power_categories[region] = j; move16(); } }
Word16 block_norm (Word16 * in, Word16 * out, Word16 length, Word16 headroom) { Word16 i, max, scnt, adata; max = abs_s(in[0]); for (i = 1; i < length; i++) { adata = abs_s(in[i]); test(); if (sub(adata, max) > 0) { max = adata; move16(); } } test(); if (max != 0) { scnt = sub(norm_s(max), headroom); for (i = 0; i < length; i++) { out[i] = shl(in[i], scnt); move16(); } } else { scnt = sub(16, headroom); for (i = 0; i < length; i++) { out[i] = 0; move16(); } } return (scnt); }
/************************************************************************* * * FUNCTION set_sign() * * PURPOSE: Builds sign[] vector according to "dn[]" and "cn[]". * Also finds the position of maximum of correlation in each track * and the starting position for each pulse. * *************************************************************************/ void set_sign(Word16 dn[], /* i/o : correlation between target and h[] */ Word16 sign[], /* o : sign of dn[] */ Word16 dn2[], /* o : maximum of correlation in each track. */ Word16 n /* i : # of maximum correlations in dn2[] */ ) { Word16 i, j, k; Word16 val, min; Word16 pos = 0; /* initialization only needed to keep gcc silent */ /* set sign according to dn[] */ for (i = 0; i < L_CODE; i++) { val = dn[i]; move16 (); test (); if (val >= 0) { sign[i] = 32767; move16 (); } else { sign[i] = -32767; move16 (); val = negate(val); } dn[i] = val; move16 (); /* modify dn[] according to the fixed sign */ dn2[i] = val; move16 (); } /* keep 8-n maximum positions/8 of each track and store it in dn2[] */ for (i = 0; i < NB_TRACK; i++) { for (k = 0; k < (8-n); k++) { min = 0x7fff; move16 (); for (j = i; j < L_CODE; j += STEP) { test (); move16 (); if (dn2[j] >= 0) { val = sub(dn2[j], min); test (); if (val < 0) { min = dn2[j]; move16 (); pos = j; move16 (); } } } dn2[pos] = -1; move16 (); } } return; }
/* ******************************************************************************** * PUBLIC PROGRAM CODE ******************************************************************************** */ int pre_big( enum Mode mode, /* i : coder mode */ const Word16 gamma1[], /* i : spectral exp. factor 1 */ const Word16 gamma1_12k2[],/* i : spectral exp. factor 1 for EFR */ const Word16 gamma2[], /* i : spectral exp. factor 2 */ Word16 A_t[], /* i : A(z) unquantized, for 4 subframes, Q12 */ Word16 frameOffset, /* i : Start position in speech vector, Q0 */ Word16 speech[], /* i : speech, Q0 */ Word16 mem_w[], /* i/o: synthesis filter memory state, Q0 */ Word16 wsp[] /* o : weighted speech Q0 */ ) { Word16 Ap1[MP1]; /* A(z) with spectral expansion */ Word16 Ap2[MP1]; /* A(z) with spectral expansion */ const Word16 *g1; /* Pointer to correct gammma1 vector */ Word16 aOffset; Word16 i; test (); if (sub (mode, MR795) <= 0 ) { g1 = gamma1; move16 (); } else { g1 = gamma1_12k2; move16 (); } test (); if (frameOffset > 0) { aOffset = 2*MP1; move16 (); } else { aOffset = 0; move16 (); } /* process two subframes (which form the "big" subframe) */ for (i = 0; i < 2; i++) { Weight_Ai(&A_t[aOffset], g1, Ap1); Weight_Ai(&A_t[aOffset], gamma2, Ap2); Residu(Ap1, &speech[frameOffset], &wsp[frameOffset], L_SUBFR); Syn_filt(Ap2, &wsp[frameOffset], &wsp[frameOffset], L_SUBFR, mem_w, 1); aOffset = add (aOffset, MP1); frameOffset = add (frameOffset, L_SUBFR); } return 0; }
/* ******************************************************************************** * PUBLIC PROGRAM CODE ******************************************************************************** */ void Weight_Ai ( Word16 a[], /* (i) : a[M+1] LPC coefficients (M=10) */ const Word16 fac[], /* (i) : Spectral expansion factors. */ Word16 a_exp[] /* (o) : Spectral expanded LPC coefficients */ ) { Word16 i; a_exp[0] = a[0]; move16 (); for (i = 1; i <= M; i++) { a_exp[i] = round (L_mult (a[i], fac[i - 1])); move16 (); } return; }
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)); }
int vad2_reset (vadState2 * st) { Word16 i; Word16 *ptr; if (st == (vadState2 *) NULL){ fprintf(stderr, "vad2_reset: invalid parameter\n"); return -1; } ptr = (Word16 *)st; move16(); for (i = 0; i < sizeof(vadState2)/2; i++) { *ptr++ = 0; move16(); } return 0; } /* end of vad2_reset () */
/* ************************************************************************** * * Function : Bin2int * Purpose : Read "no_of_bits" bits from the array bitstream[] * and convert to integer. * ************************************************************************** */ static Word16 Bin2int ( /* Reconstructed parameter */ Word16 no_of_bits, /* input : number of bits associated with value */ Word16 *bitstream /* output: address where bits are written */ ) { Word16 value, i, bit; value = 0; move16 (); for (i = 0; i < no_of_bits; i++) { value = shl (value, 1); bit = *bitstream++; move16 (); test (); if (sub (bit, BIT_1) == 0) value = add (value, 1); } return (value); }
void dtx_dec_activity_update(dtx_decState *st, Word16 lsf[], Word16 frame[]) { Word16 i; Word32 L_frame_en; Word16 log_en_e, log_en_m, log_en; /* update lsp history */ st->lsf_hist_ptr = add(st->lsf_hist_ptr,M); move16(); test(); if (sub(st->lsf_hist_ptr, 80) == 0) { st->lsf_hist_ptr = 0; move16(); } Copy(lsf, &st->lsf_hist[st->lsf_hist_ptr], M); /* compute log energy based on frame energy */ L_frame_en = 0; /* Q0 */ move32(); for (i=0; i < L_FRAME; i++) { L_frame_en = L_mac(L_frame_en, frame[i], frame[i]); } Log2(L_frame_en, &log_en_e, &log_en_m); /* convert exponent and mantissa to Word16 Q10 */ log_en = shl(log_en_e, 10); /* Q10 */ log_en = add(log_en, shr(log_en_m, 15-10)); /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */ log_en = sub(log_en, 7497+1024); /* insert into log energy buffer, no division by two as * * log_en in decoder is Q11 */ st->log_en_hist_ptr = add(st->log_en_hist_ptr, 1); test(); if (sub(st->log_en_hist_ptr, DTX_HIST_SIZE) == 0) { st->log_en_hist_ptr = 0; move16(); } st->log_en_hist[st->log_en_hist_ptr] = log_en; /* Q11 */ move16(); }
/* ************************************************************************** * * Function : Int_lsf * Purpose : Interpolates the LSFs for selected subframe * Description : The 20 ms speech frame is divided into 4 subframes. * The LSFs are interpolated at the 1st, 2nd and 3rd * subframe and only forwarded at the 4th subframe. * * |------|------|------|------| * sf1 sf2 sf3 sf4 * F0 F1 * * sf1: 3/4 F0 + 1/4 F1 sf3: 1/4 F0 + 3/4 F1 * sf2: 1/2 F0 + 1/2 F1 sf4: F1 * Returns : void * ************************************************************************** */ void Int_lsf( Word16 lsf_old[], /* i : LSF vector at the 4th SF of past frame */ Word16 lsf_new[], /* i : LSF vector at the 4th SF of present frame */ Word16 i_subfr, /* i : Pointer to current sf (equal to 0,40,80 or 120) */ Word16 lsf_out[] /* o : interpolated LSF parameters for current sf */ ) { Word16 i; if ( i_subfr == 0 ) { test (); for (i = 0; i < M; i++) { lsf_out[i] = add(sub(lsf_old[i], shr(lsf_old[i], 2)), shr(lsf_new[i], 2)); move16 (); } } else if ( sub(i_subfr, 40) == 0 ) { test (); test (); for (i = 0; i < M; i++) { lsf_out[i] = add(shr(lsf_old[i],1), shr(lsf_new[i], 1) ); move16 (); } } else if ( sub(i_subfr, 80) == 0 ) { test (); test (); test (); for (i = 0; i < M; i++) { lsf_out[i] = add(shr(lsf_old[i], 2), sub(lsf_new[i], shr(lsf_new[i], 2))); move16 (); } } else if ( sub(i_subfr, 120) == 0 ) { test (); test (); test (); test (); for (i = 0; i < M; i++) { lsf_out[i] = lsf_new[i]; 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; }
/* ************************************************************************** * * Function : Bits2prm * Purpose : Retrieves the vector of encoder parameters from * the received serial bits in a frame. * ************************************************************************** */ void Bits2prm ( enum Mode mode, /* i : AMR mode */ Word16 bits[], /* i : serial bits (size <= MAX_SERIAL_SIZE) */ Word16 prm[] /* o : analysis parameters (size <= MAX_PRM_SIZE) */ ) { Word16 i; move16(); /* account for pointer init (bitno[mode]) */ for (i = 0; i < prmno[mode]; i++) { prm[i] = Bin2int (bitno[mode][i], bits); move16 (); bits += bitno[mode][i]; add(0,0); /* account for above pointer update */ } return; }
/************************************************************************* * * FUNCTION: Reorder_lsf() * * PURPOSE: To make sure that the LSFs are properly ordered and to keep a * certain minimum distance between adjacent LSFs. * * The LSFs are in the frequency range 0-0.5 and represented in Q15 * *************************************************************************/ void Reorder_lsf ( Word16 *lsf, /* (i/o) : vector of LSFs (range: 0<=val<=0.5) */ Word16 min_dist, /* (i) : minimum required distance */ Word16 n /* (i) : LPC order */ ) { Word16 i; Word16 lsf_min; lsf_min = min_dist; move16 (); for (i = 0; i < n; i++) { test (); if (sub (lsf[i], lsf_min) < 0) { lsf[i] = lsf_min; move16 (); } lsf_min = add (lsf[i], min_dist); } }
/************************************************************************* * * FUNCTION: gc_pred_update() * * PURPOSE: update MA predictor with last quantized energy * *************************************************************************/ void gc_pred_update( gc_predState *st, /* i/o: State struct */ Word16 qua_ener_MR122, /* i : quantized energy for update, Q10 */ /* (log2(qua_err)) */ Word16 qua_ener /* i : quantized energy for update, Q10 */ /* (20*log10(qua_err)) */ ) { Word16 i; for (i = 3; i > 0; i--) { st->past_qua_en[i] = st->past_qua_en[i - 1]; move16 (); st->past_qua_en_MR122[i] = st->past_qua_en_MR122[i - 1]; move16 (); } st->past_qua_en_MR122[0] = qua_ener_MR122; /* log2 (qua_err), Q10 */ move16 (); st->past_qua_en[0] = qua_ener; /* 20*log10(qua_err), Q10 */ move16 (); }
void Lsf_wt ( Word16 *lsf, /* input : LSF vector */ Word16 *wf) /* output: square of weighting factors */ { Word16 temp; Word16 i; /* wf[0] = lsf[1] - 0 */ wf[0] = lsf[1]; move16 (); for (i = 1; i < 9; i++) { wf[i] = sub (lsf[i + 1], lsf[i - 1]); move16 (); } /* wf[9] = 0.5 - lsf[8] */ wf[9] = sub (16384, lsf[8]);move16 (); for (i = 0; i < 10; i++) { temp = sub (wf[i], 1843); test (); if (temp < 0) { wf[i] = sub (3427, mult (wf[i], 28160)); move16 (); } else { wf[i] = sub (1843, mult (temp, 6242)); move16 (); } wf[i] = shl (wf[i], 3); move16 (); } return; }
static Word16 Vq_subvec (/* o : quantization index, Q0 */ Word16 *lsf_r1, /* i : 1st LSF residual vector, Q15 */ Word16 *lsf_r2, /* i : 2nd LSF residual vector, Q15 */ const Word16 *dico, /* i : quantization codebook, Q15 */ Word16 *wf1, /* i : 1st LSF weighting factors Q13 */ Word16 *wf2, /* i : 2nd LSF weighting factors Q13 */ Word16 dico_size /* i : size of quantization codebook, Q0 */ ) { Word16 index = 0; /* initialization only needed to keep gcc silent */ Word16 i, temp; const Word16 *p_dico; Word32 dist_min, dist; dist_min = MAX_32; move32 (); p_dico = dico; move16 (); for (i = 0; i < dico_size; i++) { temp = sub (lsf_r1[0], *p_dico++); temp = mult (wf1[0], temp); dist = L_mult (temp, temp); temp = sub (lsf_r1[1], *p_dico++); temp = mult (wf1[1], temp); dist = L_mac (dist, temp, temp); temp = sub (lsf_r2[0], *p_dico++); temp = mult (wf2[0], temp); dist = L_mac (dist, temp, temp); temp = sub (lsf_r2[1], *p_dico++); temp = mult (wf2[1], temp); dist = L_mac (dist, temp, temp); test (); if (L_sub (dist, dist_min) < (Word32) 0) { dist_min = dist; move32 (); index = i; move16 (); } } /* Reading the selected vector */ p_dico = &dico[shl (index, 2)]; move16 (); lsf_r1[0] = *p_dico++; move16 (); lsf_r1[1] = *p_dico++; move16 (); lsf_r2[0] = *p_dico++; move16 (); lsf_r2[1] = *p_dico++; move16 (); return index; }
/************************************************************************* * * FUNCTION: gc_pred_average_limited() * * PURPOSE: get average of MA predictor state values (with a lower limit) * [used in error concealment] * *************************************************************************/ void gc_pred_average_limited( gc_predState *st, /* i: State struct */ Word16 *ener_avg_MR122, /* o: everaged quantized energy, Q10 */ /* (log2(qua_err)) */ Word16 *ener_avg /* o: averaged quantized energy, Q10 */ /* (20*log10(qua_err)) */ ) { Word16 av_pred_en; Word16 i; /* do average in MR122 mode (log2() domain) */ av_pred_en = 0; move16 (); for (i = 0; i < NPRED; i++) { av_pred_en = add (av_pred_en, st->past_qua_en_MR122[i]); } /* av_pred_en = 0.25*av_pred_en */ av_pred_en = mult (av_pred_en, 8192); /* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */ test (); if (sub (av_pred_en, MIN_ENERGY_MR122) < 0) { av_pred_en = MIN_ENERGY_MR122; move16 (); } *ener_avg_MR122 = av_pred_en; move16 (); /* do average for other modes (20*log10() domain) */ av_pred_en = 0; move16 (); for (i = 0; i < NPRED; i++) { av_pred_en = add (av_pred_en, st->past_qua_en[i]); } /* av_pred_en = 0.25*av_pred_en */ av_pred_en = mult (av_pred_en, 8192); /* if (av_pred_en < -14) av_pred_en = .. */ test (); if (sub (av_pred_en, MIN_ENERGY) < 0) { av_pred_en = MIN_ENERGY; move16 (); } *ener_avg = av_pred_en; move16 (); }
Word16 gmed_n ( /* o : index of the median value (0...N-1) */ Word16 ind[], /* i : Past gain values */ Word16 n /* i : The number of gains; this routine */ /* is only valid for a odd number of gains */ /* (n <= NMAX) */ ) { Word16 i, j, ix = 0; Word16 max; Word16 medianIndex; Word16 tmp[NMAX]; Word16 tmp2[NMAX]; for (i = 0; i < n; i++) { tmp2[i] = ind[i]; move16 (); } for (i = 0; i < n; i++) { max = -32767; move16 (); for (j = 0; j < n; j++) { test (); if (sub (tmp2[j], max) >= 0) { max = tmp2[j]; move16 (); ix = j; move16 (); } } tmp2[ix] = -32768; move16 (); tmp[i] = ix; move16 (); } medianIndex=tmp[ shr(n,1) ]; move16 (); /* account for complex addressing */ return (ind[medianIndex]); }
/************************************************************************* * * FUNCTION: calc_target_energy * * PURPOSE: calculation of target energy * * en = <xn, xn> * *************************************************************************/ void calc_target_energy( Word16 xn[], /* i: LTP target vector, Q0 */ Word16 *en_exp, /* o: optimum codebook gain (exponent part), Q0 */ Word16 *en_frac /* o: optimum codebook gain (fraction part), Q15 */ ) { Word32 s; Word16 i, exp; /* Compute scalar product <xn[], xn[]> */ s = L_mac(0L, xn[0], xn[0]); for (i = 1; i < L_SUBFR; i++) s = L_mac(s, xn[i], xn[i]); /* s = SUM 2*xn(i) * xn(i) = <xn xn> * 2 */ exp = norm_l(s); *en_frac = extract_h(L_shl(s, exp)); *en_exp = sub(16, exp); move16(); }
/*************************************************************************** Function: adjust_abs_region_power_index Syntax: adjust_abs_region_power_index(Word16 *absolute_region_power_index, Word16 *mlt_coefs, Word16 number_of_regions) inputs: *mlt_coefs *absolute_region_power_index number_of_regions outputs: *absolute_region_power_index Description: Adjusts the absolute power index WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.03 | 0.03 -------|--------------|---------------- MAX | 0.12 | 0.12 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.03 | 0.03 | 0.03 -------|--------------|----------------|---------------- MAX | 0.14 | 0.14 | 0.14 -------|--------------|----------------|---------------- ***************************************************************************/ void adjust_abs_region_power_index(Word16 *absolute_region_power_index,Word16 *mlt_coefs,Word16 number_of_regions) { Word16 n,i; Word16 region; Word16 *raw_mlt_ptr; Word32 acca; Word16 temp; for (region=0; region<number_of_regions; region++) { n = sub(absolute_region_power_index[region],39); n = shr_nocheck(n,1); test(); if (n > 0) { temp = extract_l(L_mult0(region,REGION_SIZE)); raw_mlt_ptr = &mlt_coefs[temp]; for (i=0; i<REGION_SIZE; i++) { acca = L_shl_nocheck(*raw_mlt_ptr,16); acca = L_add(acca,32768L); acca = L_shr_nocheck(acca,n); acca = L_shr_nocheck(acca,16); *raw_mlt_ptr++ = extract_l(acca); } temp = shl_nocheck(n,1); temp = sub(absolute_region_power_index[region],temp); absolute_region_power_index[region] = temp; move16(); } } }
/* ************************************************************************** * * Function : Chebps * Purpose : Evaluates the Chebyshev polynomial series * Description : - The polynomial order is n = m/2 = 5 * - The polynomial F(z) (F1(z) or F2(z)) is given by * F(w) = 2 exp(-j5w) C(x) * where * C(x) = T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 * and T_m(x) = cos(mw) is the mth order Chebyshev * polynomial ( x=cos(w) ) * Returns : C(x) for the input x. * ************************************************************************** */ static Word16 Chebps (Word16 x, Word16 f[], /* (n) */ Word16 n) { Word16 i, cheb; Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l; Word32 t0; b2_h = 256; move16 (); /* b2 = 1.0 */ b2_l = 0; move16 (); t0 = L_mult (x, 512); /* 2*x */ t0 = L_mac (t0, f[1], 8192); /* + f[1] */ L_Extract (t0, &b1_h, &b1_l); /* b1 = 2*x + f[1] */ for (i = 2; i < n; i++) { t0 = Mpy_32_16 (b1_h, b1_l, x); /* t0 = 2.0*x*b1 */ t0 = L_shl (t0, 1); t0 = L_mac (t0, b2_h, (Word16) 0x8000); /* t0 = 2.0*x*b1 - b2 */ t0 = L_msu (t0, b2_l, 1); t0 = L_mac (t0, f[i], 8192); /* t0 = 2.0*x*b1 - b2 + f[i] */ L_Extract (t0, &b0_h, &b0_l); /* b0 = 2.0*x*b1 - b2 + f[i]*/ b2_l = b1_l; move16 (); /* b2 = b1; */ b2_h = b1_h; move16 (); b1_l = b0_l; move16 (); /* b1 = b0; */ b1_h = b0_h; move16 (); } t0 = Mpy_32_16 (b1_h, b1_l, x); /* t0 = x*b1; */ t0 = L_mac (t0, b2_h, (Word16) 0x8000); /* t0 = x*b1 - b2 */ t0 = L_msu (t0, b2_l, 1); t0 = L_mac (t0, f[i], 4096); /* t0 = x*b1 - b2 + f[i]/2 */ t0 = L_shl (t0, 6); cheb = extract_h (t0); return (cheb); }
/************************************************************************* * * FUNCTION: Post_Process() * * PURPOSE: Postprocessing of input speech. * * DESCRIPTION: * - 2nd order high pass filtering with cut off frequency at 60 Hz. * - Multiplication of output by two. * * Algorithm: * * y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b[2]*x[i-2]*2 * + a[1]*y[i-1] + a[2]*y[i-2]; * * *************************************************************************/ int Post_Process ( Post_ProcessState *st, /* i/o : post process state */ Word16 signal[], /* i/o : signal */ Word16 lg /* i : length of signal */ ) { Word16 i, x2; Word32 L_tmp; test (); test (); for (i = 0; i < lg; i++) { x2 = st->x1; move16 (); st->x1 = st->x0; move16 (); st->x0 = signal[i]; move16 (); /* y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2 */ /* + a[1]*y[i-1] + a[2] * y[i-2]; */ L_tmp = Mpy_32_16 (st->y1_hi, st->y1_lo, a[1]); L_tmp = L_add (L_tmp, Mpy_32_16 (st->y2_hi, st->y2_lo, a[2])); L_tmp = L_mac (L_tmp, st->x0, b[0]); L_tmp = L_mac (L_tmp, st->x1, b[1]); L_tmp = L_mac (L_tmp, x2, b[2]); L_tmp = L_shl (L_tmp, 2); /* Multiplication by two of output speech with saturation. */ signal[i] = round(L_shl(L_tmp, 1)); move16 (); st->y2_hi = st->y1_hi; move16 (); st->y2_lo = st->y1_lo; move16 (); L_Extract (L_tmp, &st->y1_hi, &st->y1_lo); } return 0; }
/************************************************************************* * * FUNCTION: Dec_gain() * * PURPOSE: Decode the pitch and codebook gains * ************************************************************************/ void Dec_gain( gc_predState *pred_state, /* i/o: MA predictor state */ enum Mode mode, /* i : AMR mode */ Word16 index, /* i : index of quantization. */ Word16 code[], /* i : Innovative vector. */ Word16 evenSubfr, /* i : Flag for even subframes */ Word16 * gain_pit, /* o : Pitch gain. */ Word16 * gain_cod /* o : Code gain. */ ) { const Word16 *p; Word16 frac, gcode0, exp, qua_ener, qua_ener_MR122; Word16 g_code; Word32 L_tmp; /* Read the quantized gains (table depends on mode) */ index = shl (index, 2); test(); test(); test(); if ( sub (mode, MR102) == 0 || sub (mode, MR74) == 0 || sub (mode, MR67) == 0) { p = &table_gain_highrates[index]; move16 (); *gain_pit = *p++; move16 (); g_code = *p++; move16 (); qua_ener_MR122 = *p++; move16 (); qua_ener = *p; move16 (); } else { test(); if (sub (mode, MR475) == 0) { index = add (index, shl(sub(1, evenSubfr), 1)); p = &table_gain_MR475[index]; move16 (); *gain_pit = *p++; move16 (); g_code = *p++; move16 (); /*---------------------------------------------------------* * calculate predictor update values (not stored in 4.75 * * quantizer table to save space): * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * qua_ener = log2(g) * * qua_ener_MR122 = 20*log10(g) * *---------------------------------------------------------*/ /* Log2(x Q12) = log2(x) + 12 */ Log2 (L_deposit_l (g_code), &exp, &frac); exp = sub(exp, 12); qua_ener_MR122 = add (shr_r (frac, 5), shl (exp, 10)); /* 24660 Q12 ~= 6.0206 = 20*log10(2) */ L_tmp = Mpy_32_16(exp, frac, 24660); qua_ener = round (L_shl (L_tmp, 13)); /* Q12 * Q0 = Q13 -> Q10 */ } else { p = &table_gain_lowrates[index]; move16 (); *gain_pit = *p++; move16 (); g_code = *p++; move16 (); qua_ener_MR122 = *p++; move16 (); qua_ener = *p; move16 (); } } /*-------------------------------------------------------------------* * predict codebook gain * * ~~~~~~~~~~~~~~~~~~~~~ * * gc0 = Pow2(int(d)+frac(d)) * * = 2^exp + 2^frac * * * * gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp) * *-------------------------------------------------------------------*/ gc_pred(pred_state, mode, code, &exp, &frac, NULL, NULL); gcode0 = extract_l(Pow2(14, frac)); /*------------------------------------------------------------------* * read quantized gains, update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * st->past_qua_en(Q10) = 20 * Log10(g_fac) / constant * * = Log2(g_fac) * * = qua_ener * * constant = 20*Log10(2) * *------------------------------------------------------------------*/ L_tmp = L_mult(g_code, gcode0); L_tmp = L_shr(L_tmp, sub(10, exp)); *gain_cod = extract_h(L_tmp); /* update table of past quantized energies */ gc_pred_update(pred_state, qua_ener_MR122, qua_ener); return; }
/* ************************************************************************** * * Function : Az_lsp * Purpose : Compute the LSPs from the LP coefficients * ************************************************************************** */ void Az_lsp ( Word16 a[], /* (i) : predictor coefficients (MP1) */ Word16 lsp[], /* (o) : line spectral pairs (M) */ Word16 old_lsp[] /* (i) : old lsp[] (in case not found 10 roots) (M) */ ) { Word16 i, j, nf, ip; Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint; Word16 x, y, sign, exp; Word16 *coef; Word16 f1[M / 2 + 1], f2[M / 2 + 1]; Word32 t0; /*-------------------------------------------------------------* * find the sum and diff. pol. F1(z) and F2(z) * * F1(z) <--- F1(z)/(1+z**-1) & F2(z) <--- F2(z)/(1-z**-1) * * * * f1[0] = 1.0; * * f2[0] = 1.0; * * * * for (i = 0; i< NC; i++) * * { * * f1[i+1] = a[i+1] + a[M-i] - f1[i] ; * * f2[i+1] = a[i+1] - a[M-i] + f2[i] ; * * } * *-------------------------------------------------------------*/ f1[0] = 1024; move16 (); /* f1[0] = 1.0 */ f2[0] = 1024; move16 (); /* f2[0] = 1.0 */ for (i = 0; i < NC; i++) { t0 = L_mult (a[i + 1], 8192); /* x = (a[i+1] + a[M-i]) >> 2 */ t0 = L_mac (t0, a[M - i], 8192); x = extract_h (t0); /* f1[i+1] = a[i+1] + a[M-i] - f1[i] */ f1[i + 1] = sub (x, f1[i]);move16 (); t0 = L_mult (a[i + 1], 8192); /* x = (a[i+1] - a[M-i]) >> 2 */ t0 = L_msu (t0, a[M - i], 8192); x = extract_h (t0); /* f2[i+1] = a[i+1] - a[M-i] + f2[i] */ f2[i + 1] = add (x, f2[i]);move16 (); } /*-------------------------------------------------------------* * find the LSPs using the Chebychev pol. evaluation * *-------------------------------------------------------------*/ nf = 0; move16 (); /* number of found frequencies */ ip = 0; move16 (); /* indicator for f1 or f2 */ coef = f1; move16 (); xlow = grid[0]; move16 (); ylow = Chebps (xlow, coef, NC);move16 (); j = 0; test (); test (); /* while ( (nf < M) && (j < grid_points) ) */ while ((sub (nf, M) < 0) && (sub (j, grid_points) < 0)) { j++; xhigh = xlow; move16 (); yhigh = ylow; move16 (); xlow = grid[j]; move16 (); ylow = Chebps (xlow, coef, NC); move16 (); test (); if (L_mult (ylow, yhigh) <= (Word32) 0L) { /* divide 4 times the interval */ for (i = 0; i < 4; i++) { /* xmid = (xlow + xhigh)/2 */ xmid = add (shr (xlow, 1), shr (xhigh, 1)); ymid = Chebps (xmid, coef, NC); move16 (); test (); if (L_mult (ylow, ymid) <= (Word32) 0L) { yhigh = ymid; move16 (); xhigh = xmid; move16 (); } else { ylow = ymid; move16 (); xlow = xmid; move16 (); } } /*-------------------------------------------------------------* * Linear interpolation * * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); * *-------------------------------------------------------------*/ x = sub (xhigh, xlow); y = sub (yhigh, ylow); test (); if (y == 0) { xint = xlow; move16 (); } else { sign = y; move16 (); y = abs_s (y); exp = norm_s (y); y = shl (y, exp); y = div_s ((Word16) 16383, y); t0 = L_mult (x, y); t0 = L_shr (t0, sub (20, exp)); y = extract_l (t0); /* y= (xhigh-xlow)/(yhigh-ylow) */ test (); if (sign < 0) y = negate (y); t0 = L_mult (ylow, y); t0 = L_shr (t0, 11); xint = sub (xlow, extract_l (t0)); /* xint = xlow - ylow*y */ } lsp[nf] = xint; move16 (); xlow = xint; move16 (); nf++; test (); if (ip == 0) { ip = 1; move16 (); coef = f2; move16 (); } else { ip = 0; move16 (); coef = f1; move16 (); } ylow = Chebps (xlow, coef, NC); move16 (); } test (); test (); } /* Check if M roots found */ test (); if (sub (nf, M) < 0) { for (i = 0; i < M; i++) { lsp[i] = old_lsp[i]; move16 (); } } return; }
/* ************************************************************************** * * Function : Bgn_scd * Purpose : Charaterice synthesis speech and detect background noise * Returns : background noise decision; 0 = no bgn, 1 = bgn * ************************************************************************** */ Word16 Bgn_scd (Bgn_scdState *st, /* i : State variables for bgn SCD */ Word16 ltpGainHist[], /* i : LTP gain history */ Word16 speech[], /* o : synthesis speech frame */ Word16 *voicedHangover /* o : # of frames after last voiced frame */ ) { Word16 i; Word16 prevVoiced, inbgNoise; Word16 temp; Word16 ltpLimit, frameEnergyMin; Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart; Word32 s; /* Update the inBackgroundNoise flag (valid for use in next frame if BFI) */ /* it now works as a energy detector floating on top */ /* not as good as a VAD. */ currEnergy = 0; move16 (); s = (Word32) 0; move32 (); for (i = 0; i < L_FRAME; i++) { s = L_mac (s, speech[i], speech[i]); } s = L_shl(s, 2); currEnergy = extract_h (s); frameEnergyMin = 32767; move16 (); for (i = 0; i < L_ENERGYHIST; i++) { test (); if (sub(st->frameEnergyHist[i], frameEnergyMin) < 0) frameEnergyMin = st->frameEnergyHist[i]; move16 (); } noiseFloor = shl (frameEnergyMin, 4); /* Frame Energy Margin of 16 */ maxEnergy = st->frameEnergyHist[0]; move16 (); for (i = 1; i < L_ENERGYHIST-4; i++) { test (); if ( sub (maxEnergy, st->frameEnergyHist[i]) < 0) { maxEnergy = st->frameEnergyHist[i]; move16 (); } } maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3]; move16 (); for (i = 2*L_ENERGYHIST/3+1; i < L_ENERGYHIST; i++) { test (); if ( sub (maxEnergyLastPart, st->frameEnergyHist[i] ) < 0) { maxEnergyLastPart = st->frameEnergyHist[i]; move16 (); } } inbgNoise = 0; /* false */ move16 (); /* Do not consider silence as noise */ /* Do not consider continuous high volume as noise */ /* Or if the current noise level is very low */ /* Mark as noise if under current noise limit */ /* OR if the maximum energy is below the upper limit */ test (); test (); test (); test (); test (); if ( (sub(maxEnergy, LOWERNOISELIMIT) > 0) && (sub(currEnergy, FRAMEENERGYLIMIT) < 0) && (sub(currEnergy, LOWERNOISELIMIT) > 0) && ( (sub(currEnergy, noiseFloor) < 0) || (sub(maxEnergyLastPart, UPPERNOISELIMIT) < 0))) { test (); if (sub(add(st->bgHangover, 1), 30) > 0) { st->bgHangover = 30; move16 (); } else { st->bgHangover = add(st->bgHangover, 1); } } else { st->bgHangover = 0; move16 (); } /* make final decision about frame state , act somewhat cautiosly */ test (); if (sub(st->bgHangover,1) > 0) inbgNoise = 1; /* true */ move16 (); for (i = 0; i < L_ENERGYHIST-1; i++) { st->frameEnergyHist[i] = st->frameEnergyHist[i+1]; move16 (); } st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy; move16 (); /* prepare for voicing decision; tighten the threshold after some time in noise */ ltpLimit = 13926; /* 0.85 Q14 */ move16 (); test (); if (sub(st->bgHangover, 8) > 0) { ltpLimit = 15565; /* 0.95 Q14 */ move16 (); } test (); if (sub(st->bgHangover, 15) > 0) { ltpLimit = 16383; /* 1.00 Q14 */ move16 (); } /* weak sort of voicing indication. */ prevVoiced = 0; /* false */ move16 (); test (); if (sub(gmed_n(<pGainHist[4], 5), ltpLimit) > 0) { prevVoiced = 1; /* true */ move16 (); } test (); if (sub(st->bgHangover, 20) > 0) { if (sub(gmed_n(ltpGainHist, 9), ltpLimit) > 0) { prevVoiced = 1; /* true */ move16 (); } else { prevVoiced = 0; /* false */ move16 (); } } test (); if (prevVoiced) { *voicedHangover = 0; move16 (); } else { temp = add(*voicedHangover, 1); test (); if (sub(temp, 10) > 0) { *voicedHangover = 10; move16 (); } else { *voicedHangover = temp; move16 (); } } return inbgNoise; }
/************************************************************************* * * FUNCTION set_sign12k2() * * PURPOSE: Builds sign[] vector according to "dn[]" and "cn[]", and modifies * dn[] to include the sign information (dn[i]=sign[i]*dn[i]). * Also finds the position of maximum of correlation in each track * and the starting position for each pulse. * *************************************************************************/ void set_sign12k2 ( Word16 dn[], /* i/o : correlation between target and h[] */ Word16 cn[], /* i : residual after long term prediction */ Word16 sign[], /* o : sign of d[n] */ Word16 pos_max[], /* o : position of maximum correlation */ Word16 nb_track, /* i : number of tracks tracks */ Word16 ipos[], /* o : starting position for each pulse */ Word16 step /* i : the step size in the tracks */ ) { Word16 i, j; Word16 val, cor, k_cn, k_dn, max, max_of_all; Word16 pos = 0; /* initialization only needed to keep gcc silent */ Word16 en[L_CODE]; /* correlation vector */ Word32 s; /* calculate energy for normalization of cn[] and dn[] */ s = 256; move32 (); for (i = 0; i < L_CODE; i++) { s = L_mac (s, cn[i], cn[i]); } s = Inv_sqrt (s); move32 (); k_cn = extract_h (L_shl (s, 5)); s = 256; move32 (); for (i = 0; i < L_CODE; i++) { s = L_mac (s, dn[i], dn[i]); } s = Inv_sqrt (s); move32 (); k_dn = extract_h (L_shl (s, 5)); for (i = 0; i < L_CODE; i++) { val = dn[i]; move16 (); cor = round (L_shl (L_mac (L_mult (k_cn, cn[i]), k_dn, val), 10)); test (); if (cor >= 0) { sign[i] = 32767; move16 (); /* sign = +1 */ } else { sign[i] = -32767; move16 (); /* sign = -1 */ cor = negate (cor); val = negate (val); } /* modify dn[] according to the fixed sign */ dn[i] = val; move16 (); en[i] = cor; move16 (); } max_of_all = -1; move16 (); for (i = 0; i < nb_track; i++) { max = -1; move16 (); for (j = i; j < L_CODE; j += step) { cor = en[j]; move16 (); val = sub (cor, max); test (); if (val > 0) { max = cor; move16 (); pos = j; move16 (); } } /* store maximum correlation position */ pos_max[i] = pos; move16 (); val = sub (max, max_of_all); test (); if (val > 0) { max_of_all = max; move16 (); /* starting position for i0 */ ipos[0] = i; move16 (); } } /*----------------------------------------------------------------* * Set starting position of each pulse. * *----------------------------------------------------------------*/ pos = ipos[0]; move16 (); ipos[nb_track] = pos; move16 (); for (i = 1; i < nb_track; i++) { pos = add (pos, 1); test (); if (sub (pos, nb_track) >= 0) { pos = 0; move16 (); } ipos[i] = pos; move16 (); ipos[add(i, nb_track)] = pos; move16 (); } }
/* ************************************************************************** * Function: Post_Filter * Purpose: postfiltering of synthesis speech. * Description: * The postfiltering process is described as follows: * * - inverse filtering of syn[] through A(z/0.7) to get res2[] * - tilt compensation filtering; 1 - MU*k*z^-1 * - synthesis filtering through 1/A(z/0.75) * - adaptive gain control * ************************************************************************** */ int Post_Filter ( Post_FilterState *st, /* i/o : post filter states */ enum Mode mode, /* i : AMR mode */ Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */ Word16 *Az_4 /* i : interpolated LPC parameters in all subfr. */ ) { /*-------------------------------------------------------------------* * Declaration of parameters * *-------------------------------------------------------------------*/ Word16 Ap3[MP1], Ap4[MP1]; /* bandwidth expanded LP parameters */ Word16 *Az; /* pointer to Az_4: */ /* LPC parameters in each subframe */ Word16 i_subfr; /* index for beginning of subframe */ Word16 h[L_H]; Word16 i; Word16 temp1, temp2; Word32 L_tmp; Word16 *syn_work = &st->synth_buf[M]; move16 (); /*-----------------------------------------------------* * Post filtering * *-----------------------------------------------------*/ Copy (syn, syn_work , L_FRAME); Az = Az_4; for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { /* Find weighted filter coefficients Ap3[] and ap[4] */ test (); test (); if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0) { Weight_Ai (Az, gamma3_MR122, Ap3); Weight_Ai (Az, gamma4_MR122, Ap4); } else { Weight_Ai (Az, gamma3, Ap3); Weight_Ai (Az, gamma4, Ap4); } /* filtering of synthesis speech by A(z/0.7) to find res2[] */ Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR); /* tilt compensation filter */ /* impulse response of A(z/0.7)/A(z/0.75) */ Copy (Ap3, h, M + 1); Set_zero (&h[M + 1], L_H - M - 1); Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0); /* 1st correlation of h[] */ L_tmp = L_mult (h[0], h[0]); for (i = 1; i < L_H; i++) { L_tmp = L_mac (L_tmp, h[i], h[i]); } temp1 = extract_h (L_tmp); L_tmp = L_mult (h[0], h[1]); for (i = 1; i < L_H - 1; i++) { L_tmp = L_mac (L_tmp, h[i], h[i + 1]); } temp2 = extract_h (L_tmp); test (); if (temp2 <= 0) { temp2 = 0; move16 (); } else { temp2 = mult (temp2, MU); temp2 = div_s (temp2, temp1); } preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR); /* filtering through 1/A(z/0.75) */ Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1); /* scale output to input */ agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr], AGC_FAC, L_SUBFR); Az += MP1; } /* update syn_work[] buffer */ Copy (&syn_work[L_FRAME - M], &syn_work[-M], M); return 0; }
void dct_type_iv_a (Word16 *input,Word16 *output,Word16 dct_length) { Word16 buffer_a[MAX_DCT_LENGTH], buffer_b[MAX_DCT_LENGTH], buffer_c[MAX_DCT_LENGTH]; Word16 *in_ptr, *in_ptr_low, *in_ptr_high, *next_in_base; Word16 *out_ptr_low, *out_ptr_high, *next_out_base; Word16 *out_buffer, *in_buffer, *buffer_swap; Word16 in_val_low, in_val_high; Word16 out_val_low, out_val_high; Word16 in_low_even, in_low_odd; Word16 in_high_even, in_high_odd; Word16 out_low_even, out_low_odd; Word16 out_high_even, out_high_odd; Word16 *pair_ptr; Word16 cos_even, cos_odd, msin_even, msin_odd; Word16 neg_cos_odd; Word16 neg_msin_even; Word32 sum; Word16 set_span, set_count, set_count_log, pairs_left, sets_left; Word16 i,k; Word16 index; cos_msin_t **table_ptr_ptr, *cos_msin_ptr; Word16 temp; Word32 acca; Word16 dct_length_log; /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* Do the sum/difference butterflies, the first part of */ /* converting one N-point transform into N/2 two-point */ /* transforms, where N = 1 << DCT_LENGTH_LOG. = 64/128 */ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ test(); if (dct_length==DCT_LENGTH) { dct_length_log = DCT_LENGTH_LOG; /* Add bias offsets */ for (i=0;i<dct_length;i++) { input[i] = add(input[i],anal_bias[i]); move16(); } } else dct_length_log = MAX_DCT_LENGTH_LOG; index = 0L; move16(); in_buffer = input; move16(); out_buffer = buffer_a; move16(); temp = sub(dct_length_log,2); for (set_count_log=0;set_count_log<=temp;set_count_log++) { /*===========================================================*/ /* Initialization for the loop over sets at the current size */ /*===========================================================*/ /* set_span = 1 << (DCT_LENGTH_LOG - set_count_log); */ set_span = shr_nocheck(dct_length,set_count_log); set_count = shl_nocheck(1,set_count_log); in_ptr = in_buffer; move16(); next_out_base = out_buffer; move16(); /*=====================================*/ /* Loop over all the sets of this size */ /*=====================================*/ for (sets_left=set_count;sets_left>0;sets_left--) { /*||||||||||||||||||||||||||||||||||||||||||||*/ /* Set up output pointers for the current set */ /*||||||||||||||||||||||||||||||||||||||||||||*/ out_ptr_low = next_out_base; next_out_base = next_out_base + set_span; out_ptr_high = next_out_base; /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ /* Loop over all the butterflies in the current set */ /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ do { in_val_low = *in_ptr++; in_val_high = *in_ptr++; // blp: addition of two 16bits vars, there's no way // they'll overflow a 32bit var //acca = L_add(in_val_low,in_val_high); acca = (in_val_low + in_val_high); acca = L_shr_nocheck(acca,1); out_val_low = extract_l(acca); acca = L_sub(in_val_low,in_val_high); acca = L_shr_nocheck(acca,1); out_val_high = extract_l(acca); *out_ptr_low++ = out_val_low; *--out_ptr_high = out_val_high; test(); } while (out_ptr_low < out_ptr_high); } /* End of loop over sets of the current size */ /*============================================================*/ /* Decide which buffers to use as input and output next time. */ /* Except for the first time (when the input buffer is the */ /* subroutine input) we just alternate the local buffers. */ /*============================================================*/ in_buffer = out_buffer; move16(); if (out_buffer == buffer_a) out_buffer = buffer_b; else out_buffer = buffer_a; index = add(index,1); } /* End of loop over set sizes */ /*++++++++++++++++++++++++++++++++*/ /* Do N/2 two-point transforms, */ /* where N = 1 << DCT_LENGTH_LOG */ /*++++++++++++++++++++++++++++++++*/ pair_ptr = in_buffer; move16(); buffer_swap = buffer_c; move16(); temp = sub(dct_length_log,1); temp = shl_nocheck(1,temp); for (pairs_left=temp; pairs_left > 0; pairs_left--) { for ( k=0; k<CORE_SIZE; k++ ) { #if PJ_HAS_INT64 /* blp: danger danger! not really compatible but faster */ pj_int64_t sum64=0; move32(); for ( i=0; i<CORE_SIZE; i++ ) { sum64 += L_mult(pair_ptr[i], dct_core_a[i][k]); } sum = L_saturate(sum64); #else sum=0L; move32(); for ( i=0; i<CORE_SIZE; i++ ) { sum = L_mac(sum, pair_ptr[i],dct_core_a[i][k]); } #endif buffer_swap[k] = itu_round(sum); } /* address arithmetic */ pair_ptr += CORE_SIZE; buffer_swap += CORE_SIZE; } for (i=0;i<dct_length;i++) { in_buffer[i] = buffer_c[i]; move16(); } table_ptr_ptr = a_cos_msin_table; /*++++++++++++++++++++++++++++++*/ /* Perform rotation butterflies */ /*++++++++++++++++++++++++++++++*/ temp = sub(dct_length_log,2); for (set_count_log = temp; set_count_log >= 0; set_count_log--) { /*===========================================================*/ /* Initialization for the loop over sets at the current size */ /*===========================================================*/ /* set_span = 1 << (DCT_LENGTH_LOG - set_count_log); */ set_span = shr_nocheck(dct_length,set_count_log); set_count = shl_nocheck(1,set_count_log); next_in_base = in_buffer; move16(); test(); if (set_count_log == 0) { next_out_base = output; } else { next_out_base = out_buffer; } /*=====================================*/ /* Loop over all the sets of this size */ /*=====================================*/ for (sets_left = set_count; sets_left > 0;sets_left--) { /*|||||||||||||||||||||||||||||||||||||||||*/ /* Set up the pointers for the current set */ /*|||||||||||||||||||||||||||||||||||||||||*/ in_ptr_low = next_in_base; move16(); temp = shr_nocheck(set_span,1); /* address arithmetic */ in_ptr_high = in_ptr_low + temp; next_in_base += set_span; out_ptr_low = next_out_base; next_out_base += set_span; out_ptr_high = next_out_base; cos_msin_ptr = *table_ptr_ptr; /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ /* Loop over all the butterfly pairs in the current set */ /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ do { /* address arithmetic */ in_low_even = *in_ptr_low++; in_low_odd = *in_ptr_low++; in_high_even = *in_ptr_high++; in_high_odd = *in_ptr_high++; cos_even = cos_msin_ptr[0].cosine; move16(); msin_even = cos_msin_ptr[0].minus_sine; move16(); cos_odd = cos_msin_ptr[1].cosine; move16(); msin_odd = cos_msin_ptr[1].minus_sine; move16(); cos_msin_ptr += 2; sum = 0L; sum=L_mac(sum,cos_even,in_low_even); neg_msin_even = negate(msin_even); sum=L_mac(sum,neg_msin_even,in_high_even); out_low_even = itu_round(sum); sum = 0L; sum=L_mac(sum,msin_even,in_low_even); sum=L_mac(sum,cos_even,in_high_even); out_high_even= itu_round(sum); sum = 0L; sum=L_mac(sum,cos_odd,in_low_odd); sum=L_mac(sum,msin_odd,in_high_odd); out_low_odd= itu_round(sum); sum = 0L; sum=L_mac(sum,msin_odd,in_low_odd); neg_cos_odd = negate(cos_odd); sum=L_mac(sum,neg_cos_odd,in_high_odd); out_high_odd= itu_round(sum); *out_ptr_low++ = out_low_even; *--out_ptr_high = out_high_even; *out_ptr_low++ = out_low_odd; *--out_ptr_high = out_high_odd; test(); } while (out_ptr_low < out_ptr_high); } /* End of loop over sets of the current size */ /*=============================================*/ /* Swap input and output buffers for next time */ /*=============================================*/ buffer_swap = in_buffer; in_buffer = out_buffer; out_buffer = buffer_swap; table_ptr_ptr++; } }