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