1 /*---------------------------------------------------------------------------- 2 * 3 * File: 4 * eas_wtengine.c 5 * 6 * Contents and purpose: 7 * This file contains the critical synthesizer components that need to 8 * be optimized for best performance. 9 * 10 * Copyright Sonic Network Inc. 2004-2005 11 12 * Licensed under the Apache License, Version 2.0 (the "License"); 13 * you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 * See the License for the specific language governing permissions and 22 * limitations under the License. 23 * 24 *---------------------------------------------------------------------------- 25 * Revision Control: 26 * $Revision: 844 $ 27 * $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $ 28 *---------------------------------------------------------------------------- 29 */ 30 31 /*------------------------------------ 32 * includes 33 *------------------------------------ 34 */ 35 #include "eas_types.h" 36 #include "eas_math.h" 37 #include "eas_audioconst.h" 38 #include "eas_sndlib.h" 39 #include "eas_wtengine.h" 40 #include "eas_mixer.h" 41 42 /*---------------------------------------------------------------------------- 43 * prototypes 44 *---------------------------------------------------------------------------- 45 */ 46 extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); 47 extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); 48 49 #if defined(_OPTIMIZED_MONO) 50 extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); 51 #else 52 extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); 53 extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); 54 #endif 55 56 #if defined(_FILTER_ENABLED) 57 extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame); 58 #endif 59 60 #if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL) 61 /*---------------------------------------------------------------------------- 62 * WT_VoiceGain 63 *---------------------------------------------------------------------------- 64 * Purpose: 65 * Output gain for individual voice 66 * 67 * Inputs: 68 * 69 * Outputs: 70 * 71 *---------------------------------------------------------------------------- 72 */ 73 /*lint -esym(715, pWTVoice) reserved for future use */ 74 void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 75 { 76 EAS_I32 *pMixBuffer; 77 EAS_PCM *pInputBuffer; 78 EAS_I32 gain; 79 EAS_I32 gainIncrement; 80 EAS_I32 tmp0; 81 EAS_I32 tmp1; 82 EAS_I32 tmp2; 83 EAS_I32 numSamples; 84 85 #if (NUM_OUTPUT_CHANNELS == 2) 86 EAS_I32 gainLeft, gainRight; 87 #endif 88 89 /* initialize some local variables */ 90 numSamples = pWTIntFrame->numSamples; 91 pMixBuffer = pWTIntFrame->pMixBuffer; 92 pInputBuffer = pWTIntFrame->pAudioBuffer; 93 94 /*lint -e{703} <avoid multiply for performance>*/ 95 gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); 96 if (gainIncrement < 0) 97 gainIncrement++; 98 /*lint -e{703} <avoid multiply for performance>*/ 99 gain = pWTIntFrame->prevGain << 16; 100 101 #if (NUM_OUTPUT_CHANNELS == 2) 102 gainLeft = pWTVoice->gainLeft; 103 gainRight = pWTVoice->gainRight; 104 #endif 105 106 while (numSamples--) { 107 108 /* incremental gain step to prevent zipper noise */ 109 tmp0 = *pInputBuffer++; 110 gain += gainIncrement; 111 /*lint -e{704} <avoid divide>*/ 112 tmp2 = gain >> 16; 113 114 /* scale sample by gain */ 115 tmp2 *= tmp0; 116 117 118 /* stereo output */ 119 #if (NUM_OUTPUT_CHANNELS == 2) 120 /*lint -e{704} <avoid divide>*/ 121 tmp2 = tmp2 >> 14; 122 123 /* get the current sample in the final mix buffer */ 124 tmp1 = *pMixBuffer; 125 126 /* left channel */ 127 tmp0 = tmp2 * gainLeft; 128 /*lint -e{704} <avoid divide>*/ 129 tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; 130 tmp1 += tmp0; 131 *pMixBuffer++ = tmp1; 132 133 /* get the current sample in the final mix buffer */ 134 tmp1 = *pMixBuffer; 135 136 /* right channel */ 137 tmp0 = tmp2 * gainRight; 138 /*lint -e{704} <avoid divide>*/ 139 tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; 140 tmp1 += tmp0; 141 *pMixBuffer++ = tmp1; 142 143 /* mono output */ 144 #else 145 146 /* get the current sample in the final mix buffer */ 147 tmp1 = *pMixBuffer; 148 /*lint -e{704} <avoid divide>*/ 149 tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1); 150 tmp1 += tmp2; 151 *pMixBuffer++ = tmp1; 152 #endif 153 154 } 155 } 156 #endif 157 158 #ifndef NATIVE_EAS_KERNEL 159 /*---------------------------------------------------------------------------- 160 * WT_Interpolate 161 *---------------------------------------------------------------------------- 162 * Purpose: 163 * Interpolation engine for wavetable synth 164 * 165 * Inputs: 166 * 167 * Outputs: 168 * 169 *---------------------------------------------------------------------------- 170 */ 171 void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 172 { 173 EAS_PCM *pOutputBuffer; 174 EAS_I32 phaseInc; 175 EAS_I32 phaseFrac; 176 EAS_I32 acc0; 177 const EAS_SAMPLE *pSamples; 178 const EAS_SAMPLE *loopEnd; 179 EAS_I32 samp1; 180 EAS_I32 samp2; 181 EAS_I32 numSamples; 182 183 /* initialize some local variables */ 184 numSamples = pWTIntFrame->numSamples; 185 pOutputBuffer = pWTIntFrame->pAudioBuffer; 186 187 loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1; 188 pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; 189 /*lint -e{713} truncation is OK */ 190 phaseFrac = pWTVoice->phaseFrac; 191 phaseInc = pWTIntFrame->frame.phaseIncrement; 192 193 /* fetch adjacent samples */ 194 #if defined(_8_BIT_SAMPLES) 195 /*lint -e{701} <avoid multiply for performance>*/ 196 samp1 = pSamples[0] << 8; 197 /*lint -e{701} <avoid multiply for performance>*/ 198 samp2 = pSamples[1] << 8; 199 #else 200 samp1 = pSamples[0]; 201 samp2 = pSamples[1]; 202 #endif 203 204 while (numSamples--) { 205 206 /* linear interpolation */ 207 acc0 = samp2 - samp1; 208 acc0 = acc0 * phaseFrac; 209 /*lint -e{704} <avoid divide>*/ 210 acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); 211 212 /* save new output sample in buffer */ 213 /*lint -e{704} <avoid divide>*/ 214 *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); 215 216 /* increment phase */ 217 phaseFrac += phaseInc; 218 /*lint -e{704} <avoid divide>*/ 219 acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; 220 221 /* next sample */ 222 if (acc0 > 0) { 223 224 /* advance sample pointer */ 225 pSamples += acc0; 226 phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); 227 228 /* check for loop end */ 229 acc0 = (EAS_I32) (pSamples - loopEnd); 230 if (acc0 >= 0) 231 pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0; 232 233 /* fetch new samples */ 234 #if defined(_8_BIT_SAMPLES) 235 /*lint -e{701} <avoid multiply for performance>*/ 236 samp1 = pSamples[0] << 8; 237 /*lint -e{701} <avoid multiply for performance>*/ 238 samp2 = pSamples[1] << 8; 239 #else 240 samp1 = pSamples[0]; 241 samp2 = pSamples[1]; 242 #endif 243 } 244 } 245 246 /* save pointer and phase */ 247 pWTVoice->phaseAccum = (EAS_U32) pSamples; 248 pWTVoice->phaseFrac = (EAS_U32) phaseFrac; 249 } 250 #endif 251 252 #ifndef NATIVE_EAS_KERNEL 253 /*---------------------------------------------------------------------------- 254 * WT_InterpolateNoLoop 255 *---------------------------------------------------------------------------- 256 * Purpose: 257 * Interpolation engine for wavetable synth 258 * 259 * Inputs: 260 * 261 * Outputs: 262 * 263 *---------------------------------------------------------------------------- 264 */ 265 void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 266 { 267 EAS_PCM *pOutputBuffer; 268 EAS_I32 phaseInc; 269 EAS_I32 phaseFrac; 270 EAS_I32 acc0; 271 const EAS_SAMPLE *pSamples; 272 EAS_I32 samp1; 273 EAS_I32 samp2; 274 EAS_I32 numSamples; 275 276 /* initialize some local variables */ 277 numSamples = pWTIntFrame->numSamples; 278 pOutputBuffer = pWTIntFrame->pAudioBuffer; 279 280 phaseInc = pWTIntFrame->frame.phaseIncrement; 281 pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; 282 phaseFrac = (EAS_I32)pWTVoice->phaseFrac; 283 284 /* fetch adjacent samples */ 285 #if defined(_8_BIT_SAMPLES) 286 /*lint -e{701} <avoid multiply for performance>*/ 287 samp1 = pSamples[0] << 8; 288 /*lint -e{701} <avoid multiply for performance>*/ 289 samp2 = pSamples[1] << 8; 290 #else 291 samp1 = pSamples[0]; 292 samp2 = pSamples[1]; 293 #endif 294 295 while (numSamples--) { 296 297 298 /* linear interpolation */ 299 acc0 = samp2 - samp1; 300 acc0 = acc0 * phaseFrac; 301 /*lint -e{704} <avoid divide>*/ 302 acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); 303 304 /* save new output sample in buffer */ 305 /*lint -e{704} <avoid divide>*/ 306 *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); 307 308 /* increment phase */ 309 phaseFrac += phaseInc; 310 /*lint -e{704} <avoid divide>*/ 311 acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; 312 313 /* next sample */ 314 if (acc0 > 0) { 315 316 /* advance sample pointer */ 317 pSamples += acc0; 318 phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); 319 320 /* fetch new samples */ 321 #if defined(_8_BIT_SAMPLES) 322 /*lint -e{701} <avoid multiply for performance>*/ 323 samp1 = pSamples[0] << 8; 324 /*lint -e{701} <avoid multiply for performance>*/ 325 samp2 = pSamples[1] << 8; 326 #else 327 samp1 = pSamples[0]; 328 samp2 = pSamples[1]; 329 #endif 330 } 331 } 332 333 /* save pointer and phase */ 334 pWTVoice->phaseAccum = (EAS_U32) pSamples; 335 pWTVoice->phaseFrac = (EAS_U32) phaseFrac; 336 } 337 #endif 338 339 #if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL) 340 /*---------------------------------------------------------------------------- 341 * WT_VoiceFilter 342 *---------------------------------------------------------------------------- 343 * Purpose: 344 * Implements a 2-pole filter 345 * 346 * Inputs: 347 * 348 * Outputs: 349 * 350 *---------------------------------------------------------------------------- 351 */ 352 void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame) 353 { 354 EAS_PCM *pAudioBuffer; 355 EAS_I32 k; 356 EAS_I32 b1; 357 EAS_I32 b2; 358 EAS_I32 z1; 359 EAS_I32 z2; 360 EAS_I32 acc0; 361 EAS_I32 acc1; 362 EAS_I32 numSamples; 363 364 /* initialize some local variables */ 365 numSamples = pWTIntFrame->numSamples; 366 pAudioBuffer = pWTIntFrame->pAudioBuffer; 367 368 z1 = pFilter->z1; 369 z2 = pFilter->z2; 370 b1 = -pWTIntFrame->frame.b1; 371 372 /*lint -e{702} <avoid divide> */ 373 b2 = -pWTIntFrame->frame.b2 >> 1; 374 375 /*lint -e{702} <avoid divide> */ 376 k = pWTIntFrame->frame.k >> 1; 377 378 while (numSamples--) 379 { 380 381 /* do filter calculations */ 382 acc0 = *pAudioBuffer; 383 acc1 = z1 * b1; 384 acc1 += z2 * b2; 385 acc0 = acc1 + k * acc0; 386 z2 = z1; 387 388 /*lint -e{702} <avoid divide> */ 389 z1 = acc0 >> 14; 390 *pAudioBuffer++ = (EAS_I16) z1; 391 } 392 393 /* save delay values */ 394 pFilter->z1 = (EAS_I16) z1; 395 pFilter->z2 = (EAS_I16) z2; 396 } 397 #endif 398 399 /*---------------------------------------------------------------------------- 400 * WT_NoiseGenerator 401 *---------------------------------------------------------------------------- 402 * Purpose: 403 * Generate pseudo-white noise using PRNG and interpolation engine 404 * 405 * Inputs: 406 * 407 * Outputs: 408 * 409 * Notes: 410 * This output is scaled -12dB to prevent saturation in the filter. For a 411 * high quality synthesizer, the output can be set to full scale, however 412 * if the filter is used, it can overflow with certain coefficients. In this 413 * case, either a saturation operation should take in the filter before 414 * scaling back to 16 bits or the signal path should be increased to 18 bits 415 * or more. 416 *---------------------------------------------------------------------------- 417 */ 418 void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 419 { 420 EAS_PCM *pOutputBuffer; 421 EAS_I32 phaseInc; 422 EAS_I32 tmp0; 423 EAS_I32 tmp1; 424 EAS_I32 nInterpolatedSample; 425 EAS_I32 numSamples; 426 427 /* initialize some local variables */ 428 numSamples = pWTIntFrame->numSamples; 429 pOutputBuffer = pWTIntFrame->pAudioBuffer; 430 phaseInc = pWTIntFrame->frame.phaseIncrement; 431 432 /* get last two samples generated */ 433 /*lint -e{704} <avoid divide for performance>*/ 434 tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18; 435 /*lint -e{704} <avoid divide for performance>*/ 436 tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; 437 438 /* generate a buffer of noise */ 439 while (numSamples--) { 440 nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac)); 441 nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac); 442 *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample; 443 444 /* update PRNG */ 445 pWTVoice->phaseFrac += (EAS_U32) phaseInc; 446 if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) { 447 tmp0 = tmp1; 448 pWTVoice->phaseAccum = pWTVoice->loopEnd; 449 pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1); 450 tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; 451 pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac); 452 } 453 454 } 455 } 456 457 #ifndef _OPTIMIZED_MONO 458 /*---------------------------------------------------------------------------- 459 * WT_ProcessVoice 460 *---------------------------------------------------------------------------- 461 * Purpose: 462 * This routine does the block processing for one voice. It is isolated 463 * from the main synth code to allow for various implementation-specific 464 * optimizations. It calls the interpolator, filter, and gain routines 465 * appropriate for a particular configuration. 466 * 467 * Inputs: 468 * 469 * Outputs: 470 * 471 * Notes: 472 *---------------------------------------------------------------------------- 473 */ 474 void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 475 { 476 477 /* use noise generator */ 478 if (pWTVoice->loopStart == WT_NOISE_GENERATOR) 479 WT_NoiseGenerator(pWTVoice, pWTIntFrame); 480 481 /* generate interpolated samples for looped waves */ 482 else if (pWTVoice->loopStart != pWTVoice->loopEnd) 483 WT_Interpolate(pWTVoice, pWTIntFrame); 484 485 /* generate interpolated samples for unlooped waves */ 486 else 487 { 488 WT_InterpolateNoLoop(pWTVoice, pWTIntFrame); 489 } 490 491 #ifdef _FILTER_ENABLED 492 if (pWTIntFrame->frame.k != 0) 493 WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame); 494 #endif 495 496 //2 TEST NEW MIXER FUNCTION 497 #ifdef UNIFIED_MIXER 498 { 499 EAS_I32 gainLeft, gainIncLeft; 500 501 #if (NUM_OUTPUT_CHANNELS == 2) 502 EAS_I32 gainRight, gainIncRight; 503 #endif 504 505 gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1; 506 gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS; 507 508 #if (NUM_OUTPUT_CHANNELS == 2) 509 gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1; 510 gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS; 511 EAS_MixStream( 512 pWTIntFrame->pAudioBuffer, 513 pWTIntFrame->pMixBuffer, 514 pWTIntFrame->numSamples, 515 gainLeft, 516 gainRight, 517 gainIncLeft, 518 gainIncRight, 519 MIX_FLAGS_STEREO_OUTPUT); 520 521 #else 522 EAS_MixStream( 523 pWTIntFrame->pAudioBuffer, 524 pWTIntFrame->pMixBuffer, 525 pWTIntFrame->numSamples, 526 gainLeft, 527 0, 528 gainIncLeft, 529 0, 530 0); 531 #endif 532 } 533 534 #else 535 /* apply gain, and left and right gain */ 536 WT_VoiceGain(pWTVoice, pWTIntFrame); 537 #endif 538 } 539 #endif 540 541 #if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL) 542 /*---------------------------------------------------------------------------- 543 * WT_InterpolateMono 544 *---------------------------------------------------------------------------- 545 * Purpose: 546 * A C version of the sample interpolation + gain routine, optimized for mono. 547 * It's not pretty, but it matches the assembly code exactly. 548 * 549 * Inputs: 550 * 551 * Outputs: 552 * 553 * Notes: 554 *---------------------------------------------------------------------------- 555 */ 556 void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 557 { 558 EAS_I32 *pMixBuffer; 559 const EAS_I8 *pLoopEnd; 560 const EAS_I8 *pCurrentPhaseInt; 561 EAS_I32 numSamples; 562 EAS_I32 gain; 563 EAS_I32 gainIncrement; 564 EAS_I32 currentPhaseFrac; 565 EAS_I32 phaseInc; 566 EAS_I32 tmp0; 567 EAS_I32 tmp1; 568 EAS_I32 tmp2; 569 EAS_I8 *pLoopStart; 570 571 numSamples = pWTIntFrame->numSamples; 572 pMixBuffer = pWTIntFrame->pMixBuffer; 573 574 /* calculate gain increment */ 575 gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); 576 if (gainIncrement < 0) 577 gainIncrement++; 578 gain = pWTIntFrame->prevGain << 16; 579 580 pCurrentPhaseInt = pWTVoice->pPhaseAccum; 581 currentPhaseFrac = pWTVoice->phaseFrac; 582 phaseInc = pWTIntFrame->phaseIncrement; 583 584 pLoopStart = pWTVoice->pLoopStart; 585 pLoopEnd = pWTVoice->pLoopEnd + 1; 586 587 InterpolationLoop: 588 tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd); 589 if (tmp0 >= 0) 590 pCurrentPhaseInt = pLoopStart + tmp0; 591 592 tmp0 = *pCurrentPhaseInt; 593 tmp1 = *(pCurrentPhaseInt + 1); 594 595 tmp2 = phaseInc + currentPhaseFrac; 596 597 tmp1 = tmp1 - tmp0; 598 tmp1 = tmp1 * currentPhaseFrac; 599 600 tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS); 601 602 pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS); 603 currentPhaseFrac = tmp2 & PHASE_FRAC_MASK; 604 605 gain += gainIncrement; 606 tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS); 607 608 tmp0 = *pMixBuffer; 609 tmp2 = tmp1 * tmp2; 610 tmp2 = (tmp2 >> 9); 611 tmp0 = tmp2 + tmp0; 612 *pMixBuffer++ = tmp0; 613 614 numSamples--; 615 if (numSamples > 0) 616 goto InterpolationLoop; 617 618 pWTVoice->pPhaseAccum = pCurrentPhaseInt; 619 pWTVoice->phaseFrac = currentPhaseFrac; 620 /*lint -e{702} <avoid divide>*/ 621 pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS); 622 } 623 #endif 624 625 #ifdef _OPTIMIZED_MONO 626 /*---------------------------------------------------------------------------- 627 * WT_ProcessVoice 628 *---------------------------------------------------------------------------- 629 * Purpose: 630 * This routine does the block processing for one voice. It is isolated 631 * from the main synth code to allow for various implementation-specific 632 * optimizations. It calls the interpolator, filter, and gain routines 633 * appropriate for a particular configuration. 634 * 635 * Inputs: 636 * 637 * Outputs: 638 * 639 * Notes: 640 * This special version works handles an optimized mono-only signal 641 * without filters 642 *---------------------------------------------------------------------------- 643 */ 644 void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) 645 { 646 647 /* use noise generator */ 648 if (pWTVoice->loopStart== WT_NOISE_GENERATOR) 649 { 650 WT_NoiseGenerator(pWTVoice, pWTIntFrame); 651 WT_VoiceGain(pWTVoice, pWTIntFrame); 652 } 653 654 /* or generate interpolated samples */ 655 else 656 { 657 WT_InterpolateMono(pWTVoice, pWTIntFrame); 658 } 659 } 660 #endif 661 662