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 */
WT_VoiceGain(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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 */
WT_Interpolate(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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 */
WT_InterpolateNoLoop(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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 */
WT_VoiceFilter(S_FILTER_CONTROL * pFilter,S_WT_INT_FRAME * pWTIntFrame)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 */
WT_NoiseGenerator(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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 */
WT_ProcessVoice(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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 */
WT_InterpolateMono(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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)
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 */
WT_ProcessVoice(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)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