diff options
author | 2008-02-17 18:28:36 +0000 | |
---|---|---|
committer | 2008-02-17 18:28:36 +0000 | |
commit | 8877f5321b3108eb8cf9402253ac12c71a264939 (patch) | |
tree | 07bdd73df0f660e539259656121a60538f531362 /src/emu/sound/aicalfo.c | |
parent | b469de6db7d6f578b75abe75fdb477ed0438e545 (diff) |
[NAOMI] Added and hooked up AICA (sound chip). Naomi boot sounds now play.
Since it's an SCSPx2 with ADPCM instead of FM it's already feature-complete except filter envelopes.
A bug in the ARM7 core causes incorrect pan/level values to be computed in e.g. the Naomi SOUND TEST menu (I've also been seeing this in DSF playback). This is not a defect in the AICA.
Please credit ElSemi, Deunan Knute, kingshriek, and myself.
Diffstat (limited to 'src/emu/sound/aicalfo.c')
-rw-r--r-- | src/emu/sound/aicalfo.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/emu/sound/aicalfo.c b/src/emu/sound/aicalfo.c new file mode 100644 index 00000000000..d1a382d9a98 --- /dev/null +++ b/src/emu/sound/aicalfo.c @@ -0,0 +1,159 @@ +/* + AICA LFO handling + + Part of the AICA emulator package. + (not compiled directly, #included from aica.c) + + By ElSemi, kingshriek, Deunan Knute, and R. Belmont +*/ + +#define LFO_SHIFT 8 + +struct _LFO +{ + unsigned short phase; + UINT32 phase_step; + int *table; + int *scale; +}; + +#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v))) + +//Convert DB to multiply amplitude +#define DB(v) LFIX(pow(10.0,v/20.0)) + +//Convert cents to step increment +#define CENTS(v) LFIX(pow(2.0,v/1200.0)) + +static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256]; +static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256]; +static float LFOFreq[32]={0.17,0.19,0.23,0.27,0.34,0.39,0.45,0.55,0.68,0.78,0.92,1.10,1.39,1.60,1.87,2.27, + 2.87,3.31,3.92,4.79,6.15,7.18,8.60,10.8,14.4,17.2,21.5,28.7,43.1,57.4,86.1,172.3}; +static float ASCALE[8]={0.0,0.4,0.8,1.5,3.0,6.0,12.0,24.0}; +static float PSCALE[8]={0.0,7.0,13.5,27.0,55.0,112.0,230.0,494}; +static int PSCALES[8][256]; +static int ASCALES[8][256]; + +void AICALFO_Init(void) +{ + int i,s; + for(i=0;i<256;++i) + { + int a,p; +// float TL; + //Saw + a=255-i; + if(i<128) + p=i; + else + p=i-256; + ALFO_SAW[i]=a; + PLFO_SAW[i]=p; + + //Square + if(i<128) + { + a=255; + p=127; + } + else + { + a=0; + p=-128; + } + ALFO_SQR[i]=a; + PLFO_SQR[i]=p; + + //Tri + if(i<128) + a=255-(i*2); + else + a=(i*2)-256; + if(i<64) + p=i*2; + else if(i<128) + p=255-i*2; + else if(i<192) + p=256-i*2; + else + p=i*2-511; + ALFO_TRI[i]=a; + PLFO_TRI[i]=p; + + //noise + //a=lfo_noise[i]; + a=mame_rand(Machine)&0xff; + p=128-a; + ALFO_NOI[i]=a; + PLFO_NOI[i]=p; + } + + for(s=0;s<8;++s) + { + float limit=PSCALE[s]; + for(i=-128;i<128;++i) + { + PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0)); + } + limit=-ASCALE[s]; + for(i=0;i<256;++i) + { + ASCALES[s][i]=DB(((limit*(float) i)/256.0)); + } + } +} + +signed int INLINE AICAPLFO_Step(struct _LFO *LFO) +{ + int p; + + LFO->phase+=LFO->phase_step; +#if LFO_SHIFT!=8 + LFO->phase&=(1<<(LFO_SHIFT+8))-1; +#endif + p=LFO->table[LFO->phase>>LFO_SHIFT]; + p=LFO->scale[p+128]; + return p<<(SHIFT-LFO_SHIFT); +} + +signed int INLINE AICAALFO_Step(struct _LFO *LFO) +{ + int p; + LFO->phase+=LFO->phase_step; +#if LFO_SHIFT!=8 + LFO->phase&=(1<<(LFO_SHIFT+8))-1; +#endif + p=LFO->table[LFO->phase>>LFO_SHIFT]; + p=LFO->scale[p]; + return p<<(SHIFT-LFO_SHIFT); +} + +void AICALFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO) +{ + float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0; + LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step); + if(ALFO) + { + switch(LFOWS) + { + case 0: LFO->table=ALFO_SAW; break; + case 1: LFO->table=ALFO_SQR; break; + case 2: LFO->table=ALFO_TRI; break; + case 3: LFO->table=ALFO_NOI; break; + default: printf("Unknown ALFO %d\n", LFOWS); + } + LFO->scale=ASCALES[LFOS]; + } + else + { + switch(LFOWS) + { + case 0: LFO->table=PLFO_SAW; break; + case 1: LFO->table=PLFO_SQR; break; + case 2: LFO->table=PLFO_TRI; break; + case 3: LFO->table=PLFO_NOI; break; + default: printf("Unknown PLFO %d\n", LFOWS); + } + LFO->scale=PSCALES[LFOS]; + } +} |