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