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