xref: /aosp_15_r20/external/sonivox/arm-wt-22k/lib_src/eas_wtsynth.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_wtsynth.c
5*f81fb7c4SAndroid Build Coastguard Worker  *
6*f81fb7c4SAndroid Build Coastguard Worker  * Contents and purpose:
7*f81fb7c4SAndroid Build Coastguard Worker  * Implements the synthesizer functions.
8*f81fb7c4SAndroid Build Coastguard Worker  *
9*f81fb7c4SAndroid Build Coastguard Worker  * Copyright Sonic Network Inc. 2004
10*f81fb7c4SAndroid Build Coastguard Worker 
11*f81fb7c4SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
12*f81fb7c4SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
13*f81fb7c4SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
14*f81fb7c4SAndroid Build Coastguard Worker  *
15*f81fb7c4SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
16*f81fb7c4SAndroid Build Coastguard Worker  *
17*f81fb7c4SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
18*f81fb7c4SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
19*f81fb7c4SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20*f81fb7c4SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
21*f81fb7c4SAndroid Build Coastguard Worker  * limitations under the License.
22*f81fb7c4SAndroid Build Coastguard Worker  *
23*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
24*f81fb7c4SAndroid Build Coastguard Worker  * Revision Control:
25*f81fb7c4SAndroid Build Coastguard Worker  *   $Revision: 795 $
26*f81fb7c4SAndroid Build Coastguard Worker  *   $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
27*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
28*f81fb7c4SAndroid Build Coastguard Worker */
29*f81fb7c4SAndroid Build Coastguard Worker 
30*f81fb7c4SAndroid Build Coastguard Worker // includes
31*f81fb7c4SAndroid Build Coastguard Worker #define LOG_TAG "SYNTH"
32*f81fb7c4SAndroid Build Coastguard Worker #include "log/log.h"
33*f81fb7c4SAndroid Build Coastguard Worker #include <cutils/log.h>
34*f81fb7c4SAndroid Build Coastguard Worker 
35*f81fb7c4SAndroid Build Coastguard Worker #include "eas_data.h"
36*f81fb7c4SAndroid Build Coastguard Worker #include "eas_report.h"
37*f81fb7c4SAndroid Build Coastguard Worker #include "eas_host.h"
38*f81fb7c4SAndroid Build Coastguard Worker #include "eas_math.h"
39*f81fb7c4SAndroid Build Coastguard Worker #include "eas_synth_protos.h"
40*f81fb7c4SAndroid Build Coastguard Worker #include "eas_wtsynth.h"
41*f81fb7c4SAndroid Build Coastguard Worker #include "eas_pan.h"
42*f81fb7c4SAndroid Build Coastguard Worker 
43*f81fb7c4SAndroid Build Coastguard Worker #ifdef DLS_SYNTHESIZER
44*f81fb7c4SAndroid Build Coastguard Worker #include "eas_dlssynth.h"
45*f81fb7c4SAndroid Build Coastguard Worker #endif
46*f81fb7c4SAndroid Build Coastguard Worker 
47*f81fb7c4SAndroid Build Coastguard Worker #ifdef _METRICS_ENABLED
48*f81fb7c4SAndroid Build Coastguard Worker #include "eas_perf.h"
49*f81fb7c4SAndroid Build Coastguard Worker #endif
50*f81fb7c4SAndroid Build Coastguard Worker 
51*f81fb7c4SAndroid Build Coastguard Worker /* local prototypes */
52*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT WT_Initialize(S_VOICE_MGR *pVoiceMgr);
53*f81fb7c4SAndroid Build Coastguard Worker static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
54*f81fb7c4SAndroid Build Coastguard Worker static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
55*f81fb7c4SAndroid Build Coastguard Worker static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum);
56*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex);
57*f81fb7c4SAndroid Build Coastguard Worker static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples);
58*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel);
59*f81fb7c4SAndroid Build Coastguard Worker static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents);
60*f81fb7c4SAndroid Build Coastguard Worker static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain);
61*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv);
62*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv);
63*f81fb7c4SAndroid Build Coastguard Worker 
64*f81fb7c4SAndroid Build Coastguard Worker #ifdef EAS_SPLIT_WT_SYNTH
65*f81fb7c4SAndroid Build Coastguard Worker extern EAS_BOOL WTE_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
66*f81fb7c4SAndroid Build Coastguard Worker extern EAS_BOOL WTE_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain);
67*f81fb7c4SAndroid Build Coastguard Worker #endif
68*f81fb7c4SAndroid Build Coastguard Worker 
69*f81fb7c4SAndroid Build Coastguard Worker #ifdef _FILTER_ENABLED
70*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt);
71*f81fb7c4SAndroid Build Coastguard Worker #endif
72*f81fb7c4SAndroid Build Coastguard Worker 
73*f81fb7c4SAndroid Build Coastguard Worker #ifdef _STATS
74*f81fb7c4SAndroid Build Coastguard Worker extern double statsPhaseIncrement;
75*f81fb7c4SAndroid Build Coastguard Worker extern double statsMaxPhaseIncrement;
76*f81fb7c4SAndroid Build Coastguard Worker extern long statsPhaseSampleCount;
77*f81fb7c4SAndroid Build Coastguard Worker extern double statsSampleSize;
78*f81fb7c4SAndroid Build Coastguard Worker extern long statsSampleCount;
79*f81fb7c4SAndroid Build Coastguard Worker #endif
80*f81fb7c4SAndroid Build Coastguard Worker 
81*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
82*f81fb7c4SAndroid Build Coastguard Worker  * Synthesizer interface
83*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
84*f81fb7c4SAndroid Build Coastguard Worker */
85*f81fb7c4SAndroid Build Coastguard Worker 
86*f81fb7c4SAndroid Build Coastguard Worker const S_SYNTH_INTERFACE wtSynth =
87*f81fb7c4SAndroid Build Coastguard Worker {
88*f81fb7c4SAndroid Build Coastguard Worker     WT_Initialize,
89*f81fb7c4SAndroid Build Coastguard Worker     WT_StartVoice,
90*f81fb7c4SAndroid Build Coastguard Worker     WT_UpdateVoice,
91*f81fb7c4SAndroid Build Coastguard Worker     WT_ReleaseVoice,
92*f81fb7c4SAndroid Build Coastguard Worker     WT_MuteVoice,
93*f81fb7c4SAndroid Build Coastguard Worker     WT_SustainPedal,
94*f81fb7c4SAndroid Build Coastguard Worker     WT_UpdateChannel
95*f81fb7c4SAndroid Build Coastguard Worker };
96*f81fb7c4SAndroid Build Coastguard Worker 
97*f81fb7c4SAndroid Build Coastguard Worker #ifdef EAS_SPLIT_WT_SYNTH
98*f81fb7c4SAndroid Build Coastguard Worker const S_FRAME_INTERFACE wtFrameInterface =
99*f81fb7c4SAndroid Build Coastguard Worker {
100*f81fb7c4SAndroid Build Coastguard Worker     WTE_StartFrame,
101*f81fb7c4SAndroid Build Coastguard Worker     WTE_EndFrame
102*f81fb7c4SAndroid Build Coastguard Worker };
103*f81fb7c4SAndroid Build Coastguard Worker #endif
104*f81fb7c4SAndroid Build Coastguard Worker 
105*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
106*f81fb7c4SAndroid Build Coastguard Worker  * WT_Initialize()
107*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
108*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
109*f81fb7c4SAndroid Build Coastguard Worker  *
110*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
111*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - pointer to voice to initialize
112*f81fb7c4SAndroid Build Coastguard Worker  *
113*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
114*f81fb7c4SAndroid Build Coastguard Worker  *
115*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
116*f81fb7c4SAndroid Build Coastguard Worker */
WT_Initialize(S_VOICE_MGR * pVoiceMgr)117*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT WT_Initialize (S_VOICE_MGR *pVoiceMgr)
118*f81fb7c4SAndroid Build Coastguard Worker {
119*f81fb7c4SAndroid Build Coastguard Worker     EAS_INT i;
120*f81fb7c4SAndroid Build Coastguard Worker 
121*f81fb7c4SAndroid Build Coastguard Worker     for (i = 0; i < NUM_WT_VOICES; i++)
122*f81fb7c4SAndroid Build Coastguard Worker     {
123*f81fb7c4SAndroid Build Coastguard Worker 
124*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].artIndex = DEFAULT_ARTICULATION_INDEX;
125*f81fb7c4SAndroid Build Coastguard Worker 
126*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].eg1State = DEFAULT_EG1_STATE;
127*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].eg1Value = DEFAULT_EG1_VALUE;
128*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].eg1Increment = DEFAULT_EG1_INCREMENT;
129*f81fb7c4SAndroid Build Coastguard Worker 
130*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].eg2State = DEFAULT_EG2_STATE;
131*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].eg2Value = DEFAULT_EG2_VALUE;
132*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].eg2Increment = DEFAULT_EG2_INCREMENT;
133*f81fb7c4SAndroid Build Coastguard Worker 
134*f81fb7c4SAndroid Build Coastguard Worker         /* left and right gain values are needed only if stereo output */
135*f81fb7c4SAndroid Build Coastguard Worker #if (NUM_OUTPUT_CHANNELS == 2)
136*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].gainLeft = DEFAULT_VOICE_GAIN;
137*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].gainRight = DEFAULT_VOICE_GAIN;
138*f81fb7c4SAndroid Build Coastguard Worker #endif
139*f81fb7c4SAndroid Build Coastguard Worker 
140*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].phaseFrac = DEFAULT_PHASE_FRAC;
141*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].phaseAccum = DEFAULT_PHASE_INT;
142*f81fb7c4SAndroid Build Coastguard Worker 
143*f81fb7c4SAndroid Build Coastguard Worker #ifdef _FILTER_ENABLED
144*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].filter.z1 = DEFAULT_FILTER_ZERO;
145*f81fb7c4SAndroid Build Coastguard Worker         pVoiceMgr->wtVoices[i].filter.z2 = DEFAULT_FILTER_ZERO;
146*f81fb7c4SAndroid Build Coastguard Worker #endif
147*f81fb7c4SAndroid Build Coastguard Worker     }
148*f81fb7c4SAndroid Build Coastguard Worker 
149*f81fb7c4SAndroid Build Coastguard Worker     return EAS_TRUE;
150*f81fb7c4SAndroid Build Coastguard Worker }
151*f81fb7c4SAndroid Build Coastguard Worker 
152*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
153*f81fb7c4SAndroid Build Coastguard Worker  * WT_ReleaseVoice()
154*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
155*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
156*f81fb7c4SAndroid Build Coastguard Worker  * The selected voice is being released.
157*f81fb7c4SAndroid Build Coastguard Worker  *
158*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
159*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to S_EAS_DATA
160*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - pointer to voice to release
161*f81fb7c4SAndroid Build Coastguard Worker  *
162*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
163*f81fb7c4SAndroid Build Coastguard Worker  * None
164*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
165*f81fb7c4SAndroid Build Coastguard Worker */
166*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pVoice) used in some implementations */
WT_ReleaseVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum)167*f81fb7c4SAndroid Build Coastguard Worker static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
168*f81fb7c4SAndroid Build Coastguard Worker {
169*f81fb7c4SAndroid Build Coastguard Worker     S_WT_VOICE *pWTVoice;
170*f81fb7c4SAndroid Build Coastguard Worker     const S_ARTICULATION *pArticulation;
171*f81fb7c4SAndroid Build Coastguard Worker 
172*f81fb7c4SAndroid Build Coastguard Worker #ifdef DLS_SYNTHESIZER
173*f81fb7c4SAndroid Build Coastguard Worker     if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
174*f81fb7c4SAndroid Build Coastguard Worker     {
175*f81fb7c4SAndroid Build Coastguard Worker         DLS_ReleaseVoice(pVoiceMgr, pSynth, pVoice, voiceNum);
176*f81fb7c4SAndroid Build Coastguard Worker         return;
177*f81fb7c4SAndroid Build Coastguard Worker     }
178*f81fb7c4SAndroid Build Coastguard Worker #endif
179*f81fb7c4SAndroid Build Coastguard Worker 
180*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
181*f81fb7c4SAndroid Build Coastguard Worker     pArticulation = &pSynth->pEAS->pArticulations[pWTVoice->artIndex];
182*f81fb7c4SAndroid Build Coastguard Worker 
183*f81fb7c4SAndroid Build Coastguard Worker     /* release EG1 */
184*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1State = eEnvelopeStateRelease;
185*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1Increment = pArticulation->eg1.releaseTime;
186*f81fb7c4SAndroid Build Coastguard Worker 
187*f81fb7c4SAndroid Build Coastguard Worker     /*
188*f81fb7c4SAndroid Build Coastguard Worker     The spec says we should release EG2, but doing so with the current
189*f81fb7c4SAndroid Build Coastguard Worker     voicing is causing clicks. This fix will need to be coordinated with
190*f81fb7c4SAndroid Build Coastguard Worker     a new sound library release
191*f81fb7c4SAndroid Build Coastguard Worker     */
192*f81fb7c4SAndroid Build Coastguard Worker 
193*f81fb7c4SAndroid Build Coastguard Worker     /* release EG2 */
194*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg2State = eEnvelopeStateRelease;
195*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg2Increment = pArticulation->eg2.releaseTime;
196*f81fb7c4SAndroid Build Coastguard Worker }
197*f81fb7c4SAndroid Build Coastguard Worker 
198*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
199*f81fb7c4SAndroid Build Coastguard Worker  * WT_MuteVoice()
200*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
201*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
202*f81fb7c4SAndroid Build Coastguard Worker  * The selected voice is being muted.
203*f81fb7c4SAndroid Build Coastguard Worker  *
204*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
205*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - pointer to voice to release
206*f81fb7c4SAndroid Build Coastguard Worker  *
207*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
208*f81fb7c4SAndroid Build Coastguard Worker  * None
209*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
210*f81fb7c4SAndroid Build Coastguard Worker */
211*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pSynth) used in some implementations */
WT_MuteVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum)212*f81fb7c4SAndroid Build Coastguard Worker static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
213*f81fb7c4SAndroid Build Coastguard Worker {
214*f81fb7c4SAndroid Build Coastguard Worker 
215*f81fb7c4SAndroid Build Coastguard Worker #ifdef DLS_SYNTHESIZER
216*f81fb7c4SAndroid Build Coastguard Worker     if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
217*f81fb7c4SAndroid Build Coastguard Worker     {
218*f81fb7c4SAndroid Build Coastguard Worker         DLS_MuteVoice(pVoiceMgr, pSynth, pVoice, voiceNum);
219*f81fb7c4SAndroid Build Coastguard Worker         return;
220*f81fb7c4SAndroid Build Coastguard Worker     }
221*f81fb7c4SAndroid Build Coastguard Worker #endif
222*f81fb7c4SAndroid Build Coastguard Worker 
223*f81fb7c4SAndroid Build Coastguard Worker     /* clear deferred action flags */
224*f81fb7c4SAndroid Build Coastguard Worker     pVoice->voiceFlags &=
225*f81fb7c4SAndroid Build Coastguard Worker         ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF |
226*f81fb7c4SAndroid Build Coastguard Worker         VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF |
227*f81fb7c4SAndroid Build Coastguard Worker         VOICE_FLAG_DEFER_MUTE);
228*f81fb7c4SAndroid Build Coastguard Worker 
229*f81fb7c4SAndroid Build Coastguard Worker     /* set the envelope state */
230*f81fb7c4SAndroid Build Coastguard Worker     pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateMuted;
231*f81fb7c4SAndroid Build Coastguard Worker     pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateMuted;
232*f81fb7c4SAndroid Build Coastguard Worker }
233*f81fb7c4SAndroid Build Coastguard Worker 
234*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
235*f81fb7c4SAndroid Build Coastguard Worker  * WT_SustainPedal()
236*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
237*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
238*f81fb7c4SAndroid Build Coastguard Worker  * The selected voice is held due to sustain pedal
239*f81fb7c4SAndroid Build Coastguard Worker  *
240*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
241*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - pointer to voice to sustain
242*f81fb7c4SAndroid Build Coastguard Worker  *
243*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
244*f81fb7c4SAndroid Build Coastguard Worker  * None
245*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
246*f81fb7c4SAndroid Build Coastguard Worker */
247*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pChannel) used in some implementations */
WT_SustainPedal(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,S_SYNTH_CHANNEL * pChannel,EAS_I32 voiceNum)248*f81fb7c4SAndroid Build Coastguard Worker static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum)
249*f81fb7c4SAndroid Build Coastguard Worker {
250*f81fb7c4SAndroid Build Coastguard Worker     S_WT_VOICE *pWTVoice;
251*f81fb7c4SAndroid Build Coastguard Worker 
252*f81fb7c4SAndroid Build Coastguard Worker #ifdef DLS_SYNTHESIZER
253*f81fb7c4SAndroid Build Coastguard Worker     if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
254*f81fb7c4SAndroid Build Coastguard Worker     {
255*f81fb7c4SAndroid Build Coastguard Worker         DLS_SustainPedal(pVoiceMgr, pSynth, pVoice, pChannel, voiceNum);
256*f81fb7c4SAndroid Build Coastguard Worker         return;
257*f81fb7c4SAndroid Build Coastguard Worker     }
258*f81fb7c4SAndroid Build Coastguard Worker #endif
259*f81fb7c4SAndroid Build Coastguard Worker 
260*f81fb7c4SAndroid Build Coastguard Worker     /* don't catch the voice if below the sustain level */
261*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
262*f81fb7c4SAndroid Build Coastguard Worker     if (pWTVoice->eg1Value < pSynth->pEAS->pArticulations[pWTVoice->artIndex].eg1.sustainLevel)
263*f81fb7c4SAndroid Build Coastguard Worker         return;
264*f81fb7c4SAndroid Build Coastguard Worker 
265*f81fb7c4SAndroid Build Coastguard Worker     /* sustain flag is set, damper pedal is on */
266*f81fb7c4SAndroid Build Coastguard Worker     /* defer releasing this note until the damper pedal is off */
267*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1State = eEnvelopeStateDecay;
268*f81fb7c4SAndroid Build Coastguard Worker     pVoice->voiceState = eVoiceStatePlay;
269*f81fb7c4SAndroid Build Coastguard Worker 
270*f81fb7c4SAndroid Build Coastguard Worker     /*
271*f81fb7c4SAndroid Build Coastguard Worker     because sustain pedal is on, this voice
272*f81fb7c4SAndroid Build Coastguard Worker     should defer releasing its note
273*f81fb7c4SAndroid Build Coastguard Worker     */
274*f81fb7c4SAndroid Build Coastguard Worker     pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF;
275*f81fb7c4SAndroid Build Coastguard Worker 
276*f81fb7c4SAndroid Build Coastguard Worker #ifdef _DEBUG_SYNTH
277*f81fb7c4SAndroid Build Coastguard Worker     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_SustainPedal: defer note off because sustain pedal is on\n"); */ }
278*f81fb7c4SAndroid Build Coastguard Worker #endif
279*f81fb7c4SAndroid Build Coastguard Worker }
280*f81fb7c4SAndroid Build Coastguard Worker 
281*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
282*f81fb7c4SAndroid Build Coastguard Worker  * WT_StartVoice()
283*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
284*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
285*f81fb7c4SAndroid Build Coastguard Worker  * Assign the region for the given instrument using the midi key number
286*f81fb7c4SAndroid Build Coastguard Worker  * and the RPN2 (coarse tuning) value. By using RPN2 as part of the
287*f81fb7c4SAndroid Build Coastguard Worker  * region selection process, we reduce the amount a given sample has
288*f81fb7c4SAndroid Build Coastguard Worker  * to be transposed by selecting the closest recorded root instead.
289*f81fb7c4SAndroid Build Coastguard Worker  *
290*f81fb7c4SAndroid Build Coastguard Worker  * This routine is the second half of SynthAssignRegion().
291*f81fb7c4SAndroid Build Coastguard Worker  * If the region was successfully found by SynthFindRegionIndex(),
292*f81fb7c4SAndroid Build Coastguard Worker  * then assign the region's parameters to the voice.
293*f81fb7c4SAndroid Build Coastguard Worker  *
294*f81fb7c4SAndroid Build Coastguard Worker  * Setup and initialize the following voice parameters:
295*f81fb7c4SAndroid Build Coastguard Worker  * m_nRegionIndex
296*f81fb7c4SAndroid Build Coastguard Worker  *
297*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
298*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - ptr to the voice we have assigned for this channel
299*f81fb7c4SAndroid Build Coastguard Worker  * nRegionIndex - index of the region
300*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
301*f81fb7c4SAndroid Build Coastguard Worker  *
302*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
303*f81fb7c4SAndroid Build Coastguard Worker  * success - could find and assign the region for this voice's note otherwise
304*f81fb7c4SAndroid Build Coastguard Worker  * failure - could not find nor assign the region for this voice's note
305*f81fb7c4SAndroid Build Coastguard Worker  *
306*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
307*f81fb7c4SAndroid Build Coastguard Worker  * psSynthObject->m_sVoice[].m_nRegionIndex is assigned
308*f81fb7c4SAndroid Build Coastguard Worker  * psSynthObject->m_sVoice[] parameters are assigned
309*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
310*f81fb7c4SAndroid Build Coastguard Worker */
WT_StartVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum,EAS_U16 regionIndex)311*f81fb7c4SAndroid Build Coastguard Worker static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex)
312*f81fb7c4SAndroid Build Coastguard Worker {
313*f81fb7c4SAndroid Build Coastguard Worker     S_WT_VOICE *pWTVoice;
314*f81fb7c4SAndroid Build Coastguard Worker     const S_WT_REGION *pRegion;
315*f81fb7c4SAndroid Build Coastguard Worker     const S_ARTICULATION *pArt;
316*f81fb7c4SAndroid Build Coastguard Worker     S_SYNTH_CHANNEL *pChannel;
317*f81fb7c4SAndroid Build Coastguard Worker 
318*f81fb7c4SAndroid Build Coastguard Worker #if (NUM_OUTPUT_CHANNELS == 2)
319*f81fb7c4SAndroid Build Coastguard Worker     EAS_INT pan;
320*f81fb7c4SAndroid Build Coastguard Worker #endif
321*f81fb7c4SAndroid Build Coastguard Worker 
322*f81fb7c4SAndroid Build Coastguard Worker #ifdef EAS_SPLIT_WT_SYNTH
323*f81fb7c4SAndroid Build Coastguard Worker     S_WT_CONFIG wtConfig;
324*f81fb7c4SAndroid Build Coastguard Worker #endif
325*f81fb7c4SAndroid Build Coastguard Worker 
326*f81fb7c4SAndroid Build Coastguard Worker     /* no samples have been synthesized for this note yet */
327*f81fb7c4SAndroid Build Coastguard Worker     pVoice->regionIndex = regionIndex;
328*f81fb7c4SAndroid Build Coastguard Worker     pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
329*f81fb7c4SAndroid Build Coastguard Worker 
330*f81fb7c4SAndroid Build Coastguard Worker     /* get the articulation index for this region */
331*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
332*f81fb7c4SAndroid Build Coastguard Worker     pChannel = &pSynth->channels[pVoice->channel & 15];
333*f81fb7c4SAndroid Build Coastguard Worker 
334*f81fb7c4SAndroid Build Coastguard Worker     /* update static channel parameters */
335*f81fb7c4SAndroid Build Coastguard Worker     if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)
336*f81fb7c4SAndroid Build Coastguard Worker         WT_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15);
337*f81fb7c4SAndroid Build Coastguard Worker 
338*f81fb7c4SAndroid Build Coastguard Worker #ifdef DLS_SYNTHESIZER
339*f81fb7c4SAndroid Build Coastguard Worker     if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
340*f81fb7c4SAndroid Build Coastguard Worker         return DLS_StartVoice(pVoiceMgr, pSynth, pVoice, voiceNum, regionIndex);
341*f81fb7c4SAndroid Build Coastguard Worker #endif
342*f81fb7c4SAndroid Build Coastguard Worker 
343*f81fb7c4SAndroid Build Coastguard Worker     pRegion = &(pSynth->pEAS->pWTRegions[regionIndex]);
344*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->artIndex = pRegion->artIndex;
345*f81fb7c4SAndroid Build Coastguard Worker 
346*f81fb7c4SAndroid Build Coastguard Worker #ifdef _DEBUG_SYNTH
347*f81fb7c4SAndroid Build Coastguard Worker     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ }
348*f81fb7c4SAndroid Build Coastguard Worker #endif
349*f81fb7c4SAndroid Build Coastguard Worker 
350*f81fb7c4SAndroid Build Coastguard Worker     pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex];
351*f81fb7c4SAndroid Build Coastguard Worker 
352*f81fb7c4SAndroid Build Coastguard Worker     /* MIDI note on puts this voice into attack state */
353*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1State = eEnvelopeStateAttack;
354*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1Value = 0;
355*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1Increment = pArt->eg1.attackTime;
356*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg2State = eEnvelopeStateAttack;
357*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg2Value = 0;
358*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg2Increment = pArt->eg2.attackTime;
359*f81fb7c4SAndroid Build Coastguard Worker 
360*f81fb7c4SAndroid Build Coastguard Worker     /* init the LFO */
361*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->modLFO.lfoValue = 0;
362*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->modLFO.lfoPhase = -pArt->lfoDelay;
363*f81fb7c4SAndroid Build Coastguard Worker 
364*f81fb7c4SAndroid Build Coastguard Worker     pVoice->gain = 0;
365*f81fb7c4SAndroid Build Coastguard Worker 
366*f81fb7c4SAndroid Build Coastguard Worker #if (NUM_OUTPUT_CHANNELS == 2)
367*f81fb7c4SAndroid Build Coastguard Worker     /*
368*f81fb7c4SAndroid Build Coastguard Worker     Get the Midi CC10 pan value for this voice's channel
369*f81fb7c4SAndroid Build Coastguard Worker     convert the pan value to an "angle" representation suitable for
370*f81fb7c4SAndroid Build Coastguard Worker     our sin, cos calculator. This representation is NOT necessarily the same
371*f81fb7c4SAndroid Build Coastguard Worker     as the transform in the GM manuals because of our sin, cos calculator.
372*f81fb7c4SAndroid Build Coastguard Worker     "angle" = (CC10 - 64)/128
373*f81fb7c4SAndroid Build Coastguard Worker     */
374*f81fb7c4SAndroid Build Coastguard Worker     pan = (EAS_INT) pSynth->channels[pVoice->channel & 15].pan - 64;
375*f81fb7c4SAndroid Build Coastguard Worker     pan += pArt->pan;
376*f81fb7c4SAndroid Build Coastguard Worker     EAS_CalcPanControl(pan, &pWTVoice->gainLeft, &pWTVoice->gainRight);
377*f81fb7c4SAndroid Build Coastguard Worker #endif
378*f81fb7c4SAndroid Build Coastguard Worker 
379*f81fb7c4SAndroid Build Coastguard Worker #ifdef _FILTER_ENABLED
380*f81fb7c4SAndroid Build Coastguard Worker     /* clear out the filter states */
381*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->filter.z1 = 0;
382*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->filter.z2 = 0;
383*f81fb7c4SAndroid Build Coastguard Worker #endif
384*f81fb7c4SAndroid Build Coastguard Worker 
385*f81fb7c4SAndroid Build Coastguard Worker     /* if this wave is to be generated using noise generator */
386*f81fb7c4SAndroid Build Coastguard Worker     if (pRegion->region.keyGroupAndFlags & REGION_FLAG_USE_WAVE_GENERATOR)
387*f81fb7c4SAndroid Build Coastguard Worker     {
388*f81fb7c4SAndroid Build Coastguard Worker         pWTVoice->phaseAccum = 4574296;
389*f81fb7c4SAndroid Build Coastguard Worker         pWTVoice->loopStart = WT_NOISE_GENERATOR;
390*f81fb7c4SAndroid Build Coastguard Worker         pWTVoice->loopEnd = 4574295;
391*f81fb7c4SAndroid Build Coastguard Worker     }
392*f81fb7c4SAndroid Build Coastguard Worker 
393*f81fb7c4SAndroid Build Coastguard Worker     /* normal sample */
394*f81fb7c4SAndroid Build Coastguard Worker     else
395*f81fb7c4SAndroid Build Coastguard Worker     {
396*f81fb7c4SAndroid Build Coastguard Worker 
397*f81fb7c4SAndroid Build Coastguard Worker #ifdef EAS_SPLIT_WT_SYNTH
398*f81fb7c4SAndroid Build Coastguard Worker         if (voiceNum < NUM_PRIMARY_VOICES)
399*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex];
400*f81fb7c4SAndroid Build Coastguard Worker         else
401*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->phaseAccum = pSynth->pEAS->pSampleOffsets[pRegion->waveIndex];
402*f81fb7c4SAndroid Build Coastguard Worker #else
403*f81fb7c4SAndroid Build Coastguard Worker         pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex];
404*f81fb7c4SAndroid Build Coastguard Worker #endif
405*f81fb7c4SAndroid Build Coastguard Worker 
406*f81fb7c4SAndroid Build Coastguard Worker         if (pRegion->region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED)
407*f81fb7c4SAndroid Build Coastguard Worker         {
408*f81fb7c4SAndroid Build Coastguard Worker #if defined (_8_BIT_SAMPLES)
409*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->loopStart = pWTVoice->phaseAccum + pRegion->loopStart;
410*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->loopEnd = pWTVoice->phaseAccum + pRegion->loopEnd - 1;
411*f81fb7c4SAndroid Build Coastguard Worker #else //_16_BIT_SAMPLES
412*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->loopStart = pWTVoice->phaseAccum + (pRegion->loopStart<<1);
413*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->loopEnd = pWTVoice->phaseAccum + (pRegion->loopEnd<<1) - 2;
414*f81fb7c4SAndroid Build Coastguard Worker #endif
415*f81fb7c4SAndroid Build Coastguard Worker         }
416*f81fb7c4SAndroid Build Coastguard Worker         else {
417*f81fb7c4SAndroid Build Coastguard Worker #if defined (_8_BIT_SAMPLES)
418*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 1;
419*f81fb7c4SAndroid Build Coastguard Worker #else //_16_BIT_SAMPLES
420*f81fb7c4SAndroid Build Coastguard Worker             pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 2;
421*f81fb7c4SAndroid Build Coastguard Worker #endif
422*f81fb7c4SAndroid Build Coastguard Worker         }
423*f81fb7c4SAndroid Build Coastguard Worker     }
424*f81fb7c4SAndroid Build Coastguard Worker 
425*f81fb7c4SAndroid Build Coastguard Worker #ifdef EAS_SPLIT_WT_SYNTH
426*f81fb7c4SAndroid Build Coastguard Worker     /* configure off-chip voices */
427*f81fb7c4SAndroid Build Coastguard Worker     if (voiceNum >= NUM_PRIMARY_VOICES)
428*f81fb7c4SAndroid Build Coastguard Worker     {
429*f81fb7c4SAndroid Build Coastguard Worker         wtConfig.phaseAccum = pWTVoice->phaseAccum;
430*f81fb7c4SAndroid Build Coastguard Worker         wtConfig.loopStart = pWTVoice->loopStart;
431*f81fb7c4SAndroid Build Coastguard Worker         wtConfig.loopEnd = pWTVoice->loopEnd;
432*f81fb7c4SAndroid Build Coastguard Worker         wtConfig.gain = pVoice->gain;
433*f81fb7c4SAndroid Build Coastguard Worker 
434*f81fb7c4SAndroid Build Coastguard Worker #if (NUM_OUTPUT_CHANNELS == 2)
435*f81fb7c4SAndroid Build Coastguard Worker         wtConfig.gainLeft = pWTVoice->gainLeft;
436*f81fb7c4SAndroid Build Coastguard Worker         wtConfig.gainRight = pWTVoice->gainRight;
437*f81fb7c4SAndroid Build Coastguard Worker #endif
438*f81fb7c4SAndroid Build Coastguard Worker 
439*f81fb7c4SAndroid Build Coastguard Worker         WTE_ConfigVoice(voiceNum - NUM_PRIMARY_VOICES, &wtConfig, pVoiceMgr->pFrameBuffer);
440*f81fb7c4SAndroid Build Coastguard Worker     }
441*f81fb7c4SAndroid Build Coastguard Worker #endif
442*f81fb7c4SAndroid Build Coastguard Worker 
443*f81fb7c4SAndroid Build Coastguard Worker     return EAS_SUCCESS;
444*f81fb7c4SAndroid Build Coastguard Worker }
445*f81fb7c4SAndroid Build Coastguard Worker 
446*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
447*f81fb7c4SAndroid Build Coastguard Worker  * WT_CheckSampleEnd
448*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
449*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
450*f81fb7c4SAndroid Build Coastguard Worker  * Check for end of sample and calculate number of samples to synthesize
451*f81fb7c4SAndroid Build Coastguard Worker  *
452*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
453*f81fb7c4SAndroid Build Coastguard Worker  *
454*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
455*f81fb7c4SAndroid Build Coastguard Worker  *
456*f81fb7c4SAndroid Build Coastguard Worker  * Notes:
457*f81fb7c4SAndroid Build Coastguard Worker  *
458*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
459*f81fb7c4SAndroid Build Coastguard Worker */
WT_CheckSampleEnd(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame,EAS_BOOL update)460*f81fb7c4SAndroid Build Coastguard Worker EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update)
461*f81fb7c4SAndroid Build Coastguard Worker {
462*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 endPhaseAccum;
463*f81fb7c4SAndroid Build Coastguard Worker     EAS_U32 endPhaseFrac;
464*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 numSamples;
465*f81fb7c4SAndroid Build Coastguard Worker     EAS_BOOL done = EAS_FALSE;
466*f81fb7c4SAndroid Build Coastguard Worker 
467*f81fb7c4SAndroid Build Coastguard Worker     /* check to see if we hit the end of the waveform this time */
468*f81fb7c4SAndroid Build Coastguard Worker     /*lint -e{703} use shift for performance */
469*f81fb7c4SAndroid Build Coastguard Worker     endPhaseFrac = pWTVoice->phaseFrac + (pWTIntFrame->frame.phaseIncrement << SYNTH_UPDATE_PERIOD_IN_BITS);
470*f81fb7c4SAndroid Build Coastguard Worker #if defined (_8_BIT_SAMPLES)
471*f81fb7c4SAndroid Build Coastguard Worker     endPhaseAccum = pWTVoice->phaseAccum + GET_PHASE_INT_PART(endPhaseFrac);
472*f81fb7c4SAndroid Build Coastguard Worker #else //_16_BIT_SAMPLES
473*f81fb7c4SAndroid Build Coastguard Worker     // Multiply by 2 for 16 bit processing module implementation
474*f81fb7c4SAndroid Build Coastguard Worker     endPhaseAccum = pWTVoice->phaseAccum + (EAS_U32)(endPhaseFrac >> 14);
475*f81fb7c4SAndroid Build Coastguard Worker #endif
476*f81fb7c4SAndroid Build Coastguard Worker     if (endPhaseAccum >= pWTVoice->loopEnd)
477*f81fb7c4SAndroid Build Coastguard Worker     {
478*f81fb7c4SAndroid Build Coastguard Worker         /* calculate how far current ptr is from end */
479*f81fb7c4SAndroid Build Coastguard Worker         numSamples = (EAS_I32) (pWTVoice->loopEnd - pWTVoice->phaseAccum);
480*f81fb7c4SAndroid Build Coastguard Worker #if defined (_16_BIT_SAMPLES)
481*f81fb7c4SAndroid Build Coastguard Worker         numSamples >>= 1;        // Divide by 2 for 16 bit processing module implementation
482*f81fb7c4SAndroid Build Coastguard Worker #endif
483*f81fb7c4SAndroid Build Coastguard Worker         /* now account for the fractional portion */
484*f81fb7c4SAndroid Build Coastguard Worker         /*lint -e{703} use shift for performance */
485*f81fb7c4SAndroid Build Coastguard Worker         numSamples = (numSamples << NUM_PHASE_FRAC_BITS) - (EAS_I32) pWTVoice->phaseFrac;
486*f81fb7c4SAndroid Build Coastguard Worker         if (pWTIntFrame->frame.phaseIncrement) {
487*f81fb7c4SAndroid Build Coastguard Worker             EAS_I32 oldMethod = 1 + (numSamples / pWTIntFrame->frame.phaseIncrement);
488*f81fb7c4SAndroid Build Coastguard Worker             pWTIntFrame->numSamples =
489*f81fb7c4SAndroid Build Coastguard Worker                 (numSamples + pWTIntFrame->frame.phaseIncrement - 1) / pWTIntFrame->frame.phaseIncrement;
490*f81fb7c4SAndroid Build Coastguard Worker             if (oldMethod != pWTIntFrame->numSamples) {
491*f81fb7c4SAndroid Build Coastguard Worker                 ALOGE("b/317780080 old %ld new %ld", oldMethod, pWTIntFrame->numSamples);
492*f81fb7c4SAndroid Build Coastguard Worker             }
493*f81fb7c4SAndroid Build Coastguard Worker         } else {
494*f81fb7c4SAndroid Build Coastguard Worker             pWTIntFrame->numSamples = numSamples;
495*f81fb7c4SAndroid Build Coastguard Worker         }
496*f81fb7c4SAndroid Build Coastguard Worker         if (pWTIntFrame->numSamples < 0) {
497*f81fb7c4SAndroid Build Coastguard Worker             ALOGE("b/26366256");
498*f81fb7c4SAndroid Build Coastguard Worker             android_errorWriteLog(0x534e4554, "26366256");
499*f81fb7c4SAndroid Build Coastguard Worker             pWTIntFrame->numSamples = 0;
500*f81fb7c4SAndroid Build Coastguard Worker         } else if (pWTIntFrame->numSamples > BUFFER_SIZE_IN_MONO_SAMPLES) {
501*f81fb7c4SAndroid Build Coastguard Worker             ALOGE("b/317780080 clip numSamples %ld -> %d",
502*f81fb7c4SAndroid Build Coastguard Worker                   pWTIntFrame->numSamples, BUFFER_SIZE_IN_MONO_SAMPLES);
503*f81fb7c4SAndroid Build Coastguard Worker             android_errorWriteLog(0x534e4554, "317780080");
504*f81fb7c4SAndroid Build Coastguard Worker             pWTIntFrame->numSamples = BUFFER_SIZE_IN_MONO_SAMPLES;
505*f81fb7c4SAndroid Build Coastguard Worker         }
506*f81fb7c4SAndroid Build Coastguard Worker 
507*f81fb7c4SAndroid Build Coastguard Worker         /* sound will be done this frame */
508*f81fb7c4SAndroid Build Coastguard Worker         done = EAS_TRUE;
509*f81fb7c4SAndroid Build Coastguard Worker     }
510*f81fb7c4SAndroid Build Coastguard Worker 
511*f81fb7c4SAndroid Build Coastguard Worker     /* update data for off-chip synth */
512*f81fb7c4SAndroid Build Coastguard Worker     if (update)
513*f81fb7c4SAndroid Build Coastguard Worker     {
514*f81fb7c4SAndroid Build Coastguard Worker         pWTVoice->phaseFrac = endPhaseFrac;
515*f81fb7c4SAndroid Build Coastguard Worker         pWTVoice->phaseAccum = endPhaseAccum;
516*f81fb7c4SAndroid Build Coastguard Worker     }
517*f81fb7c4SAndroid Build Coastguard Worker 
518*f81fb7c4SAndroid Build Coastguard Worker     return done;
519*f81fb7c4SAndroid Build Coastguard Worker }
520*f81fb7c4SAndroid Build Coastguard Worker 
521*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
522*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateVoice()
523*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
524*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
525*f81fb7c4SAndroid Build Coastguard Worker  * Synthesize a block of samples for the given voice.
526*f81fb7c4SAndroid Build Coastguard Worker  * Use linear interpolation.
527*f81fb7c4SAndroid Build Coastguard Worker  *
528*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
529*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
530*f81fb7c4SAndroid Build Coastguard Worker  *
531*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
532*f81fb7c4SAndroid Build Coastguard Worker  * number of samples actually written to buffer
533*f81fb7c4SAndroid Build Coastguard Worker  *
534*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
535*f81fb7c4SAndroid Build Coastguard Worker  * - samples are added to the presently free buffer
536*f81fb7c4SAndroid Build Coastguard Worker  *
537*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
538*f81fb7c4SAndroid Build Coastguard Worker */
WT_UpdateVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum,EAS_I32 * pMixBuffer,EAS_I32 numSamples)539*f81fb7c4SAndroid Build Coastguard Worker static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32  numSamples)
540*f81fb7c4SAndroid Build Coastguard Worker {
541*f81fb7c4SAndroid Build Coastguard Worker     S_WT_VOICE *pWTVoice;
542*f81fb7c4SAndroid Build Coastguard Worker     S_WT_INT_FRAME intFrame;
543*f81fb7c4SAndroid Build Coastguard Worker     S_SYNTH_CHANNEL *pChannel;
544*f81fb7c4SAndroid Build Coastguard Worker     const S_WT_REGION *pWTRegion;
545*f81fb7c4SAndroid Build Coastguard Worker     const S_ARTICULATION *pArt;
546*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 temp;
547*f81fb7c4SAndroid Build Coastguard Worker     EAS_BOOL done;
548*f81fb7c4SAndroid Build Coastguard Worker 
549*f81fb7c4SAndroid Build Coastguard Worker #ifdef DLS_SYNTHESIZER
550*f81fb7c4SAndroid Build Coastguard Worker     if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
551*f81fb7c4SAndroid Build Coastguard Worker         return DLS_UpdateVoice(pVoiceMgr, pSynth, pVoice, voiceNum, pMixBuffer, numSamples);
552*f81fb7c4SAndroid Build Coastguard Worker #endif
553*f81fb7c4SAndroid Build Coastguard Worker     /* establish pointers to critical data */
554*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
555*f81fb7c4SAndroid Build Coastguard Worker     pWTRegion = &pSynth->pEAS->pWTRegions[pVoice->regionIndex & REGION_INDEX_MASK];
556*f81fb7c4SAndroid Build Coastguard Worker     pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex];
557*f81fb7c4SAndroid Build Coastguard Worker     pChannel = &pSynth->channels[pVoice->channel & 15];
558*f81fb7c4SAndroid Build Coastguard Worker     intFrame.prevGain = pVoice->gain;
559*f81fb7c4SAndroid Build Coastguard Worker 
560*f81fb7c4SAndroid Build Coastguard Worker     /* update the envelopes */
561*f81fb7c4SAndroid Build Coastguard Worker     WT_UpdateEG1(pWTVoice, &pArt->eg1);
562*f81fb7c4SAndroid Build Coastguard Worker     WT_UpdateEG2(pWTVoice, &pArt->eg2);
563*f81fb7c4SAndroid Build Coastguard Worker 
564*f81fb7c4SAndroid Build Coastguard Worker     /* update the LFO */
565*f81fb7c4SAndroid Build Coastguard Worker     WT_UpdateLFO(&pWTVoice->modLFO, pArt->lfoFreq);
566*f81fb7c4SAndroid Build Coastguard Worker 
567*f81fb7c4SAndroid Build Coastguard Worker #ifdef _FILTER_ENABLED
568*f81fb7c4SAndroid Build Coastguard Worker     /* calculate filter if library uses filter */
569*f81fb7c4SAndroid Build Coastguard Worker     if (pSynth->pEAS->libAttr & LIB_FORMAT_FILTER_ENABLED)
570*f81fb7c4SAndroid Build Coastguard Worker         WT_UpdateFilter(pWTVoice, &intFrame, pArt);
571*f81fb7c4SAndroid Build Coastguard Worker     else
572*f81fb7c4SAndroid Build Coastguard Worker         intFrame.frame.k = 0;
573*f81fb7c4SAndroid Build Coastguard Worker #endif
574*f81fb7c4SAndroid Build Coastguard Worker 
575*f81fb7c4SAndroid Build Coastguard Worker     /* update the gain */
576*f81fb7c4SAndroid Build Coastguard Worker     intFrame.frame.gainTarget = WT_UpdateGain(pVoice, pWTVoice, pArt, pChannel, pWTRegion->gain);
577*f81fb7c4SAndroid Build Coastguard Worker 
578*f81fb7c4SAndroid Build Coastguard Worker     /* calculate base pitch*/
579*f81fb7c4SAndroid Build Coastguard Worker     temp = pChannel->staticPitch + pWTRegion->tuning;
580*f81fb7c4SAndroid Build Coastguard Worker 
581*f81fb7c4SAndroid Build Coastguard Worker     /* include global transpose */
582*f81fb7c4SAndroid Build Coastguard Worker     if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)
583*f81fb7c4SAndroid Build Coastguard Worker         temp += pVoice->note * 100;
584*f81fb7c4SAndroid Build Coastguard Worker     else
585*f81fb7c4SAndroid Build Coastguard Worker         temp += (pVoice->note + pSynth->globalTranspose) * 100;
586*f81fb7c4SAndroid Build Coastguard Worker     intFrame.frame.phaseIncrement = WT_UpdatePhaseInc(pWTVoice, pArt, pChannel, temp);
587*f81fb7c4SAndroid Build Coastguard Worker     if (pWTVoice->loopStart == WT_NOISE_GENERATOR) {
588*f81fb7c4SAndroid Build Coastguard Worker         temp = 0;
589*f81fb7c4SAndroid Build Coastguard Worker     } else {
590*f81fb7c4SAndroid Build Coastguard Worker         temp = pWTVoice->loopEnd - pWTVoice->loopStart;
591*f81fb7c4SAndroid Build Coastguard Worker     }
592*f81fb7c4SAndroid Build Coastguard Worker #ifdef _16_BIT_SAMPLES
593*f81fb7c4SAndroid Build Coastguard Worker     temp >>= 1;
594*f81fb7c4SAndroid Build Coastguard Worker #endif
595*f81fb7c4SAndroid Build Coastguard Worker     if (temp != 0) {
596*f81fb7c4SAndroid Build Coastguard Worker         temp = temp << NUM_PHASE_FRAC_BITS;
597*f81fb7c4SAndroid Build Coastguard Worker         if (intFrame.frame.phaseIncrement > temp) {
598*f81fb7c4SAndroid Build Coastguard Worker             ALOGW("%p phaseIncrement=%d", pWTVoice, (int)intFrame.frame.phaseIncrement);
599*f81fb7c4SAndroid Build Coastguard Worker             intFrame.frame.phaseIncrement %= temp;
600*f81fb7c4SAndroid Build Coastguard Worker         }
601*f81fb7c4SAndroid Build Coastguard Worker     }
602*f81fb7c4SAndroid Build Coastguard Worker 
603*f81fb7c4SAndroid Build Coastguard Worker     /* call into engine to generate samples */
604*f81fb7c4SAndroid Build Coastguard Worker     intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer;
605*f81fb7c4SAndroid Build Coastguard Worker     intFrame.pMixBuffer = pMixBuffer;
606*f81fb7c4SAndroid Build Coastguard Worker     intFrame.numSamples = numSamples;
607*f81fb7c4SAndroid Build Coastguard Worker 
608*f81fb7c4SAndroid Build Coastguard Worker     /* check for end of sample */
609*f81fb7c4SAndroid Build Coastguard Worker     if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd))
610*f81fb7c4SAndroid Build Coastguard Worker         done = WT_CheckSampleEnd(pWTVoice, &intFrame, (EAS_BOOL) (voiceNum >= NUM_PRIMARY_VOICES));
611*f81fb7c4SAndroid Build Coastguard Worker     else
612*f81fb7c4SAndroid Build Coastguard Worker         done = EAS_FALSE;
613*f81fb7c4SAndroid Build Coastguard Worker 
614*f81fb7c4SAndroid Build Coastguard Worker     if (intFrame.numSamples < 0) intFrame.numSamples = 0;
615*f81fb7c4SAndroid Build Coastguard Worker 
616*f81fb7c4SAndroid Build Coastguard Worker     if (intFrame.numSamples > BUFFER_SIZE_IN_MONO_SAMPLES)
617*f81fb7c4SAndroid Build Coastguard Worker         intFrame.numSamples = BUFFER_SIZE_IN_MONO_SAMPLES;
618*f81fb7c4SAndroid Build Coastguard Worker 
619*f81fb7c4SAndroid Build Coastguard Worker #ifdef EAS_SPLIT_WT_SYNTH
620*f81fb7c4SAndroid Build Coastguard Worker     if (voiceNum < NUM_PRIMARY_VOICES)
621*f81fb7c4SAndroid Build Coastguard Worker     {
622*f81fb7c4SAndroid Build Coastguard Worker #ifndef _SPLIT_WT_TEST_HARNESS
623*f81fb7c4SAndroid Build Coastguard Worker         WT_ProcessVoice(pWTVoice, &intFrame);
624*f81fb7c4SAndroid Build Coastguard Worker #endif
625*f81fb7c4SAndroid Build Coastguard Worker     }
626*f81fb7c4SAndroid Build Coastguard Worker     else
627*f81fb7c4SAndroid Build Coastguard Worker         WTE_ProcessVoice(voiceNum - NUM_PRIMARY_VOICES, &intFrame.frame, pVoiceMgr->pFrameBuffer);
628*f81fb7c4SAndroid Build Coastguard Worker #else
629*f81fb7c4SAndroid Build Coastguard Worker     WT_ProcessVoice(pWTVoice, &intFrame);
630*f81fb7c4SAndroid Build Coastguard Worker #endif
631*f81fb7c4SAndroid Build Coastguard Worker 
632*f81fb7c4SAndroid Build Coastguard Worker     /* clear flag */
633*f81fb7c4SAndroid Build Coastguard Worker     pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
634*f81fb7c4SAndroid Build Coastguard Worker 
635*f81fb7c4SAndroid Build Coastguard Worker     /* if voice has finished, set flag for voice manager */
636*f81fb7c4SAndroid Build Coastguard Worker     if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted))
637*f81fb7c4SAndroid Build Coastguard Worker         done = EAS_TRUE;
638*f81fb7c4SAndroid Build Coastguard Worker 
639*f81fb7c4SAndroid Build Coastguard Worker     /* if the update interval has elapsed, then force the current gain to the next
640*f81fb7c4SAndroid Build Coastguard Worker      * gain since we never actually reach the next gain when ramping -- we just get
641*f81fb7c4SAndroid Build Coastguard Worker      * very close to the target gain.
642*f81fb7c4SAndroid Build Coastguard Worker      */
643*f81fb7c4SAndroid Build Coastguard Worker     pVoice->gain = (EAS_I16) intFrame.frame.gainTarget;
644*f81fb7c4SAndroid Build Coastguard Worker 
645*f81fb7c4SAndroid Build Coastguard Worker     return done;
646*f81fb7c4SAndroid Build Coastguard Worker }
647*f81fb7c4SAndroid Build Coastguard Worker 
648*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
649*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdatePhaseInc()
650*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
651*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
652*f81fb7c4SAndroid Build Coastguard Worker  * Calculate the phase increment
653*f81fb7c4SAndroid Build Coastguard Worker  *
654*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
655*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - pointer to the voice being updated
656*f81fb7c4SAndroid Build Coastguard Worker  * psRegion - pointer to the region
657*f81fb7c4SAndroid Build Coastguard Worker  * psArticulation - pointer to the articulation
658*f81fb7c4SAndroid Build Coastguard Worker  * nChannelPitchForThisVoice - the portion of the pitch that is fixed for this
659*f81fb7c4SAndroid Build Coastguard Worker  *                  voice during the duration of this synthesis
660*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
661*f81fb7c4SAndroid Build Coastguard Worker  *
662*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
663*f81fb7c4SAndroid Build Coastguard Worker  *
664*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
665*f81fb7c4SAndroid Build Coastguard Worker  * set the phase increment for this voice
666*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
667*f81fb7c4SAndroid Build Coastguard Worker */
WT_UpdatePhaseInc(S_WT_VOICE * pWTVoice,const S_ARTICULATION * pArt,S_SYNTH_CHANNEL * pChannel,EAS_I32 pitchCents)668*f81fb7c4SAndroid Build Coastguard Worker static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents)
669*f81fb7c4SAndroid Build Coastguard Worker {
670*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 temp;
671*f81fb7c4SAndroid Build Coastguard Worker 
672*f81fb7c4SAndroid Build Coastguard Worker     /*pitchCents due to CC1 = LFO * (CC1 / 128) * DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS */
673*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_EG1_EG1(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS,
674*f81fb7c4SAndroid Build Coastguard Worker         ((pChannel->modWheel) << (NUM_EG1_FRAC_BITS -7)));
675*f81fb7c4SAndroid Build Coastguard Worker 
676*f81fb7c4SAndroid Build Coastguard Worker     /* pitchCents due to channel pressure = LFO * (channel pressure / 128) * DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS */
677*f81fb7c4SAndroid Build Coastguard Worker     temp += MULT_EG1_EG1(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS,
678*f81fb7c4SAndroid Build Coastguard Worker          ((pChannel->channelPressure) << (NUM_EG1_FRAC_BITS -7)));
679*f81fb7c4SAndroid Build Coastguard Worker 
680*f81fb7c4SAndroid Build Coastguard Worker     /* now multiply the (channel pressure + CC1) pitch values by the LFO value */
681*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, temp);
682*f81fb7c4SAndroid Build Coastguard Worker 
683*f81fb7c4SAndroid Build Coastguard Worker     /*
684*f81fb7c4SAndroid Build Coastguard Worker     add in the LFO pitch due to
685*f81fb7c4SAndroid Build Coastguard Worker     channel pressure and CC1 along with
686*f81fb7c4SAndroid Build Coastguard Worker     the LFO pitch, the EG2 pitch, and the
687*f81fb7c4SAndroid Build Coastguard Worker     "static" pitch for this voice on this channel
688*f81fb7c4SAndroid Build Coastguard Worker     */
689*f81fb7c4SAndroid Build Coastguard Worker     temp += pitchCents +
690*f81fb7c4SAndroid Build Coastguard Worker         (MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToPitch)) +
691*f81fb7c4SAndroid Build Coastguard Worker         (MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToPitch));
692*f81fb7c4SAndroid Build Coastguard Worker 
693*f81fb7c4SAndroid Build Coastguard Worker     /* convert from cents to linear phase increment */
694*f81fb7c4SAndroid Build Coastguard Worker     return EAS_Calculate2toX(temp);
695*f81fb7c4SAndroid Build Coastguard Worker }
696*f81fb7c4SAndroid Build Coastguard Worker 
697*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
698*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateChannel()
699*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
700*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
701*f81fb7c4SAndroid Build Coastguard Worker  * Calculate and assign static channel parameters
702*f81fb7c4SAndroid Build Coastguard Worker  * These values only need to be updated if one of the controller values
703*f81fb7c4SAndroid Build Coastguard Worker  * for this channel changes
704*f81fb7c4SAndroid Build Coastguard Worker  *
705*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
706*f81fb7c4SAndroid Build Coastguard Worker  * nChannel - channel to update
707*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
708*f81fb7c4SAndroid Build Coastguard Worker  *
709*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
710*f81fb7c4SAndroid Build Coastguard Worker  *
711*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
712*f81fb7c4SAndroid Build Coastguard Worker  * - the given channel's static gain and static pitch are updated
713*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
714*f81fb7c4SAndroid Build Coastguard Worker */
715*f81fb7c4SAndroid Build Coastguard Worker /*lint -esym(715, pVoiceMgr) reserved for future use */
WT_UpdateChannel(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,EAS_U8 channel)716*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel)
717*f81fb7c4SAndroid Build Coastguard Worker {
718*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 staticGain;
719*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 pitchBend;
720*f81fb7c4SAndroid Build Coastguard Worker     S_SYNTH_CHANNEL *pChannel;
721*f81fb7c4SAndroid Build Coastguard Worker 
722*f81fb7c4SAndroid Build Coastguard Worker     pChannel = &pSynth->channels[channel];
723*f81fb7c4SAndroid Build Coastguard Worker 
724*f81fb7c4SAndroid Build Coastguard Worker     /*
725*f81fb7c4SAndroid Build Coastguard Worker     nChannelGain = (CC7 * CC11)^2  * master volume
726*f81fb7c4SAndroid Build Coastguard Worker     where CC7 == 100 by default, CC11 == 127, master volume == 32767
727*f81fb7c4SAndroid Build Coastguard Worker     */
728*f81fb7c4SAndroid Build Coastguard Worker     staticGain = MULT_EG1_EG1((pChannel->volume) << (NUM_EG1_FRAC_BITS - 7),
729*f81fb7c4SAndroid Build Coastguard Worker         (pChannel->expression) << (NUM_EG1_FRAC_BITS - 7));
730*f81fb7c4SAndroid Build Coastguard Worker 
731*f81fb7c4SAndroid Build Coastguard Worker     /* staticGain has to be squared */
732*f81fb7c4SAndroid Build Coastguard Worker     staticGain = MULT_EG1_EG1(staticGain, staticGain);
733*f81fb7c4SAndroid Build Coastguard Worker 
734*f81fb7c4SAndroid Build Coastguard Worker     pChannel->staticGain = (EAS_I16) MULT_EG1_EG1(staticGain, pSynth->masterVolume);
735*f81fb7c4SAndroid Build Coastguard Worker 
736*f81fb7c4SAndroid Build Coastguard Worker     /*
737*f81fb7c4SAndroid Build Coastguard Worker     calculate pitch bend: RPN0 * ((2*pitch wheel)/16384  -1)
738*f81fb7c4SAndroid Build Coastguard Worker     However, if we use the EG1 macros, remember that EG1 has a full
739*f81fb7c4SAndroid Build Coastguard Worker     scale value of 32768 (instead of 16384). So instead of multiplying
740*f81fb7c4SAndroid Build Coastguard Worker     by 2, multiply by 4 (left shift by 2), and subtract by 32768 instead
741*f81fb7c4SAndroid Build Coastguard Worker     of 16384. This utilizes the fact that the EG1 macro places a binary
742*f81fb7c4SAndroid Build Coastguard Worker     point 15 places to the left instead of 14 places.
743*f81fb7c4SAndroid Build Coastguard Worker     */
744*f81fb7c4SAndroid Build Coastguard Worker     /*lint -e{703} <avoid multiply for performance>*/
745*f81fb7c4SAndroid Build Coastguard Worker     pitchBend =
746*f81fb7c4SAndroid Build Coastguard Worker         (((EAS_I32)(pChannel->pitchBend) << 2)
747*f81fb7c4SAndroid Build Coastguard Worker         - 32768);
748*f81fb7c4SAndroid Build Coastguard Worker 
749*f81fb7c4SAndroid Build Coastguard Worker     pChannel->staticPitch =
750*f81fb7c4SAndroid Build Coastguard Worker         MULT_EG1_EG1(pitchBend, pChannel->pitchBendSensitivity);
751*f81fb7c4SAndroid Build Coastguard Worker 
752*f81fb7c4SAndroid Build Coastguard Worker     /* if this is not a drum channel, then add in the per-channel tuning */
753*f81fb7c4SAndroid Build Coastguard Worker     if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL))
754*f81fb7c4SAndroid Build Coastguard Worker         pChannel->staticPitch += pChannel->finePitch + (pChannel->coarsePitch * 100);
755*f81fb7c4SAndroid Build Coastguard Worker 
756*f81fb7c4SAndroid Build Coastguard Worker     /* clear update flag */
757*f81fb7c4SAndroid Build Coastguard Worker     pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS;
758*f81fb7c4SAndroid Build Coastguard Worker     return;
759*f81fb7c4SAndroid Build Coastguard Worker }
760*f81fb7c4SAndroid Build Coastguard Worker 
761*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
762*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateGain()
763*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
764*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
765*f81fb7c4SAndroid Build Coastguard Worker  * Calculate and assign static voice parameters as part of WT_UpdateVoice()
766*f81fb7c4SAndroid Build Coastguard Worker  *
767*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
768*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - ptr to the synth voice that we want to synthesize
769*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
770*f81fb7c4SAndroid Build Coastguard Worker  *
771*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
772*f81fb7c4SAndroid Build Coastguard Worker  *
773*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
774*f81fb7c4SAndroid Build Coastguard Worker  * - various voice parameters are calculated and assigned
775*f81fb7c4SAndroid Build Coastguard Worker  *
776*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
777*f81fb7c4SAndroid Build Coastguard Worker */
WT_UpdateGain(S_SYNTH_VOICE * pVoice,S_WT_VOICE * pWTVoice,const S_ARTICULATION * pArt,S_SYNTH_CHANNEL * pChannel,EAS_I32 gain)778*f81fb7c4SAndroid Build Coastguard Worker static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain)
779*f81fb7c4SAndroid Build Coastguard Worker {
780*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 lfoGain;
781*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 temp;
782*f81fb7c4SAndroid Build Coastguard Worker 
783*f81fb7c4SAndroid Build Coastguard Worker     /*
784*f81fb7c4SAndroid Build Coastguard Worker     If this voice was stolen, then the velocity is actually
785*f81fb7c4SAndroid Build Coastguard Worker     for the new note, not the note that we are currently ramping down.
786*f81fb7c4SAndroid Build Coastguard Worker     So we really shouldn't use this velocity. However, that would require
787*f81fb7c4SAndroid Build Coastguard Worker     more memory to store the velocity value, and the improvement may
788*f81fb7c4SAndroid Build Coastguard Worker     not be sufficient to warrant the added memory.
789*f81fb7c4SAndroid Build Coastguard Worker     */
790*f81fb7c4SAndroid Build Coastguard Worker     /* velocity is fixed at note start for a given voice and must be squared */
791*f81fb7c4SAndroid Build Coastguard Worker     temp = (pVoice->velocity) << (NUM_EG1_FRAC_BITS - 7);
792*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_EG1_EG1(temp, temp);
793*f81fb7c4SAndroid Build Coastguard Worker 
794*f81fb7c4SAndroid Build Coastguard Worker     /* region gain is fixed as part of the articulation */
795*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_EG1_EG1(temp, gain);
796*f81fb7c4SAndroid Build Coastguard Worker 
797*f81fb7c4SAndroid Build Coastguard Worker     /* include the channel gain */
798*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_EG1_EG1(temp, pChannel->staticGain);
799*f81fb7c4SAndroid Build Coastguard Worker 
800*f81fb7c4SAndroid Build Coastguard Worker     /* calculate LFO gain using an approximation for 10^x */
801*f81fb7c4SAndroid Build Coastguard Worker     lfoGain = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToGain);
802*f81fb7c4SAndroid Build Coastguard Worker     lfoGain = MULT_EG1_EG1(lfoGain, LFO_GAIN_TO_CENTS);
803*f81fb7c4SAndroid Build Coastguard Worker 
804*f81fb7c4SAndroid Build Coastguard Worker     /* convert from a dB-like value to linear gain */
805*f81fb7c4SAndroid Build Coastguard Worker     lfoGain = EAS_Calculate2toX(lfoGain);
806*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_EG1_EG1(temp, lfoGain);
807*f81fb7c4SAndroid Build Coastguard Worker 
808*f81fb7c4SAndroid Build Coastguard Worker     /* calculate the voice's gain */
809*f81fb7c4SAndroid Build Coastguard Worker     temp = (EAS_I16)MULT_EG1_EG1(temp, pWTVoice->eg1Value);
810*f81fb7c4SAndroid Build Coastguard Worker 
811*f81fb7c4SAndroid Build Coastguard Worker     return temp;
812*f81fb7c4SAndroid Build Coastguard Worker }
813*f81fb7c4SAndroid Build Coastguard Worker 
814*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
815*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateEG1()
816*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
817*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
818*f81fb7c4SAndroid Build Coastguard Worker  * Calculate the EG1 envelope for the given voice (but do not update any
819*f81fb7c4SAndroid Build Coastguard Worker  * state)
820*f81fb7c4SAndroid Build Coastguard Worker  *
821*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
822*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - ptr to the voice whose envelope we want to update
823*f81fb7c4SAndroid Build Coastguard Worker  * nVoice - this voice's number - used only for debug
824*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
825*f81fb7c4SAndroid Build Coastguard Worker  *
826*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
827*f81fb7c4SAndroid Build Coastguard Worker  * nValue - the envelope value
828*f81fb7c4SAndroid Build Coastguard Worker  *
829*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
830*f81fb7c4SAndroid Build Coastguard Worker  * - updates EG1 state value for the given voice
831*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
832*f81fb7c4SAndroid Build Coastguard Worker */
WT_UpdateEG1(S_WT_VOICE * pWTVoice,const S_ENVELOPE * pEnv)833*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv)
834*f81fb7c4SAndroid Build Coastguard Worker {
835*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 temp;
836*f81fb7c4SAndroid Build Coastguard Worker 
837*f81fb7c4SAndroid Build Coastguard Worker     switch (pWTVoice->eg1State)
838*f81fb7c4SAndroid Build Coastguard Worker     {
839*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateAttack:
840*f81fb7c4SAndroid Build Coastguard Worker             temp = pWTVoice->eg1Value + pWTVoice->eg1Increment;
841*f81fb7c4SAndroid Build Coastguard Worker 
842*f81fb7c4SAndroid Build Coastguard Worker             /* check if we have reached peak amplitude */
843*f81fb7c4SAndroid Build Coastguard Worker             if (temp >= SYNTH_FULL_SCALE_EG1_GAIN)
844*f81fb7c4SAndroid Build Coastguard Worker             {
845*f81fb7c4SAndroid Build Coastguard Worker                 /* limit the volume */
846*f81fb7c4SAndroid Build Coastguard Worker                 temp = SYNTH_FULL_SCALE_EG1_GAIN;
847*f81fb7c4SAndroid Build Coastguard Worker 
848*f81fb7c4SAndroid Build Coastguard Worker                 /* prepare to move to decay state */
849*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg1State = eEnvelopeStateDecay;
850*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg1Increment = pEnv->decayTime;
851*f81fb7c4SAndroid Build Coastguard Worker             }
852*f81fb7c4SAndroid Build Coastguard Worker 
853*f81fb7c4SAndroid Build Coastguard Worker             break;
854*f81fb7c4SAndroid Build Coastguard Worker 
855*f81fb7c4SAndroid Build Coastguard Worker         /* exponential decay */
856*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateDecay:
857*f81fb7c4SAndroid Build Coastguard Worker             temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment);
858*f81fb7c4SAndroid Build Coastguard Worker 
859*f81fb7c4SAndroid Build Coastguard Worker             /* check if we have reached sustain level */
860*f81fb7c4SAndroid Build Coastguard Worker             if (temp <= pEnv->sustainLevel)
861*f81fb7c4SAndroid Build Coastguard Worker             {
862*f81fb7c4SAndroid Build Coastguard Worker                 /* enforce the sustain level */
863*f81fb7c4SAndroid Build Coastguard Worker                 temp = pEnv->sustainLevel;
864*f81fb7c4SAndroid Build Coastguard Worker 
865*f81fb7c4SAndroid Build Coastguard Worker                 /* if sustain level is zero, skip sustain & release the voice */
866*f81fb7c4SAndroid Build Coastguard Worker                 if (temp > 0)
867*f81fb7c4SAndroid Build Coastguard Worker                     pWTVoice->eg1State = eEnvelopeStateSustain;
868*f81fb7c4SAndroid Build Coastguard Worker 
869*f81fb7c4SAndroid Build Coastguard Worker                 /* move to sustain state */
870*f81fb7c4SAndroid Build Coastguard Worker                 else
871*f81fb7c4SAndroid Build Coastguard Worker                     pWTVoice->eg1State = eEnvelopeStateMuted;
872*f81fb7c4SAndroid Build Coastguard Worker             }
873*f81fb7c4SAndroid Build Coastguard Worker 
874*f81fb7c4SAndroid Build Coastguard Worker             break;
875*f81fb7c4SAndroid Build Coastguard Worker 
876*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateSustain:
877*f81fb7c4SAndroid Build Coastguard Worker             return;
878*f81fb7c4SAndroid Build Coastguard Worker 
879*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateRelease:
880*f81fb7c4SAndroid Build Coastguard Worker             temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment);
881*f81fb7c4SAndroid Build Coastguard Worker 
882*f81fb7c4SAndroid Build Coastguard Worker             /* if we hit zero, this voice isn't contributing any audio */
883*f81fb7c4SAndroid Build Coastguard Worker             if (temp <= 0)
884*f81fb7c4SAndroid Build Coastguard Worker             {
885*f81fb7c4SAndroid Build Coastguard Worker                 temp = 0;
886*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg1State = eEnvelopeStateMuted;
887*f81fb7c4SAndroid Build Coastguard Worker             }
888*f81fb7c4SAndroid Build Coastguard Worker             break;
889*f81fb7c4SAndroid Build Coastguard Worker 
890*f81fb7c4SAndroid Build Coastguard Worker         /* voice is muted, set target to zero */
891*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateMuted:
892*f81fb7c4SAndroid Build Coastguard Worker             temp = 0;
893*f81fb7c4SAndroid Build Coastguard Worker             break;
894*f81fb7c4SAndroid Build Coastguard Worker 
895*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateInvalid:
896*f81fb7c4SAndroid Build Coastguard Worker         default:
897*f81fb7c4SAndroid Build Coastguard Worker             temp = 0;
898*f81fb7c4SAndroid Build Coastguard Worker #ifdef  _DEBUG_SYNTH
899*f81fb7c4SAndroid Build Coastguard Worker             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG1: error, %d is an unrecognized state\n",
900*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg1State); */ }
901*f81fb7c4SAndroid Build Coastguard Worker #endif
902*f81fb7c4SAndroid Build Coastguard Worker             break;
903*f81fb7c4SAndroid Build Coastguard Worker 
904*f81fb7c4SAndroid Build Coastguard Worker     }
905*f81fb7c4SAndroid Build Coastguard Worker 
906*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg1Value = (EAS_I16) temp;
907*f81fb7c4SAndroid Build Coastguard Worker }
908*f81fb7c4SAndroid Build Coastguard Worker 
909*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
910*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateEG2()
911*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
912*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
913*f81fb7c4SAndroid Build Coastguard Worker  * Update the EG2 envelope for the given voice
914*f81fb7c4SAndroid Build Coastguard Worker  *
915*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
916*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - ptr to the voice whose envelope we want to update
917*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
918*f81fb7c4SAndroid Build Coastguard Worker  *
919*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
920*f81fb7c4SAndroid Build Coastguard Worker  *
921*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
922*f81fb7c4SAndroid Build Coastguard Worker  * - updates EG2 values for the given voice
923*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
924*f81fb7c4SAndroid Build Coastguard Worker */
925*f81fb7c4SAndroid Build Coastguard Worker 
WT_UpdateEG2(S_WT_VOICE * pWTVoice,const S_ENVELOPE * pEnv)926*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv)
927*f81fb7c4SAndroid Build Coastguard Worker {
928*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 temp;
929*f81fb7c4SAndroid Build Coastguard Worker 
930*f81fb7c4SAndroid Build Coastguard Worker     switch (pWTVoice->eg2State)
931*f81fb7c4SAndroid Build Coastguard Worker     {
932*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateAttack:
933*f81fb7c4SAndroid Build Coastguard Worker             temp = pWTVoice->eg2Value + pWTVoice->eg2Increment;
934*f81fb7c4SAndroid Build Coastguard Worker 
935*f81fb7c4SAndroid Build Coastguard Worker             /* check if we have reached peak amplitude */
936*f81fb7c4SAndroid Build Coastguard Worker             if (temp >= SYNTH_FULL_SCALE_EG1_GAIN)
937*f81fb7c4SAndroid Build Coastguard Worker             {
938*f81fb7c4SAndroid Build Coastguard Worker                 /* limit the volume */
939*f81fb7c4SAndroid Build Coastguard Worker                 temp = SYNTH_FULL_SCALE_EG1_GAIN;
940*f81fb7c4SAndroid Build Coastguard Worker 
941*f81fb7c4SAndroid Build Coastguard Worker                 /* prepare to move to decay state */
942*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg2State = eEnvelopeStateDecay;
943*f81fb7c4SAndroid Build Coastguard Worker 
944*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg2Increment = pEnv->decayTime;
945*f81fb7c4SAndroid Build Coastguard Worker             }
946*f81fb7c4SAndroid Build Coastguard Worker 
947*f81fb7c4SAndroid Build Coastguard Worker             break;
948*f81fb7c4SAndroid Build Coastguard Worker 
949*f81fb7c4SAndroid Build Coastguard Worker             /* implement linear pitch decay in cents */
950*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateDecay:
951*f81fb7c4SAndroid Build Coastguard Worker             temp = pWTVoice->eg2Value -pWTVoice->eg2Increment;
952*f81fb7c4SAndroid Build Coastguard Worker 
953*f81fb7c4SAndroid Build Coastguard Worker             /* check if we have reached sustain level */
954*f81fb7c4SAndroid Build Coastguard Worker             if (temp <= pEnv->sustainLevel)
955*f81fb7c4SAndroid Build Coastguard Worker             {
956*f81fb7c4SAndroid Build Coastguard Worker                 /* enforce the sustain level */
957*f81fb7c4SAndroid Build Coastguard Worker                 temp = pEnv->sustainLevel;
958*f81fb7c4SAndroid Build Coastguard Worker 
959*f81fb7c4SAndroid Build Coastguard Worker                 /* prepare to move to sustain state */
960*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg2State = eEnvelopeStateSustain;
961*f81fb7c4SAndroid Build Coastguard Worker             }
962*f81fb7c4SAndroid Build Coastguard Worker             break;
963*f81fb7c4SAndroid Build Coastguard Worker 
964*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateSustain:
965*f81fb7c4SAndroid Build Coastguard Worker             return;
966*f81fb7c4SAndroid Build Coastguard Worker 
967*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateRelease:
968*f81fb7c4SAndroid Build Coastguard Worker             temp = pWTVoice->eg2Value - pWTVoice->eg2Increment;
969*f81fb7c4SAndroid Build Coastguard Worker 
970*f81fb7c4SAndroid Build Coastguard Worker             if (temp <= 0)
971*f81fb7c4SAndroid Build Coastguard Worker             {
972*f81fb7c4SAndroid Build Coastguard Worker                 temp = 0;
973*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg2State = eEnvelopeStateMuted;
974*f81fb7c4SAndroid Build Coastguard Worker             }
975*f81fb7c4SAndroid Build Coastguard Worker 
976*f81fb7c4SAndroid Build Coastguard Worker             break;
977*f81fb7c4SAndroid Build Coastguard Worker 
978*f81fb7c4SAndroid Build Coastguard Worker         /* voice is muted, set target to zero */
979*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateMuted:
980*f81fb7c4SAndroid Build Coastguard Worker             temp = 0;
981*f81fb7c4SAndroid Build Coastguard Worker             break;
982*f81fb7c4SAndroid Build Coastguard Worker 
983*f81fb7c4SAndroid Build Coastguard Worker         case eEnvelopeStateInvalid:
984*f81fb7c4SAndroid Build Coastguard Worker         default:
985*f81fb7c4SAndroid Build Coastguard Worker             temp = 0;
986*f81fb7c4SAndroid Build Coastguard Worker #ifdef  _DEBUG_SYNTH
987*f81fb7c4SAndroid Build Coastguard Worker             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG2: error, %d is an unrecognized state\n",
988*f81fb7c4SAndroid Build Coastguard Worker                 pWTVoice->eg2State); */ }
989*f81fb7c4SAndroid Build Coastguard Worker #endif
990*f81fb7c4SAndroid Build Coastguard Worker             break;
991*f81fb7c4SAndroid Build Coastguard Worker     }
992*f81fb7c4SAndroid Build Coastguard Worker 
993*f81fb7c4SAndroid Build Coastguard Worker     pWTVoice->eg2Value = (EAS_I16) temp;
994*f81fb7c4SAndroid Build Coastguard Worker }
995*f81fb7c4SAndroid Build Coastguard Worker 
996*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
997*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateLFO ()
998*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
999*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
1000*f81fb7c4SAndroid Build Coastguard Worker  * Calculate the LFO for the given voice
1001*f81fb7c4SAndroid Build Coastguard Worker  *
1002*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
1003*f81fb7c4SAndroid Build Coastguard Worker  * pLFO         - ptr to the LFO data
1004*f81fb7c4SAndroid Build Coastguard Worker  * phaseInc     - phase increment
1005*f81fb7c4SAndroid Build Coastguard Worker  *
1006*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
1007*f81fb7c4SAndroid Build Coastguard Worker  *
1008*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
1009*f81fb7c4SAndroid Build Coastguard Worker  * - updates LFO values for the given voice
1010*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1011*f81fb7c4SAndroid Build Coastguard Worker */
WT_UpdateLFO(S_LFO_CONTROL * pLFO,EAS_I16 phaseInc)1012*f81fb7c4SAndroid Build Coastguard Worker void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc)
1013*f81fb7c4SAndroid Build Coastguard Worker {
1014*f81fb7c4SAndroid Build Coastguard Worker 
1015*f81fb7c4SAndroid Build Coastguard Worker     /* To save memory, if m_nPhaseValue is negative, we are in the
1016*f81fb7c4SAndroid Build Coastguard Worker      * delay phase, and m_nPhaseValue represents the time left
1017*f81fb7c4SAndroid Build Coastguard Worker      * in the delay.
1018*f81fb7c4SAndroid Build Coastguard Worker      */
1019*f81fb7c4SAndroid Build Coastguard Worker      if (pLFO->lfoPhase < 0)
1020*f81fb7c4SAndroid Build Coastguard Worker      {
1021*f81fb7c4SAndroid Build Coastguard Worker         pLFO->lfoPhase++;
1022*f81fb7c4SAndroid Build Coastguard Worker         return;
1023*f81fb7c4SAndroid Build Coastguard Worker      }
1024*f81fb7c4SAndroid Build Coastguard Worker 
1025*f81fb7c4SAndroid Build Coastguard Worker     /* calculate LFO output from phase value */
1026*f81fb7c4SAndroid Build Coastguard Worker     /*lint -e{701} Use shift for performance */
1027*f81fb7c4SAndroid Build Coastguard Worker     pLFO->lfoValue = (EAS_I16) (pLFO->lfoPhase << 2);
1028*f81fb7c4SAndroid Build Coastguard Worker     /*lint -e{502} <shortcut to turn sawtooth into triangle wave> */
1029*f81fb7c4SAndroid Build Coastguard Worker     if ((pLFO->lfoPhase > 0x1fff) && (pLFO->lfoPhase < 0x6000))
1030*f81fb7c4SAndroid Build Coastguard Worker         pLFO->lfoValue = ~pLFO->lfoValue;
1031*f81fb7c4SAndroid Build Coastguard Worker 
1032*f81fb7c4SAndroid Build Coastguard Worker     /* update LFO phase */
1033*f81fb7c4SAndroid Build Coastguard Worker     pLFO->lfoPhase = (pLFO->lfoPhase + phaseInc) & 0x7fff;
1034*f81fb7c4SAndroid Build Coastguard Worker }
1035*f81fb7c4SAndroid Build Coastguard Worker 
1036*f81fb7c4SAndroid Build Coastguard Worker #ifdef _FILTER_ENABLED
1037*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
1038*f81fb7c4SAndroid Build Coastguard Worker  * WT_UpdateFilter()
1039*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1040*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
1041*f81fb7c4SAndroid Build Coastguard Worker  * Update the Filter parameters
1042*f81fb7c4SAndroid Build Coastguard Worker  *
1043*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
1044*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - ptr to the voice whose filter we want to update
1045*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
1046*f81fb7c4SAndroid Build Coastguard Worker  *
1047*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
1048*f81fb7c4SAndroid Build Coastguard Worker  *
1049*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
1050*f81fb7c4SAndroid Build Coastguard Worker  * - updates Filter values for the given voice
1051*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1052*f81fb7c4SAndroid Build Coastguard Worker */
WT_UpdateFilter(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pIntFrame,const S_ARTICULATION * pArt)1053*f81fb7c4SAndroid Build Coastguard Worker static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt)
1054*f81fb7c4SAndroid Build Coastguard Worker {
1055*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 cutoff;
1056*f81fb7c4SAndroid Build Coastguard Worker 
1057*f81fb7c4SAndroid Build Coastguard Worker     /* no need to calculate filter coefficients if it is bypassed */
1058*f81fb7c4SAndroid Build Coastguard Worker     if (pArt->filterCutoff == DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY)
1059*f81fb7c4SAndroid Build Coastguard Worker     {
1060*f81fb7c4SAndroid Build Coastguard Worker         pIntFrame->frame.k = 0;
1061*f81fb7c4SAndroid Build Coastguard Worker         return;
1062*f81fb7c4SAndroid Build Coastguard Worker     }
1063*f81fb7c4SAndroid Build Coastguard Worker 
1064*f81fb7c4SAndroid Build Coastguard Worker     /* determine the dynamic cutoff frequency */
1065*f81fb7c4SAndroid Build Coastguard Worker     cutoff = MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToFc);
1066*f81fb7c4SAndroid Build Coastguard Worker     cutoff += pArt->filterCutoff;
1067*f81fb7c4SAndroid Build Coastguard Worker 
1068*f81fb7c4SAndroid Build Coastguard Worker     /* subtract the A5 offset and the sampling frequency */
1069*f81fb7c4SAndroid Build Coastguard Worker     cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS;
1070*f81fb7c4SAndroid Build Coastguard Worker 
1071*f81fb7c4SAndroid Build Coastguard Worker     /* limit the cutoff frequency */
1072*f81fb7c4SAndroid Build Coastguard Worker     if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS)
1073*f81fb7c4SAndroid Build Coastguard Worker         cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS;
1074*f81fb7c4SAndroid Build Coastguard Worker     else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS)
1075*f81fb7c4SAndroid Build Coastguard Worker         cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS;
1076*f81fb7c4SAndroid Build Coastguard Worker 
1077*f81fb7c4SAndroid Build Coastguard Worker     WT_SetFilterCoeffs(pIntFrame, cutoff, pArt->filterQ);
1078*f81fb7c4SAndroid Build Coastguard Worker }
1079*f81fb7c4SAndroid Build Coastguard Worker #endif
1080*f81fb7c4SAndroid Build Coastguard Worker 
1081*f81fb7c4SAndroid Build Coastguard Worker #if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER)
1082*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
1083*f81fb7c4SAndroid Build Coastguard Worker  * coef
1084*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1085*f81fb7c4SAndroid Build Coastguard Worker  * Table of filter coefficients for low-pass filter
1086*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1087*f81fb7c4SAndroid Build Coastguard Worker  *
1088*f81fb7c4SAndroid Build Coastguard Worker  * polynomial coefficients are based on 8kHz sampling frequency
1089*f81fb7c4SAndroid Build Coastguard Worker  * filter coef b2 = k2 = k2g0*k^0 + k2g1*k^1*(2^x) + k2g2*k^2*(2^x)
1090*f81fb7c4SAndroid Build Coastguard Worker  *
1091*f81fb7c4SAndroid Build Coastguard Worker  *where k2g0, k2g1, k2g2 are from the truncated power series expansion on theta
1092*f81fb7c4SAndroid Build Coastguard Worker  *(k*2^x = theta, but we incorporate the k along with the k2g0, k2g1, k2g2)
1093*f81fb7c4SAndroid Build Coastguard Worker  *note: this is a power series in 2^x, not k*2^x
1094*f81fb7c4SAndroid Build Coastguard Worker  *where k = (2*pi*440)/8kHz == convert octaves to radians
1095*f81fb7c4SAndroid Build Coastguard Worker  *
1096*f81fb7c4SAndroid Build Coastguard Worker  *  so actually, the following coefs listed as k2g0, k2g1, k2g2 are really
1097*f81fb7c4SAndroid Build Coastguard Worker  *  k2g0*k^0 = k2g0
1098*f81fb7c4SAndroid Build Coastguard Worker  *  k2g1*k^1
1099*f81fb7c4SAndroid Build Coastguard Worker  *  k2g2*k^2
1100*f81fb7c4SAndroid Build Coastguard Worker  *
1101*f81fb7c4SAndroid Build Coastguard Worker  *
1102*f81fb7c4SAndroid Build Coastguard Worker  * filter coef n1 = numerator = n1g0*k^0 + n1g1*k^1*(2^x) + n1g2*k^2*(2^x) + n1g3*k^3*(2^x)
1103*f81fb7c4SAndroid Build Coastguard Worker  *
1104*f81fb7c4SAndroid Build Coastguard Worker  *where n1g0, n1g1, n1g2, n1g3 are from the truncated power series expansion on theta
1105*f81fb7c4SAndroid Build Coastguard Worker  *(k*2^x = theta, but we incorporate the k along with the n1g0, n1g1, n1g2, n2g3)
1106*f81fb7c4SAndroid Build Coastguard Worker  *note: this is a power series in 2^x, not k*2^x
1107*f81fb7c4SAndroid Build Coastguard Worker  *where k = (2*pi*440)/8kHz == convert octaves to radians
1108*f81fb7c4SAndroid Build Coastguard Worker  *we also include the optimization factor of 0.81
1109*f81fb7c4SAndroid Build Coastguard Worker  *
1110*f81fb7c4SAndroid Build Coastguard Worker  *  so actually, the following coefs listed as n1g0, n1g1, n1g2, n2g3 are really
1111*f81fb7c4SAndroid Build Coastguard Worker  *  n1g0*k^0 = n1g0
1112*f81fb7c4SAndroid Build Coastguard Worker  *  n1g1*k^1
1113*f81fb7c4SAndroid Build Coastguard Worker  *  n1g2*k^2
1114*f81fb7c4SAndroid Build Coastguard Worker  *  n1g3*k^3
1115*f81fb7c4SAndroid Build Coastguard Worker  *
1116*f81fb7c4SAndroid Build Coastguard Worker  *  NOTE that n1g0 == n1g1 == 0, always, so we only need to store n1g2 and n1g3
1117*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1118*f81fb7c4SAndroid Build Coastguard Worker */
1119*f81fb7c4SAndroid Build Coastguard Worker 
1120*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 nk1g0 = -32768;
1121*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 nk1g2 = 1580;
1122*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 k2g0 = 32767;
1123*f81fb7c4SAndroid Build Coastguard Worker 
1124*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 k2g1[] =
1125*f81fb7c4SAndroid Build Coastguard Worker {
1126*f81fb7c4SAndroid Build Coastguard Worker         -11324, /* k2g1[0] = -0.3455751918948761 */
1127*f81fb7c4SAndroid Build Coastguard Worker         -10387, /* k2g1[1] = -0.3169878073928751 */
1128*f81fb7c4SAndroid Build Coastguard Worker         -9528,  /* k2g1[2] = -0.29076528753345476 */
1129*f81fb7c4SAndroid Build Coastguard Worker         -8740,  /* k2g1[3] = -0.2667120011011279 */
1130*f81fb7c4SAndroid Build Coastguard Worker         -8017,  /* k2g1[4] = -0.24464850028971705 */
1131*f81fb7c4SAndroid Build Coastguard Worker         -7353,  /* k2g1[5] = -0.22441018194495696 */
1132*f81fb7c4SAndroid Build Coastguard Worker         -6745,  /* k2g1[6] = -0.20584605955455101 */
1133*f81fb7c4SAndroid Build Coastguard Worker         -6187,  /* k2g1[7] = -0.18881763682420102 */
1134*f81fb7c4SAndroid Build Coastguard Worker         -5675,  /* k2g1[8] = -0.1731978744360067 */
1135*f81fb7c4SAndroid Build Coastguard Worker         -5206,  /* k2g1[9] = -0.15887024228080968 */
1136*f81fb7c4SAndroid Build Coastguard Worker         -4775,  /* k2g1[10] = -0.14572785009373057 */
1137*f81fb7c4SAndroid Build Coastguard Worker         -4380,  /* k2g1[11] = -0.13367265000706827 */
1138*f81fb7c4SAndroid Build Coastguard Worker         -4018,  /* k2g1[12] = -0.1226147050712642 */
1139*f81fb7c4SAndroid Build Coastguard Worker         -3685,  /* k2g1[13] = -0.11247151828678581 */
1140*f81fb7c4SAndroid Build Coastguard Worker         -3381,  /* k2g1[14] = -0.10316741714122014 */
1141*f81fb7c4SAndroid Build Coastguard Worker         -3101,  /* k2g1[15] = -0.0946329890599603 */
1142*f81fb7c4SAndroid Build Coastguard Worker         -2844,  /* k2g1[16] = -0.08680456355870586 */
1143*f81fb7c4SAndroid Build Coastguard Worker         -2609,  /* k2g1[17] = -0.07962373723441349 */
1144*f81fb7c4SAndroid Build Coastguard Worker         -2393,  /* k2g1[18] = -0.07303693805092666 */
1145*f81fb7c4SAndroid Build Coastguard Worker         -2195,  /* k2g1[19] = -0.06699502566866912 */
1146*f81fb7c4SAndroid Build Coastguard Worker         -2014,  /* k2g1[20] = -0.06145292483669077 */
1147*f81fb7c4SAndroid Build Coastguard Worker         -1847,  /* k2g1[21] = -0.056369289112013346 */
1148*f81fb7c4SAndroid Build Coastguard Worker         -1694,  /* k2g1[22] = -0.05170619239747895 */
1149*f81fb7c4SAndroid Build Coastguard Worker         -1554,  /* k2g1[23] = -0.04742884599684141 */
1150*f81fb7c4SAndroid Build Coastguard Worker         -1426,  /* k2g1[24] = -0.043505339076210514 */
1151*f81fb7c4SAndroid Build Coastguard Worker         -1308,  /* k2g1[25] = -0.03990640059558053 */
1152*f81fb7c4SAndroid Build Coastguard Worker         -1199,  /* k2g1[26] = -0.03660518093435039 */
1153*f81fb7c4SAndroid Build Coastguard Worker         -1100,  /* k2g1[27] = -0.03357705158166837 */
1154*f81fb7c4SAndroid Build Coastguard Worker         -1009,  /* k2g1[28] = -0.030799421397205727 */
1155*f81fb7c4SAndroid Build Coastguard Worker         -926,   /* k2g1[29] = -0.028251568071585884 */
1156*f81fb7c4SAndroid Build Coastguard Worker         -849    /* k2g1[30] = -0.025914483529091967 */
1157*f81fb7c4SAndroid Build Coastguard Worker };
1158*f81fb7c4SAndroid Build Coastguard Worker 
1159*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 k2g2[] =
1160*f81fb7c4SAndroid Build Coastguard Worker {
1161*f81fb7c4SAndroid Build Coastguard Worker         1957,   /* k2g2[0] = 0.059711106626580836 */
1162*f81fb7c4SAndroid Build Coastguard Worker         1646,   /* k2g2[1] = 0.05024063501786333 */
1163*f81fb7c4SAndroid Build Coastguard Worker         1385,   /* k2g2[2] = 0.042272226217199664 */
1164*f81fb7c4SAndroid Build Coastguard Worker         1165,   /* k2g2[3] = 0.03556764576567844 */
1165*f81fb7c4SAndroid Build Coastguard Worker         981,    /* k2g2[4] = 0.029926444346999134 */
1166*f81fb7c4SAndroid Build Coastguard Worker         825,    /* k2g2[5] = 0.025179964880280382 */
1167*f81fb7c4SAndroid Build Coastguard Worker         694,    /* k2g2[6] = 0.02118630011706455 */
1168*f81fb7c4SAndroid Build Coastguard Worker         584,    /* k2g2[7] = 0.01782604998793514 */
1169*f81fb7c4SAndroid Build Coastguard Worker         491,    /* k2g2[8] = 0.014998751854573014 */
1170*f81fb7c4SAndroid Build Coastguard Worker         414,    /* k2g2[9] = 0.012619876941179595 */
1171*f81fb7c4SAndroid Build Coastguard Worker         348,    /* k2g2[10] = 0.010618303146468736 */
1172*f81fb7c4SAndroid Build Coastguard Worker         293,    /* k2g2[11] = 0.008934188679954682 */
1173*f81fb7c4SAndroid Build Coastguard Worker         246,    /* k2g2[12] = 0.007517182949855368 */
1174*f81fb7c4SAndroid Build Coastguard Worker         207,    /* k2g2[13] = 0.006324921212866403 */
1175*f81fb7c4SAndroid Build Coastguard Worker         174,    /* k2g2[14] = 0.005321757979794424 */
1176*f81fb7c4SAndroid Build Coastguard Worker         147,    /* k2g2[15] = 0.004477701309210577 */
1177*f81fb7c4SAndroid Build Coastguard Worker         123,    /* k2g2[16] = 0.00376751612730811 */
1178*f81fb7c4SAndroid Build Coastguard Worker         104,    /* k2g2[17] = 0.0031699697655869644 */
1179*f81fb7c4SAndroid Build Coastguard Worker         87,     /* k2g2[18] = 0.00266719715992703 */
1180*f81fb7c4SAndroid Build Coastguard Worker         74,     /* k2g2[19] = 0.0022441667321724647 */
1181*f81fb7c4SAndroid Build Coastguard Worker         62,     /* k2g2[20] = 0.0018882309854916855 */
1182*f81fb7c4SAndroid Build Coastguard Worker         52,     /* k2g2[21] = 0.0015887483774966232 */
1183*f81fb7c4SAndroid Build Coastguard Worker         44,     /* k2g2[22] = 0.0013367651661223448 */
1184*f81fb7c4SAndroid Build Coastguard Worker         37,     /* k2g2[23] = 0.0011247477162958733 */
1185*f81fb7c4SAndroid Build Coastguard Worker         31,     /* k2g2[24] = 0.0009463572640678758 */
1186*f81fb7c4SAndroid Build Coastguard Worker         26,     /* k2g2[25] = 0.0007962604042473498 */
1187*f81fb7c4SAndroid Build Coastguard Worker         22,     /* k2g2[26] = 0.0006699696356181593 */
1188*f81fb7c4SAndroid Build Coastguard Worker         18,     /* k2g2[27] = 0.0005637091964589207 */
1189*f81fb7c4SAndroid Build Coastguard Worker         16,     /* k2g2[28] = 0.00047430217920125243 */
1190*f81fb7c4SAndroid Build Coastguard Worker         13,     /* k2g2[29] = 0.00039907554925166274 */
1191*f81fb7c4SAndroid Build Coastguard Worker         11      /* k2g2[30] = 0.00033578022828973666 */
1192*f81fb7c4SAndroid Build Coastguard Worker };
1193*f81fb7c4SAndroid Build Coastguard Worker 
1194*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 n1g2[] =
1195*f81fb7c4SAndroid Build Coastguard Worker {
1196*f81fb7c4SAndroid Build Coastguard Worker         3170,   /* n1g2[0] = 0.0967319927350769 */
1197*f81fb7c4SAndroid Build Coastguard Worker         3036,   /* n1g2[1] = 0.0926446051254155 */
1198*f81fb7c4SAndroid Build Coastguard Worker         2908,   /* n1g2[2] = 0.08872992911818503 */
1199*f81fb7c4SAndroid Build Coastguard Worker         2785,   /* n1g2[3] = 0.08498066682523227 */
1200*f81fb7c4SAndroid Build Coastguard Worker         2667,   /* n1g2[4] = 0.08138982872895201 */
1201*f81fb7c4SAndroid Build Coastguard Worker         2554,   /* n1g2[5] = 0.07795072065216213 */
1202*f81fb7c4SAndroid Build Coastguard Worker         2446,   /* n1g2[6] = 0.0746569312785634 */
1203*f81fb7c4SAndroid Build Coastguard Worker         2343,   /* n1g2[7] = 0.07150232020051943 */
1204*f81fb7c4SAndroid Build Coastguard Worker         2244,   /* n1g2[8] = 0.06848100647187474 */
1205*f81fb7c4SAndroid Build Coastguard Worker         2149,   /* n1g2[9] = 0.06558735764447099 */
1206*f81fb7c4SAndroid Build Coastguard Worker         2058,   /* n1g2[10] = 0.06281597926792246 */
1207*f81fb7c4SAndroid Build Coastguard Worker         1971,   /* n1g2[11] = 0.06016170483307614 */
1208*f81fb7c4SAndroid Build Coastguard Worker         1888,   /* n1g2[12] = 0.05761958614040857 */
1209*f81fb7c4SAndroid Build Coastguard Worker         1808,   /* n1g2[13] = 0.05518488407540374 */
1210*f81fb7c4SAndroid Build Coastguard Worker         1732,   /* n1g2[14] = 0.052853059773715245 */
1211*f81fb7c4SAndroid Build Coastguard Worker         1659,   /* n1g2[15] = 0.05061976615964251 */
1212*f81fb7c4SAndroid Build Coastguard Worker         1589,   /* n1g2[16] = 0.04848083984214659 */
1213*f81fb7c4SAndroid Build Coastguard Worker         1521,   /* n1g2[17] = 0.046432293353298 */
1214*f81fb7c4SAndroid Build Coastguard Worker         1457,   /* n1g2[18] = 0.04447030771468711 */
1215*f81fb7c4SAndroid Build Coastguard Worker         1396,   /* n1g2[19] = 0.04259122531793907 */
1216*f81fb7c4SAndroid Build Coastguard Worker         1337,   /* n1g2[20] = 0.040791543106060944 */
1217*f81fb7c4SAndroid Build Coastguard Worker         1280,   /* n1g2[21] = 0.03906790604290942 */
1218*f81fb7c4SAndroid Build Coastguard Worker         1226,   /* n1g2[22] = 0.037417100858604564 */
1219*f81fb7c4SAndroid Build Coastguard Worker         1174,   /* n1g2[23] = 0.035836050059229754 */
1220*f81fb7c4SAndroid Build Coastguard Worker         1125,   /* n1g2[24] = 0.03432180618965023 */
1221*f81fb7c4SAndroid Build Coastguard Worker         1077,   /* n1g2[25] = 0.03287154633875494 */
1222*f81fb7c4SAndroid Build Coastguard Worker         1032,   /* n1g2[26] = 0.03148256687687814 */
1223*f81fb7c4SAndroid Build Coastguard Worker         988,    /* n1g2[27] = 0.030152278415589925 */
1224*f81fb7c4SAndroid Build Coastguard Worker         946,    /* n1g2[28] = 0.028878200980459685 */
1225*f81fb7c4SAndroid Build Coastguard Worker         906,    /* n1g2[29] = 0.02765795938779331 */
1226*f81fb7c4SAndroid Build Coastguard Worker         868     /* n1g2[30] = 0.02648927881672521 */
1227*f81fb7c4SAndroid Build Coastguard Worker };
1228*f81fb7c4SAndroid Build Coastguard Worker 
1229*f81fb7c4SAndroid Build Coastguard Worker static const EAS_I16 n1g3[] =
1230*f81fb7c4SAndroid Build Coastguard Worker {
1231*f81fb7c4SAndroid Build Coastguard Worker         -548,   /* n1g3[0] = -0.016714088475899017 */
1232*f81fb7c4SAndroid Build Coastguard Worker         -481,   /* n1g3[1] = -0.014683605122742116 */
1233*f81fb7c4SAndroid Build Coastguard Worker         -423,   /* n1g3[2] = -0.012899791676436092 */
1234*f81fb7c4SAndroid Build Coastguard Worker         -371,   /* n1g3[3] = -0.01133268185193299 */
1235*f81fb7c4SAndroid Build Coastguard Worker         -326,   /* n1g3[4] = -0.00995594976868754 */
1236*f81fb7c4SAndroid Build Coastguard Worker         -287,   /* n1g3[5] = -0.008746467702146129 */
1237*f81fb7c4SAndroid Build Coastguard Worker         -252,   /* n1g3[6] = -0.00768391756106361 */
1238*f81fb7c4SAndroid Build Coastguard Worker         -221,   /* n1g3[7] = -0.006750449563854721 */
1239*f81fb7c4SAndroid Build Coastguard Worker         -194,   /* n1g3[8] = -0.005930382380083576 */
1240*f81fb7c4SAndroid Build Coastguard Worker         -171,   /* n1g3[9] = -0.005209939699767622 */
1241*f81fb7c4SAndroid Build Coastguard Worker         -150,   /* n1g3[10] = -0.004577018805123356 */
1242*f81fb7c4SAndroid Build Coastguard Worker         -132,   /* n1g3[11] = -0.004020987256990177 */
1243*f81fb7c4SAndroid Build Coastguard Worker         -116,   /* n1g3[12] = -0.003532504280467257 */
1244*f81fb7c4SAndroid Build Coastguard Worker         -102,   /* n1g3[13] = -0.00310336384922047 */
1245*f81fb7c4SAndroid Build Coastguard Worker         -89,    /* n1g3[14] = -0.002726356832432369 */
1246*f81fb7c4SAndroid Build Coastguard Worker         -78,    /* n1g3[15] = -0.002395149888601605 */
1247*f81fb7c4SAndroid Build Coastguard Worker         -69,    /* n1g3[16] = -0.0021041790717285314 */
1248*f81fb7c4SAndroid Build Coastguard Worker         -61,    /* n1g3[17] = -0.0018485563625771063 */
1249*f81fb7c4SAndroid Build Coastguard Worker         -53,    /* n1g3[18] = -0.001623987554831628 */
1250*f81fb7c4SAndroid Build Coastguard Worker         -47,    /* n1g3[19] = -0.0014267001167177025 */
1251*f81fb7c4SAndroid Build Coastguard Worker         -41,    /* n1g3[20] = -0.0012533798162347005 */
1252*f81fb7c4SAndroid Build Coastguard Worker         -36,    /* n1g3[21] = -0.0011011150453668693 */
1253*f81fb7c4SAndroid Build Coastguard Worker         -32,    /* n1g3[22] = -0.0009673479079754438 */
1254*f81fb7c4SAndroid Build Coastguard Worker         -28,    /* n1g3[23] = -0.0008498312496971563 */
1255*f81fb7c4SAndroid Build Coastguard Worker         -24,    /* n1g3[24] = -0.0007465909079943587 */
1256*f81fb7c4SAndroid Build Coastguard Worker         -21,    /* n1g3[25] = -0.0006558925481952733 */
1257*f81fb7c4SAndroid Build Coastguard Worker         -19,    /* n1g3[26] = -0.0005762125284029567 */
1258*f81fb7c4SAndroid Build Coastguard Worker         -17,    /* n1g3[27] = -0.0005062123038325457 */
1259*f81fb7c4SAndroid Build Coastguard Worker         -15,    /* n1g3[28] = -0.0004447159405951901 */
1260*f81fb7c4SAndroid Build Coastguard Worker         -13,    /* n1g3[29] = -0.00039069036118270117 */
1261*f81fb7c4SAndroid Build Coastguard Worker         -11     /* n1g3[30] = -0.00034322798979677605 */
1262*f81fb7c4SAndroid Build Coastguard Worker };
1263*f81fb7c4SAndroid Build Coastguard Worker 
1264*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
1265*f81fb7c4SAndroid Build Coastguard Worker  * WT_SetFilterCoeffs()
1266*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1267*f81fb7c4SAndroid Build Coastguard Worker  * Purpose:
1268*f81fb7c4SAndroid Build Coastguard Worker  * Update the Filter parameters
1269*f81fb7c4SAndroid Build Coastguard Worker  *
1270*f81fb7c4SAndroid Build Coastguard Worker  * Inputs:
1271*f81fb7c4SAndroid Build Coastguard Worker  * pVoice - ptr to the voice whose filter we want to update
1272*f81fb7c4SAndroid Build Coastguard Worker  * pEASData - pointer to overall EAS data structure
1273*f81fb7c4SAndroid Build Coastguard Worker  *
1274*f81fb7c4SAndroid Build Coastguard Worker  * Outputs:
1275*f81fb7c4SAndroid Build Coastguard Worker  *
1276*f81fb7c4SAndroid Build Coastguard Worker  * Side Effects:
1277*f81fb7c4SAndroid Build Coastguard Worker  * - updates Filter values for the given voice
1278*f81fb7c4SAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
1279*f81fb7c4SAndroid Build Coastguard Worker */
WT_SetFilterCoeffs(S_WT_INT_FRAME * pIntFrame,EAS_I32 cutoff,EAS_I32 resonance)1280*f81fb7c4SAndroid Build Coastguard Worker void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance)
1281*f81fb7c4SAndroid Build Coastguard Worker {
1282*f81fb7c4SAndroid Build Coastguard Worker     EAS_I32 temp;
1283*f81fb7c4SAndroid Build Coastguard Worker 
1284*f81fb7c4SAndroid Build Coastguard Worker     /*
1285*f81fb7c4SAndroid Build Coastguard Worker     Convert the cutoff, which has had A5 subtracted, using the 2^x approx
1286*f81fb7c4SAndroid Build Coastguard Worker     Note, this cutoff is related to theta cutoff by
1287*f81fb7c4SAndroid Build Coastguard Worker     theta = k * 2^x
1288*f81fb7c4SAndroid Build Coastguard Worker     We use 2^x and incorporate k in the power series coefs instead
1289*f81fb7c4SAndroid Build Coastguard Worker     */
1290*f81fb7c4SAndroid Build Coastguard Worker     cutoff = EAS_Calculate2toX(cutoff);
1291*f81fb7c4SAndroid Build Coastguard Worker 
1292*f81fb7c4SAndroid Build Coastguard Worker     /* calculate b2 coef */
1293*f81fb7c4SAndroid Build Coastguard Worker     temp = k2g1[resonance] + MULT_AUDIO_COEF(cutoff, k2g2[resonance]);
1294*f81fb7c4SAndroid Build Coastguard Worker     temp = k2g0 + MULT_AUDIO_COEF(cutoff, temp);
1295*f81fb7c4SAndroid Build Coastguard Worker     pIntFrame->frame.b2 = temp;
1296*f81fb7c4SAndroid Build Coastguard Worker 
1297*f81fb7c4SAndroid Build Coastguard Worker     /* calculate b1 coef */
1298*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_AUDIO_COEF(cutoff, nk1g2);
1299*f81fb7c4SAndroid Build Coastguard Worker     temp = nk1g0 + MULT_AUDIO_COEF(cutoff, temp);
1300*f81fb7c4SAndroid Build Coastguard Worker     temp += MULT_AUDIO_COEF(temp, pIntFrame->frame.b2);
1301*f81fb7c4SAndroid Build Coastguard Worker     pIntFrame->frame.b1 = temp >> 1;
1302*f81fb7c4SAndroid Build Coastguard Worker 
1303*f81fb7c4SAndroid Build Coastguard Worker     /* calculate K coef */
1304*f81fb7c4SAndroid Build Coastguard Worker     temp = n1g2[resonance] + MULT_AUDIO_COEF(cutoff, n1g3[resonance]);
1305*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_AUDIO_COEF(cutoff, temp);
1306*f81fb7c4SAndroid Build Coastguard Worker     temp = MULT_AUDIO_COEF(cutoff, temp);
1307*f81fb7c4SAndroid Build Coastguard Worker     pIntFrame->frame.k = temp;
1308*f81fb7c4SAndroid Build Coastguard Worker }
1309*f81fb7c4SAndroid Build Coastguard Worker #endif
1310*f81fb7c4SAndroid Build Coastguard Worker 
1311