00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #ifdef USE_FMOPL_MIDI
00031
00032 #include "common_types.h"
00033 #include <cstdio>
00034 #include <cstdlib>
00035 #include <cstring>
00036 #include <cstdarg>
00037 #include <cmath>
00038 #include <iostream>
00039 #include "fmopl.h"
00040
00041 #ifndef UNDER_CE
00042 using std::malloc;
00043 using std::free;
00044 #endif
00045
00046 #ifndef PI
00047 #define PI 3.14159265358979323846
00048 #endif
00049
00050
00051
00052 #define OPL_ARRATE 141280
00053 #define OPL_DRRATE 1956000
00054
00055 #define FREQ_BITS 24
00056
00057
00058 #define FREQ_RATE (1<<(FREQ_BITS-20))
00059 #define TL_BITS (FREQ_BITS+2)
00060
00061
00062 #define OPL_OUTSB (TL_BITS+3-16)
00063 #define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
00064 #define OPL_MINOUT (-0x8000<<OPL_OUTSB)
00065
00066
00067
00068
00069
00070 #define SIN_ENT 2048
00071
00072
00073
00074 #define ENV_BITS 16
00075
00076 #define EG_ENT 4096
00077
00078
00079
00080 #define EG_OFF ((2*EG_ENT)<<ENV_BITS)
00081 #define EG_DED EG_OFF
00082 #define EG_DST (EG_ENT<<ENV_BITS)
00083 #define EG_AED EG_DST
00084 #define EG_AST 0
00085
00086 #define EG_STEP (96.0/EG_ENT)
00087
00088
00089 #define VIB_ENT 512
00090 #define VIB_SHIFT (32-9)
00091 #define AMS_ENT 512
00092 #define AMS_SHIFT (32-9)
00093
00094 #define VIB_RATE 256
00095
00096
00097
00098
00099 #define SLOT1 0
00100 #define SLOT2 1
00101
00102
00103 #define ENV_MOD_RR 0x00
00104 #define ENV_MOD_DR 0x01
00105 #define ENV_MOD_AR 0x02
00106
00107
00108 static const int slot_array[32]=
00109 {
00110 0, 2, 4, 1, 3, 5,-1,-1,
00111 6, 8,10, 7, 9,11,-1,-1,
00112 12,14,16,13,15,17,-1,-1,
00113 -1,-1,-1,-1,-1,-1,-1,-1
00114 };
00115
00116 #define SC(mydb) ((uint32) (mydb / (EG_STEP/2)))
00117
00118 static const uint32 KSL_TABLE[8 * 16] = {
00119
00120 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00121 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00122 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00123 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00124
00125 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00126 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00127 SC(0.000), SC(0.750), SC(1.125), SC(1.500),
00128 SC(1.875), SC(2.250), SC(2.625), SC(3.000),
00129
00130 SC(0.000), SC(0.000), SC(0.000), SC(0.000),
00131 SC(0.000), SC(1.125), SC(1.875), SC(2.625),
00132 SC(3.000), SC(3.750), SC(4.125), SC(4.500),
00133 SC(4.875), SC(5.250), SC(5.625), SC(6.000),
00134
00135 SC(0.000), SC(0.000), SC(0.000), SC(1.875),
00136 SC(3.000), SC(4.125), SC(4.875), SC(5.625),
00137 SC(6.000), SC(6.750), SC(7.125), SC(7.500),
00138 SC(7.875), SC(8.250), SC(8.625), SC(9.000),
00139
00140 SC(0.000), SC(0.000), SC(3.000), SC(4.875),
00141 SC(6.000), SC(7.125), SC(7.875), SC(8.625),
00142 SC(9.000), SC(9.750), SC(10.125), SC(10.500),
00143 SC(10.875), SC(11.250), SC(11.625), SC(12.000),
00144
00145 SC(0.000), SC(3.000), SC(6.000), SC(7.875),
00146 SC(9.000), SC(10.125), SC(10.875), SC(11.625),
00147 SC(12.000), SC(12.750), SC(13.125), SC(13.500),
00148 SC(13.875), SC(14.250), SC(14.625), SC(15.000),
00149
00150 SC(0.000), SC(6.000), SC(9.000), SC(10.875),
00151 SC(12.000), SC(13.125), SC(13.875), SC(14.625),
00152 SC(15.000), SC(15.750), SC(16.125), SC(16.500),
00153 SC(16.875), SC(17.250), SC(17.625), SC(18.000),
00154
00155 SC(0.000), SC(9.000), SC(12.000), SC(13.875),
00156 SC(15.000), SC(16.125), SC(16.875), SC(17.625),
00157 SC(18.000), SC(18.750), SC(19.125), SC(19.500),
00158 SC(19.875), SC(20.250), SC(20.625), SC(21.000)
00159 };
00160 #undef SC
00161
00162
00163
00164
00165 #define SC(db) (int)(db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
00166 static const int SL_TABLE[16]={
00167 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
00168 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
00169 };
00170 #undef SC
00171
00172 #define TL_MAX (EG_ENT*2)
00173
00174
00175
00176 static int *TL_TABLE;
00177
00178
00179 static int **SIN_TABLE;
00180
00181
00182 static int *AMS_TABLE;
00183 static int *VIB_TABLE;
00184
00185
00186
00187 static int ENV_CURVE[2*EG_ENT+1];
00188
00189
00190 #define ML(a) (int)(a*2)
00191 static const uint32 MUL_TABLE[16]= {
00192
00193 ML(0.50), ML(1.00), ML(2.00), ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
00194 ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
00195 };
00196 #undef ML
00197
00198
00199 static int RATE_0[16]=
00200 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00201
00202
00203
00204
00205 static int num_lock = 0;
00206
00207
00208 static void *cur_chip = NULL;
00209
00210
00211 static OPL_CH *S_CH;
00212 static OPL_CH *E_CH;
00213 OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
00214
00215 static int outd[1];
00216 static int ams;
00217 static int vib;
00218 int *ams_table;
00219 int *vib_table;
00220 static int amsIncr;
00221 static int vibIncr;
00222 static int feedback2;
00223
00224
00225
00226 inline int Limit( int val, int max, int min ) {
00227 if ( val > max )
00228 val = max;
00229 else if ( val < min )
00230 val = min;
00231
00232 return val;
00233 }
00234
00235
00236 inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
00237 {
00238
00239 OPL->status |= flag;
00240 if(!(OPL->status & 0x80))
00241 {
00242 if(OPL->status & OPL->statusmask)
00243 {
00244 OPL->status |= 0x80;
00245
00246 if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
00247 }
00248 }
00249 }
00250
00251
00252 inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
00253 {
00254
00255 OPL->status &=~flag;
00256 if((OPL->status & 0x80))
00257 {
00258 if (!(OPL->status & OPL->statusmask) )
00259 {
00260 OPL->status &= 0x7f;
00261
00262 if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
00263 }
00264 }
00265 }
00266
00267
00268 inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
00269 {
00270 OPL->statusmask = flag;
00271
00272 OPL_STATUS_SET(OPL,0);
00273 OPL_STATUS_RESET(OPL,0);
00274 }
00275
00276
00277 inline void OPL_KEYON(OPL_SLOT *SLOT)
00278 {
00279
00280 SLOT->Cnt = 0;
00281
00282 SLOT->evm = ENV_MOD_AR;
00283 SLOT->evs = SLOT->evsa;
00284 SLOT->evc = EG_AST;
00285 SLOT->eve = EG_AED;
00286 }
00287
00288 inline void OPL_KEYOFF(OPL_SLOT *SLOT)
00289 {
00290 if( SLOT->evm > ENV_MOD_RR)
00291 {
00292
00293 SLOT->evm = ENV_MOD_RR;
00294 if( !(SLOT->evc&EG_DST) )
00295
00296 SLOT->evc = EG_DST;
00297 SLOT->eve = EG_DED;
00298 SLOT->evs = SLOT->evsr;
00299 }
00300 }
00301
00302
00303
00304 inline uint32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
00305 {
00306
00307 if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
00308 {
00309 switch( SLOT->evm ){
00310 case ENV_MOD_AR:
00311
00312 SLOT->evm = ENV_MOD_DR;
00313 SLOT->evc = EG_DST;
00314 SLOT->eve = SLOT->SL;
00315 SLOT->evs = SLOT->evsd;
00316 break;
00317 case ENV_MOD_DR:
00318 SLOT->evc = SLOT->SL;
00319 SLOT->eve = EG_DED;
00320 if(SLOT->eg_typ)
00321 {
00322 SLOT->evs = 0;
00323 }
00324 else
00325 {
00326 SLOT->evm = ENV_MOD_RR;
00327 SLOT->evs = SLOT->evsr;
00328 }
00329 break;
00330 case ENV_MOD_RR:
00331 SLOT->evc = EG_OFF;
00332 SLOT->eve = EG_OFF+1;
00333 SLOT->evs = 0;
00334 break;
00335 }
00336 }
00337
00338 return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
00339 }
00340
00341
00342 static void set_algorythm( OPL_CH *CH)
00343 {
00344 int *carrier = &outd[0];
00345 CH->connect1 = CH->CON ? carrier : &feedback2;
00346 CH->connect2 = carrier;
00347 }
00348
00349
00350 inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
00351 {
00352 int ksr;
00353
00354
00355 SLOT->Incr = CH->fc * SLOT->mul;
00356 ksr = CH->kcode >> SLOT->KSR;
00357
00358 if( SLOT->ksr != ksr )
00359 {
00360 SLOT->ksr = ksr;
00361
00362 SLOT->evsa = SLOT->AR[ksr];
00363 SLOT->evsd = SLOT->DR[ksr];
00364 SLOT->evsr = SLOT->RR[ksr];
00365 }
00366 SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
00367 }
00368
00369
00370 inline void set_mul(FM_OPL *OPL,int slot,int v)
00371 {
00372 OPL_CH *CH = &OPL->P_CH[slot/2];
00373 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
00374
00375 SLOT->mul = MUL_TABLE[v&0x0f];
00376 SLOT->KSR = (v&0x10) ? 0 : 2;
00377 SLOT->eg_typ = (v&0x20)>>5;
00378 SLOT->vib = (v&0x40);
00379 SLOT->ams = (v&0x80);
00380 CALC_FCSLOT(CH,SLOT);
00381 }
00382
00383
00384 inline void set_ksl_tl(FM_OPL *OPL,int slot,int v)
00385 {
00386 OPL_CH *CH = &OPL->P_CH[slot/2];
00387 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
00388 int ksl = v>>6;
00389
00390 SLOT->ksl = ksl ? 3-ksl : 31;
00391 SLOT->TL = (int)((v&0x3f)*(0.75/EG_STEP));
00392
00393 if( !(OPL->mode&0x80) )
00394 {
00395 SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
00396 }
00397 }
00398
00399
00400 inline void set_ar_dr(FM_OPL *OPL,int slot,int v)
00401 {
00402 OPL_CH *CH = &OPL->P_CH[slot/2];
00403 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
00404 int ar = v>>4;
00405 int dr = v&0x0f;
00406
00407 SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
00408 SLOT->evsa = SLOT->AR[SLOT->ksr];
00409 if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
00410
00411 SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
00412 SLOT->evsd = SLOT->DR[SLOT->ksr];
00413 if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
00414 }
00415
00416
00417 inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
00418 {
00419 OPL_CH *CH = &OPL->P_CH[slot/2];
00420 OPL_SLOT *SLOT = &CH->SLOT[slot&1];
00421 int sl = v>>4;
00422 int rr = v & 0x0f;
00423
00424 SLOT->SL = SL_TABLE[sl];
00425 if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
00426 SLOT->RR = &OPL->DR_TABLE[rr<<2];
00427 SLOT->evsr = SLOT->RR[SLOT->ksr];
00428 if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
00429 }
00430
00431
00432 #define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
00433
00434 inline void OPL_CALC_CH( OPL_CH *CH )
00435 {
00436 uint32 env_out;
00437 OPL_SLOT *SLOT;
00438
00439 feedback2 = 0;
00440
00441 SLOT = &CH->SLOT[SLOT1];
00442 env_out=OPL_CALC_SLOT(SLOT);
00443 if( env_out < EG_ENT-1 )
00444 {
00445
00446 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
00447 else SLOT->Cnt += SLOT->Incr;
00448
00449 if(CH->FB)
00450 {
00451 int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
00452 CH->op1_out[1] = CH->op1_out[0];
00453 *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
00454 }
00455 else
00456 {
00457 *CH->connect1 += OP_OUT(SLOT,env_out,0);
00458 }
00459 }else
00460 {
00461 CH->op1_out[1] = CH->op1_out[0];
00462 CH->op1_out[0] = 0;
00463 }
00464
00465 SLOT = &CH->SLOT[SLOT2];
00466 env_out=OPL_CALC_SLOT(SLOT);
00467 if( env_out < EG_ENT-1 )
00468 {
00469
00470 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
00471 else SLOT->Cnt += SLOT->Incr;
00472
00473 outd[0] += OP_OUT(SLOT,env_out, feedback2);
00474 }
00475 }
00476
00477
00478 #define WHITE_NOISE_db 6.0
00479 inline void OPL_CALC_RH( OPL_CH *CH )
00480 {
00481 uint32 env_tam,env_sd,env_top,env_hh;
00482 int whitenoise = int((std::rand()&1)*(WHITE_NOISE_db/EG_STEP));
00483 int tone8;
00484
00485 OPL_SLOT *SLOT;
00486 int env_out;
00487
00488
00489 feedback2 = 0;
00490
00491 SLOT = &CH[6].SLOT[SLOT1];
00492 env_out=OPL_CALC_SLOT(SLOT);
00493 if( env_out < EG_ENT-1 )
00494 {
00495
00496 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
00497 else SLOT->Cnt += SLOT->Incr;
00498
00499 if(CH[6].FB)
00500 {
00501 int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
00502 CH[6].op1_out[1] = CH[6].op1_out[0];
00503 feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
00504 }
00505 else
00506 {
00507 feedback2 = OP_OUT(SLOT,env_out,0);
00508 }
00509 }else
00510 {
00511 feedback2 = 0;
00512 CH[6].op1_out[1] = CH[6].op1_out[0];
00513 CH[6].op1_out[0] = 0;
00514 }
00515
00516 SLOT = &CH[6].SLOT[SLOT2];
00517 env_out=OPL_CALC_SLOT(SLOT);
00518 if( env_out < EG_ENT-1 )
00519 {
00520
00521 if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
00522 else SLOT->Cnt += SLOT->Incr;
00523
00524 outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
00525 }
00526
00527
00528
00529
00530
00531 env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
00532 env_tam=OPL_CALC_SLOT(SLOT8_1);
00533 env_top=OPL_CALC_SLOT(SLOT8_2);
00534 env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
00535
00536
00537 if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
00538 else SLOT7_1->Cnt += 2*SLOT7_1->Incr;
00539 if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
00540 else SLOT7_2->Cnt += (CH[7].fc*8);
00541 if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
00542 else SLOT8_1->Cnt += SLOT8_1->Incr;
00543 if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
00544 else SLOT8_2->Cnt += (CH[8].fc*48);
00545
00546 tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
00547
00548
00549 if( env_sd < EG_ENT-1 )
00550 outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
00551
00552 if( env_tam < EG_ENT-1 )
00553 outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
00554
00555 if( env_top < EG_ENT-1 )
00556 outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
00557
00558 if( env_hh < EG_ENT-1 )
00559 outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
00560 }
00561
00562
00563 static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
00564 {
00565 int i;
00566 double rate;
00567
00568
00569 for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
00570 for (i = 4;i <= 60;i++){
00571 rate = OPL->freqbase;
00572 if( i < 60 ) rate *= 1.0+(i&3)*0.25;
00573 rate *= 1<<((i>>2)-1);
00574 rate *= (double)(EG_ENT<<ENV_BITS);
00575 OPL->AR_TABLE[i] = (int)(rate / ARRATE);
00576 OPL->DR_TABLE[i] = (int)(rate / DRRATE);
00577 }
00578 for (i = 60;i < 76;i++)
00579 {
00580 OPL->AR_TABLE[i] = EG_AED-1;
00581 OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
00582 }
00583 }
00584
00585
00586 static int OPLOpenTable( void )
00587 {
00588 int s,t;
00589 double rate;
00590 int i,j;
00591 double pom;
00592
00593
00594 if( (TL_TABLE = (int *)malloc(TL_MAX*2*sizeof(int))) == NULL)
00595 return 0;
00596 if( (SIN_TABLE = (int **)malloc(SIN_ENT*4 *sizeof(int *))) == NULL)
00597 {
00598 free(TL_TABLE);
00599 return 0;
00600 }
00601 if( (AMS_TABLE = (int *)malloc(AMS_ENT*2 *sizeof(int))) == NULL)
00602 {
00603 free(TL_TABLE);
00604 free(SIN_TABLE);
00605 return 0;
00606 }
00607 if( (VIB_TABLE = (int *)malloc(VIB_ENT*2 *sizeof(int))) == NULL)
00608 {
00609 free(TL_TABLE);
00610 free(SIN_TABLE);
00611 free(AMS_TABLE);
00612 return 0;
00613 }
00614
00615 for (t = 0;t < EG_ENT-1 ;t++){
00616 rate = ((1<<TL_BITS)-1)/std::pow(10,EG_STEP*t/20);
00617 TL_TABLE[ t] = (int)rate;
00618 TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
00619 }
00620
00621 for ( t = EG_ENT-1; t < TL_MAX ;t++){
00622 TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
00623 }
00624
00625
00626
00627 SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1];
00628 for (s = 1;s <= SIN_ENT/4;s++){
00629 pom = std::sin(2*PI*s/SIN_ENT);
00630 pom = 20*std::log10(1/pom);
00631 j = int(pom / EG_STEP);
00632
00633
00634 SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
00635
00636 SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j];
00637 }
00638 for (s = 0;s < SIN_ENT;s++)
00639 {
00640 SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
00641 SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
00642 SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
00643 }
00644
00645
00646 for (i=0; i<EG_ENT; i++)
00647 {
00648
00649 pom = std::pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
00650
00651 ENV_CURVE[i] = (int)pom;
00652
00653 ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
00654 }
00655
00656 ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
00657
00658 for (i=0; i<AMS_ENT; i++)
00659 {
00660 pom = (1.0+std::sin(2*PI*i/AMS_ENT))/2;
00661 AMS_TABLE[i] = (int)((1.0/EG_STEP)*pom);
00662 AMS_TABLE[AMS_ENT+i] = (int)((4.8/EG_STEP)*pom);
00663 }
00664
00665 for (i=0; i<VIB_ENT; i++)
00666 {
00667
00668 pom = (double)VIB_RATE*0.06*std::sin(2*PI*i/VIB_ENT);
00669 VIB_TABLE[i] = (int)(VIB_RATE + (pom*0.07));
00670 VIB_TABLE[VIB_ENT+i] = (int)(VIB_RATE + (pom*0.14));
00671 }
00672 return 1;
00673 }
00674
00675
00676 static void OPLCloseTable( void )
00677 {
00678 free(TL_TABLE);
00679 free(SIN_TABLE);
00680 free(AMS_TABLE);
00681 free(VIB_TABLE);
00682 }
00683
00684
00685 inline void CSMKeyControll(OPL_CH *CH)
00686 {
00687 OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
00688 OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
00689
00690 OPL_KEYOFF(slot1);
00691 OPL_KEYOFF(slot2);
00692
00693 slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
00694 slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
00695
00696 CH->op1_out[0] = CH->op1_out[1] = 0;
00697 OPL_KEYON(slot1);
00698 OPL_KEYON(slot2);
00699 }
00700
00701
00702 static void OPL_initalize(FM_OPL *OPL)
00703 {
00704 int fn;
00705
00706
00707 OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
00708
00709 OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
00710
00711 init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
00712
00713 for( fn=0 ; fn < 1024 ; fn++ )
00714 {
00715 OPL->FN_TABLE[fn] = (uint32)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
00716 }
00717
00718 OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
00719 OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
00720 }
00721
00722
00723 void OPLWriteReg(FM_OPL *OPL, int r, int v)
00724 {
00725 OPL_CH *CH;
00726 int slot;
00727 uint32 block_fnum;
00728
00729 switch(r&0xe0)
00730 {
00731 case 0x00:
00732 switch(r&0x1f)
00733 {
00734 case 0x01:
00735
00736 if(OPL->type&OPL_TYPE_WAVESEL)
00737 {
00738 OPL->wavesel = v&0x20;
00739 if(!OPL->wavesel)
00740 {
00741
00742 int c;
00743 for(c=0;c<OPL->max_ch;c++)
00744 {
00745 OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
00746 OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
00747 }
00748 }
00749 }
00750 return;
00751 case 0x02:
00752 OPL->T[0] = (256-v)*4;
00753 break;
00754 case 0x03:
00755 OPL->T[1] = (256-v)*16;
00756 return;
00757 case 0x04:
00758 if(v&0x80)
00759 {
00760 OPL_STATUS_RESET(OPL,0x7f);
00761 }
00762 else
00763 {
00764 uint8 st1 = v&1;
00765 uint8 st2 = (v>>1)&1;
00766
00767 OPL_STATUS_RESET(OPL,v&0x78);
00768 OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
00769
00770 if(OPL->st[1] != st2)
00771 {
00772 double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
00773 OPL->st[1] = st2;
00774 if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);
00775 }
00776
00777 if(OPL->st[0] != st1)
00778 {
00779 double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
00780 OPL->st[0] = st1;
00781 if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
00782 }
00783 }
00784 return;
00785 }
00786 break;
00787 case 0x20:
00788 slot = slot_array[r&0x1f];
00789 if(slot == -1) return;
00790 set_mul(OPL,slot,v);
00791 return;
00792 case 0x40:
00793 slot = slot_array[r&0x1f];
00794 if(slot == -1) return;
00795 set_ksl_tl(OPL,slot,v);
00796 return;
00797 case 0x60:
00798 slot = slot_array[r&0x1f];
00799 if(slot == -1) return;
00800 set_ar_dr(OPL,slot,v);
00801 return;
00802 case 0x80:
00803 slot = slot_array[r&0x1f];
00804 if(slot == -1) return;
00805 set_sl_rr(OPL,slot,v);
00806 return;
00807 case 0xa0:
00808 switch(r)
00809 {
00810 case 0xbd:
00811
00812 {
00813 uint8 rkey = OPL->rythm^v;
00814 OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
00815 OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
00816 OPL->rythm = v&0x3f;
00817 if(OPL->rythm&0x20)
00818 {
00819
00820 if(rkey&0x10)
00821 {
00822 if(v&0x10)
00823 {
00824 OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
00825 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
00826 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
00827 }
00828 else
00829 {
00830 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
00831 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
00832 }
00833 }
00834
00835 if(rkey&0x08)
00836 {
00837 if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
00838 else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
00839 }
00840 if(rkey&0x04)
00841 {
00842 if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
00843 else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
00844 }
00845
00846 if(rkey&0x02)
00847 {
00848 if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
00849 else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
00850 }
00851
00852 if(rkey&0x01)
00853 {
00854 if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
00855 else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
00856 }
00857 }
00858 }
00859 return;
00860 }
00861
00862 if( (r&0x0f) > 8) return;
00863 CH = &OPL->P_CH[r&0x0f];
00864 if(!(r&0x10))
00865 {
00866 block_fnum = (CH->block_fnum&0x1f00) | v;
00867 }
00868 else
00869 {
00870 int keyon = (v>>5)&1;
00871 block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
00872 if(CH->keyon != keyon)
00873 {
00874 if( (CH->keyon=keyon) )
00875 {
00876 CH->op1_out[0] = CH->op1_out[1] = 0;
00877 OPL_KEYON(&CH->SLOT[SLOT1]);
00878 OPL_KEYON(&CH->SLOT[SLOT2]);
00879 }
00880 else
00881 {
00882 OPL_KEYOFF(&CH->SLOT[SLOT1]);
00883 OPL_KEYOFF(&CH->SLOT[SLOT2]);
00884 }
00885 }
00886 }
00887
00888 if(CH->block_fnum != block_fnum)
00889 {
00890 int blockRv = 7-(block_fnum>>10);
00891 int fnum = block_fnum&0x3ff;
00892 CH->block_fnum = block_fnum;
00893
00894 CH->ksl_base = KSL_TABLE[block_fnum>>6];
00895 CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
00896 CH->kcode = CH->block_fnum>>9;
00897 if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
00898 CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
00899 CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
00900 }
00901 return;
00902 case 0xc0:
00903
00904 if( (r&0x0f) > 8) return;
00905 CH = &OPL->P_CH[r&0x0f];
00906 {
00907 int feedback = (v>>1)&7;
00908 CH->FB = feedback ? (8+1) - feedback : 0;
00909 CH->CON = v&1;
00910 set_algorythm(CH);
00911 }
00912 return;
00913 case 0xe0:
00914 slot = slot_array[r&0x1f];
00915 if(slot == -1) return;
00916 CH = &OPL->P_CH[slot/2];
00917 if(OPL->wavesel)
00918 {
00919 CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
00920 }
00921 return;
00922 }
00923 }
00924
00925
00926 static int OPL_LockTable(void)
00927 {
00928 num_lock++;
00929 if(num_lock>1) return 0;
00930
00931 cur_chip = NULL;
00932
00933 if( !OPLOpenTable() )
00934 {
00935 num_lock--;
00936 return -1;
00937 }
00938 return 0;
00939 }
00940
00941 static void OPL_UnLockTable(void)
00942 {
00943 if(num_lock) num_lock--;
00944 if(num_lock) return;
00945
00946 cur_chip = NULL;
00947 OPLCloseTable();
00948 }
00949
00950
00951
00952
00953
00954
00955 void YM3812UpdateOne(FM_OPL *OPL, sint16 *buffer, int length)
00956 {
00957 int i;
00958 int data;
00959 sint16 *buf = buffer;
00960 uint32 amsCnt = OPL->amsCnt;
00961 uint32 vibCnt = OPL->vibCnt;
00962 uint8 rythm = OPL->rythm&0x20;
00963 OPL_CH *CH,*R_CH;
00964
00965 if( (void *)OPL != cur_chip ){
00966 cur_chip = (void *)OPL;
00967
00968 S_CH = OPL->P_CH;
00969 E_CH = &S_CH[9];
00970
00971 SLOT7_1 = &S_CH[7].SLOT[SLOT1];
00972 SLOT7_2 = &S_CH[7].SLOT[SLOT2];
00973 SLOT8_1 = &S_CH[8].SLOT[SLOT1];
00974 SLOT8_2 = &S_CH[8].SLOT[SLOT2];
00975
00976 amsIncr = OPL->amsIncr;
00977 vibIncr = OPL->vibIncr;
00978 ams_table = OPL->ams_table;
00979 vib_table = OPL->vib_table;
00980 }
00981 R_CH = rythm ? &S_CH[6] : E_CH;
00982 for( i=0; i < length ; i++ )
00983 {
00984
00985
00986 ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
00987 vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
00988 outd[0] = 0;
00989
00990 for(CH=S_CH ; CH < R_CH ; CH++)
00991 OPL_CALC_CH(CH);
00992
00993 if(rythm)
00994 OPL_CALC_RH(S_CH);
00995
00996 data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
00997
00998 buf[i] = data >> OPL_OUTSB;
00999 }
01000
01001 OPL->amsCnt = amsCnt;
01002 OPL->vibCnt = vibCnt;
01003 }
01004
01005
01006 void OPLResetChip(FM_OPL *OPL)
01007 {
01008 int c,s;
01009 int i;
01010
01011
01012 OPL->mode = 0;
01013 OPL_STATUS_RESET(OPL,0x7f);
01014
01015 OPLWriteReg(OPL,0x01,0);
01016 OPLWriteReg(OPL,0x02,0);
01017 OPLWriteReg(OPL,0x03,0);
01018 OPLWriteReg(OPL,0x04,0);
01019 for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
01020
01021 for( c = 0 ; c < OPL->max_ch ; c++ )
01022 {
01023 OPL_CH *CH = &OPL->P_CH[c];
01024
01025 for(s = 0 ; s < 2 ; s++ )
01026 {
01027
01028 CH->SLOT[s].wavetable = &SIN_TABLE[0];
01029
01030 CH->SLOT[s].evc = EG_OFF;
01031 CH->SLOT[s].eve = EG_OFF+1;
01032 CH->SLOT[s].evs = 0;
01033 }
01034 }
01035 }
01036
01037
01038
01039 FM_OPL *OPLCreate(int type, int clock, int rate)
01040 {
01041 char *ptr;
01042 FM_OPL *OPL;
01043 int state_size;
01044 int max_ch = 9;
01045
01046 if( OPL_LockTable() ==-1) return NULL;
01047
01048 state_size = sizeof(FM_OPL);
01049 state_size += sizeof(OPL_CH)*max_ch;
01050
01051
01052 ptr = (char *)malloc(state_size);
01053 if(ptr==NULL) return NULL;
01054
01055
01056 memset(ptr,0,state_size);
01057 OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
01058 OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
01059
01060
01061 OPL->type = type;
01062 OPL->clock = clock;
01063 OPL->rate = rate;
01064 OPL->max_ch = max_ch;
01065
01066
01067 OPL_initalize(OPL);
01068
01069
01070 OPLResetChip(OPL);
01071 return OPL;
01072 }
01073
01074
01075 void OPLDestroy(FM_OPL *OPL)
01076 {
01077 OPL_UnLockTable();
01078 free(OPL);
01079 }
01080
01081
01082
01083 void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
01084 {
01085 OPL->TimerHandler = TimerHandler;
01086 OPL->TimerParam = channelOffset;
01087 }
01088 void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
01089 {
01090 OPL->IRQHandler = IRQHandler;
01091 OPL->IRQParam = param;
01092 }
01093 void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
01094 {
01095 OPL->UpdateHandler = UpdateHandler;
01096 OPL->UpdateParam = param;
01097 }
01098
01099
01100 int OPLWrite(FM_OPL *OPL,int a,int v)
01101 {
01102 if( !(a&1) )
01103 {
01104 OPL->address = v & 0xff;
01105 }
01106 else
01107 {
01108 if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
01109 OPLWriteReg(OPL,OPL->address,v);
01110 }
01111 return OPL->status>>7;
01112 }
01113
01114 unsigned char OPLRead(FM_OPL *OPL,int a)
01115 {
01116 if( !(a&1) )
01117 {
01118 return OPL->status & (OPL->statusmask|0x80);
01119 }
01120
01121 switch(OPL->address)
01122 {
01123 case 0x05:
01124 CERR(("OPL:read unmapped KEYBOARD port\n"));
01125 return 0;
01126 case 0x19:
01127 CERR(("OPL:read unmapped I/O port\n"));
01128 return 0;
01129 case 0x1a:
01130 return 0;
01131 }
01132 return 0;
01133 }
01134
01135 int OPLTimerOver(FM_OPL *OPL,int c)
01136 {
01137 if( c )
01138 {
01139 OPL_STATUS_SET(OPL,0x20);
01140 }
01141 else
01142 {
01143 OPL_STATUS_SET(OPL,0x40);
01144
01145 if( OPL->mode & 0x80 )
01146 {
01147 int ch;
01148 if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
01149 for(ch=0;ch<9;ch++)
01150 CSMKeyControll( &OPL->P_CH[ch] );
01151 }
01152 }
01153
01154 if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
01155 return OPL->status>>7;
01156 }
01157
01158 #endif //USE_FMOPL_MIDI