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