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