static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBands, int start, int end, int len, int C) { int c, i; opus_val32 dist = 0; c=0; do { for (i=start;i<end;i++) { opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3)); dist = MAC16_16(dist, d,d); } } while (++c<C); return MIN32(200,SHR32(dist,2*DB_SHIFT-6)); }
/*Makes sure the LSPs are stable*/ void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin) { int i; spx_word16_t m = margin; spx_word16_t m2 = 25736-margin; if (lsp[0]<m) lsp[0]=m; if (lsp[len-1]>m2) lsp[len-1]=m2; for (i=1;i<len-1;i++) { if (lsp[i]<lsp[i-1]+m) lsp[i]=lsp[i-1]+m; if (lsp[i]>lsp[i+1]-m) lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); } }
void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *lsp, int len, int subframe, int nb_subframes, spx_word16_t margin) { int i; spx_word16_t m = margin; spx_word16_t m2 = 25736-margin; spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); spx_word16_t tmp2 = 16384-tmp; for (i=0;i<len;i++) lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]); /* Enforce margin to sure the LSPs are stable*/ if (lsp[0]<m) lsp[0]=m; if (lsp[len-1]>m2) lsp[len-1]=m2; for (i=1;i<len-1;i++) { if (lsp[i]<lsp[i-1]+m) lsp[i]=lsp[i-1]+m; if (lsp[i]>lsp[i+1]-m) lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); } }
/*Makes sure the LSPs are stable*/ void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin) { #ifndef FIXED_LPC_SIZE int i; #endif spx_word16_t m = margin; spx_word16_t m2 = 25736-margin; if (lsp[0]<m) lsp[0]=m; if (lsp[len-1]>m2) lsp[len-1]=m2; #ifndef FIXED_LPC_SIZE for (i=1;i<len-1;i++) { if (lsp[i]<lsp[i-1]+m) lsp[i]=lsp[i-1]+m; if (lsp[i]>lsp[i+1]-m) lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); } #else if (lsp[1]<lsp[1-1]+m) lsp[1]=lsp[1-1]+m; if (lsp[1]>lsp[1+1]-m) lsp[1]= SHR16(lsp[1],1) + SHR16(lsp[1+1]-m,1); if (lsp[2]<lsp[2-1]+m) lsp[2]=lsp[2-1]+m; if (lsp[2]>lsp[2+1]-m) lsp[2]= SHR16(lsp[2],1) + SHR16(lsp[2+1]-m,1); if (lsp[3]<lsp[3-1]+m) lsp[3]=lsp[3-1]+m; if (lsp[3]>lsp[3+1]-m) lsp[3]= SHR16(lsp[3],1) + SHR16(lsp[3+1]-m,1); if (lsp[4]<lsp[4-1]+m) lsp[4]=lsp[4-1]+m; if (lsp[4]>lsp[4+1]-m) lsp[4]= SHR16(lsp[4],1) + SHR16(lsp[4+1]-m,1); if (lsp[5]<lsp[5-1]+m) lsp[5]=lsp[5-1]+m; if (lsp[5]>lsp[5+1]-m) lsp[5]= SHR16(lsp[5],1) + SHR16(lsp[5+1]-m,1); if (lsp[6]<lsp[6-1]+m) lsp[6]=lsp[6-1]+m; if (lsp[6]>lsp[6+1]-m) lsp[6]= SHR16(lsp[6],1) + SHR16(lsp[6+1]-m,1); if (lsp[7]<lsp[7-1]+m) lsp[7]=lsp[7-1]+m; if (lsp[7]>lsp[7+1]-m) lsp[7]= SHR16(lsp[7],1) + SHR16(lsp[7+1]-m,1); if (lsp[8]<lsp[8-1]+m) lsp[8]=lsp[8-1]+m; if (lsp[8]>lsp[8+1]-m) lsp[8]= SHR16(lsp[8],1) + SHR16(lsp[8+1]-m,1); #endif }
void pitch_unquant_3tap( spx_word16_t exc[], /* Input excitation */ spx_word32_t exc_out[], /* Output excitation */ int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ const void* par, int nsf, /* Number of samples in subframe */ int* pitch_val, spx_word16_t* gain_val, SpeexBits* bits, char* stack, int count_lost, int subframe_offset, spx_word16_t last_pitch_gain, int cdbk_offset ) { int i; int pitch; int gain_index; spx_word16_t gain[3]; const signed char* gain_cdbk; int gain_cdbk_size; const ltp_params* params; params = (const ltp_params*) par; gain_cdbk_size = 1 << params->gain_bits; gain_cdbk = params->gain_cdbk + 4 * gain_cdbk_size * cdbk_offset; pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits); pitch += start; gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits); /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/ #ifdef FIXED_POINT gain[0] = ADD16(32, (spx_word16_t)gain_cdbk[gain_index * 4]); gain[1] = ADD16(32, (spx_word16_t)gain_cdbk[gain_index * 4 + 1]); gain[2] = ADD16(32, (spx_word16_t)gain_cdbk[gain_index * 4 + 2]); #else gain[0] = 0.015625 * gain_cdbk[gain_index * 4] + .5; gain[1] = 0.015625 * gain_cdbk[gain_index * 4 + 1] + .5; gain[2] = 0.015625 * gain_cdbk[gain_index * 4 + 2] + .5; #endif if (count_lost && pitch > subframe_offset) { spx_word16_t gain_sum; if (1) { #ifdef FIXED_POINT spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain, 1); if (tmp > 62) tmp = 62; #else spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain; if (tmp > .95) tmp = .95; #endif gain_sum = gain_3tap_to_1tap(gain); if (gain_sum > tmp) { spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp), 14), gain_sum); for (i = 0; i < 3; i++) gain[i] = MULT16_16_Q14(fact, gain[i]); } } } *pitch_val = pitch; gain_val[0] = gain[0]; gain_val[1] = gain[1]; gain_val[2] = gain[2]; gain[0] = SHL16(gain[0], 7); gain[1] = SHL16(gain[1], 7); gain[2] = SHL16(gain[2], 7); SPEEX_MEMSET(exc_out, 0, nsf); for (i = 0; i < 3; i++) { int j; int tmp1, tmp3; int pp = pitch + 1 - i; tmp1 = nsf; if (tmp1 > pp) tmp1 = pp; for (j = 0; j < tmp1; j++) exc_out[j] = MAC16_16(exc_out[j], gain[2 - i], exc[j - pp]); tmp3 = nsf; if (tmp3 > pp + pitch) tmp3 = pp + pitch; for (j = tmp1; j < tmp3; j++) exc_out[j] = MAC16_16(exc_out[j], gain[2 - i], exc[j - pp - pitch]); } /*for (i=0;i<nsf;i++) exc[i]=PSHR32(exc32[i],13);*/ }
/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ static spx_word32_t pitch_gain_search_3tap( const spx_word16_t target[], /* Target vector */ const spx_coef_t ak[], /* LPCs for this subframe */ const spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ const spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ spx_sig_t exc[], /* Excitation */ const signed char* gain_cdbk, int gain_cdbk_size, int pitch, /* Pitch value */ int p, /* Number of LPC coeffs */ int nsf, /* Number of samples in subframe */ SpeexBits* bits, char* stack, const spx_word16_t* exc2, const spx_word16_t* r, spx_word16_t* new_target, int* cdbk_index, int plc_tuning, spx_word32_t cumul_gain, int scaledown ) { int i, j; VARDECL(spx_word16_t * tmp1); VARDECL(spx_word16_t * e); spx_word16_t* x[3]; spx_word32_t corr[3]; spx_word32_t A[3][3]; spx_word16_t gain[3]; spx_word32_t err; spx_word16_t max_gain = 128; int best_cdbk = 0; ALLOC(tmp1, 3 * nsf, spx_word16_t); ALLOC(e, nsf, spx_word16_t); if (cumul_gain > 262144) max_gain = 31; x[0] = tmp1; x[1] = tmp1 + nsf; x[2] = tmp1 + 2 * nsf; for (j = 0; j < nsf; j++) new_target[j] = target[j]; { VARDECL(spx_mem_t * mm); int pp = pitch - 1; ALLOC(mm, p, spx_mem_t); for (j = 0; j < nsf; j++) { if (j - pp < 0) e[j] = exc2[j - pp]; else if (j - pp - pitch < 0) e[j] = exc2[j - pp - pitch]; else e[j] = 0; } #ifdef FIXED_POINT /* Scale target and excitation down if needed (avoiding overflow) */ if (scaledown) { for (j = 0; j < nsf; j++) e[j] = SHR16(e[j], 1); for (j = 0; j < nsf; j++) new_target[j] = SHR16(new_target[j], 1); } #endif for (j = 0; j < p; j++) mm[j] = 0; iir_mem16(e, ak, e, nsf, p, mm, stack); for (j = 0; j < p; j++) mm[j] = 0; filter_mem16(e, awk1, awk2, e, nsf, p, mm, stack); for (j = 0; j < nsf; j++) x[2][j] = e[j]; } for (i = 1; i >= 0; i--) { spx_word16_t e0 = exc2[-pitch - 1 + i]; #ifdef FIXED_POINT /* Scale excitation down if needed (avoiding overflow) */ if (scaledown) e0 = SHR16(e0, 1); #endif x[i][0] = MULT16_16_Q14(r[0], e0); for (j = 0; j < nsf - 1; j++) x[i][j + 1] = ADD32(x[i + 1][j], MULT16_16_P14(r[j + 1], e0)); } for (i = 0; i < 3; i++) corr[i] = inner_prod(x[i], new_target, nsf); for (i = 0; i < 3; i++) for (j = 0; j <= i; j++) A[i][j] = A[j][i] = inner_prod(x[i], x[j], nsf); { spx_word32_t C[9]; #ifdef FIXED_POINT spx_word16_t C16[9]; #else spx_word16_t* C16 = C; #endif C[0] = corr[2]; C[1] = corr[1]; C[2] = corr[0]; C[3] = A[1][2]; C[4] = A[0][1]; C[5] = A[0][2]; C[6] = A[2][2]; C[7] = A[1][1]; C[8] = A[0][0]; /*plc_tuning *= 2;*/ if (plc_tuning < 2) plc_tuning = 2; if (plc_tuning > 30) plc_tuning = 30; #ifdef FIXED_POINT C[0] = SHL32(C[0], 1); C[1] = SHL32(C[1], 1); C[2] = SHL32(C[2], 1); C[3] = SHL32(C[3], 1); C[4] = SHL32(C[4], 1); C[5] = SHL32(C[5], 1); C[6] = MAC16_32_Q15(C[6], MULT16_16_16(plc_tuning, 655), C[6]); C[7] = MAC16_32_Q15(C[7], MULT16_16_16(plc_tuning, 655), C[7]); C[8] = MAC16_32_Q15(C[8], MULT16_16_16(plc_tuning, 655), C[8]); normalize16(C, C16, 32767, 9); #else C[6] *= .5 * (1 + .02 * plc_tuning); C[7] *= .5 * (1 + .02 * plc_tuning); C[8] *= .5 * (1 + .02 * plc_tuning); #endif best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain); #ifdef FIXED_POINT gain[0] = ADD16(32, (spx_word16_t)gain_cdbk[best_cdbk * 4]); gain[1] = ADD16(32, (spx_word16_t)gain_cdbk[best_cdbk * 4 + 1]); gain[2] = ADD16(32, (spx_word16_t)gain_cdbk[best_cdbk * 4 + 2]); /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/ #else gain[0] = 0.015625 * gain_cdbk[best_cdbk * 4] + .5; gain[1] = 0.015625 * gain_cdbk[best_cdbk * 4 + 1] + .5; gain[2] = 0.015625 * gain_cdbk[best_cdbk * 4 + 2] + .5; #endif *cdbk_index = best_cdbk; } SPEEX_MEMSET(exc, 0, nsf); for (i = 0; i < 3; i++) { int j; int tmp1, tmp3; int pp = pitch + 1 - i; tmp1 = nsf; if (tmp1 > pp) tmp1 = pp; for (j = 0; j < tmp1; j++) exc[j] = MAC16_16(exc[j], SHL16(gain[2 - i], 7), exc2[j - pp]); tmp3 = nsf; if (tmp3 > pp + pitch) tmp3 = pp + pitch; for (j = tmp1; j < tmp3; j++) exc[j] = MAC16_16(exc[j], SHL16(gain[2 - i], 7), exc2[j - pp - pitch]); } for (i = 0; i < nsf; i++) { spx_word32_t tmp = ADD32(ADD32(MULT16_16(gain[0], x[2][i]), MULT16_16(gain[1], x[1][i])), MULT16_16(gain[2], x[0][i])); new_target[i] = SUB16(new_target[i], EXTRACT16(PSHR32(tmp, 6))); } err = inner_prod(new_target, new_target, nsf); return err; }
void open_loop_nbest_pitch(spx_word16_t* sw, int start, int end, int len, int* pitch, spx_word16_t* gain, int N, char* stack) { int i, j, k; VARDECL(spx_word32_t * best_score); VARDECL(spx_word32_t * best_ener); spx_word32_t e0; VARDECL(spx_word32_t * corr); #ifdef FIXED_POINT /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16) arrays for (normalized) 16-bit values */ VARDECL(spx_word16_t * corr16); VARDECL(spx_word16_t * ener16); spx_word32_t* energy; int cshift = 0, eshift = 0; int scaledown = 0; ALLOC(corr16, end - start + 1, spx_word16_t); ALLOC(ener16, end - start + 1, spx_word16_t); ALLOC(corr, end - start + 1, spx_word32_t); energy = corr; #else /* In floating-point, we need to float arrays and no normalized copies */ VARDECL(spx_word32_t * energy); spx_word16_t* corr16; spx_word16_t* ener16; ALLOC(energy, end - start + 2, spx_word32_t); ALLOC(corr, end - start + 1, spx_word32_t); corr16 = corr; ener16 = energy; #endif ALLOC(best_score, N, spx_word32_t); ALLOC(best_ener, N, spx_word32_t); for (i = 0; i < N; i++) { best_score[i] = -1; best_ener[i] = 0; pitch[i] = start; } #ifdef FIXED_POINT for (i = -end; i < len; i++) { if (ABS16(sw[i]) > 16383) { scaledown = 1; break; } } /* If the weighted input is close to saturation, then we scale it down */ if (scaledown) { for (i = -end; i < len; i++) { sw[i] = SHR16(sw[i], 1); } } #endif energy[0] = inner_prod(sw - start, sw - start, len); e0 = inner_prod(sw, sw, len); for (i = start; i < end; i++) { /* Update energy for next pitch*/ energy[i - start + 1] = SUB32(ADD32(energy[i - start], SHR32(MULT16_16(sw[-i - 1], sw[-i - 1]), 6)), SHR32(MULT16_16(sw[-i + len - 1], sw[-i + len - 1]), 6)); if (energy[i - start + 1] < 0) energy[i - start + 1] = 0; } #ifdef FIXED_POINT eshift = normalize16(energy, ener16, 32766, end - start + 1); #endif /* In fixed-point, this actually overrites the energy array (aliased to corr) */ pitch_xcorr(sw, sw - end, corr, len, end - start + 1, stack); #ifdef FIXED_POINT /* Normalize to 180 so we can square it and it still fits in 16 bits */ cshift = normalize16(corr, corr16, 180, end - start + 1); /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */ if (scaledown) { for (i = -end; i < len; i++) { sw[i] = SHL16(sw[i], 1); } } #endif /* Search for the best pitch prediction gain */ for (i = start; i <= end; i++) { spx_word16_t tmp = MULT16_16_16(corr16[i - start], corr16[i - start]); /* Instead of dividing the tmp by the energy, we multiply on the other side */ if (MULT16_16(tmp, best_ener[N - 1]) > MULT16_16(best_score[N - 1], ADD16(1, ener16[i - start]))) { /* We can safely put it last and then check */ best_score[N - 1] = tmp; best_ener[N - 1] = ener16[i - start] + 1; pitch[N - 1] = i; /* Check if it comes in front of others */ for (j = 0; j < N - 1; j++) { if (MULT16_16(tmp, best_ener[j]) > MULT16_16(best_score[j], ADD16(1, ener16[i - start]))) { for (k = N - 1; k > j; k--) { best_score[k] = best_score[k - 1]; best_ener[k] = best_ener[k - 1]; pitch[k] = pitch[k - 1]; } best_score[j] = tmp; best_ener[j] = ener16[i - start] + 1; pitch[j] = i; break; } } } } /* Compute open-loop gain if necessary */ if (gain) { for (j = 0; j < N; j++) { spx_word16_t g; i = pitch[j]; g = DIV32(SHL32(EXTEND32(corr16[i - start]), cshift), 10 + SHR32(MULT16_16(spx_sqrt(e0), spx_sqrt(SHL32(EXTEND32(ener16[i - start]), eshift))), 6)); /* FIXME: g = max(g,corr/energy) */ if (g < 0) g = 0; gain[j] = g; } } }
EXPORT void speex_encode_stereo_int(spx_int16_t * data, int frame_size, SpeexBits * bits) { int i, tmp; spx_word32_t e_left = 0, e_right = 0, e_tot = 0; spx_word32_t balance, e_ratio; spx_word32_t largest, smallest; int balance_id; #ifdef FIXED_POINT int shift; #endif /* In band marker */ speex_bits_pack(bits, 14, 5); /* Stereo marker */ speex_bits_pack(bits, SPEEX_INBAND_STEREO, 4); for (i = 0; i < frame_size; i++) { e_left += SHR32(MULT16_16(data[2 * i], data[2 * i]), 8); e_right += SHR32(MULT16_16(data[2 * i + 1], data[2 * i + 1]), 8); #ifdef FIXED_POINT /* I think this is actually unbiased */ data[i] = SHR16(data[2 * i], 1) + PSHR16(data[2 * i + 1], 1); #else data[i] = .5 * (((float)data[2 * i]) + data[2 * i + 1]); #endif e_tot += SHR32(MULT16_16(data[i], data[i]), 8); } if (e_left > e_right) { speex_bits_pack(bits, 0, 1); largest = e_left; smallest = e_right; } else { speex_bits_pack(bits, 1, 1); largest = e_right; smallest = e_left; } /* Balance quantization */ #ifdef FIXED_POINT shift = spx_ilog2(largest) - 15; largest = VSHR32(largest, shift - 4); smallest = VSHR32(smallest, shift); balance = DIV32(largest, ADD32(smallest, 1)); if (balance > 32767) balance = 32767; balance_id = scal_quant(EXTRACT16(balance), balance_bounds, 32); #else balance = (largest + 1.) / (smallest + 1.); balance = 4 * log(balance); balance_id = floor(.5 + fabs(balance)); if (balance_id > 30) balance_id = 31; #endif speex_bits_pack(bits, balance_id, 5); /* "coherence" quantisation */ #ifdef FIXED_POINT shift = spx_ilog2(e_tot); e_tot = VSHR32(e_tot, shift - 25); e_left = VSHR32(e_left, shift - 10); e_right = VSHR32(e_right, shift - 10); e_ratio = DIV32(e_tot, e_left + e_right + 1); #else e_ratio = e_tot / (1. + e_left + e_right); #endif tmp = scal_quant(EXTRACT16(e_ratio), e_ratio_quant_bounds, 4); /*fprintf (stderr, "%d %d %d %d\n", largest, smallest, balance_id, e_ratio); */ speex_bits_pack(bits, tmp, 2); }
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end, const opus_val16 *eBands, opus_val16 *oldEBands, opus_int32 budget, opus_int32 tell, const unsigned char *prob_model, opus_val16 *error, ec_enc *enc, int C, int LM, int intra, opus_val16 max_decay) { int i, c; int badness = 0; opus_val32 prev[2] = {0,0}; opus_val16 coef; opus_val16 beta; if (tell+3 <= budget) ec_enc_bit_logp(enc, intra, 3); if (intra) { coef = 0; beta = beta_intra; } else { beta = beta_coef[LM]; coef = pred_coef[LM]; } /* Encode at a fixed coarse resolution */ for (i=start;i<end;i++) { c=0; do { int bits_left; int qi, qi0; opus_val32 q; opus_val16 x; opus_val32 f, tmp; opus_val16 oldE; opus_val16 decay_bound; x = eBands[i+c*m->nbEBands]; oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); #ifdef FIXED_POINT f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c]; /* Rounding to nearest integer here is really important! */ qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7); decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT), SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay))); #else f = x-coef*oldE-prev[c]; /* Rounding to nearest integer here is really important! */ qi = (int)floor(.5f+f); decay_bound = MAX16(-QCONST16(28.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]) - max_decay; #endif /* Prevent the energy from going down too quickly (e.g. for bands that have just one bin) */ if (qi < 0 && x < decay_bound) { qi += (int)SHR16(SUB16(decay_bound,x), DB_SHIFT); if (qi > 0) qi = 0; } qi0 = qi; /* If we don't have enough bits to encode all the energy, just assume something safe. */ tell = ec_tell(enc); bits_left = budget-tell-3*C*(end-i); if (i!=start && bits_left < 30) { if (bits_left < 24) qi = IMIN(1, qi); if (bits_left < 16) qi = IMAX(-1, qi); } if (budget-tell >= 15) { int pi; pi = 2*IMIN(i,20); ec_laplace_encode(enc, &qi, prob_model[pi]<<7, prob_model[pi+1]<<6); } else if(budget-tell >= 2) { qi = IMAX(-1, IMIN(qi, 1)); ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2); } else if(budget-tell >= 1) { qi = IMIN(0, qi); ec_enc_bit_logp(enc, -qi, 1); } else qi = -1; error[i+c*m->nbEBands] = PSHR32(f,7) - SHL16(qi,DB_SHIFT); badness += abs(qi0-qi); q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7); #ifdef FIXED_POINT tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); #endif oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); } while (++c < C); } return badness; }
void open_loop_nbest_pitch(spx_sig_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack) { int i,j,k; VARDECL(spx_word32_t *best_score); spx_word32_t e0; VARDECL(spx_word32_t *corr); VARDECL(spx_word32_t *energy); VARDECL(spx_word32_t *score); #ifdef FIXED_POINT VARDECL(spx_word16_t *swn2); #endif spx_word16_t *swn; ALLOC(best_score, N, spx_word32_t); ALLOC(corr, end-start+1, spx_word32_t); ALLOC(energy, end-start+2, spx_word32_t); ALLOC(score, end-start+1, spx_word32_t); #ifdef FIXED_POINT ALLOC(swn2, end+len, spx_word16_t); normalize16(sw-end, swn2, 16384, end+len); swn = swn2 + end; #else swn = sw; #endif for (i=0; i<N; i++) { best_score[i]=-1; pitch[i]=start; } energy[0]=inner_prod(swn-start, swn-start, len); e0=inner_prod(swn, swn, len); for (i=start; i<=end; i++) { /* Update energy for next pitch*/ energy[i-start+1] = SUB32(ADD32(energy[i-start],SHR32(MULT16_16(swn[-i-1],swn[-i-1]),6)), SHR32(MULT16_16(swn[-i+len-1],swn[-i+len-1]),6)); } pitch_xcorr(swn, swn-end, corr, len, end-start+1, stack); #ifdef FIXED_POINT { VARDECL(spx_word16_t *corr16); VARDECL(spx_word16_t *ener16); ALLOC(corr16, end-start+1, spx_word16_t); ALLOC(ener16, end-start+1, spx_word16_t); normalize16(corr, corr16, 16384, end-start+1); normalize16(energy, ener16, 16384, end-start+1); for (i=start; i<=end; i++) { spx_word16_t g; spx_word32_t tmp; tmp = corr16[i-start]; if (tmp>0) { if (SHR16(corr16[i-start],4)>ener16[i-start]) tmp = SHL32(EXTEND32(ener16[i-start]),14); else if (-SHR16(corr16[i-start],4)>ener16[i-start]) tmp = -SHL32(EXTEND32(ener16[i-start]),14); else tmp = SHL32(tmp,10); g = DIV32_16(tmp, 8+ener16[i-start]); score[i-start] = MULT16_16(corr16[i-start],g); } else { score[i-start] = 1; } } } #else for (i=start; i<=end; i++) { float g = corr[i-start]/(1+energy[i-start]); if (g>16) g = 16; else if (g<-16) g = -16; score[i-start] = g*corr[i-start]; } #endif /* Extract best scores */ for (i=start; i<=end; i++) { if (score[i-start]>best_score[N-1]) { for (j=0; j<N; j++) { if (score[i-start] > best_score[j]) { for (k=N-1; k>j; k--) { best_score[k]=best_score[k-1]; pitch[k]=pitch[k-1]; } best_score[j]=score[i-start]; pitch[j]=i; break; } } } } /* Compute open-loop gain */ if (gain) { for (j=0; j<N; j++) { spx_word16_t g; i=pitch[j]; g = DIV32(corr[i-start], 10+SHR32(MULT16_16(spx_sqrt(e0),spx_sqrt(energy[i-start])),6)); /* FIXME: g = max(g,corr/energy) */ if (g<0) g = 0; gain[j]=g; } } }