\r
INLINE void StartADSR(int ch) // MIX ADSR\r
{\r
- s_chan[ch].ADSRX.State=0; // and init some adsr vars\r
+ s_chan[ch].ADSRX.State=ADSR_ATTACK; // and init some adsr vars\r
s_chan[ch].ADSRX.EnvelopeVol=0;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-static int MixADSR(int ch, int ns_to) // MIX ADSR\r
+static int MixADSR(ADSRInfoEx *adsr, int ns_to)\r
{\r
- int EnvelopeVol = s_chan[ch].ADSRX.EnvelopeVol;\r
+ int EnvelopeVol = adsr->EnvelopeVol;\r
int ns = 0, val, rto, level;\r
\r
- if (s_chan[ch].bStop) // should be stopped:\r
- { // do release\r
- val = RateTableSub[s_chan[ch].ADSRX.ReleaseRate * 4];\r
+ if (adsr->State == ADSR_RELEASE)\r
+ {\r
+ val = RateTableSub[adsr->ReleaseRate * 4];\r
\r
- if (s_chan[ch].ADSRX.ReleaseModeExp)\r
+ if (adsr->ReleaseModeExp)\r
{\r
for (; ns < ns_to; ns++)\r
{\r
goto done;\r
}\r
\r
- switch (s_chan[ch].ADSRX.State)\r
+ switch (adsr->State)\r
{\r
- case 0: // -> attack\r
+ case ADSR_ATTACK: // -> attack\r
rto = 0;\r
- if (s_chan[ch].ADSRX.AttackModeExp && EnvelopeVol >= 0x60000000)\r
+ if (adsr->AttackModeExp && EnvelopeVol >= 0x60000000)\r
rto = 8;\r
- val = RateTableAdd[s_chan[ch].ADSRX.AttackRate + rto];\r
+ val = RateTableAdd[adsr->AttackRate + rto];\r
\r
for (; ns < ns_to; ns++)\r
{\r
if (EnvelopeVol < 0) // overflow\r
{\r
EnvelopeVol = 0x7fffffff;\r
- s_chan[ch].ADSRX.State = 1;\r
+ adsr->State = ADSR_DECAY;\r
ns++; // sample is good already\r
goto decay;\r
}\r
\r
//--------------------------------------------------//\r
decay:\r
- case 1: // -> decay\r
- val = RateTableSub[s_chan[ch].ADSRX.DecayRate * 4];\r
- level = s_chan[ch].ADSRX.SustainLevel;\r
+ case ADSR_DECAY: // -> decay\r
+ val = RateTableSub[adsr->DecayRate * 4];\r
+ level = adsr->SustainLevel;\r
\r
for (; ns < ns_to; )\r
{\r
\r
if (((EnvelopeVol >> 27) & 0xf) <= level)\r
{\r
- s_chan[ch].ADSRX.State = 2;\r
+ adsr->State = ADSR_SUSTAIN;\r
goto sustain;\r
}\r
}\r
\r
//--------------------------------------------------//\r
sustain:\r
- case 2: // -> sustain\r
- if (s_chan[ch].ADSRX.SustainIncrease)\r
+ case ADSR_SUSTAIN: // -> sustain\r
+ if (adsr->SustainIncrease)\r
{\r
if (EnvelopeVol >= 0x7fff0000)\r
{\r
}\r
\r
rto = 0;\r
- if (s_chan[ch].ADSRX.SustainModeExp && EnvelopeVol >= 0x60000000)\r
+ if (adsr->SustainModeExp && EnvelopeVol >= 0x60000000)\r
rto = 8;\r
- val = RateTableAdd[s_chan[ch].ADSRX.SustainRate + rto];\r
+ val = RateTableAdd[adsr->SustainRate + rto];\r
\r
for (; ns < ns_to; ns++)\r
{\r
}\r
else\r
{\r
- val = RateTableSub[s_chan[ch].ADSRX.SustainRate];\r
- if (s_chan[ch].ADSRX.SustainModeExp)\r
+ val = RateTableSub[adsr->SustainRate];\r
+ if (adsr->SustainModeExp)\r
{\r
for (; ns < ns_to; ns++)\r
{\r
}\r
\r
done:\r
- s_chan[ch].ADSRX.EnvelopeVol = EnvelopeVol;\r
+ adsr->EnvelopeVol = EnvelopeVol;\r
return ns;\r
}\r
\r
// struct defines\r
///////////////////////////////////////////////////////////\r
\r
+enum ADSR_State {\r
+ ADSR_ATTACK = 0,\r
+ ADSR_DECAY = 1,\r
+ ADSR_SUSTAIN = 2,\r
+ ADSR_RELEASE = 3,\r
+};\r
+\r
// ADSR INFOS PER CHANNEL\r
typedef struct\r
{\r
- unsigned char State:2;\r
+ unsigned char State:2; // ADSR_State\r
unsigned char AttackModeExp:1;\r
unsigned char SustainModeExp:1;\r
unsigned char SustainIncrease:1;\r
unsigned char * pCurr; // current pos in sound mem\r
unsigned char * pLoop; // loop ptr in sound mem\r
\r
- unsigned int bStop:1; // is channel stopped (sample _can_ still be playing, ADSR Release phase)\r
unsigned int bReverb:1; // can we do reverb on this channel? must have ctrl register bit, to get active\r
unsigned int bRVBActive:1; // reverb active flag\r
unsigned int bNoise:1; // noise active flag\r
d->iCurr = 0; // set by the caller\r
d->iLoop = 0; // set by the caller\r
d->bOn = !!(spu.dwChannelOn & (1<<ch));\r
- d->bStop = s->bStop;\r
+ d->bStop = s->ADSRX.State == ADSR_RELEASE;\r
d->bReverb = s->bReverb;\r
d->iActFreq = 1;\r
d->iUsedFreq = 2;\r
memcpy(d->SB, s->SB, sizeof(d->SB));\r
d->pCurr = (void *)((long)s->iCurr & 0x7fff0);\r
d->pLoop = (void *)((long)s->iLoop & 0x7fff0);\r
- d->bStop = s->bStop;\r
d->bReverb = s->bReverb;\r
d->iLeftVolume = s->iLeftVolume;\r
d->iRightVolume = s->iRightVolume;\r
d->bFMod = s->bFMod;\r
d->prevflags = (s->bIgnoreLoop >> 1) ^ 2;\r
d->ADSRX.State = s->ADSRX.State;\r
+ if (s->bStop) d->ADSRX.State = ADSR_RELEASE;\r
d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
d->ADSRX.DecayRate = s->ADSRX.DecayRate;\r
\r
for(i=0;i<MAXCHAN;i++)\r
{\r
- s_chan[i].bStop=0;\r
s_chan[i].pLoop=spu.spuMemC;\r
}\r
\r