some movies fixed
[fceu.git] / mappers / fmopl.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
4 * Copyright (C) 1999,2000 Tatsuyuki Satoh
5 * Copyright (C) 2001,2002 Ben Parnell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/* This file has been heavily modified from the original(mostly unused
23 code was removed). If you want to use it for anything other than
24 VRC7 sound emulation, you should get the original from the AdPlug
25 source distribution or the MAME(version 0.37b16) source distribution
26 (but be careful about the different licenses).
27 - Xodnizel
28*/
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <stdarg.h>
34#include <math.h>
35#include "mapinc.h"
36#include "fmopl.h"
37
38#ifndef PI
39#define PI 3.14159265358979323846
40#endif
41
42/* -------------------- preliminary define section --------------------- */
43/* attack/decay rate time rate */
44#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
45#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
46
47#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
48
49#define FREQ_BITS 24 /* frequency turn */
50
51/* counter bits = 20 , octerve 7 */
52#define FREQ_RATE (1<<(FREQ_BITS-20))
53#define TL_BITS (FREQ_BITS+2)
54
55/* final output shift , limit minimum and maximum */
56#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
57#define OPL_MAXOUT (0x7fff<<OPL_OUTSB<<3)
58#define OPL_MINOUT (-0x8000<<OPL_OUTSB<<3)
59
60/* -------------------- quality selection --------------------- */
61
62/* sinwave entries */
63/* used static memory = SIN_ENT * 4 (byte) */
64#define SIN_ENT 2048
65
66/* output level entries (envelope,sinwave) */
67/* envelope counter lower bits */
68#define ENV_BITS 16
69/* envelope output entries */
70#define EG_ENT 4096
71/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
72/* used static memory = EG_ENT*4 (byte) */
73
74#define EG_OFF ((2*EG_ENT)<<ENV_BITS) /* OFF */
75#define EG_DED EG_OFF
76#define EG_DST (EG_ENT<<ENV_BITS) /* DECAY START */
77#define EG_AED EG_DST
78#define EG_AST 0 /* ATTACK START */
79
80#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
81
82/* LFO table entries */
83#define VIB_ENT 512
84#define VIB_SHIFT (32-9)
85#define AMS_ENT 512
86#define AMS_SHIFT (32-9)
87
88#define VIB_RATE 256
89
90/* -------------------- local defines , macros --------------------- */
91
92/* register number to channel number , slot offset */
93#define SLOT1 0
94#define SLOT2 1
95
96/* envelope phase */
97#define ENV_MOD_RR 0x00
98#define ENV_MOD_DR 0x01
99#define ENV_MOD_AR 0x02
100
101/* -------------------- tables --------------------- */
102static const int slot_array[32]=
103{
104 0, 2, 4, 1, 3, 5,-1,-1,
105 6, 8,10, 7, 9,11,-1,-1,
106 12,14,16,13,15,17,-1,-1,
107 -1,-1,-1,-1,-1,-1,-1,-1
108};
109
110/* key scale level */
111/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
112#define DV (EG_STEP/2)
113static const UINT32 KSL_TABLE[8*16]=
114{
115 /* OCT 0 */
116 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
117 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
118 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
119 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
120 /* OCT 1 */
121 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
122 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
123 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
124 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
125 /* OCT 2 */
126 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
127 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
128 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
129 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
130 /* OCT 3 */
131 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
132 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
133 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
134 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
135 /* OCT 4 */
136 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
137 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
138 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
139 10.875/DV,11.250/DV,11.625/DV,12.000/DV,
140 /* OCT 5 */
141 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
142 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
143 12.000/DV,12.750/DV,13.125/DV,13.500/DV,
144 13.875/DV,14.250/DV,14.625/DV,15.000/DV,
145 /* OCT 6 */
146 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
147 12.000/DV,13.125/DV,13.875/DV,14.625/DV,
148 15.000/DV,15.750/DV,16.125/DV,16.500/DV,
149 16.875/DV,17.250/DV,17.625/DV,18.000/DV,
150 /* OCT 7 */
151 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
152 15.000/DV,16.125/DV,16.875/DV,17.625/DV,
153 18.000/DV,18.750/DV,19.125/DV,19.500/DV,
154 19.875/DV,20.250/DV,20.625/DV,21.000/DV
155};
156#undef DV
157
158/* sustain lebel table (3db per step) */
159/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
160#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
161static const INT32 SL_TABLE[16]={
162 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
163 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
164};
165#undef SC
166
167#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
168/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
169/* TL_TABLE[ 0 to TL_MAX ] : plus section */
170/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
171static INT32 *TL_TABLE;
172
173/* pointers to TL_TABLE with sinwave output offset */
174static INT32 **SIN_TABLE;
175
176/* LFO table */
177static INT32 *AMS_TABLE;
178static INT32 *VIB_TABLE;
179
180/* envelope output curve table */
181/* attack + decay + OFF */
182static INT32 ENV_CURVE[2*EG_ENT+1];
183
184/* multiple table */
185#define ML 2
186static const UINT32 MUL_TABLE[16]= {
187/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
188 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
189 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
190};
191#undef ML
192
193/* dummy attack / decay rate ( when rate == 0 ) */
194static INT32 RATE_0[16]=
195{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
196
197/* -------------------- static state --------------------- */
198
199/* lock level of common table */
200static int num_lock = 0;
201
202/* work table */
203static void *cur_chip = NULL; /* current chip point */
204/* currenct chip state */
205/* static OPLSAMPLE *bufL,*bufR; */
206static OPL_CH *S_CH;
207static OPL_CH *E_CH;
208OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
209
210static INT32 outd[1];
211static INT32 ams;
212static INT32 vib;
213INT32 *ams_table;
214INT32 *vib_table;
215static INT32 amsIncr;
216static INT32 vibIncr;
217static INT32 feedback2; /* connect for SLOT 2 */
218
219/* --------------------- subroutines --------------------- */
220
221INLINE int Limit( int val, int max, int min ) {
222 if ( val > max )
223 val = max;
224 else if ( val < min )
225 val = min;
226
227 return val;
228}
229
230/* ----- key on ----- */
231INLINE void OPL_KEYON(OPL_SLOT *SLOT)
232{
233 /* sin wave restart */
234 SLOT->Cnt = 0;
235 /* set attack */
236 SLOT->evm = ENV_MOD_AR;
237 SLOT->evs = SLOT->evsa;
238 SLOT->evc = EG_AST;
239 SLOT->eve = EG_AED;
240}
241/* ----- key off ----- */
242INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
243{
244 if( SLOT->evm > ENV_MOD_RR)
245 {
246 /* set envelope counter from envleope output */
247 SLOT->evm = ENV_MOD_RR;
248 if( !(SLOT->evc&EG_DST) )
249 //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
250 SLOT->evc = EG_DST;
251 SLOT->eve = EG_DED;
252 SLOT->evs = SLOT->evsr;
253 }
254}
255
256/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
257/* return : envelope output */
258INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
259{
260 /* calcrate envelope generator */
261 if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
262 {
263 switch( SLOT->evm ){
264 case ENV_MOD_AR: /* ATTACK -> DECAY1 */
265 /* next DR */
266 SLOT->evm = ENV_MOD_DR;
267 SLOT->evc = EG_DST;
268 SLOT->eve = SLOT->SL;
269 SLOT->evs = SLOT->evsd;
270 break;
271 case ENV_MOD_DR: /* DECAY -> SL or RR */
272 SLOT->evc = SLOT->SL;
273 SLOT->eve = EG_DED;
274 if(SLOT->eg_typ)
275 {
276 SLOT->evs = 0;
277 }
278 else
279 {
280 SLOT->evm = ENV_MOD_RR;
281 SLOT->evs = SLOT->evsr;
282 }
283 break;
284 case ENV_MOD_RR: /* RR -> OFF */
285 SLOT->evc = EG_OFF;
286 SLOT->eve = EG_OFF+1;
287 SLOT->evs = 0;
288 break;
289 }
290 }
291 /* calcrate envelope */
292 return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
293}
294
295/* set algorythm connection */
296static void set_algorythm( OPL_CH *CH)
297{
298 INT32 *carrier = &outd[0];
299 CH->connect1 = CH->CON ? carrier : &feedback2;
300 CH->connect2 = carrier;
301}
302
303/* ---------- frequency counter for operater update ---------- */
304INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
305{
306 int ksr;
307
308 /* frequency step counter */
309 SLOT->Incr = CH->fc * SLOT->mul;
310 ksr = CH->kcode >> SLOT->KSR;
311
312 if( SLOT->ksr != ksr )
313 {
314 SLOT->ksr = ksr;
315 /* attack , decay rate recalcration */
316 SLOT->evsa = SLOT->AR[ksr];
317 SLOT->evsd = SLOT->DR[ksr];
318 SLOT->evsr = SLOT->RR[ksr];
319 }
320 SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
321}
322
323/* set multi,am,vib,EG-TYP,KSR,mul */
324INLINE void set_mul(FM_OPL *OPL,int slot,int v)
325{
326 OPL_CH *CH = &OPL->P_CH[slot/2];
327 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
328
329 SLOT->mul = MUL_TABLE[v&0x0f];
330 SLOT->KSR = (v&0x10) ? 0 : 2;
331 SLOT->eg_typ = (v&0x20)>>5;
332 SLOT->vib = (v&0x40);
333 SLOT->ams = (v&0x80);
334 CALC_FCSLOT(CH,SLOT);
335}
336
337/* set ksl & tl */
338INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
339{
340 OPL_CH *CH = &OPL->P_CH[slot/2];
341 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
342 int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
343
344// if(slot&1)
345// if(ksl) {sprintf(errmsg,"doh");howlong=255;ksl=0;}
346
347 SLOT->ksl = ksl ? ksl : 31;
348// SLOT->ksl = ksl ? 3-ksl : 31;
349 SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
350
351 if( !(OPL->mode&0x80) )
352 { /* not CSM latch total level */
353 SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
354 }
355}
356
357/* set attack rate & decay rate */
358INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
359{
360 OPL_CH *CH = &OPL->P_CH[slot/2];
361 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
362 int ar = v>>4;
363 int dr = v&0x0f;
364
365 SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
366 SLOT->evsa = SLOT->AR[SLOT->ksr];
367 if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
368
369 SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
370 SLOT->evsd = SLOT->DR[SLOT->ksr];
371 if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
372}
373
374/* set sustain level & release rate */
375INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
376{
377 OPL_CH *CH = &OPL->P_CH[slot/2];
378 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
379 int sl = v>>4;
380 int rr = v & 0x0f;
381
382 SLOT->SL = SL_TABLE[sl];
383 if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
384 SLOT->RR = &OPL->DR_TABLE[rr<<2];
385 SLOT->evsr = SLOT->RR[SLOT->ksr];
386 if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
387}
388
389/* operator output calcrator */
390#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
391/* ---------- calcrate one of channel ---------- */
392INLINE void OPL_CALC_CH( OPL_CH *CH )
393{
394 UINT32 env_out;
395 OPL_SLOT *SLOT;
396
397 feedback2 = 0;
398 /* SLOT 1 */
399 SLOT = &CH->SLOT[SLOT1];
400 env_out=OPL_CALC_SLOT(SLOT);
401 if( env_out < EG_ENT-1 )
402 {
403 /* PG */
404 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
405 else SLOT->Cnt += SLOT->Incr;
406 /* connectoion */
407 if(CH->FB)
408 {
409 int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
410 CH->op1_out[1] = CH->op1_out[0];
411 *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
412 }
413 else
414 {
415 *CH->connect1 += OP_OUT(SLOT,env_out,0);
416 }
417 }else
418 {
419 CH->op1_out[1] = CH->op1_out[0];
420 CH->op1_out[0] = 0;
421 }
422 /* SLOT 2 */
423 SLOT = &CH->SLOT[SLOT2];
424 env_out=OPL_CALC_SLOT(SLOT);
425 if( env_out < EG_ENT-1 )
426 {
427 /* PG */
428 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
429 else SLOT->Cnt += SLOT->Incr;
430 /* connectoion */
431 outd[0] += OP_OUT(SLOT,env_out, feedback2);
432 }
433}
434
435/* ----------- initialize time tabls ----------- */
436static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
437{
438 int i;
439 double rate;
440
441 /* make attack rate & decay rate tables */
442 for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
443 for (i = 4;i <= 60;i++){
444 rate = OPL->freqbase; /* frequency rate */
445 if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
446 rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */
447 rate *= (double)(EG_ENT<<ENV_BITS);
448 OPL->AR_TABLE[i] = rate / ARRATE;
449 OPL->DR_TABLE[i] = rate / DRRATE;
450 }
451 for (i = 60;i < 76;i++)
452 {
453 OPL->AR_TABLE[i] = EG_AED-1;
454 OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
455 }
456}
457
458/* ---------- generic table initialize ---------- */
459static int OPLOpenTable( void )
460{
461 int s,t;
462 double rate;
463 int i,j;
464 double pom;
465
466 /* allocate dynamic tables */
467 if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
468 return 0;
469 if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
470 {
471 free(TL_TABLE);
472 return 0;
473 }
474 if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
475 {
476 free(TL_TABLE);
477 free(SIN_TABLE);
478 return 0;
479 }
480 if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
481 {
482 free(TL_TABLE);
483 free(SIN_TABLE);
484 free(AMS_TABLE);
485 return 0;
486 }
487 /* make total level table */
488 for (t = 0;t < EG_ENT-1 ;t++){
489 rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */
490 TL_TABLE[ t] = (int)rate;
491 TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
492
493 }
494 /* fill volume off area */
495 for ( t = EG_ENT-1; t < TL_MAX ;t++){
496 TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
497 }
498
499 /* make sinwave table (total level offet) */
500 /* degree 0 = degree 180 = off */
501 SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1];
502 for (s = 1;s <= SIN_ENT/4;s++){
503 pom = sin(2*PI*s/SIN_ENT); /* sin */
504 pom = 20*log10(1/pom); /* decibel */
505 j = pom / EG_STEP; /* TL_TABLE steps */
506
507 /* degree 0 - 90 , degree 180 - 90 : plus section */
508 SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
509 /* degree 180 - 270 , degree 360 - 270 : minus section */
510 SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j];
511
512 }
513 for (s = 0;s < SIN_ENT;s++)
514 {
515 SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
516 SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
517 SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
518 }
519
520 /* envelope counter -> envelope output table */
521 for (i=0; i<EG_ENT; i++)
522 {
523 /* ATTACK curve */
524 pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
525 /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
526 ENV_CURVE[i] = (int)pom;
527 /* DECAY ,RELEASE curve */
528 ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
529 }
530 /* off */
531 ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
532 /* make LFO ams table */
533 for (i=0; i<AMS_ENT; i++)
534 {
535 pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
536 AMS_TABLE[i] = (1.0/EG_STEP)*pom; /* 1dB */
537 AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
538 }
539 /* make LFO vibrate table */
540 for (i=0; i<VIB_ENT; i++)
541 {
542 /* 100cent = 1seminote = 6% ?? */
543 pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
544 VIB_TABLE[i] = VIB_RATE + (pom*0.07); /* +- 7cent */
545 VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
546 }
547 return 1;
548}
549
550
551static void OPLCloseTable( void )
552{
553 free(TL_TABLE);
554 free(SIN_TABLE);
555 free(AMS_TABLE);
556 free(VIB_TABLE);
557}
558
559/* CSM Key Controll */
560INLINE void CSMKeyControll(OPL_CH *CH)
561{
562 OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
563 OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
564 /* all key off */
565 OPL_KEYOFF(slot1);
566 OPL_KEYOFF(slot2);
567 /* total level latch */
568 slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
569 slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
570 /* key on */
571 CH->op1_out[0] = CH->op1_out[1] = 0;
572 OPL_KEYON(slot1);
573 OPL_KEYON(slot2);
574}
575
576/* ---------- opl initialize ---------- */
577static void OPL_initalize(FM_OPL *OPL)
578{
579 int fn;
580
581 /* frequency base */
582 OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
583 /* make time tables */
584 init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
585 /* make fnumber -> increment counter table */
586 for( fn=0 ; fn < 1024 ; fn++ )
587 {
588 OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
589 }
590 /* LFO freq.table */
591 OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
592 OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
593}
594
595/* ---------- write a OPL registers ---------- */
596static void OPLWriteReg(FM_OPL *OPL, int r, int v)
597{
598 OPL_CH *CH;
599 int slot;
600 int block_fnum;
601
602 switch(r&0xe0)
603 {
604 case 0x00: /* 00-1f:controll */
605 switch(r&0x1f)
606 {
607 case 0x01:
608 /* wave selector enable */
609 if(OPL->type&OPL_TYPE_WAVESEL)
610 {
611 OPL->wavesel = v&0x20;
612 if(!OPL->wavesel)
613 {
614 /* preset compatible mode */
615 int c;
616 for(c=0;c<OPL->max_ch;c++)
617 {
618 OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
619 OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
620 }
621 }
622 }
623 return;
624 }
625 break;
626 case 0x20: /* am,vib,ksr,eg type,mul */
627 slot = slot_array[r&0x1f];
628 if(slot == -1) return;
629 set_mul(OPL,slot,v);
630 return;
631 case 0x40:
632 slot = slot_array[r&0x1f];
633 if(slot == -1) return;
634 set_ksl_tl(OPL,slot,v);
635 return;
636 case 0x60:
637 slot = slot_array[r&0x1f];
638 if(slot == -1) return;
639 set_ar_dr(OPL,slot,v);
640 return;
641 case 0x80:
642 slot = slot_array[r&0x1f];
643 if(slot == -1) return;
644 set_sl_rr(OPL,slot,v);
645 return;
646 case 0xa0:
647 switch(r)
648 {
649 case 0xbd:
650 /* amsep,vibdep,r,bd,sd,tom,tc,hh */
651 {
652 OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
653 OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
654 }
655 return;
656 }
657 /* keyon,block,fnum */
658 if( (r&0x0f) > 8) return;
659 CH = &OPL->P_CH[r&0x0f];
660 if(!(r&0x10))
661 { /* a0-a8 */
662 block_fnum = (CH->block_fnum&0x1f00) | v;
663 }
664 else
665 { /* b0-b8 */
666 int keyon = (v>>5)&1;
667 block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
668 if(CH->keyon != keyon)
669 {
670 if( (CH->keyon=keyon) )
671 {
672 CH->op1_out[0] = CH->op1_out[1] = 0;
673 OPL_KEYON(&CH->SLOT[SLOT1]);
674 OPL_KEYON(&CH->SLOT[SLOT2]);
675 }
676 else
677 {
678 OPL_KEYOFF(&CH->SLOT[SLOT1]);
679 OPL_KEYOFF(&CH->SLOT[SLOT2]);
680 }
681 }
682 }
683 /* update */
684 if(CH->block_fnum != block_fnum)
685 {
686 int blockRv = 7-(block_fnum>>10);
687 int fnum = block_fnum&0x3ff;
688 CH->block_fnum = block_fnum;
689
690 CH->ksl_base = KSL_TABLE[block_fnum>>6];
691 CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
692 CH->kcode = CH->block_fnum>>9;
693 if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
694 CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
695 CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
696 }
697 return;
698 case 0xc0:
699 /* FB,C */
700 if( (r&0x0f) > 8) return;
701 CH = &OPL->P_CH[r&0x0f];
702 {
703 int feedback = (v>>1)&7;
704 CH->FB = feedback ? (8+1) - feedback : 0;
705 CH->CON = v&1;
706 set_algorythm(CH);
707 }
708 return;
709 case 0xe0: /* wave type */
710 slot = slot_array[r&0x1f];
711 if(slot == -1) return;
712 CH = &OPL->P_CH[slot/2];
713 if(OPL->wavesel)
714 {
715 CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
716 }
717 return;
718 }
719}
720
721/* lock/unlock for common table */
722static int OPL_LockTable(void)
723{
724 num_lock++;
725 if(num_lock>1) return 0;
726 /* first time */
727 cur_chip = NULL;
728 /* allocate total level table (128kb space) */
729 if( !OPLOpenTable() )
730 {
731 num_lock--;
732 return -1;
733 }
734 return 0;
735}
736
737static void OPL_UnLockTable(void)
738{
739 if(num_lock) num_lock--;
740 if(num_lock) return;
741 /* last time */
742 cur_chip = NULL;
743 OPLCloseTable();
744}
745
746/*******************************************************************************/
747/* YM3812 local section */
748/*******************************************************************************/
749
750/* ---------- update one of chip ----------- */
751void YM3812UpdateOne(FM_OPL *OPL, UINT32 *buffer, int length)
752{
753 int i;
754 UINT32 *buf = buffer;
755 UINT32 amsCnt = OPL->amsCnt;
756 UINT32 vibCnt = OPL->vibCnt;
757 OPL_CH *CH,*R_CH;
758
759 if( (void *)OPL != cur_chip ){
760 cur_chip = (void *)OPL;
761 /* channel pointers */
762 S_CH = OPL->P_CH;
763 E_CH = &S_CH[6];
764 /* LFO state */
765 amsIncr = OPL->amsIncr;
766 vibIncr = OPL->vibIncr;
767 ams_table = OPL->ams_table;
768 vib_table = OPL->vib_table;
769 }
770 R_CH = E_CH;
771 for( i=0; i < length ; i++ )
772 {
773 /* channel A channel B channel C */
774 /* LFO */
775 ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
776 vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
777 outd[0] = 0;
778 /* FM part */
779 for(CH=S_CH ; CH < R_CH ; CH++)
780 OPL_CALC_CH(CH);
781 /* limit check */
782 //data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
783 /* store to sound buffer */
784 {
785 int32 d=outd[0]>>OPL_OUTSB;
786 if(d<-32768) d=-32768;
787 d+=32768;
788 buf[i] += d;
789 }
790 }
791
792 OPL->amsCnt = amsCnt;
793 OPL->vibCnt = vibCnt;
794}
795
796/* ---------- reset one of chip ---------- */
797void OPLResetChip(FM_OPL *OPL)
798{
799 int c,s;
800 int i;
801
802 /* reset chip */
803 OPL->mode = 0; /* normal mode */
804
805 /* reset with register write */
806 OPLWriteReg(OPL,0x01,0); /* wabesel disable */
807 for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
808 /* reset OPerator paramater */
809 for( c = 0 ; c < OPL->max_ch ; c++ )
810 {
811 OPL_CH *CH = &OPL->P_CH[c];
812 /* OPL->P_CH[c].PAN = OPN_CENTER; */
813 for(s = 0 ; s < 2 ; s++ )
814 {
815 /* wave table */
816 CH->SLOT[s].wavetable = &SIN_TABLE[0];
817 /* CH->SLOT[s].evm = ENV_MOD_RR; */
818 CH->SLOT[s].evc = EG_OFF;
819 CH->SLOT[s].eve = EG_OFF+1;
820 CH->SLOT[s].evs = 0;
821 }
822 }
823}
824
825/* ---------- Create one of vietual YM3812 ---------- */
826/* 'rate' is sampling rate and 'bufsiz' is the size of the */
827FM_OPL *OPLCreate(int type, int clock, int rate)
828{
829 char *ptr;
830 FM_OPL *OPL;
831 int state_size;
832 int max_ch = 9; /* normaly 9 channels */
833
834 if( OPL_LockTable() ==-1) return NULL;
835 /* allocate OPL state space */
836 state_size = sizeof(FM_OPL);
837 state_size += sizeof(OPL_CH)*max_ch;
838
839 /* allocate memory block */
840 ptr = malloc(state_size);
841 if(ptr==NULL) return NULL;
842 /* clear */
843 memset(ptr,0,state_size);
844 OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
845 OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
846
847 /* set channel state pointer */
848 OPL->type = type;
849 OPL->clock = clock;
850 OPL->rate = rate;
851 OPL->max_ch = max_ch;
852 /* init grobal tables */
853 OPL_initalize(OPL);
854 /* reset chip */
855 OPLResetChip(OPL);
856
857 return OPL;
858}
859
860/* ---------- Destroy one of vietual YM3812 ---------- */
861void OPLDestroy(FM_OPL *OPL)
862{
863 OPL_UnLockTable();
864 free(OPL);
865}
866
867/* ---------- YM3812 I/O interface ---------- */
868void OPLWrite(FM_OPL *OPL,UINT8 a,UINT8 v)
869{
870 OPLWriteReg(OPL,a,v);
871}