12a6a4076SMarkus Armbruster #ifndef FMOPL_H 22a6a4076SMarkus Armbruster #define FMOPL_H 385571bc7Sbellard 44a796e97SJuan Quintela 5c57fbf50SHervé Poussineau typedef void (*OPL_TIMERHANDLER)(void *param, int channel, double interval_Sec); 685571bc7Sbellard 785571bc7Sbellard /* !!!!! here is private section , do not access there member direct !!!!! */ 885571bc7Sbellard 985571bc7Sbellard /* Saving is necessary for member of the 'R' mark for suspend/resume */ 1085571bc7Sbellard /* ---------- OPL one of slot ---------- */ 1185571bc7Sbellard typedef struct fm_opl_slot { 127f643fb5SJuan Quintela int32_t TL; /* total level :TL << 8 */ 137f643fb5SJuan Quintela int32_t TLL; /* adjusted now TL */ 144a796e97SJuan Quintela uint8_t KSR; /* key scale rate :(shift down bit) */ 157f643fb5SJuan Quintela int32_t *AR; /* attack rate :&AR_TABLE[AR<<2] */ 167f643fb5SJuan Quintela int32_t *DR; /* decay rate :&DR_TALBE[DR<<2] */ 177f643fb5SJuan Quintela int32_t SL; /* sustin level :SL_TALBE[SL] */ 187f643fb5SJuan Quintela int32_t *RR; /* release rate :&DR_TABLE[RR<<2] */ 194a796e97SJuan Quintela uint8_t ksl; /* keyscale level :(shift down bits) */ 204a796e97SJuan Quintela uint8_t ksr; /* key scale rate :kcode>>KSR */ 213795f180SJuan Quintela uint32_t mul; /* multiple :ML_TABLE[ML] */ 223795f180SJuan Quintela uint32_t Cnt; /* frequency count : */ 233795f180SJuan Quintela uint32_t Incr; /* frequency step : */ 2485571bc7Sbellard /* envelope generator state */ 254a796e97SJuan Quintela uint8_t eg_typ; /* envelope type flag */ 264a796e97SJuan Quintela uint8_t evm; /* envelope phase */ 277f643fb5SJuan Quintela int32_t evc; /* envelope counter */ 287f643fb5SJuan Quintela int32_t eve; /* envelope counter end point */ 297f643fb5SJuan Quintela int32_t evs; /* envelope counter step */ 307f643fb5SJuan Quintela int32_t evsa; /* envelope step for AR :AR[ksr] */ 317f643fb5SJuan Quintela int32_t evsd; /* envelope step for DR :DR[ksr] */ 327f643fb5SJuan Quintela int32_t evsr; /* envelope step for RR :RR[ksr] */ 3385571bc7Sbellard /* LFO */ 344a796e97SJuan Quintela uint8_t ams; /* ams flag */ 354a796e97SJuan Quintela uint8_t vib; /* vibrate flag */ 3685571bc7Sbellard /* wave selector */ 377f643fb5SJuan Quintela int32_t **wavetable; 3885571bc7Sbellard }OPL_SLOT; 3985571bc7Sbellard 4085571bc7Sbellard /* ---------- OPL one of channel ---------- */ 4185571bc7Sbellard typedef struct fm_opl_channel { 4285571bc7Sbellard OPL_SLOT SLOT[2]; 434a796e97SJuan Quintela uint8_t CON; /* connection type */ 444a796e97SJuan Quintela uint8_t FB; /* feed back :(shift down bit) */ 457f643fb5SJuan Quintela int32_t *connect1; /* slot1 output pointer */ 467f643fb5SJuan Quintela int32_t *connect2; /* slot2 output pointer */ 477f643fb5SJuan Quintela int32_t op1_out[2]; /* slot1 output for selfeedback */ 4885571bc7Sbellard /* phase generator state */ 493795f180SJuan Quintela uint32_t block_fnum; /* block+fnum : */ 504a796e97SJuan Quintela uint8_t kcode; /* key code : KeyScaleCode */ 513795f180SJuan Quintela uint32_t fc; /* Freq. Increment base */ 523795f180SJuan Quintela uint32_t ksl_base; /* KeyScaleLevel Base step */ 534a796e97SJuan Quintela uint8_t keyon; /* key on/off flag */ 5485571bc7Sbellard } OPL_CH; 5585571bc7Sbellard 5685571bc7Sbellard /* OPL state */ 5785571bc7Sbellard typedef struct fm_opl_f { 5885571bc7Sbellard int clock; /* master clock (Hz) */ 5985571bc7Sbellard int rate; /* sampling rate (Hz) */ 6085571bc7Sbellard double freqbase; /* frequency base */ 6185571bc7Sbellard double TimerBase; /* Timer base time (==sampling time) */ 624a796e97SJuan Quintela uint8_t address; /* address register */ 634a796e97SJuan Quintela uint8_t status; /* status flag */ 644a796e97SJuan Quintela uint8_t statusmask; /* status mask */ 653795f180SJuan Quintela uint32_t mode; /* Reg.08 : CSM , notesel,etc. */ 6685571bc7Sbellard /* Timer */ 6785571bc7Sbellard int T[2]; /* timer counter */ 684a796e97SJuan Quintela uint8_t st[2]; /* timer enable */ 6985571bc7Sbellard /* FM channel slots */ 7085571bc7Sbellard OPL_CH *P_CH; /* pointer of CH */ 7185571bc7Sbellard int max_ch; /* maximum channel */ 72*528ea579SMichael Tokarev /* Rhythm section */ 734a796e97SJuan Quintela uint8_t rhythm; /* Rhythm mode , key flag */ 7485571bc7Sbellard /* time tables */ 7557ac4a7aSGerd Hoffmann int32_t AR_TABLE[76]; /* attack rate tables */ 7657ac4a7aSGerd Hoffmann int32_t DR_TABLE[76]; /* decay rate tables */ 773795f180SJuan Quintela uint32_t FN_TABLE[1024]; /* fnumber -> increment counter */ 7885571bc7Sbellard /* LFO */ 797f643fb5SJuan Quintela int32_t *ams_table; 807f643fb5SJuan Quintela int32_t *vib_table; 817f643fb5SJuan Quintela int32_t amsCnt; 827f643fb5SJuan Quintela int32_t amsIncr; 837f643fb5SJuan Quintela int32_t vibCnt; 847f643fb5SJuan Quintela int32_t vibIncr; 8585571bc7Sbellard /* wave selector enable flag */ 864a796e97SJuan Quintela uint8_t wavesel; 8785571bc7Sbellard /* external event callback handler */ 8885571bc7Sbellard OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ 89c57fbf50SHervé Poussineau void *TimerParam; /* TIMER parameter */ 9085571bc7Sbellard } FM_OPL; 9185571bc7Sbellard 9285571bc7Sbellard /* ---------- Generic interface section ---------- */ 938f7e2c2cSJuan Quintela FM_OPL *OPLCreate(int clock, int rate); 9485571bc7Sbellard void OPLDestroy(FM_OPL *OPL); 95c57fbf50SHervé Poussineau void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, 96c57fbf50SHervé Poussineau void *param); 9785571bc7Sbellard 9885571bc7Sbellard int OPLWrite(FM_OPL *OPL,int a,int v); 9985571bc7Sbellard unsigned char OPLRead(FM_OPL *OPL,int a); 10085571bc7Sbellard int OPLTimerOver(FM_OPL *OPL,int c); 10185571bc7Sbellard 1027bf10b1dSJuan Quintela void YM3812UpdateOne(FM_OPL *OPL, int16_t *buffer, int length); 10385571bc7Sbellard #endif 104