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