• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 > 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 */
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