# spu
OBJS += plugins/dfsound/dma.o plugins/dfsound/freeze.o \
plugins/dfsound/registers.o plugins/dfsound/spu.o
-plugins/dfsound/spu.o: plugins/dfsound/xa.c
+plugins/dfsound/spu.o: plugins/dfsound/adsr.c plugins/dfsound/reverb.c \
+ plugins/dfsound/xa.c
+plugins/dfsound/%.o: CFLAGS += -Wall
ifeq "$(USE_OSS)" "1"
plugins/dfsound/%.o: CFLAGS += -DUSEOSS
OBJS += plugins/dfsound/oss.o
# gpu
plugins/dfxvideo/%.o: CFLAGS += -Wall
OBJS += plugins/dfxvideo/gpu.o
+plugins/dfxvideo/gpu.o: plugins/dfxvideo/fps.c plugins/dfxvideo/prim.c \
+ plugins/dfxvideo/gpu.c plugins/dfxvideo/soft.c
ifdef X11
LDFLAGS += -lX11 -lXv
OBJS += plugins/dfxvideo/draw.o
\r
INLINE void StartADSR(int ch) // MIX ADSR\r
{\r
- s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars\r
- s_chan[ch].ADSRX.State=0;\r
+ s_chan[ch].ADSRX.State=0; // and init some adsr vars\r
s_chan[ch].ADSRX.EnvelopeVol=0;\r
}\r
\r
//s_chan[ch].bNoise=0;\r
}\r
\r
- s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;\r
- return s_chan[ch].ADSRX.lVolume;\r
+ return s_chan[ch].ADSRX.EnvelopeVol>>21;\r
}\r
else // not stopped yet?\r
{\r
s_chan[ch].ADSRX.State=1;\r
}\r
\r
- s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;\r
- return s_chan[ch].ADSRX.lVolume;\r
+ return s_chan[ch].ADSRX.EnvelopeVol>>21;\r
}\r
//--------------------------------------------------//\r
if(s_chan[ch].ADSRX.State==1) // -> decay\r
s_chan[ch].ADSRX.State=2;\r
}\r
\r
- s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;\r
- return s_chan[ch].ADSRX.lVolume;\r
+ return s_chan[ch].ADSRX.EnvelopeVol>>21;\r
}\r
//--------------------------------------------------//\r
if(s_chan[ch].ADSRX.State==2) // -> sustain\r
s_chan[ch].ADSRX.EnvelopeVol=0;\r
}\r
}\r
- s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;\r
- return s_chan[ch].ADSRX.lVolume;\r
+ return s_chan[ch].ADSRX.EnvelopeVol>>21;\r
}\r
}\r
return 0;\r
\r
typedef struct\r
{\r
- int State;\r
- int AttackModeExp;\r
- int AttackRate;\r
- int DecayRate;\r
- int SustainLevel;\r
- int SustainModeExp;\r
- int SustainIncrease;\r
- int SustainRate;\r
- int ReleaseModeExp;\r
- int ReleaseRate;\r
+ unsigned char State:2;\r
+ unsigned char AttackModeExp:1;\r
+ unsigned char SustainModeExp:1;\r
+ unsigned char SustainIncrease:1;\r
+ unsigned char ReleaseModeExp:1;\r
+ unsigned char AttackRate;\r
+ unsigned char DecayRate;\r
+ unsigned char SustainLevel;\r
+ unsigned char SustainRate;\r
+ unsigned char ReleaseRate;\r
int EnvelopeVol;\r
- long lVolume;\r
- long lDummy1;\r
- long lDummy2;\r
} ADSRInfoEx;\r
\r
///////////////////////////////////////////////////////////\r
// MAIN CHANNEL STRUCT\r
typedef struct\r
{\r
- // no mutexes used anymore... don't need them to sync access\r
- //HANDLE hMutex;\r
-\r
- int bNew; // start flag\r
-\r
int iSBPos; // mixing stuff\r
int spos;\r
int sinc;\r
- int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :)\r
- int sval;\r
\r
unsigned char * pStart; // start ptr into sound mem\r
unsigned char * pCurr; // current pos in sound mem\r
unsigned char * pLoop; // loop ptr in sound mem\r
\r
- int bOn; // is channel active (sample playing?)\r
- int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase)\r
- int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active\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 bIgnoreLoop:1; // ignore loop bit, if an external loop address is used\r
+ unsigned int bRVBActive:1; // reverb active flag\r
+ unsigned int bNoise:1; // noise active flag\r
+ unsigned int bFMod:2; // freq mod (0=off, 1=sound channel, 2=freq channel)\r
+\r
int iActFreq; // current psx pitch\r
int iUsedFreq; // current pc pitch\r
int iLeftVolume; // left volume\r
- int iLeftVolRaw; // left psx volume value\r
- int bIgnoreLoop; // ignore loop bit, if an external loop address is used\r
- int iMute; // mute mode\r
int iRightVolume; // right volume\r
- int iRightVolRaw; // right psx volume value\r
- int iRawPitch; // raw pitch (0...3fff)\r
- int iIrqDone; // debug irq done flag\r
int s_1; // last decoding infos\r
int s_2;\r
- int bRVBActive; // reverb active flag\r
+ ADSRInfoEx ADSRX;\r
+ int iRawPitch; // raw pitch (0...3fff)\r
+\r
int iRVBOffset; // reverb offset\r
int iRVBRepeat; // reverb repeat\r
- int bNoise; // noise active flag\r
- int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel)\r
int iRVBNum; // another reverb helper\r
int iOldNoise; // old noise val for this channel \r
- ADSRInfo ADSR; // active ADSR settings\r
- ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start)\r
+\r
+ int SB[32+32];\r
} SPUCHAN;\r
\r
///////////////////////////////////////////////////////////\r
extern int bEndThread; \r
extern int bThreadEnded;\r
extern int bSpuInit;\r
-extern unsigned long dwNewChannel;\r
+extern unsigned int dwNewChannel;\r
+extern unsigned int dwChannelOn;\r
\r
extern int SSumR[];\r
extern int SSumL[];\r
// freeze structs\r
////////////////////////////////////////////////////////////////////////\r
\r
+typedef struct\r
+{\r
+ int State;\r
+ int AttackModeExp;\r
+ int AttackRate;\r
+ int DecayRate;\r
+ int SustainLevel;\r
+ int SustainModeExp;\r
+ int SustainIncrease;\r
+ int SustainRate;\r
+ int ReleaseModeExp;\r
+ int ReleaseRate;\r
+ int EnvelopeVol;\r
+ long lVolume;\r
+ long lDummy1;\r
+ long lDummy2;\r
+} ADSRInfoEx_orig;\r
+\r
+typedef struct\r
+{\r
+ // no mutexes used anymore... don't need them to sync access\r
+ //HANDLE hMutex;\r
+\r
+ int bNew; // start flag\r
+\r
+ int iSBPos; // mixing stuff\r
+ int spos;\r
+ int sinc;\r
+ int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :)\r
+ int sval;\r
+\r
+ unsigned char * pStart; // start ptr into sound mem\r
+ unsigned char * pCurr; // current pos in sound mem\r
+ unsigned char * pLoop; // loop ptr in sound mem\r
+\r
+ int bOn; // is channel active (sample playing?)\r
+ int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase)\r
+ int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active\r
+ int iActFreq; // current psx pitch\r
+ int iUsedFreq; // current pc pitch\r
+ int iLeftVolume; // left volume\r
+ int iLeftVolRaw; // left psx volume value\r
+ int bIgnoreLoop; // ignore loop bit, if an external loop address is used\r
+ int iMute; // mute mode\r
+ int iRightVolume; // right volume\r
+ int iRightVolRaw; // right psx volume value\r
+ int iRawPitch; // raw pitch (0...3fff)\r
+ int iIrqDone; // debug irq done flag\r
+ int s_1; // last decoding infos\r
+ int s_2;\r
+ int bRVBActive; // reverb active flag\r
+ int iRVBOffset; // reverb offset\r
+ int iRVBRepeat; // reverb repeat\r
+ int bNoise; // noise active flag\r
+ int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel)\r
+ int iRVBNum; // another reverb helper\r
+ int iOldNoise; // old noise val for this channel \r
+ ADSRInfo ADSR; // active ADSR settings\r
+ ADSRInfoEx_orig ADSRX; // next ADSR settings (will be moved to active on sample start)\r
+} SPUCHAN_orig;\r
+\r
typedef struct\r
{\r
char szSPUName[8];\r
uint32_t dummy2;\r
uint32_t dummy3;\r
\r
- SPUCHAN s_chan[MAXCHAN]; \r
+ SPUCHAN_orig s_chan[MAXCHAN]; \r
\r
} SPUOSSFreeze_t;\r
\r
\r
extern int lastch;\r
\r
+// we want to retain compatibility between versions,\r
+// so use original channel struct\r
+static void save_channel(SPUCHAN_orig *d, SPUCHAN *s, int ch)\r
+{\r
+ memset(d, 0, sizeof(*d));\r
+ d->bNew = !!(dwNewChannel & (1<<ch));\r
+ d->iSBPos = s->iSBPos;\r
+ d->spos = s->spos;\r
+ d->sinc = s->sinc;\r
+ memcpy(d->SB, s->SB, sizeof(d->SB));\r
+ d->pStart = s->pStart;\r
+ d->pCurr = s->pCurr;\r
+ d->pLoop = s->pLoop;\r
+ d->bOn = !!(dwChannelOn & (1<<ch));\r
+ d->bStop = s->bStop;\r
+ d->bReverb = s->bReverb;\r
+ d->iActFreq = s->iActFreq;\r
+ d->iUsedFreq = s->iUsedFreq;\r
+ d->iLeftVolume = s->iLeftVolume;\r
+ d->bIgnoreLoop = s->bIgnoreLoop;\r
+ d->iRightVolume = s->iRightVolume;\r
+ d->iRawPitch = s->iRawPitch;\r
+ d->s_1 = s->s_1;\r
+ d->s_2 = s->s_2;\r
+ d->bRVBActive = s->bRVBActive;\r
+ d->iRVBOffset = s->iRVBOffset;\r
+ d->iRVBRepeat = s->iRVBRepeat;\r
+ d->bNoise = s->bNoise;\r
+ d->bFMod = s->bFMod;\r
+ d->iRVBNum = s->iRVBNum;\r
+ d->iOldNoise = s->iOldNoise;\r
+ d->ADSRX.State = s->ADSRX.State;\r
+ d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
+ d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
+ d->ADSRX.DecayRate = s->ADSRX.DecayRate;\r
+ d->ADSRX.SustainLevel = s->ADSRX.SustainLevel;\r
+ d->ADSRX.SustainModeExp = s->ADSRX.SustainModeExp;\r
+ d->ADSRX.SustainIncrease = s->ADSRX.SustainIncrease;\r
+ d->ADSRX.SustainRate = s->ADSRX.SustainRate;\r
+ d->ADSRX.ReleaseModeExp = s->ADSRX.ReleaseModeExp;\r
+ d->ADSRX.ReleaseRate = s->ADSRX.ReleaseRate;\r
+ d->ADSRX.EnvelopeVol = s->ADSRX.EnvelopeVol;\r
+ d->ADSRX.lVolume = d->bOn; // hmh\r
+}\r
+\r
+static void load_channel(SPUCHAN *d, SPUCHAN_orig *s, int ch)\r
+{\r
+ memset(d, 0, sizeof(*d));\r
+ if (s->bNew) dwNewChannel |= 1<<ch;\r
+ d->iSBPos = s->iSBPos;\r
+ d->spos = s->spos;\r
+ d->sinc = s->sinc;\r
+ memcpy(d->SB, s->SB, sizeof(d->SB));\r
+ d->pStart = s->pStart;\r
+ d->pCurr = s->pCurr;\r
+ d->pLoop = s->pLoop;\r
+ if (s->bOn) dwChannelOn |= 1<<ch;\r
+ d->bStop = s->bStop;\r
+ d->bReverb = s->bReverb;\r
+ d->iActFreq = s->iActFreq;\r
+ d->iUsedFreq = s->iUsedFreq;\r
+ d->iLeftVolume = s->iLeftVolume;\r
+ d->bIgnoreLoop = s->bIgnoreLoop;\r
+ d->iRightVolume = s->iRightVolume;\r
+ d->iRawPitch = s->iRawPitch;\r
+ d->s_1 = s->s_1;\r
+ d->s_2 = s->s_2;\r
+ d->bRVBActive = s->bRVBActive;\r
+ d->iRVBOffset = s->iRVBOffset;\r
+ d->iRVBRepeat = s->iRVBRepeat;\r
+ d->bNoise = s->bNoise;\r
+ d->bFMod = s->bFMod;\r
+ d->iRVBNum = s->iRVBNum;\r
+ d->iOldNoise = s->iOldNoise;\r
+ d->ADSRX.State = s->ADSRX.State;\r
+ d->ADSRX.AttackModeExp = s->ADSRX.AttackModeExp;\r
+ d->ADSRX.AttackRate = s->ADSRX.AttackRate;\r
+ d->ADSRX.DecayRate = s->ADSRX.DecayRate;\r
+ d->ADSRX.SustainLevel = s->ADSRX.SustainLevel;\r
+ d->ADSRX.SustainModeExp = s->ADSRX.SustainModeExp;\r
+ d->ADSRX.SustainIncrease = s->ADSRX.SustainIncrease;\r
+ d->ADSRX.SustainRate = s->ADSRX.SustainRate;\r
+ d->ADSRX.ReleaseModeExp = s->ADSRX.ReleaseModeExp;\r
+ d->ADSRX.ReleaseRate = s->ADSRX.ReleaseRate;\r
+ d->ADSRX.EnvelopeVol = s->ADSRX.EnvelopeVol;\r
+}\r
+\r
////////////////////////////////////////////////////////////////////////\r
// SPUFREEZE: called by main emu on savestate load/save\r
////////////////////////////////////////////////////////////////////////\r
\r
for(i=0;i<MAXCHAN;i++)\r
{\r
- memcpy((void *)&pFO->s_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN));\r
+ save_channel(&pFO->s_chan[i],&s_chan[i],i);\r
if(pFO->s_chan[i].pStart)\r
pFO->s_chan[i].pStart-=(unsigned long)spuMemC;\r
if(pFO->s_chan[i].pCurr)\r
if (spuAddr == 0xbaadf00d) spuAddr = 0;\r
}\r
\r
+ dwNewChannel=0;\r
+ dwChannelOn=0;\r
for(i=0;i<MAXCHAN;i++)\r
{\r
- memcpy((void *)&s_chan[i],(void *)&pFO->s_chan[i],sizeof(SPUCHAN));\r
+ load_channel(&s_chan[i],&pFO->s_chan[i],i);\r
\r
s_chan[i].pStart+=(unsigned long)spuMemC;\r
s_chan[i].pCurr+=(unsigned long)spuMemC;\r
s_chan[i].pLoop+=(unsigned long)spuMemC;\r
- s_chan[i].iMute=0;\r
- s_chan[i].iIrqDone=0;\r
}\r
}\r
\r
\r
for(i=0;i<MAXCHAN;i++)\r
{\r
- s_chan[i].bOn=0;\r
- s_chan[i].bNew=0;\r
s_chan[i].bStop=0;\r
- s_chan[i].ADSR.lVolume=0;\r
s_chan[i].pLoop=spuMemC;\r
s_chan[i].pStart=spuMemC;\r
s_chan[i].pLoop=spuMemC;\r
- s_chan[i].iMute=0;\r
- s_chan[i].iIrqDone=0;\r
}\r
\r
dwNewChannel=0;\r
+ dwChannelOn=0;\r
pSpuIrq=0;\r
\r
for(i=0;i<0xc0;i++)\r
//------------------------------------------------// level with pre-calcs\r
case 8:\r
{\r
- const unsigned long lval=val;unsigned long lx;\r
+ const unsigned long lval=val;\r
//---------------------------------------------//\r
s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; \r
s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;\r
s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;\r
s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;\r
//---------------------------------------------//\r
+#if 0\r
if(!iDebugMode) break;\r
//---------------------------------------------// stuff below is only for debug mode\r
\r
}\r
s_chan[ch].ADSR.DecayTime = // so calc how long does it take to run from 100% to the wanted sus level\r
(lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;\r
+#endif\r
}\r
break;\r
//------------------------------------------------// adsr times with pre-calcs\r
case 10:\r
{\r
- const unsigned long lval=val;unsigned long lx;\r
+ const unsigned long lval=val;\r
\r
//----------------------------------------------//\r
s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;\r
s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;\r
s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;\r
//----------------------------------------------//\r
+#if 0\r
if(!iDebugMode) break;\r
//----------------------------------------------// stuff below is only for debug mode\r
\r
if(lval & 0x4000) // add/dec flag\r
s_chan[ch].ADSR.SustainModeDec=-1;\r
else s_chan[ch].ADSR.SustainModeDec=1;\r
+#endif\r
}\r
break;\r
//------------------------------------------------// adsr volume... mmm have to investigate this\r
case 12: // get adsr vol\r
{\r
const int ch=(r>>4)-0xc0;\r
- if(s_chan[ch].bNew) return 1; // we are started, but not processed? return 1\r
- if(s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well\r
- !s_chan[ch].ADSRX.EnvelopeVol) \r
+ if(dwNewChannel&(1<<ch)) return 1; // we are started, but not processed? return 1\r
+ if((dwChannelOn&(1<<ch)) && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well\r
+ !s_chan[ch].ADSRX.EnvelopeVol)\r
return 1;\r
return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16);\r
}\r
if((val&1) && s_chan[ch].pStart) // mmm... start has to be set before key on !?!\r
{\r
s_chan[ch].bIgnoreLoop=0;\r
- s_chan[ch].bNew=1;\r
\r
// do this here, not in StartSound\r
// - fixes fussy timing issues\r
s_chan[ch].bStop=0;\r
- s_chan[ch].bOn=1;\r
s_chan[ch].pCurr=s_chan[ch].pStart;\r
\r
dwNewChannel|=(1<<ch); // bitfield for faster testing\r
+ dwChannelOn|=1<<ch;\r
}\r
}\r
}\r
\r
// Jungle Book - Rhythm 'n Groove\r
// - turns off buzzing sound (loop hangs)\r
- s_chan[ch].bNew=0;\r
dwNewChannel &= ~(1<<ch);\r
} \r
}\r
\r
for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
{\r
- if(val&1) // -> noise on/off\r
- {\r
- s_chan[ch].bNoise=1;\r
- }\r
- else \r
- {\r
- s_chan[ch].bNoise=0;\r
- }\r
+ s_chan[ch].bNoise=val&1; // -> noise on/off\r
}\r
}\r
\r
\r
void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME\r
{\r
- s_chan[ch].iLeftVolRaw=vol;\r
-\r
if(vol&0x8000) // sweep?\r
{\r
short sInc=1; // -> sweep up?\r
\r
void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME\r
{\r
- s_chan[ch].iRightVolRaw=vol;\r
-\r
if(vol&0x8000) // comments... see above :)\r
{\r
short sInc=1;\r
\r
for(ch=start;ch<end;ch++,val>>=1) // loop channels\r
{\r
- if(val&1) // -> reverb on/off\r
- {\r
- s_chan[ch].bReverb=1;\r
- }\r
- else \r
- {\r
- s_chan[ch].bReverb=0;\r
- }\r
+ s_chan[ch].bReverb=val&1; // -> reverb on/off\r
}\r
}\r
// STORE REVERB\r
////////////////////////////////////////////////////////////////////////\r
\r
-INLINE void StoreREVERB(int ch,int ns)\r
+INLINE void StoreREVERB(int ch,int ns,int sval)\r
{\r
if(iUseReverb==0) return;\r
else\r
if(iUseReverb==2) // -------------------------------- // Neil's reverb\r
{\r
- const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000;\r
- const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000;\r
+ const int iRxl=(sval*s_chan[ch].iLeftVolume)/0x4000;\r
+ const int iRxr=(sval*s_chan[ch].iRightVolume)/0x4000;\r
\r
ns<<=1;\r
\r
\r
// we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on\r
\r
- int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x8000;\r
- int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x8000;\r
+ int iRxl=(sval*s_chan[ch].iLeftVolume)/0x8000;\r
+ int iRxr=(sval*s_chan[ch].iRightVolume)/0x8000;\r
\r
for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2)\r
{\r
***************************************************************************/\r
\r
void SetREVERB(unsigned short val);\r
-INLINE void StartREVERB(int ch);\r
-INLINE void StoreREVERB(int ch,int ns);\r
\r
#define N_(x) (x)
#endif
+/*
#if defined (USEMACOSX)
static char * libraryName = N_("Mac OS X Sound");
#elif defined (USEALSA)
#endif
static char * libraryInfo = N_("P.E.Op.S. Sound Driver V1.7\nCoded by Pete Bernert and the P.E.Op.S. team\n");
+*/
// globals
static pthread_t thread = (pthread_t)-1; // thread id (linux)
unsigned long dwNewChannel=0; // flags for faster testing, if new channel starts
+unsigned long dwChannelOn=0;
void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq
void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0;
// certain globals (were local before, but with the new timeproc I need em global)
-static const int f[5][2] = { { 0, 0 },
+static const int f[8][2] = { { 0, 0 },
{ 60, 0 },
{ 115, -52 },
{ 98, -55 },
s_chan[ch].s_2=0;
s_chan[ch].iSBPos=28;
- s_chan[ch].bNew=0; // init channel flags
-
s_chan[ch].SB[29]=0; // init our interpolation helpers
s_chan[ch].SB[30]=0;
{
for(;ch<MAXCHAN;ch++) // loop em all... we will collect 1 ms of sound of each playing channel
{
- if(s_chan[ch].bNew) StartSound(ch); // start new sound
- if(!s_chan[ch].bOn) continue; // channel not playing? next
+ if(dwNewChannel&(1<<ch)) StartSound(ch); // start new sound
+ if(!(dwChannelOn&(1<<ch))) continue; // channel not playing? next
if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency?
VoiceChangeFrequency(ch);
for(ns=ns_from;ns<ns_to;ns++) // loop until 1 ms of data is reached
{
+ int sval;
+
if(s_chan[ch].bFMod==1 && iFMod[ns]) // fmod freq channel
FModChangeFrequency(ch,ns);
if (start == (unsigned char*)-1) // special "stop" sign
{
- s_chan[ch].bOn=0; // -> turn everything off
- s_chan[ch].ADSRX.lVolume=0;
+ dwChannelOn&=~(1<<ch); // -> turn everything off
s_chan[ch].ADSRX.EnvelopeVol=0;
goto ENDX; // -> and done for this channel
}
(pSpuIrq > s_chan[ch].pLoop-16 &&
pSpuIrq <= s_chan[ch].pLoop)))
{
- s_chan[ch].iIrqDone=1; // -> debug flag
irqCallback(); // -> call main emu
if(iSPUIRQWait) // -> option: wait after irq for main emu
s_chan[ch].pCurr=start; // store values for next cycle
s_chan[ch].s_1=s_1;
s_chan[ch].s_2=s_2;
-
-GOON: ;
}
fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data
fa=iGetNoiseVal(ch); // get noise val
else fa=iGetInterpolationVal(ch); // get sample val
- s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // mix adsr
+ sval = (MixADSR(ch) * fa) / 1023; // mix adsr
if(s_chan[ch].bFMod==2) // fmod freq channel
- iFMod[ns]=s_chan[ch].sval; // -> store 1T sample data, use that to do fmod on next channel
+ iFMod[ns]=sval; // -> store 1T sample data, use that to do fmod on next channel
else // no fmod freq channel
{
//////////////////////////////////////////////
// ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
- if(s_chan[ch].iMute)
- s_chan[ch].sval=0; // debug mute
- else
- {
- SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L;
- SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L;
- }
+ SSumL[ns]+=(sval*s_chan[ch].iLeftVolume)/0x4000L;
+ SSumR[ns]+=(sval*s_chan[ch].iRightVolume)/0x4000L;
//////////////////////////////////////////////
// now let us store sound data for reverb
- if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns);
+ if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns,sval);
}
////////////////////////////////////////////////
for(ch=0;ch<4;ch++)
{
if(pSpuIrq>=pMixIrq+(ch*0x400) && pSpuIrq<pMixIrq+(ch*0x400)+2)
- {irqCallback();s_chan[ch].iIrqDone=1;}
+ irqCallback();
}
}
pMixIrq+=2;if(pMixIrq>spuMemC+0x3ff) pMixIrq=spuMemC;
// we don't use mutex sync... not needed, would only
// slow us down:
// s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL);
- s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain
- s_chan[i].iMute=0;
- s_chan[i].iIrqDone=0;
+ s_chan[i].ADSRX.SustainLevel = 0xf; // -> init sustain
s_chan[i].pLoop=spuMemC;
s_chan[i].pStart=spuMemC;
s_chan[i].pCurr=spuMemC;
return _(libraryInfo);
}
*/
+
+// vim:shiftwidth=1:expandtab
#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF))
#ifndef INLINE
-#define INLINE inline
+#define INLINE static inline
#endif
#include "psemuxa.h"