eas_wtsynth.c revision e442bb7cd6a085b33a4dd52c0e20a157ada7feb1
1950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
2950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
3950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * File:
4950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * eas_wtsynth.c
5950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
6950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Contents and purpose:
7950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Implements the synthesizer functions.
8950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
9950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Copyright Sonic Network Inc. 2004
10950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
11950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Licensed under the Apache License, Version 2.0 (the "License");
12950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * you may not use this file except in compliance with the License.
13950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * You may obtain a copy of the License at
14950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
15950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *      http://www.apache.org/licenses/LICENSE-2.0
16950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
17950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Unless required by applicable law or agreed to in writing, software
18950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * distributed under the License is distributed on an "AS IS" BASIS,
19950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * See the License for the specific language governing permissions and
21950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * limitations under the License.
22950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
23950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
24950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Revision Control:
25950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *   $Revision: 795 $
26950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *   $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
27950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
28950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
29950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
30950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com// includes
31950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_data.h"
32950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_report.h"
33950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_host.h"
34950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_math.h"
35950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_synth_protos.h"
36950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_wtsynth.h"
37950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_pan.h"
38950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
39950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef DLS_SYNTHESIZER
40950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_dlssynth.h"
41950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
42950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
43950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _METRICS_ENABLED
44950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#include "eas_perf.h"
45950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
46950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
47950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/* local prototypes */
48950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_RESULT WT_Initialize(S_VOICE_MGR *pVoiceMgr);
49950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
50950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum);
51950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum);
52950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex);
53950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples);
54950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel);
55950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents);
56950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain);
57950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv);
58950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv);
59950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
60950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef EAS_SPLIT_WT_SYNTH
61950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern EAS_BOOL WTE_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer);
62950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern EAS_BOOL WTE_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain);
63950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
64950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
65950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _FILTER_ENABLED
66950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt);
67950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
68950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
69950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _STATS
70950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern double statsPhaseIncrement;
71950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern double statsMaxPhaseIncrement;
72950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern long statsPhaseSampleCount;
73950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern double statsSampleSize;
74950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comextern long statsSampleCount;
75950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
76950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
77950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
78950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Synthesizer interface
79950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
80950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
81950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
82950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comconst S_SYNTH_INTERFACE wtSynth =
83950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
84950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_Initialize,
85950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_StartVoice,
86950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_UpdateVoice,
87950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_ReleaseVoice,
88950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_MuteVoice,
89950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_SustainPedal,
90950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WT_UpdateChannel
91950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com};
92950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
93950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef EAS_SPLIT_WT_SYNTH
94950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comconst S_FRAME_INTERFACE wtFrameInterface =
95950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
96950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WTE_StartFrame,
97950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	WTE_EndFrame
98950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com};
99950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
100950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
101950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
102950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WT_Initialize()
103950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
104950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Purpose:
105950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
106950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Inputs:
107950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pVoice - pointer to voice to initialize
108950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
109950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Outputs:
110950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
111950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
112950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
113950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_RESULT WT_Initialize (S_VOICE_MGR *pVoiceMgr)
114950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
115950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	EAS_INT i;
116950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
117950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	for (i = 0; i < NUM_WT_VOICES; i++)
118950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
119950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
120950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].artIndex = DEFAULT_ARTICULATION_INDEX;
121950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
122950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].eg1State = DEFAULT_EG1_STATE;
123950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].eg1Value = DEFAULT_EG1_VALUE;
124950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].eg1Increment = DEFAULT_EG1_INCREMENT;
125950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
126950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].eg2State = DEFAULT_EG2_STATE;
127950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].eg2Value = DEFAULT_EG2_VALUE;
128950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].eg2Increment = DEFAULT_EG2_INCREMENT;
129950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
130950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    /* left and right gain values are needed only if stereo output */
131950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#if	(NUM_OUTPUT_CHANNELS == 2)
132950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].gainLeft = DEFAULT_VOICE_GAIN;
133950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].gainRight = DEFAULT_VOICE_GAIN;
134950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
135950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
136950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].phaseFrac = DEFAULT_PHASE_FRAC;
137950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].phaseAccum = DEFAULT_PHASE_INT;
138950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
139950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _FILTER_ENABLED
140950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].filter.z1 = DEFAULT_FILTER_ZERO;
141950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	    pVoiceMgr->wtVoices[i].filter.z2 = DEFAULT_FILTER_ZERO;
142950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
143950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
144950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
145950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	return EAS_TRUE;
146950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com}
147950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
148950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
149950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WT_ReleaseVoice()
150950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
151950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Purpose:
152950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * The selected voice is being released.
153950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
154950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Inputs:
155950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pEASData - pointer to S_EAS_DATA
156950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pVoice - pointer to voice to release
157950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
158950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Outputs:
159950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * None
160950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
161950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
162950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*lint -esym(715, pVoice) used in some implementations */
163950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
164950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
165950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	S_WT_VOICE *pWTVoice;
166950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	const S_ARTICULATION *pArticulation;
167950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
168950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef DLS_SYNTHESIZER
169950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
170950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
171950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		DLS_ReleaseVoice(pVoiceMgr, pSynth, pVoice, voiceNum);
172950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		return;
173950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
174950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
175950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
176950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
177950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pArticulation = &pSynth->pEAS->pArticulations[pWTVoice->artIndex];
178950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
179950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    /* release EG1 */
180950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pWTVoice->eg1State = eEnvelopeStateRelease;
181950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pWTVoice->eg1Increment = pArticulation->eg1.releaseTime;
182950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
183950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    /*
184950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    The spec says we should release EG2, but doing so with the current
185950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    voicing is causing clicks. This fix will need to be coordinated with
186950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    a new sound library release
187950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    */
188950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
189950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    /* release EG2 */
190950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pWTVoice->eg2State = eEnvelopeStateRelease;
191950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pWTVoice->eg2Increment = pArticulation->eg2.releaseTime;
192950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com}
193950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
194950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
195950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WT_MuteVoice()
196950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
197950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Purpose:
198950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * The selected voice is being muted.
199950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
200950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Inputs:
201950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pVoice - pointer to voice to release
202950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
203950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Outputs:
204950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * None
205950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
206950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
207950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*lint -esym(715, pSynth) used in some implementations */
208950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
209950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
210950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
211950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef DLS_SYNTHESIZER
212950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
213950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
214950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		DLS_MuteVoice(pVoiceMgr, pSynth, pVoice, voiceNum);
215950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		return;
216950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
217950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
218950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
219950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* clear deferred action flags */
220950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pVoice->voiceFlags &=
221950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF |
222950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF |
223950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		VOICE_FLAG_DEFER_MUTE);
224950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
225950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* set the envelope state */
226950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateMuted;
227950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateMuted;
228950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com}
229950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
230950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
231950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WT_SustainPedal()
232950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
233950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Purpose:
234950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * The selected voice is held due to sustain pedal
235950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
236950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Inputs:
237950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pVoice - pointer to voice to sustain
238950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
239950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Outputs:
240950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * None
241950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
242950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
243950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*lint -esym(715, pChannel) used in some implementations */
244950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum)
245950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
246950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	S_WT_VOICE *pWTVoice;
247950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
248950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef DLS_SYNTHESIZER
249950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
250950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
251950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		DLS_SustainPedal(pVoiceMgr, pSynth, pVoice, pChannel, voiceNum);
252950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		return;
253950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
254950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
255950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
256950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* don't catch the voice if below the sustain level */
257950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
258950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pWTVoice->eg1Value < pSynth->pEAS->pArticulations[pWTVoice->artIndex].eg1.sustainLevel)
259950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		return;
260950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
261950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    /* sustain flag is set, damper pedal is on */
262950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    /* defer releasing this note until the damper pedal is off */
263950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pWTVoice->eg1State = eEnvelopeStateDecay;
264950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pVoice->voiceState = eVoiceStatePlay;
265950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
266950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    /*
267950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    because sustain pedal is on, this voice
268950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    should defer releasing its note
269950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    */
270950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF;
271950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
272950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _DEBUG_SYNTH
273950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com    { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_SustainPedal: defer note off because sustain pedal is on\n"); */ }
274950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
275950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com}
276950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
277950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
278950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WT_StartVoice()
279950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
280950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Purpose:
281950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Assign the region for the given instrument using the midi key number
282950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * and the RPN2 (coarse tuning) value. By using RPN2 as part of the
283950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * region selection process, we reduce the amount a given sample has
284950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * to be transposed by selecting the closest recorded root instead.
285950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
286950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * This routine is the second half of SynthAssignRegion().
287950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * If the region was successfully found by SynthFindRegionIndex(),
288950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * then assign the region's parameters to the voice.
289950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
290950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Setup and initialize the following voice parameters:
291950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * m_nRegionIndex
292950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
293950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Inputs:
294950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pVoice - ptr to the voice we have assigned for this channel
295950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * nRegionIndex - index of the region
296950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * pEASData - pointer to overall EAS data structure
297950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
298950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Outputs:
299950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * success - could find and assign the region for this voice's note otherwise
300950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * failure - could not find nor assign the region for this voice's note
301950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *
302950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Side Effects:
303950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * psSynthObject->m_sVoice[].m_nRegionIndex is assigned
304950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * psSynthObject->m_sVoice[] parameters are assigned
305950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
306950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com*/
307950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.comstatic EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex)
308950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com{
309950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	S_WT_VOICE *pWTVoice;
310950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	const S_WT_REGION *pRegion;
311950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	const S_ARTICULATION *pArt;
312950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	S_SYNTH_CHANNEL *pChannel;
313950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
314950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#if (NUM_OUTPUT_CHANNELS == 2)
315950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	EAS_INT pan;
316950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
317950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
318950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef EAS_SPLIT_WT_SYNTH
319950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	S_WT_CONFIG wtConfig;
320950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
321950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
322950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* no samples have been synthesized for this note yet */
323950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pVoice->regionIndex = regionIndex;
324950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
325950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
326950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* get the articulation index for this region */
327950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
328950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pChannel = &pSynth->channels[pVoice->channel & 15];
329950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
330950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* update static channel parameters */
331950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)
332950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		WT_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15);
333950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
334950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef DLS_SYNTHESIZER
335950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
336950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		return DLS_StartVoice(pVoiceMgr, pSynth, pVoice, voiceNum, regionIndex);
337950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
338950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
339950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pRegion = &(pSynth->pEAS->pWTRegions[regionIndex]);
340950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->artIndex = pRegion->artIndex;
341950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
342950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _DEBUG_SYNTH
343950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ }
344950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
345950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
346950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex];
347950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
348950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* MIDI note on puts this voice into attack state */
349950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->eg1State = eEnvelopeStateAttack;
350950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->eg1Value = 0;
351950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->eg1Increment = pArt->eg1.attackTime;
352950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->eg2State = eEnvelopeStateAttack;
353950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->eg2Value = 0;
354950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->eg2Increment = pArt->eg2.attackTime;
355950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
356950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* init the LFO */
357950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->modLFO.lfoValue = 0;
358950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->modLFO.lfoPhase = -pArt->lfoDelay;
359950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
360950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pVoice->gain = 0;
361950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
362950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#if (NUM_OUTPUT_CHANNELS == 2)
363950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/*
364950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	Get the Midi CC10 pan value for this voice's channel
365950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	convert the pan value to an "angle" representation suitable for
366950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	our sin, cos calculator. This representation is NOT necessarily the same
367950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	as the transform in the GM manuals because of our sin, cos calculator.
368950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	"angle" = (CC10 - 64)/128
369950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	*/
370950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pan = (EAS_INT) pSynth->channels[pVoice->channel & 15].pan - 64;
371950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pan += pArt->pan;
372950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	EAS_CalcPanControl(pan, &pWTVoice->gainLeft, &pWTVoice->gainRight);
373950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
374950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
375950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef _FILTER_ENABLED
376950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* clear out the filter states */
377950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->filter.z1 = 0;
378950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	pWTVoice->filter.z2 = 0;
379950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
380950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
381950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* if this wave is to be generated using noise generator */
382950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (pRegion->region.keyGroupAndFlags & REGION_FLAG_USE_WAVE_GENERATOR)
383950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
384950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		pWTVoice->phaseAccum = 4574296;
385950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		pWTVoice->loopStart = WT_NOISE_GENERATOR;
386950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		pWTVoice->loopEnd = 4574295;
387950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
388950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
389950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* normal sample */
390950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	else
391950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
392950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
393950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef EAS_SPLIT_WT_SYNTH
394950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		if (voiceNum < NUM_PRIMARY_VOICES)
395950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com			pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex];
396950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		else
397950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com			pWTVoice->phaseAccum = pSynth->pEAS->pSampleOffsets[pRegion->waveIndex];
398950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#else
399950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex];
400950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
401950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
402950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		if (pRegion->region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED)
403950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		{
404950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com			pWTVoice->loopStart = pWTVoice->phaseAccum + pRegion->loopStart;
405950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com			pWTVoice->loopEnd = pWTVoice->phaseAccum + pRegion->loopEnd - 1;
406950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		}
407950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		else
408950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com			pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 1;
409950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
410950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
411950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#ifdef EAS_SPLIT_WT_SYNTH
412950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	/* configure off-chip voices */
413950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	if (voiceNum >= NUM_PRIMARY_VOICES)
414950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	{
415950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		wtConfig.phaseAccum = pWTVoice->phaseAccum;
416950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		wtConfig.loopStart = pWTVoice->loopStart;
417950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		wtConfig.loopEnd = pWTVoice->loopEnd;
418950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		wtConfig.gain = pVoice->gain;
419950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
420950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#if (NUM_OUTPUT_CHANNELS == 2)
421950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		wtConfig.gainLeft = pWTVoice->gainLeft;
422950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		wtConfig.gainRight = pWTVoice->gainRight;
423950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
424950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
425950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com		WTE_ConfigVoice(voiceNum - NUM_PRIMARY_VOICES, &wtConfig, pVoiceMgr->pFrameBuffer);
426950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	}
427950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com#endif
428950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
429950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com	return EAS_SUCCESS;
430950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com}
431950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com
432950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com/*----------------------------------------------------------------------------
433950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * WT_CheckSampleEnd
434950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com *----------------------------------------------------------------------------
435950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Purpose:
436950306ccf1af3f07944636df55daf3da878b7fc4fmalita@google.com * Check for end of sample and calculate number of samples to synthesize
437 *
438 * Inputs:
439 *
440 * Outputs:
441 *
442 * Notes:
443 *
444 *----------------------------------------------------------------------------
445*/
446EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update)
447{
448	EAS_U32 endPhaseAccum;
449	EAS_U32 endPhaseFrac;
450	EAS_I32 numSamples;
451	EAS_BOOL done = EAS_FALSE;
452
453	/* check to see if we hit the end of the waveform this time */
454	/*lint -e{703} use shift for performance */
455	endPhaseFrac = pWTVoice->phaseFrac + (pWTIntFrame->frame.phaseIncrement << SYNTH_UPDATE_PERIOD_IN_BITS);
456	endPhaseAccum = pWTVoice->phaseAccum + GET_PHASE_INT_PART(endPhaseFrac);
457	if (endPhaseAccum >= pWTVoice->loopEnd)
458	{
459		/* calculate how far current ptr is from end */
460		numSamples = (EAS_I32) (pWTVoice->loopEnd - pWTVoice->phaseAccum);
461
462		/* now account for the fractional portion */
463		/*lint -e{703} use shift for performance */
464		numSamples = (EAS_I32) ((numSamples << NUM_PHASE_FRAC_BITS) - pWTVoice->phaseFrac);
465		pWTIntFrame->numSamples = 1 + (numSamples / pWTIntFrame->frame.phaseIncrement);
466
467		/* sound will be done this frame */
468		done = EAS_TRUE;
469	}
470
471	/* update data for off-chip synth */
472	if (update)
473	{
474		pWTVoice->phaseFrac = endPhaseFrac;
475		pWTVoice->phaseAccum = endPhaseAccum;
476	}
477
478	return done;
479}
480
481/*----------------------------------------------------------------------------
482 * WT_UpdateVoice()
483 *----------------------------------------------------------------------------
484 * Purpose:
485 * Synthesize a block of samples for the given voice.
486 * Use linear interpolation.
487 *
488 * Inputs:
489 * pEASData - pointer to overall EAS data structure
490 *
491 * Outputs:
492 * number of samples actually written to buffer
493 *
494 * Side Effects:
495 * - samples are added to the presently free buffer
496 *
497 *----------------------------------------------------------------------------
498*/
499static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32  numSamples)
500{
501	S_WT_VOICE *pWTVoice;
502	S_WT_INT_FRAME intFrame;
503	S_SYNTH_CHANNEL *pChannel;
504	const S_WT_REGION *pWTRegion;
505	const S_ARTICULATION *pArt;
506	EAS_I32 temp;
507	EAS_BOOL done;
508
509#ifdef DLS_SYNTHESIZER
510	if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH)
511		return DLS_UpdateVoice(pVoiceMgr, pSynth, pVoice, voiceNum, pMixBuffer, numSamples);
512#endif
513
514	/* establish pointers to critical data */
515	pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
516	pWTRegion = &pSynth->pEAS->pWTRegions[pVoice->regionIndex & REGION_INDEX_MASK];
517	pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex];
518	pChannel = &pSynth->channels[pVoice->channel & 15];
519	intFrame.prevGain = pVoice->gain;
520
521	/* update the envelopes */
522	WT_UpdateEG1(pWTVoice, &pArt->eg1);
523	WT_UpdateEG2(pWTVoice, &pArt->eg2);
524
525	/* update the LFO */
526	WT_UpdateLFO(&pWTVoice->modLFO, pArt->lfoFreq);
527
528#ifdef _FILTER_ENABLED
529	/* calculate filter if library uses filter */
530	if (pSynth->pEAS->libAttr & LIB_FORMAT_FILTER_ENABLED)
531		WT_UpdateFilter(pWTVoice, &intFrame, pArt);
532	else
533		intFrame.frame.k = 0;
534#endif
535
536	/* update the gain */
537	intFrame.frame.gainTarget = WT_UpdateGain(pVoice, pWTVoice, pArt, pChannel, pWTRegion->gain);
538
539	/* calculate base pitch*/
540	temp = pChannel->staticPitch + pWTRegion->tuning;
541
542	/* include global transpose */
543	if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)
544		temp += pVoice->note * 100;
545	else
546		temp += (pVoice->note + pSynth->globalTranspose) * 100;
547	intFrame.frame.phaseIncrement = WT_UpdatePhaseInc(pWTVoice, pArt, pChannel, temp);
548
549	/* call into engine to generate samples */
550	intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer;
551	intFrame.pMixBuffer = pMixBuffer;
552	intFrame.numSamples = numSamples;
553
554	/* check for end of sample */
555	if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd))
556		done = WT_CheckSampleEnd(pWTVoice, &intFrame, (EAS_BOOL) (voiceNum >= NUM_PRIMARY_VOICES));
557	else
558		done = EAS_FALSE;
559
560#ifdef EAS_SPLIT_WT_SYNTH
561	if (voiceNum < NUM_PRIMARY_VOICES)
562	{
563#ifndef _SPLIT_WT_TEST_HARNESS
564		WT_ProcessVoice(pWTVoice, &intFrame);
565#endif
566	}
567	else
568		WTE_ProcessVoice(voiceNum - NUM_PRIMARY_VOICES, &intFrame.frame, pVoiceMgr->pFrameBuffer);
569#else
570	WT_ProcessVoice(pWTVoice, &intFrame);
571#endif
572
573	/* clear flag */
574	pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
575
576    /* if voice has finished, set flag for voice manager */
577	if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted))
578		done = EAS_TRUE;
579
580	/* if the update interval has elapsed, then force the current gain to the next
581	 * gain since we never actually reach the next gain when ramping -- we just get
582	 * very close to the target gain.
583	 */
584	pVoice->gain = (EAS_I16) intFrame.frame.gainTarget;
585
586	return done;
587}
588
589/*----------------------------------------------------------------------------
590 * WT_UpdatePhaseInc()
591 *----------------------------------------------------------------------------
592 * Purpose:
593 * Calculate the phase increment
594 *
595 * Inputs:
596 * pVoice - pointer to the voice being updated
597 * psRegion - pointer to the region
598 * psArticulation - pointer to the articulation
599 * nChannelPitchForThisVoice - the portion of the pitch that is fixed for this
600 *					voice during the duration of this synthesis
601 * pEASData - pointer to overall EAS data structure
602 *
603 * Outputs:
604 *
605 * Side Effects:
606 * set the phase increment for this voice
607 *----------------------------------------------------------------------------
608*/
609static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents)
610{
611	EAS_I32 temp;
612
613	/*pitchCents due to CC1 = LFO * (CC1 / 128) * DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS */
614	temp = MULT_EG1_EG1(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS,
615		((pChannel->modWheel) << (NUM_EG1_FRAC_BITS -7)));
616
617	/* pitchCents due to channel pressure = LFO * (channel pressure / 128) * DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS */
618	temp += MULT_EG1_EG1(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS,
619		 ((pChannel->channelPressure) << (NUM_EG1_FRAC_BITS -7)));
620
621	/* now multiply the (channel pressure + CC1) pitch values by the LFO value */
622	temp = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, temp);
623
624	/*
625	add in the LFO pitch due to
626	channel pressure and CC1 along with
627	the LFO pitch, the EG2 pitch, and the
628	"static" pitch for this voice on this channel
629	*/
630	temp += pitchCents +
631		(MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToPitch)) +
632		(MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToPitch));
633
634	/* convert from cents to linear phase increment */
635	return EAS_Calculate2toX(temp);
636}
637
638/*----------------------------------------------------------------------------
639 * WT_UpdateChannel()
640 *----------------------------------------------------------------------------
641 * Purpose:
642 * Calculate and assign static channel parameters
643 * These values only need to be updated if one of the controller values
644 * for this channel changes
645 *
646 * Inputs:
647 * nChannel - channel to update
648 * pEASData - pointer to overall EAS data structure
649 *
650 * Outputs:
651 *
652 * Side Effects:
653 * - the given channel's static gain and static pitch are updated
654 *----------------------------------------------------------------------------
655*/
656/*lint -esym(715, pVoiceMgr) reserved for future use */
657static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel)
658{
659	EAS_I32 staticGain;
660	EAS_I32 pitchBend;
661	S_SYNTH_CHANNEL *pChannel;
662
663	pChannel = &pSynth->channels[channel];
664
665	/*
666	nChannelGain = (CC7 * CC11)^2  * master volume
667	where CC7 == 100 by default, CC11 == 127, master volume == 32767
668	*/
669	staticGain = MULT_EG1_EG1((pChannel->volume) << (NUM_EG1_FRAC_BITS - 7),
670		(pChannel->expression) << (NUM_EG1_FRAC_BITS - 7));
671
672	/* staticGain has to be squared */
673	staticGain = MULT_EG1_EG1(staticGain, staticGain);
674
675	pChannel->staticGain = (EAS_I16) MULT_EG1_EG1(staticGain, pSynth->masterVolume);
676
677	/*
678	calculate pitch bend: RPN0 * ((2*pitch wheel)/16384  -1)
679	However, if we use the EG1 macros, remember that EG1 has a full
680	scale value of 32768 (instead of 16384). So instead of multiplying
681	by 2, multiply by 4 (left shift by 2), and subtract by 32768 instead
682	of 16384. This utilizes the fact that the EG1 macro places a binary
683	point 15 places to the left instead of 14 places.
684	*/
685	/*lint -e{703} <avoid multiply for performance>*/
686	pitchBend =
687		(((EAS_I32)(pChannel->pitchBend) << 2)
688		- 32768);
689
690	pChannel->staticPitch =
691		MULT_EG1_EG1(pitchBend, pChannel->pitchBendSensitivity);
692
693	/* if this is not a drum channel, then add in the per-channel tuning */
694	if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL))
695		pChannel->staticPitch += pChannel->finePitch + (pChannel->coarsePitch * 100);
696
697	/* clear update flag */
698	pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS;
699	return;
700}
701
702/*----------------------------------------------------------------------------
703 * WT_UpdateGain()
704 *----------------------------------------------------------------------------
705 * Purpose:
706 * Calculate and assign static voice parameters as part of WT_UpdateVoice()
707 *
708 * Inputs:
709 * pVoice - ptr to the synth voice that we want to synthesize
710 * pEASData - pointer to overall EAS data structure
711 *
712 * Outputs:
713 *
714 * Side Effects:
715 * - various voice parameters are calculated and assigned
716 *
717 *----------------------------------------------------------------------------
718*/
719static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain)
720{
721	EAS_I32 lfoGain;
722	EAS_I32 temp;
723
724	/*
725	If this voice was stolen, then the velocity is actually
726	for the new note, not the note that we are currently ramping down.
727	So we really shouldn't use this velocity. However, that would require
728	more memory to store the velocity value, and the improvement may
729	not be sufficient to warrant the added memory.
730	*/
731	/* velocity is fixed at note start for a given voice and must be squared */
732	temp = (pVoice->velocity) << (NUM_EG1_FRAC_BITS - 7);
733	temp = MULT_EG1_EG1(temp, temp);
734
735	/* region gain is fixed as part of the articulation */
736	temp = MULT_EG1_EG1(temp, gain);
737
738	/* include the channel gain */
739	temp = MULT_EG1_EG1(temp, pChannel->staticGain);
740
741	/* calculate LFO gain using an approximation for 10^x */
742	lfoGain = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToGain);
743	lfoGain = MULT_EG1_EG1(lfoGain, LFO_GAIN_TO_CENTS);
744
745	/* convert from a dB-like value to linear gain */
746	lfoGain = EAS_Calculate2toX(lfoGain);
747	temp = MULT_EG1_EG1(temp, lfoGain);
748
749	/* calculate the voice's gain */
750	temp = (EAS_I16)MULT_EG1_EG1(temp, pWTVoice->eg1Value);
751
752	return temp;
753}
754
755/*----------------------------------------------------------------------------
756 * WT_UpdateEG1()
757 *----------------------------------------------------------------------------
758 * Purpose:
759 * Calculate the EG1 envelope for the given voice (but do not update any
760 * state)
761 *
762 * Inputs:
763 * pVoice - ptr to the voice whose envelope we want to update
764 * nVoice - this voice's number - used only for debug
765 * pEASData - pointer to overall EAS data structure
766 *
767 * Outputs:
768 * nValue - the envelope value
769 *
770 * Side Effects:
771 * - updates EG1 state value for the given voice
772 *----------------------------------------------------------------------------
773*/
774static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv)
775{
776	EAS_I32 temp;
777
778	switch (pWTVoice->eg1State)
779	{
780		case eEnvelopeStateAttack:
781			temp = pWTVoice->eg1Value + pWTVoice->eg1Increment;
782
783			/* check if we have reached peak amplitude */
784			if (temp >= SYNTH_FULL_SCALE_EG1_GAIN)
785			{
786				/* limit the volume */
787				temp = SYNTH_FULL_SCALE_EG1_GAIN;
788
789				/* prepare to move to decay state */
790				pWTVoice->eg1State = eEnvelopeStateDecay;
791				pWTVoice->eg1Increment = pEnv->decayTime;
792			}
793
794			break;
795
796		/* exponential decay */
797		case eEnvelopeStateDecay:
798			temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment);
799
800			/* check if we have reached sustain level */
801			if (temp <= pEnv->sustainLevel)
802			{
803				/* enforce the sustain level */
804				temp = pEnv->sustainLevel;
805
806				/* if sustain level is zero, skip sustain & release the voice */
807				if (temp > 0)
808					pWTVoice->eg1State = eEnvelopeStateSustain;
809
810				/* move to sustain state */
811				else
812					pWTVoice->eg1State = eEnvelopeStateMuted;
813			}
814
815			break;
816
817		case eEnvelopeStateSustain:
818			return;
819
820		case eEnvelopeStateRelease:
821			temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment);
822
823	        /* if we hit zero, this voice isn't contributing any audio */
824			if (temp <= 0)
825			{
826				temp = 0;
827				pWTVoice->eg1State = eEnvelopeStateMuted;
828			}
829			break;
830
831		/* voice is muted, set target to zero */
832		case eEnvelopeStateMuted:
833			temp = 0;
834			break;
835
836		case eEnvelopeStateInvalid:
837		default:
838			temp = 0;
839#ifdef	_DEBUG_SYNTH
840			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG1: error, %d is an unrecognized state\n",
841				pWTVoice->eg1State); */ }
842#endif
843			break;
844
845	}
846
847	pWTVoice->eg1Value = (EAS_I16) temp;
848}
849
850/*----------------------------------------------------------------------------
851 * WT_UpdateEG2()
852 *----------------------------------------------------------------------------
853 * Purpose:
854 * Update the EG2 envelope for the given voice
855 *
856 * Inputs:
857 * pVoice - ptr to the voice whose envelope we want to update
858 * pEASData - pointer to overall EAS data structure
859 *
860 * Outputs:
861 *
862 * Side Effects:
863 * - updates EG2 values for the given voice
864 *----------------------------------------------------------------------------
865*/
866
867static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv)
868{
869	EAS_I32 temp;
870
871	switch (pWTVoice->eg2State)
872	{
873		case eEnvelopeStateAttack:
874			temp = pWTVoice->eg2Value + pWTVoice->eg2Increment;
875
876			/* check if we have reached peak amplitude */
877			if (temp >= SYNTH_FULL_SCALE_EG1_GAIN)
878			{
879				/* limit the volume */
880				temp = SYNTH_FULL_SCALE_EG1_GAIN;
881
882				/* prepare to move to decay state */
883				pWTVoice->eg2State = eEnvelopeStateDecay;
884
885				pWTVoice->eg2Increment = pEnv->decayTime;
886			}
887
888			break;
889
890			/* implement linear pitch decay in cents */
891		case eEnvelopeStateDecay:
892			temp = pWTVoice->eg2Value -pWTVoice->eg2Increment;
893
894			/* check if we have reached sustain level */
895			if (temp <= pEnv->sustainLevel)
896			{
897				/* enforce the sustain level */
898				temp = pEnv->sustainLevel;
899
900				/* prepare to move to sustain state */
901				pWTVoice->eg2State = eEnvelopeStateSustain;
902			}
903			break;
904
905		case eEnvelopeStateSustain:
906			return;
907
908		case eEnvelopeStateRelease:
909			temp = pWTVoice->eg2Value - pWTVoice->eg2Increment;
910
911			if (temp <= 0)
912			{
913				temp = 0;
914				pWTVoice->eg2State = eEnvelopeStateMuted;
915			}
916
917			break;
918
919		/* voice is muted, set target to zero */
920		case eEnvelopeStateMuted:
921			temp = 0;
922			break;
923
924		case eEnvelopeStateInvalid:
925		default:
926			temp = 0;
927#ifdef	_DEBUG_SYNTH
928			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG2: error, %d is an unrecognized state\n",
929				pWTVoice->eg2State); */ }
930#endif
931			break;
932	}
933
934	pWTVoice->eg2Value = (EAS_I16) temp;
935}
936
937/*----------------------------------------------------------------------------
938 * WT_UpdateLFO ()
939 *----------------------------------------------------------------------------
940 * Purpose:
941 * Calculate the LFO for the given voice
942 *
943 * Inputs:
944 * pLFO			- ptr to the LFO data
945 * phaseInc		- phase increment
946 *
947 * Outputs:
948 *
949 * Side Effects:
950 * - updates LFO values for the given voice
951 *----------------------------------------------------------------------------
952*/
953void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc)
954{
955
956	/* To save memory, if m_nPhaseValue is negative, we are in the
957	 * delay phase, and m_nPhaseValue represents the time left
958	 * in the delay.
959	 */
960	 if (pLFO->lfoPhase < 0)
961	 {
962	 	pLFO->lfoPhase++;
963		return;
964	 }
965
966	/* calculate LFO output from phase value */
967	/*lint -e{701} Use shift for performance */
968	pLFO->lfoValue = (EAS_I16) (pLFO->lfoPhase << 2);
969	/*lint -e{502} <shortcut to turn sawtooth into triangle wave> */
970	if ((pLFO->lfoPhase > 0x1fff) && (pLFO->lfoPhase < 0x6000))
971		pLFO->lfoValue = ~pLFO->lfoValue;
972
973	/* update LFO phase */
974	pLFO->lfoPhase = (pLFO->lfoPhase + phaseInc) & 0x7fff;
975}
976
977#ifdef _FILTER_ENABLED
978/*----------------------------------------------------------------------------
979 * WT_UpdateFilter()
980 *----------------------------------------------------------------------------
981 * Purpose:
982 * Update the Filter parameters
983 *
984 * Inputs:
985 * pVoice - ptr to the voice whose filter we want to update
986 * pEASData - pointer to overall EAS data structure
987 *
988 * Outputs:
989 *
990 * Side Effects:
991 * - updates Filter values for the given voice
992 *----------------------------------------------------------------------------
993*/
994static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt)
995{
996	EAS_I32 cutoff;
997
998	/* no need to calculate filter coefficients if it is bypassed */
999	if (pArt->filterCutoff == DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY)
1000	{
1001		pIntFrame->frame.k = 0;
1002		return;
1003	}
1004
1005	/* determine the dynamic cutoff frequency */
1006	cutoff = MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToFc);
1007	cutoff += pArt->filterCutoff;
1008
1009	/* subtract the A5 offset and the sampling frequency */
1010	cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS;
1011
1012	/* limit the cutoff frequency */
1013	if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS)
1014		cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS;
1015	else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS)
1016		cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS;
1017
1018	WT_SetFilterCoeffs(pIntFrame, cutoff, pArt->filterQ);
1019}
1020#endif
1021
1022#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER)
1023/*----------------------------------------------------------------------------
1024 * coef
1025 *----------------------------------------------------------------------------
1026 * Table of filter coefficients for low-pass filter
1027 *----------------------------------------------------------------------------
1028 *
1029 * polynomial coefficients are based on 8kHz sampling frequency
1030 * filter coef b2 = k2 = k2g0*k^0 + k2g1*k^1*(2^x) + k2g2*k^2*(2^x)
1031 *
1032 *where k2g0, k2g1, k2g2 are from the truncated power series expansion on theta
1033 *(k*2^x = theta, but we incorporate the k along with the k2g0, k2g1, k2g2)
1034 *note: this is a power series in 2^x, not k*2^x
1035 *where k = (2*pi*440)/8kHz == convert octaves to radians
1036 *
1037 *  so actually, the following coefs listed as k2g0, k2g1, k2g2 are really
1038 *  k2g0*k^0 = k2g0
1039 *  k2g1*k^1
1040 *  k2g2*k^2
1041 *
1042 *
1043 * filter coef n1 = numerator = n1g0*k^0 + n1g1*k^1*(2^x) + n1g2*k^2*(2^x) + n1g3*k^3*(2^x)
1044 *
1045 *where n1g0, n1g1, n1g2, n1g3 are from the truncated power series expansion on theta
1046 *(k*2^x = theta, but we incorporate the k along with the n1g0, n1g1, n1g2, n2g3)
1047 *note: this is a power series in 2^x, not k*2^x
1048 *where k = (2*pi*440)/8kHz == convert octaves to radians
1049 *we also include the optimization factor of 0.81
1050 *
1051 *  so actually, the following coefs listed as n1g0, n1g1, n1g2, n2g3 are really
1052 *  n1g0*k^0 = n1g0
1053 *  n1g1*k^1
1054 *  n1g2*k^2
1055 *  n1g3*k^3
1056 *
1057 *	NOTE that n1g0 == n1g1 == 0, always, so we only need to store n1g2 and n1g3
1058 *----------------------------------------------------------------------------
1059*/
1060
1061static const EAS_I16 nk1g0 = -32768;
1062static const EAS_I16 nk1g2 = 1580;
1063static const EAS_I16 k2g0 = 32767;
1064
1065static const EAS_I16 k2g1[] =
1066{
1067		-11324,	/* k2g1[0] = -0.3455751918948761 */
1068		-10387,	/* k2g1[1] = -0.3169878073928751 */
1069		-9528,	/* k2g1[2] = -0.29076528753345476 */
1070		-8740,	/* k2g1[3] = -0.2667120011011279 */
1071		-8017,	/* k2g1[4] = -0.24464850028971705 */
1072		-7353,	/* k2g1[5] = -0.22441018194495696 */
1073		-6745,	/* k2g1[6] = -0.20584605955455101 */
1074		-6187,	/* k2g1[7] = -0.18881763682420102 */
1075		-5675,	/* k2g1[8] = -0.1731978744360067 */
1076		-5206,	/* k2g1[9] = -0.15887024228080968 */
1077		-4775,	/* k2g1[10] = -0.14572785009373057 */
1078		-4380,	/* k2g1[11] = -0.13367265000706827 */
1079		-4018,	/* k2g1[12] = -0.1226147050712642 */
1080		-3685,	/* k2g1[13] = -0.11247151828678581 */
1081		-3381,	/* k2g1[14] = -0.10316741714122014 */
1082		-3101,	/* k2g1[15] = -0.0946329890599603 */
1083		-2844,	/* k2g1[16] = -0.08680456355870586 */
1084		-2609,	/* k2g1[17] = -0.07962373723441349 */
1085		-2393,	/* k2g1[18] = -0.07303693805092666 */
1086		-2195,	/* k2g1[19] = -0.06699502566866912 */
1087		-2014,	/* k2g1[20] = -0.06145292483669077 */
1088		-1847,	/* k2g1[21] = -0.056369289112013346 */
1089		-1694,	/* k2g1[22] = -0.05170619239747895 */
1090		-1554,	/* k2g1[23] = -0.04742884599684141 */
1091		-1426,	/* k2g1[24] = -0.043505339076210514 */
1092		-1308,	/* k2g1[25] = -0.03990640059558053 */
1093		-1199,	/* k2g1[26] = -0.03660518093435039 */
1094		-1100,	/* k2g1[27] = -0.03357705158166837 */
1095		-1009,	/* k2g1[28] = -0.030799421397205727 */
1096		-926,	/* k2g1[29] = -0.028251568071585884 */
1097		-849	/* k2g1[30] = -0.025914483529091967 */
1098};
1099
1100static const EAS_I16 k2g2[] =
1101{
1102		1957,	/* k2g2[0] = 0.059711106626580836 */
1103		1646,	/* k2g2[1] = 0.05024063501786333 */
1104		1385,	/* k2g2[2] = 0.042272226217199664 */
1105		1165,	/* k2g2[3] = 0.03556764576567844 */
1106		981,	/* k2g2[4] = 0.029926444346999134 */
1107		825,	/* k2g2[5] = 0.025179964880280382 */
1108		694,	/* k2g2[6] = 0.02118630011706455 */
1109		584,	/* k2g2[7] = 0.01782604998793514 */
1110		491,	/* k2g2[8] = 0.014998751854573014 */
1111		414,	/* k2g2[9] = 0.012619876941179595 */
1112		348,	/* k2g2[10] = 0.010618303146468736 */
1113		293,	/* k2g2[11] = 0.008934188679954682 */
1114		246,	/* k2g2[12] = 0.007517182949855368 */
1115		207,	/* k2g2[13] = 0.006324921212866403 */
1116		174,	/* k2g2[14] = 0.005321757979794424 */
1117		147,	/* k2g2[15] = 0.004477701309210577 */
1118		123,	/* k2g2[16] = 0.00376751612730811 */
1119		104,	/* k2g2[17] = 0.0031699697655869644 */
1120		87,		/* k2g2[18] = 0.00266719715992703 */
1121		74,		/* k2g2[19] = 0.0022441667321724647 */
1122		62,		/* k2g2[20] = 0.0018882309854916855 */
1123		52,		/* k2g2[21] = 0.0015887483774966232 */
1124		44,		/* k2g2[22] = 0.0013367651661223448 */
1125		37,		/* k2g2[23] = 0.0011247477162958733 */
1126		31,		/* k2g2[24] = 0.0009463572640678758 */
1127		26,		/* k2g2[25] = 0.0007962604042473498 */
1128		22,		/* k2g2[26] = 0.0006699696356181593 */
1129		18,		/* k2g2[27] = 0.0005637091964589207 */
1130		16,		/* k2g2[28] = 0.00047430217920125243 */
1131		13,		/* k2g2[29] = 0.00039907554925166274 */
1132		11		/* k2g2[30] = 0.00033578022828973666 */
1133};
1134
1135static const EAS_I16 n1g2[] =
1136{
1137		3170,	/* n1g2[0] = 0.0967319927350769 */
1138		3036,	/* n1g2[1] = 0.0926446051254155 */
1139		2908,	/* n1g2[2] = 0.08872992911818503 */
1140		2785,	/* n1g2[3] = 0.08498066682523227 */
1141		2667,	/* n1g2[4] = 0.08138982872895201 */
1142		2554,	/* n1g2[5] = 0.07795072065216213 */
1143		2446,	/* n1g2[6] = 0.0746569312785634 */
1144		2343,	/* n1g2[7] = 0.07150232020051943 */
1145		2244,	/* n1g2[8] = 0.06848100647187474 */
1146		2149,	/* n1g2[9] = 0.06558735764447099 */
1147		2058,	/* n1g2[10] = 0.06281597926792246 */
1148		1971,	/* n1g2[11] = 0.06016170483307614 */
1149		1888,	/* n1g2[12] = 0.05761958614040857 */
1150		1808,	/* n1g2[13] = 0.05518488407540374 */
1151		1732,	/* n1g2[14] = 0.052853059773715245 */
1152		1659,	/* n1g2[15] = 0.05061976615964251 */
1153		1589,	/* n1g2[16] = 0.04848083984214659 */
1154		1521,	/* n1g2[17] = 0.046432293353298 */
1155		1457,	/* n1g2[18] = 0.04447030771468711 */
1156		1396,	/* n1g2[19] = 0.04259122531793907 */
1157		1337,	/* n1g2[20] = 0.040791543106060944 */
1158		1280,	/* n1g2[21] = 0.03906790604290942 */
1159		1226,	/* n1g2[22] = 0.037417100858604564 */
1160		1174,	/* n1g2[23] = 0.035836050059229754 */
1161		1125,	/* n1g2[24] = 0.03432180618965023 */
1162		1077,	/* n1g2[25] = 0.03287154633875494 */
1163		1032,	/* n1g2[26] = 0.03148256687687814 */
1164		988,	/* n1g2[27] = 0.030152278415589925 */
1165		946,	/* n1g2[28] = 0.028878200980459685 */
1166		906,	/* n1g2[29] = 0.02765795938779331 */
1167		868		/* n1g2[30] = 0.02648927881672521 */
1168};
1169
1170static const EAS_I16 n1g3[] =
1171{
1172		-548,	/* n1g3[0] = -0.016714088475899017 */
1173		-481,	/* n1g3[1] = -0.014683605122742116 */
1174		-423,	/* n1g3[2] = -0.012899791676436092 */
1175		-371,	/* n1g3[3] = -0.01133268185193299 */
1176		-326,	/* n1g3[4] = -0.00995594976868754 */
1177		-287,	/* n1g3[5] = -0.008746467702146129 */
1178		-252,	/* n1g3[6] = -0.00768391756106361 */
1179		-221,	/* n1g3[7] = -0.006750449563854721 */
1180		-194,	/* n1g3[8] = -0.005930382380083576 */
1181		-171,	/* n1g3[9] = -0.005209939699767622 */
1182		-150,	/* n1g3[10] = -0.004577018805123356 */
1183		-132,	/* n1g3[11] = -0.004020987256990177 */
1184		-116,	/* n1g3[12] = -0.003532504280467257 */
1185		-102,	/* n1g3[13] = -0.00310336384922047 */
1186		-89,	/* n1g3[14] = -0.002726356832432369 */
1187		-78,	/* n1g3[15] = -0.002395149888601605 */
1188		-69,	/* n1g3[16] = -0.0021041790717285314 */
1189		-61,	/* n1g3[17] = -0.0018485563625771063 */
1190		-53,	/* n1g3[18] = -0.001623987554831628 */
1191		-47,	/* n1g3[19] = -0.0014267001167177025 */
1192		-41,	/* n1g3[20] = -0.0012533798162347005 */
1193		-36,	/* n1g3[21] = -0.0011011150453668693 */
1194		-32,	/* n1g3[22] = -0.0009673479079754438 */
1195		-28,	/* n1g3[23] = -0.0008498312496971563 */
1196		-24,	/* n1g3[24] = -0.0007465909079943587 */
1197		-21,	/* n1g3[25] = -0.0006558925481952733 */
1198		-19,	/* n1g3[26] = -0.0005762125284029567 */
1199		-17,	/* n1g3[27] = -0.0005062123038325457 */
1200		-15,	/* n1g3[28] = -0.0004447159405951901 */
1201		-13,	/* n1g3[29] = -0.00039069036118270117 */
1202		-11		/* n1g3[30] = -0.00034322798979677605 */
1203};
1204
1205/*----------------------------------------------------------------------------
1206 * WT_SetFilterCoeffs()
1207 *----------------------------------------------------------------------------
1208 * Purpose:
1209 * Update the Filter parameters
1210 *
1211 * Inputs:
1212 * pVoice - ptr to the voice whose filter we want to update
1213 * pEASData - pointer to overall EAS data structure
1214 *
1215 * Outputs:
1216 *
1217 * Side Effects:
1218 * - updates Filter values for the given voice
1219 *----------------------------------------------------------------------------
1220*/
1221void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance)
1222{
1223	EAS_I32 temp;
1224
1225	/*
1226	Convert the cutoff, which has had A5 subtracted, using the 2^x approx
1227	Note, this cutoff is related to theta cutoff by
1228	theta = k * 2^x
1229	We use 2^x and incorporate k in the power series coefs instead
1230	*/
1231	cutoff = EAS_Calculate2toX(cutoff);
1232
1233	/* calculate b2 coef */
1234	temp = k2g1[resonance] + MULT_AUDIO_COEF(cutoff, k2g2[resonance]);
1235	temp = k2g0 + MULT_AUDIO_COEF(cutoff, temp);
1236	pIntFrame->frame.b2 = temp;
1237
1238	/* calculate b1 coef */
1239	temp = MULT_AUDIO_COEF(cutoff, nk1g2);
1240	temp = nk1g0 + MULT_AUDIO_COEF(cutoff, temp);
1241	temp += MULT_AUDIO_COEF(temp, pIntFrame->frame.b2);
1242	pIntFrame->frame.b1 = temp >> 1;
1243
1244	/* calculate K coef */
1245	temp = n1g2[resonance] + MULT_AUDIO_COEF(cutoff, n1g3[resonance]);
1246	temp = MULT_AUDIO_COEF(cutoff, temp);
1247	temp = MULT_AUDIO_COEF(cutoff, temp);
1248	pIntFrame->frame.k = temp;
1249}
1250#endif
1251
1252