Ignore:
Timestamp:
Jul 26, 2006 5:04:54 PM (18 years ago)
Author:
bennylp
Message:
  • Bring speex codec up to date with their SVN trunk
  • Speex codec should work in FIXED_POINT mode when PJ_HAS_FLOATING_POINT is set to zero.
  • ulaw2linear will return zero if zero is given (this would make the VAD works better, and it also fixed click noise when call is established/hangup).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-codec/speex/mdf.c

    r523 r628  
    9191 
    9292#ifdef FIXED_POINT 
    93 static const spx_float_t MIN_LEAK = ((spx_float_t){16777, -24}); 
     93static const spx_float_t MIN_LEAK = {16777, -24}; 
    9494#define TOP16(x) ((x)>>16) 
    9595#else 
     
    141141   spx_word16_t notch_radius; 
    142142   spx_mem_t notch_mem[2]; 
     143 
     144   /* NOTE: If you only use speex_echo_cancel() and want to save some memory, remove this */ 
     145   spx_int16_t *play_buf; 
     146   int play_buf_pos; 
    143147}; 
    144148 
    145 static inline void filter_dc_notch16(spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem) 
     149static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem) 
    146150{ 
    147151   int i; 
     
    167171} 
    168172 
    169 static inline spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) 
     173static inline spx_word32_t mdf_inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) 
    170174{ 
    171175   spx_word32_t sum=0; 
    172    len >>= 2; 
     176   len >>= 1; 
    173177   while(len--) 
    174178   { 
    175179      spx_word32_t part=0; 
    176       part = MAC16_16(part,*x++,*y++); 
    177       part = MAC16_16(part,*x++,*y++); 
    178180      part = MAC16_16(part,*x++,*y++); 
    179181      part = MAC16_16(part,*x++,*y++); 
     
    185187 
    186188/** Compute power spectrum of a half-complex (packed) vector */ 
    187 static inline void power_spectrum(spx_word16_t *X, spx_word32_t *ps, int N) 
     189static inline void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N) 
    188190{ 
    189191   int i, j; 
     
    198200/** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ 
    199201#ifdef FIXED_POINT 
    200 static inline void spectral_mul_accum(spx_word16_t *X, spx_word32_t *Y, spx_word16_t *acc, int N, int M) 
     202static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) 
    201203{ 
    202204   int i,j; 
     
    226228} 
    227229#else 
    228 static inline void spectral_mul_accum(spx_word16_t *X, spx_word32_t *Y, spx_word16_t *acc, int N, int M) 
     230static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) 
    229231{ 
    230232   int i,j; 
     
    247249 
    248250/** Compute weighted cross-power spectrum of a half-complex (packed) vector with conjugate */ 
    249 static inline void weighted_spectral_mul_conj(spx_float_t *w, spx_word16_t *X, spx_word16_t *Y, spx_word32_t *prod, int N) 
     251static inline void weighted_spectral_mul_conj(const spx_float_t *w, const spx_word16_t *X, const spx_word16_t *Y, spx_word32_t *prod, int N) 
    250252{ 
    251253   int i, j; 
     
    274276   /* FIXME: Make that an init option (new API call?) */ 
    275277   st->sampling_rate = 8000; 
    276    st->spec_average = DIV32_16(SHL32(st->frame_size, 15), st->sampling_rate); 
    277 #ifdef FIXED_POINT 
    278    st->beta0 = DIV32_16(SHL32(st->frame_size, 16), st->sampling_rate); 
    279    st->beta_max = DIV32_16(SHL32(st->frame_size, 14), st->sampling_rate); 
     278   st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); 
     279#ifdef FIXED_POINT 
     280   st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); 
     281   st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); 
    280282#else 
    281283   st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; 
     
    333335   st->adapted = 0; 
    334336   st->Pey = st->Pyy = FLOAT_ONE; 
     337    
     338   st->play_buf = (spx_int16_t*)speex_alloc(2*st->frame_size*sizeof(spx_int16_t)); 
     339   st->play_buf_pos = 0; 
     340 
    335341   return st; 
    336342} 
     
    386392   speex_free(st->wtmp2); 
    387393#endif 
     394   speex_free(st->play_buf); 
    388395   speex_free(st); 
    389396} 
    390397 
    391 extern int fixed_point; 
     398void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out, spx_int32_t *Yout) 
     399{ 
     400   int i; 
     401   if (st->play_buf_pos>=st->frame_size) 
     402   { 
     403      speex_echo_cancel(st, rec, st->play_buf, out, Yout); 
     404      st->play_buf_pos -= st->frame_size; 
     405      for (i=0;i<st->frame_size;i++) 
     406         st->play_buf[i] = st->play_buf[i+st->frame_size]; 
     407   } else { 
     408      speex_warning("no playback frame available"); 
     409      if (st->play_buf_pos!=0) 
     410      { 
     411         speex_warning("internal playback buffer corruption?"); 
     412         st->play_buf_pos = 0; 
     413      } 
     414      for (i=0;i<st->frame_size;i++) 
     415         out[i] = rec[i]; 
     416   } 
     417} 
     418 
     419void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play) 
     420{ 
     421   if (st->play_buf_pos<=st->frame_size) 
     422   { 
     423      int i; 
     424      for (i=0;i<st->frame_size;i++) 
     425         st->play_buf[st->play_buf_pos+i] = play[i]; 
     426      st->play_buf_pos += st->frame_size; 
     427   } else { 
     428      speex_warning("had to discard a playback frame"); 
     429   } 
     430} 
     431 
    392432/** Performs echo cancellation on a frame */ 
    393 void speex_echo_cancel(SpeexEchoState *st, short *ref, short *echo, short *out, spx_int32_t *Yout) 
     433void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *ref, const spx_int16_t *echo, spx_int16_t *out, spx_int32_t *Yout) 
    394434{ 
    395435   int i,j; 
     
    403443   spx_word32_t tmp32; 
    404444   spx_word16_t M_1; 
     445   int saturated=0; 
    405446    
    406447   N = st->window_size; 
     
    417458#endif 
    418459 
    419    filter_dc_notch16((spx_int16_t*)ref, st->notch_radius, st->d, st->frame_size, st->notch_mem); 
     460   filter_dc_notch16(ref, st->notch_radius, st->d, st->frame_size, st->notch_mem); 
    420461   /* Copy input data to buffer */ 
    421462   for (i=0;i<st->frame_size;i++) 
    422463   { 
    423464      spx_word16_t tmp; 
     465      spx_word32_t tmp32; 
    424466      st->x[i] = st->x[i+st->frame_size]; 
    425       st->x[i+st->frame_size] = SUB16(echo[i], MULT16_16_P15(st->preemph, st->memX)); 
     467      tmp32 = SUB32(EXTEND32(echo[i]), EXTEND32(MULT16_16_P15(st->preemph, st->memX))); 
     468#ifdef FIXED_POINT 
     469      /*FIXME: If saturation occurs here, we need to freeze adaptation for M frames (not just one) */ 
     470      if (tmp32 > 32767) 
     471      { 
     472         tmp32 = 32767; 
     473         saturated = 1; 
     474      }       
     475      if (tmp32 < -32767) 
     476      { 
     477         tmp32 = -32767; 
     478         saturated = 1; 
     479      }       
     480#endif 
     481      st->x[i+st->frame_size] = EXTRACT16(tmp32); 
    426482      st->memX = echo[i]; 
    427483       
    428484      tmp = st->d[i]; 
    429485      st->d[i] = st->d[i+st->frame_size]; 
    430       st->d[i+st->frame_size] = SUB16(tmp, MULT16_16_P15(st->preemph, st->memD)); 
     486      tmp32 = SUB32(EXTEND32(tmp), EXTEND32(MULT16_16_P15(st->preemph, st->memD))); 
     487#ifdef FIXED_POINT 
     488      if (tmp32 > 32767) 
     489      { 
     490         tmp32 = 32767; 
     491         saturated = 1; 
     492      }       
     493      if (tmp32 < -32767) 
     494      { 
     495         tmp32 = -32767; 
     496         saturated = 1; 
     497      } 
     498#endif 
     499      st->d[i+st->frame_size] = tmp32; 
    431500      st->memD = tmp; 
    432501   } 
     
    466535         tmp_out = -32768; 
    467536      tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE))); 
     537      /* This is an arbitrary test for saturation */ 
     538      if (ref[i] <= -32000 || ref[i] >= 32000) 
     539      { 
     540         tmp_out = 0; 
     541         saturated = 1; 
     542      } 
    468543      out[i] = tmp_out; 
    469544      st->memE = tmp_out; 
     
    478553 
    479554   /* Compute a bunch of correlations */ 
    480    See = inner_prod(st->e+st->frame_size, st->e+st->frame_size, st->frame_size); 
    481    See = ADD32(See, SHR32(10000,6)); 
    482    Syy = inner_prod(st->y+st->frame_size, st->y+st->frame_size, st->frame_size); 
     555   See = mdf_inner_prod(st->e+st->frame_size, st->e+st->frame_size, st->frame_size); 
     556   See = ADD32(See, SHR32(EXTEND32(10000),6)); 
     557   Syy = mdf_inner_prod(st->y+st->frame_size, st->y+st->frame_size, st->frame_size); 
    483558    
    484559   /* Convert error to frequency domain */ 
     
    545620   if (FLOAT_GT(st->Pey, st->Pyy)) 
    546621      st->Pey = st->Pyy; 
    547    /* leak_estimate is the limear regression result */ 
     622   /* leak_estimate is the linear regression result */ 
    548623   leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(st->Pey, st->Pyy),14)); 
     624   /* This looks like a stupid bug, but it's right (because we convert from Q14 to Q15) */ 
    549625   if (leak_estimate > 16383) 
    550626      leak_estimate = 32767; 
     
    595671      spx_word16_t adapt_rate=0; 
    596672 
    597       Sxx = inner_prod(st->x+st->frame_size, st->x+st->frame_size, st->frame_size); 
     673      Sxx = mdf_inner_prod(st->x+st->frame_size, st->x+st->frame_size, st->frame_size); 
    598674      /* Temporary adaption rate if filter is not adapted correctly */ 
    599675 
     
    621697   } 
    622698 
    623    /* Gradient descent */ 
    624    for (i=0;i<M*N;i++) 
    625    { 
    626       st->W[i] += st->PHI[i]; 
    627       /* Old value of W in PHI */ 
    628       st->PHI[i] = st->W[i] - st->PHI[i]; 
     699   if (!saturated) 
     700   { 
     701      /* Gradient descent */ 
     702      for (i=0;i<M*N;i++) 
     703      { 
     704         st->W[i] += st->PHI[i]; 
     705         /* Old value of W in PHI */ 
     706         st->PHI[i] = st->W[i] - st->PHI[i]; 
     707      } 
    629708   } 
    630709    
     
    638717#ifdef FIXED_POINT 
    639718         for (i=0;i<N;i++) 
    640             st->wtmp2[i] = PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16); 
     719            st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16)); 
    641720         spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 
    642721         for (i=0;i<st->frame_size;i++) 
     
    646725         for (i=st->frame_size;i<N;i++) 
    647726         { 
    648             st->wtmp[i]=SHL(st->wtmp[i],NORMALIZE_SCALEUP); 
     727            st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 
    649728         } 
    650729         spx_fft(st->fft_table, st->wtmp, st->wtmp2); 
    651730         /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 
    652731         for (i=0;i<N;i++) 
    653             st->W[j*N+i] -= SHL32(st->wtmp2[i],16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 
     732            st->W[j*N+i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1); 
    654733#else 
    655734         spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); 
     
    716795      case SPEEX_ECHO_SET_SAMPLING_RATE: 
    717796         st->sampling_rate = (*(int*)ptr); 
    718          st->spec_average = DIV32_16(SHL32(st->frame_size, 15), st->sampling_rate); 
    719 #ifdef FIXED_POINT 
    720          st->beta0 = DIV32_16(SHL32(st->frame_size, 16), st->sampling_rate); 
    721          st->beta_max = DIV32_16(SHL32(st->frame_size, 14), st->sampling_rate); 
     797         st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); 
     798#ifdef FIXED_POINT 
     799         st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); 
     800         st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); 
    722801#else 
    723802         st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; 
Note: See TracChangeset for help on using the changeset viewer.