Changeset 628 for pjproject/trunk/pjmedia/src/pjmedia-codec/speex/mdf.c
- Timestamp:
- Jul 26, 2006 5:04:54 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-codec/speex/mdf.c
r523 r628 91 91 92 92 #ifdef FIXED_POINT 93 static const spx_float_t MIN_LEAK = ((spx_float_t){16777, -24});93 static const spx_float_t MIN_LEAK = {16777, -24}; 94 94 #define TOP16(x) ((x)>>16) 95 95 #else … … 141 141 spx_word16_t notch_radius; 142 142 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; 143 147 }; 144 148 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)149 static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem) 146 150 { 147 151 int i; … … 167 171 } 168 172 169 static inline spx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len)173 static inline spx_word32_t mdf_inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) 170 174 { 171 175 spx_word32_t sum=0; 172 len >>= 2;176 len >>= 1; 173 177 while(len--) 174 178 { 175 179 spx_word32_t part=0; 176 part = MAC16_16(part,*x++,*y++);177 part = MAC16_16(part,*x++,*y++);178 180 part = MAC16_16(part,*x++,*y++); 179 181 part = MAC16_16(part,*x++,*y++); … … 185 187 186 188 /** 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)189 static inline void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N) 188 190 { 189 191 int i, j; … … 198 200 /** Compute cross-power spectrum of a half-complex (packed) vectors and add to acc */ 199 201 #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)202 static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) 201 203 { 202 204 int i,j; … … 226 228 } 227 229 #else 228 static inline void spectral_mul_accum( spx_word16_t *X,spx_word32_t *Y, spx_word16_t *acc, int N, int M)230 static inline void spectral_mul_accum(const spx_word16_t *X, const spx_word32_t *Y, spx_word16_t *acc, int N, int M) 229 231 { 230 232 int i,j; … … 247 249 248 250 /** 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)251 static 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) 250 252 { 251 253 int i, j; … … 274 276 /* FIXME: Make that an init option (new API call?) */ 275 277 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); 280 282 #else 281 283 st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; … … 333 335 st->adapted = 0; 334 336 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 335 341 return st; 336 342 } … … 386 392 speex_free(st->wtmp2); 387 393 #endif 394 speex_free(st->play_buf); 388 395 speex_free(st); 389 396 } 390 397 391 extern int fixed_point; 398 void 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 419 void 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 392 432 /** Performs echo cancellation on a frame */ 393 void speex_echo_cancel(SpeexEchoState *st, short *ref, short *echo, short *out, spx_int32_t *Yout)433 void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *ref, const spx_int16_t *echo, spx_int16_t *out, spx_int32_t *Yout) 394 434 { 395 435 int i,j; … … 403 443 spx_word32_t tmp32; 404 444 spx_word16_t M_1; 445 int saturated=0; 405 446 406 447 N = st->window_size; … … 417 458 #endif 418 459 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); 420 461 /* Copy input data to buffer */ 421 462 for (i=0;i<st->frame_size;i++) 422 463 { 423 464 spx_word16_t tmp; 465 spx_word32_t tmp32; 424 466 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); 426 482 st->memX = echo[i]; 427 483 428 484 tmp = st->d[i]; 429 485 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; 431 500 st->memD = tmp; 432 501 } … … 466 535 tmp_out = -32768; 467 536 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 } 468 543 out[i] = tmp_out; 469 544 st->memE = tmp_out; … … 478 553 479 554 /* 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); 483 558 484 559 /* Convert error to frequency domain */ … … 545 620 if (FLOAT_GT(st->Pey, st->Pyy)) 546 621 st->Pey = st->Pyy; 547 /* leak_estimate is the li mear regression result */622 /* leak_estimate is the linear regression result */ 548 623 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) */ 549 625 if (leak_estimate > 16383) 550 626 leak_estimate = 32767; … … 595 671 spx_word16_t adapt_rate=0; 596 672 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); 598 674 /* Temporary adaption rate if filter is not adapted correctly */ 599 675 … … 621 697 } 622 698 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 } 629 708 } 630 709 … … 638 717 #ifdef FIXED_POINT 639 718 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)); 641 720 spx_ifft(st->fft_table, st->wtmp2, st->wtmp); 642 721 for (i=0;i<st->frame_size;i++) … … 646 725 for (i=st->frame_size;i<N;i++) 647 726 { 648 st->wtmp[i]=SHL (st->wtmp[i],NORMALIZE_SCALEUP);727 st->wtmp[i]=SHL16(st->wtmp[i],NORMALIZE_SCALEUP); 649 728 } 650 729 spx_fft(st->fft_table, st->wtmp, st->wtmp2); 651 730 /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */ 652 731 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); 654 733 #else 655 734 spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); … … 716 795 case SPEEX_ECHO_SET_SAMPLING_RATE: 717 796 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); 722 801 #else 723 802 st->beta0 = (2.0f*st->frame_size)/st->sampling_rate;
Note: See TracChangeset
for help on using the changeset viewer.