mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
Implemented decent-sounding FM (kingshriek).
This commit is contained in:
parent
deeb54eab6
commit
b6a4ebd248
@ -22,6 +22,7 @@
|
||||
Enabled DSP again.
|
||||
* December 16, 2007 (kingshriek) Many EG bug fixes, implemented effects mixer,
|
||||
implemented FM.
|
||||
* January 5, 2007 (kingshriek+RB) Working, good-sounding FM, removed obsolete non-USEDSP code.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
@ -39,6 +40,7 @@
|
||||
|
||||
|
||||
#define EG_SHIFT 16
|
||||
#define FM_DELAY 4 // delay in number of slots processed before samples are written to the FM ring buffer
|
||||
|
||||
// include the LFO handling code
|
||||
#include "scsplfo.c"
|
||||
@ -184,6 +186,10 @@ struct _SCSP
|
||||
struct _SLOT Slots[32];
|
||||
signed short RINGBUF[64];
|
||||
unsigned char BUFPTR;
|
||||
#if FM_DELAY
|
||||
signed short DELAYBUF[FM_DELAY];
|
||||
unsigned char DELAYPTR;
|
||||
#endif
|
||||
unsigned char *SCSPRAM;
|
||||
UINT32 SCSPRAM_LENGTH;
|
||||
char Master;
|
||||
@ -216,9 +222,7 @@ struct _SCSP
|
||||
|
||||
int ARTABLE[64], DRTABLE[64];
|
||||
|
||||
#ifdef USEDSP
|
||||
struct _SCSPDSP DSP;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void dma_scsp(struct _SCSP *SCSP); /*SCSP DMA transfer function*/
|
||||
@ -524,10 +528,8 @@ static void SCSP_Init(struct _SCSP *SCSP, const struct SCSPinterface *intf, int
|
||||
{
|
||||
SCSP->SCSPRAM = memory_region(intf->region);
|
||||
SCSP->SCSPRAM_LENGTH = memory_region_length(intf->region);
|
||||
#ifdef USEDSP
|
||||
SCSP->DSP.SCSPRAM = (UINT16 *)SCSP->SCSPRAM;
|
||||
SCSP->DSP.SCSPRAM_LENGTH = memory_region_length(intf->region)/2;
|
||||
#endif
|
||||
SCSP->SCSPRAM += intf->roffset;
|
||||
}
|
||||
}
|
||||
@ -695,7 +697,6 @@ static void SCSP_UpdateReg(struct _SCSP *SCSP, int reg)
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
{
|
||||
#ifdef USEDSP
|
||||
unsigned int v=RBL(SCSP);
|
||||
SCSP->DSP.RBP=RBP(SCSP);
|
||||
if(v==0)
|
||||
@ -706,7 +707,6 @@ static void SCSP_UpdateReg(struct _SCSP *SCSP, int reg)
|
||||
SCSP->DSP.RBL=32*1024;
|
||||
if(v==3)
|
||||
SCSP->DSP.RBL=64*1024;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x6:
|
||||
@ -887,7 +887,6 @@ static void SCSP_w16(struct _SCSP *SCSP,unsigned int addr,unsigned short val)
|
||||
SCSP->RINGBUF[(addr-0x600)/2]=val;
|
||||
else
|
||||
{
|
||||
#ifdef USEDSP
|
||||
//DSP
|
||||
if(addr<0x780) //COEF
|
||||
*((unsigned short *) (SCSP->DSP.COEF+(addr-0x700)/2))=val;
|
||||
@ -900,7 +899,6 @@ static void SCSP_w16(struct _SCSP *SCSP,unsigned int addr,unsigned short val)
|
||||
{
|
||||
SCSPDSP_Start(&SCSP->DSP);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -931,231 +929,6 @@ static unsigned short SCSP_r16(struct _SCSP *SCSP, unsigned int addr)
|
||||
|
||||
#define REVSIGN(v) ((~v)+1)
|
||||
|
||||
|
||||
#ifndef USEDSP
|
||||
static signed int *bufl1,*bufr1;
|
||||
#define SCSPNAME(_8bit,lfo,alfo,loop) \
|
||||
static void SCSP_Update##_8bit##lfo##alfo##loop(struct _SCSP *SCSP, struct _SLOT *slot,unsigned int Enc,unsigned int nsamples)
|
||||
|
||||
#define SCSPTMPL(_8bit,lfo,alfo,loop) \
|
||||
SCSPNAME(_8bit,lfo,alfo,loop)\
|
||||
{\
|
||||
signed int sample;\
|
||||
UINT32 addr;\
|
||||
unsigned int s;\
|
||||
for(s=0;s<nsamples;++s)\
|
||||
{\
|
||||
int step=slot->step;\
|
||||
if(!slot->active)\
|
||||
return;\
|
||||
if(lfo) \
|
||||
{\
|
||||
step=step*PLFO_Step(&(slot->PLFO));\
|
||||
step>>=SHIFT; \
|
||||
}\
|
||||
if(_8bit)\
|
||||
{\
|
||||
signed char *p=(signed char *) (slot->base+BYTE_XOR_BE((slot->cur_addr>>SHIFT)));\
|
||||
int s;\
|
||||
signed int fpart=slot->cur_addr&((1<<SHIFT)-1);\
|
||||
s=(int) (p[0]<<8)*((1<<SHIFT)-fpart)+(int) slot->Prev*fpart;\
|
||||
sample=(s>>SHIFT);\
|
||||
slot->Prev=p[0]<<8;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
signed short *p=(signed short *) (slot->base+((slot->cur_addr>>(SHIFT-1))&(~1)));\
|
||||
int s;\
|
||||
signed int fpart=slot->cur_addr&((1<<SHIFT)-1);\
|
||||
s=(int) (p[0])*((1<<SHIFT)-fpart)+(int) slot->Prev*fpart;\
|
||||
sample=(s>>SHIFT);\
|
||||
slot->Prev=p[0];\
|
||||
}\
|
||||
if(slot->Backwards)\
|
||||
slot->cur_addr-=step;\
|
||||
else\
|
||||
slot->cur_addr+=step;\
|
||||
addr=slot->cur_addr>>SHIFT;\
|
||||
if(loop==0)\
|
||||
{\
|
||||
if(addr>LEA(slot))\
|
||||
{\
|
||||
SCSP_StopSlot(slot,0);\
|
||||
}\
|
||||
}\
|
||||
if(loop==1)\
|
||||
{\
|
||||
if(addr>=LEA(slot))\
|
||||
slot->cur_addr=LSA(slot)<<SHIFT;\
|
||||
}\
|
||||
if(loop==2)\
|
||||
{\
|
||||
if(addr>=LEA(slot))\
|
||||
{\
|
||||
slot->cur_addr=LEA(slot)<<SHIFT;\
|
||||
slot->step=REVSIGN(slot->step);\
|
||||
}\
|
||||
if(addr<LSA(slot) || (addr&0x80000000))\
|
||||
slot->cur_addr=LEA(slot)<<SHIFT;\
|
||||
}\
|
||||
if(loop==3)\
|
||||
{\
|
||||
if(addr>=LEA(slot)) /*reached end, reverse till start*/ \
|
||||
{\
|
||||
slot->cur_addr=LEA(slot)<<SHIFT;\
|
||||
slot->Backwards=1;\
|
||||
}\
|
||||
if((addr<=LSA(slot) || (addr&0x80000000)) && (slot->Backwards))/*reached start or negative*/\
|
||||
{\
|
||||
slot->cur_addr=LSA(slot)<<SHIFT;\
|
||||
slot->Backwards=0;\
|
||||
}\
|
||||
}\
|
||||
if(alfo)\
|
||||
{\
|
||||
sample=sample*ALFO_Step(&(slot->ALFO));\
|
||||
sample>>=SHIFT;\
|
||||
}\
|
||||
*RBUFDST=sample;\
|
||||
\
|
||||
sample=(sample*EG_Update(slot))>>SHIFT;\
|
||||
\
|
||||
*bufl1=*bufl1 + ((sample*SCSP->LPANTABLE[Enc])>>SHIFT);\
|
||||
*bufr1=*bufr1 + ((sample*SCSP->RPANTABLE[Enc])>>SHIFT);\
|
||||
++bufl1;\
|
||||
++bufr1;\
|
||||
}\
|
||||
}
|
||||
|
||||
SCSPTMPL(0,0,0,0)
|
||||
SCSPTMPL(0,0,0,1)
|
||||
SCSPTMPL(0,0,0,2)
|
||||
SCSPTMPL(0,0,0,3)
|
||||
SCSPTMPL(0,0,1,0)
|
||||
SCSPTMPL(0,0,1,1)
|
||||
SCSPTMPL(0,0,1,2)
|
||||
SCSPTMPL(0,0,1,3)
|
||||
SCSPTMPL(0,1,0,0)
|
||||
SCSPTMPL(0,1,0,1)
|
||||
SCSPTMPL(0,1,0,2)
|
||||
SCSPTMPL(0,1,0,3)
|
||||
SCSPTMPL(0,1,1,0)
|
||||
SCSPTMPL(0,1,1,1)
|
||||
SCSPTMPL(0,1,1,2)
|
||||
SCSPTMPL(0,1,1,3)
|
||||
SCSPTMPL(1,0,0,0)
|
||||
SCSPTMPL(1,0,0,1)
|
||||
SCSPTMPL(1,0,0,2)
|
||||
SCSPTMPL(1,0,0,3)
|
||||
SCSPTMPL(1,0,1,0)
|
||||
SCSPTMPL(1,0,1,1)
|
||||
SCSPTMPL(1,0,1,2)
|
||||
SCSPTMPL(1,0,1,3)
|
||||
SCSPTMPL(1,1,0,0)
|
||||
SCSPTMPL(1,1,0,1)
|
||||
SCSPTMPL(1,1,0,2)
|
||||
SCSPTMPL(1,1,0,3)
|
||||
SCSPTMPL(1,1,1,0)
|
||||
SCSPTMPL(1,1,1,1)
|
||||
SCSPTMPL(1,1,1,2)
|
||||
SCSPTMPL(1,1,1,3)
|
||||
|
||||
#undef SCSPTMPL
|
||||
#define SCSPTMPL(_8bit,lfo,alfo,loop) \
|
||||
SCSP_Update##_8bit##lfo##alfo##loop ,
|
||||
|
||||
|
||||
typedef void (*_SCSPUpdateModes)(struct _SCSP *,struct _SLOT *,unsigned int,unsigned int);
|
||||
|
||||
static const _SCSPUpdateModes SCSPUpdateModes[]=
|
||||
{
|
||||
SCSPTMPL(0,0,0,0)
|
||||
SCSPTMPL(0,0,0,1)
|
||||
SCSPTMPL(0,0,0,2)
|
||||
SCSPTMPL(0,0,0,3)
|
||||
SCSPTMPL(0,0,1,0)
|
||||
SCSPTMPL(0,0,1,1)
|
||||
SCSPTMPL(0,0,1,2)
|
||||
SCSPTMPL(0,0,1,3)
|
||||
SCSPTMPL(0,1,0,0)
|
||||
SCSPTMPL(0,1,0,1)
|
||||
SCSPTMPL(0,1,0,2)
|
||||
SCSPTMPL(0,1,0,3)
|
||||
SCSPTMPL(0,1,1,0)
|
||||
SCSPTMPL(0,1,1,1)
|
||||
SCSPTMPL(0,1,1,2)
|
||||
SCSPTMPL(0,1,1,3)
|
||||
SCSPTMPL(1,0,0,0)
|
||||
SCSPTMPL(1,0,0,1)
|
||||
SCSPTMPL(1,0,0,2)
|
||||
SCSPTMPL(1,0,0,3)
|
||||
SCSPTMPL(1,0,1,0)
|
||||
SCSPTMPL(1,0,1,1)
|
||||
SCSPTMPL(1,0,1,2)
|
||||
SCSPTMPL(1,0,1,3)
|
||||
SCSPTMPL(1,1,0,0)
|
||||
SCSPTMPL(1,1,0,1)
|
||||
SCSPTMPL(1,1,0,2)
|
||||
SCSPTMPL(1,1,0,3)
|
||||
SCSPTMPL(1,1,1,0)
|
||||
SCSPTMPL(1,1,1,1)
|
||||
SCSPTMPL(1,1,1,2)
|
||||
SCSPTMPL(1,1,1,3)
|
||||
};
|
||||
|
||||
|
||||
static void SCSP_DoMasterSamples(struct _SCSP *SCSP, int nsamples)
|
||||
{
|
||||
stream_sample_t *bufr,*bufl;
|
||||
int sl, s;
|
||||
|
||||
for(sl=0;sl<32;++sl)
|
||||
{
|
||||
bufr1=SCSP->buffertmpr;
|
||||
bufl1=SCSP->buffertmpl;
|
||||
|
||||
if(SCSP->Slots[sl].active)
|
||||
{
|
||||
struct _SLOT *slot=SCSP->Slots+sl;
|
||||
unsigned short Enc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd);
|
||||
unsigned int mode=LPCTL(slot);
|
||||
|
||||
RBUFDST=SCSP->RINGBUF+SCSP->BUFPTR;
|
||||
if(PLFOS(slot))
|
||||
mode|=8;
|
||||
if(ALFOS(slot))
|
||||
mode|=4;
|
||||
if(PCM8B(slot))
|
||||
mode|=0x10;
|
||||
|
||||
SCSPUpdateModes[mode](SCSP,slot,Enc,nsamples);
|
||||
|
||||
++SCSP->BUFPTR;
|
||||
SCSP->BUFPTR&=63;
|
||||
}
|
||||
}
|
||||
|
||||
bufr=bufferr;
|
||||
bufl=bufferl;
|
||||
bufr1=SCSP->buffertmpr;
|
||||
bufl1=SCSP->buffertmpl;
|
||||
for(s=0;s<nsamples;++s)
|
||||
{
|
||||
signed int smpl=*bufl1>>2;
|
||||
signed int smpr=*bufr1>>2;
|
||||
|
||||
*bufl=ICLIP16(smpl);
|
||||
*bufr=ICLIP16(smpr);
|
||||
*bufl1=0;
|
||||
*bufr1=0;
|
||||
++bufl;
|
||||
++bufr;
|
||||
++bufl1;
|
||||
++bufr1;
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
INLINE INT32 SCSP_UpdateSlot(struct _SCSP *SCSP, struct _SLOT *slot)
|
||||
{
|
||||
INT32 sample;
|
||||
@ -1184,47 +957,38 @@ INLINE INT32 SCSP_UpdateSlot(struct _SCSP *SCSP, struct _SLOT *slot)
|
||||
addr2=(slot->nxt_addr>>(SHIFT-1))&0x7fffe;
|
||||
}
|
||||
|
||||
/*if(MDL(slot)!=0 || MDXSL(slot)!=0 || MDYSL(slot)!=0)
|
||||
{
|
||||
INT32 smp=(SCSP->RINGBUF[(SCSP->BUFPTR+MDXSL(slot))&63]+SCSP->RINGBUF[(SCSP->BUFPTR+MDYSL(slot))&63])/2;
|
||||
INT32 cycle=LEA(slot)-LSA(slot); // cycle corresponds to 2 pi
|
||||
if(MDL(slot)!=0 || MDXSL(slot)!=0 || MDYSL(slot)!=0)
|
||||
{
|
||||
INT32 smp=(SCSP->RINGBUF[(SCSP->BUFPTR+MDXSL(slot))&63]+SCSP->RINGBUF[(SCSP->BUFPTR+MDYSL(slot))&63])/2;
|
||||
INT32 cycle=LEA(slot)-LSA(slot); // cycle corresponds to 2 pi
|
||||
|
||||
smp*=cycle; // associate cycle with full 16-bit sample range
|
||||
smp>>=0x1A-MDL(slot); // ex. for MDL=0xF, sample range corresponds to +/- 64 pi (32=2^5 cycles) so shift by 11 (16-5 == 0x1A-0xF)
|
||||
while(smp<0) smp+=cycle; smp%=cycle; // keep modulation sampler within a single cycle
|
||||
if(!PCM8B(slot)) smp<<=1;
|
||||
smp<<=0xA; // associate cycle with 1024
|
||||
smp>>=0x1A-MDL(slot); // ex. for MDL=0xF, sample range corresponds to +/- 64 pi (32=2^5 cycles) so shift by 11 (16-5 == 0x1A-0xF)
|
||||
while(smp<0) smp+=cycle; smp%=cycle; // keep modulation sampler within a single cycle
|
||||
if(!PCM8B(slot)) smp<<=1;
|
||||
|
||||
addr1+=smp; addr2+=smp;
|
||||
}
|
||||
|
||||
addr1+=smp; addr2+=smp;
|
||||
if(!PCM8B(slot))
|
||||
{
|
||||
addr1&=0x7fffe; addr2&=0x7fffe;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr1&=0x7ffff; addr2&=0x7ffff;
|
||||
}
|
||||
}*/
|
||||
|
||||
if(PCM8B(slot)) //8 bit signed
|
||||
{
|
||||
INT8 *p1=(signed char *) (SCSP->SCSPRAM+((SA(slot)+addr1)^1));
|
||||
INT8 *p2=(signed char *) (SCSP->SCSPRAM+((SA(slot)+addr2)^1));
|
||||
//sample=(p[0])<<8;
|
||||
INT32 s;
|
||||
INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
|
||||
s=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int) (p2[0]<<8)*fpart;
|
||||
sample=(s>>SHIFT);
|
||||
}
|
||||
else //16 bit signed (endianness?)
|
||||
{
|
||||
INT16 *p1=(signed short *) (slot->base+addr1);
|
||||
INT16 *p2=(signed short *) (slot->base+addr2);
|
||||
//sample=LE16(p[0]);
|
||||
INT32 s;
|
||||
INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
|
||||
s=(int) (p1[0])*((1<<SHIFT)-fpart)+(int) (p2[0])*fpart;
|
||||
sample=(s>>SHIFT);
|
||||
}
|
||||
if(PCM8B(slot)) //8 bit signed
|
||||
{
|
||||
INT8 *p1=(signed char *) (SCSP->SCSPRAM+BYTE_XOR_BE(((SA(slot)+addr1))&0x7FFFF));
|
||||
INT8 *p2=(signed char *) (SCSP->SCSPRAM+BYTE_XOR_BE(((SA(slot)+addr2))&0x7FFFF));
|
||||
//sample=(p[0])<<8;
|
||||
INT32 s;
|
||||
INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
|
||||
s=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int) (p2[0]<<8)*fpart;
|
||||
sample=(s>>SHIFT);
|
||||
}
|
||||
else //16 bit signed (endianness?)
|
||||
{
|
||||
INT16 *p1=(signed short *) (SCSP->SCSPRAM+((SA(slot)+addr1)&0x7FFFE));
|
||||
INT16 *p2=(signed short *) (SCSP->SCSPRAM+((SA(slot)+addr2)&0x7FFFE));
|
||||
INT32 s;
|
||||
INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
|
||||
s=(int)(p1[0])*((1<<SHIFT)-fpart)+(int)(p2[0])*fpart;
|
||||
sample=(s>>SHIFT);
|
||||
}
|
||||
|
||||
if(SBCTL(slot)&0x1)
|
||||
sample ^= 0x7FFF;
|
||||
@ -1318,7 +1082,11 @@ static void SCSP_DoMasterSamples(struct _SCSP *SCSP, int nsamples)
|
||||
|
||||
for(sl=0;sl<32;++sl)
|
||||
{
|
||||
#if FM_DELAY
|
||||
RBUFDST=SCSP->DELAYBUF+SCSP->DELAYPTR;
|
||||
#else
|
||||
RBUFDST=SCSP->RINGBUF+SCSP->BUFPTR;
|
||||
#endif
|
||||
if(SCSP->Slots[sl].active)
|
||||
{
|
||||
struct _SLOT *slot=SCSP->Slots+sl;
|
||||
@ -1337,8 +1105,16 @@ static void SCSP_DoMasterSamples(struct _SCSP *SCSP, int nsamples)
|
||||
smpr+=(sample*SCSP->RPANTABLE[Enc])>>SHIFT;
|
||||
}
|
||||
}
|
||||
--SCSP->BUFPTR;
|
||||
|
||||
#if FM_DELAY
|
||||
SCSP->RINGBUF[(SCSP->BUFPTR+64-(FM_DELAY-1))&63] = SCSP->DELAYBUF[(SCSP->DELAYPTR+FM_DELAY-(FM_DELAY-1))%FM_DELAY];
|
||||
#endif
|
||||
++SCSP->BUFPTR;
|
||||
SCSP->BUFPTR&=63;
|
||||
#if FM_DELAY
|
||||
++SCSP->DELAYPTR;
|
||||
if(SCSP->DELAYPTR>FM_DELAY-1) SCSP->DELAYPTR=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
SCSPDSP_Step(&SCSP->DSP);
|
||||
@ -1358,7 +1134,6 @@ static void SCSP_DoMasterSamples(struct _SCSP *SCSP, int nsamples)
|
||||
*bufr++ = ICLIP16(smpr>>2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dma_scsp(struct _SCSP *SCSP)
|
||||
{
|
||||
@ -1459,9 +1234,7 @@ void SCSP_set_ram_base(int which, void *base)
|
||||
if (SCSP)
|
||||
{
|
||||
SCSP->SCSPRAM = base;
|
||||
#ifdef USEDSP
|
||||
SCSP->DSP.SCSPRAM = base;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user