fm.c

来自「DGen源码最后版本」· C语言 代码 · 共 2,003 行 · 第 1/5 页

C
2,003
字号

#define YM2610B_WARNING

/* YM2608 rhythm data is PCM ,not an ADPCM */
#define YM2608_RHYTHM_PCM

/*
**
** File: fm.c -- software implementation of FM sound generator
**
** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
**
** Version 0.35f
**
*/

/*
**** change log. (hiro-shi) ****
** 08-12-98:
** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA
** move ROM limit check.(CALC_CH? -> 2610Write1/2)
** test program (ADPCMB_TEST)
** move ADPCM A/B end check.
** ADPCMB repeat flag(no check)
** change ADPCM volume rate (8->16) (32->48).
**
** 09-12-98:
** change ADPCM volume. (8->16, 48->64)
** replace ym2610 ch0/3 (YM-2610B)
** init cur_chip (restart bug fix)
** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff.
** add ADPCM_SHIFT_MASK
** change ADPCMA_DECODE_MIN/MAX.
*/

/*
    no check:
        YM2608 rhythm sound
        OPN  SSG type envelope
        YM2612 DAC output mode
        YM2151 CSM speech mode
    no support:
        status busy flag (already not busy)
        LFO contoller (YM2612/YM2610/YM2608/YM2151)
        YM2151 noise mode
        YM2608 DELTA-T-ADPCM and RYTHM
        YM2610 DELTA-T-ADPCM with PCM port
        YM2610 PCM memory data access

        YM2608 status mask (register :0x110)
    preliminary :
        key scale level rate (?)
        attack rate time rate , curve (?)
        decay  rate time rate , curve (?)
        self feedback calcration
        YM2610 ADPCM mixing level
    Problem :

    note:
                        OPN                           OPM
        fnum          fMus * 2^20 / (fM/(12*n))
        TimerOverA    (12*n)*(1024-NA)/fFM        64*(1024-Na)/fm
        TimerOverB    (12*n)*(256-NB)/fFM       1024*(256-Nb)/fm
        output bits   10bit<<3bit               16bit * 2ch (YM3012=10bit<<3bit)
        sampling rate fFM / (12*6) ?            fFM / 64
        lfo freq                                ( fM*2^(LFRQ/16) ) / (4295*10^6)
*/

/************************************************************************/
/*    comment of hiro-shi(Hiromitsu Shioya)                             */
/*    YM2610(B) = (OPN-B                                                */
/*    YM2610  : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */
/*    YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch      */
/************************************************************************/

//#define INLINE __inline__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include "driver.h"

#include "fm.h"
// dave
extern FILE *debug_log;

#ifndef PI
#define PI 3.14159265357989
#endif

/***** shared function building option ****/
#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2612)
#define BUILD_OPNB (BUILD_YM2610||BUILD_YM2610B)
#define BUILD_FM_ADPCMA (BUILD_YM2608||BUILD_YM2610)
#define BUILD_FM_ADPCMB (BUILD_YM2608||BUILD_YM2610)

/**** YM2610 ADPCM defines ****/
#define ADPCMA_VOLUME_RATE  (1)
#define ADPCMB_VOLUME_RATE  (2) /* DELTA-T volume rate */

#define ADPCM_SHIFT    (16)

//#define AUDIO_CONV(A) ((A))
//#define AUDIO_CONV16(A) ((A))

/* ------------------------------------------------------------------ */

//#ifdef __RAINE__
#define INTERNAL_TIMER          /* use internal timer */
//#endif

/* -------------------- speed up optimize switch -------------------- */
/* ---------- Enable ---------- */
#define TL_SAVE_MEM     /* save some memories for total level */
/* ---------- Disable ---------- */
#if 0
#define SEG_SUPPORT         /* OPN SSG type envelope support   */
#define LFO_SUPPORT         /* LFO support                     */
#endif
/* -------------------- preliminary define section --------------------- */
/* attack/decay rate time rate */
#define OPM_ARRATE     399128
#define OPM_DRRATE    5514396
/* It is not checked , because I haven't YM2203 rate */
#define OPN_ARRATE  OPM_ARRATE
#define OPN_DRRATE  OPM_DRRATE

#define FREQ_BITS 24            /* frequency turn          */

/* counter bits = 21 , octerve 7 */
#define FREQ_RATE   (1<<(FREQ_BITS-21))
#define TL_BITS    (FREQ_BITS+2)

/* final output shift , limit minimum and maximum */
#define OPN_OUTSB   (TL_BITS+2-16)      /* OPN output final shift 16bit */
#define OPN_MAXOUT (0x7fff<<OPN_OUTSB)
#define OPN_MINOUT (-0x8000<<OPN_OUTSB)

#define OPM_OUTSB   (TL_BITS+2-16)      /* OPM output final shift 16bit */
#define OPM_MAXOUT (0x7fff<<OPM_OUTSB)
#define OPM_MINOUT (-0x8000<<OPM_OUTSB)

#define OPNB_OUTSB   (TL_BITS+2-16)     /* OPN output final shift 16bit */
#define OPNB_MAXOUT (0x7fff<<OPNB_OUTSB)
#define OPNB_MINOUT (-0x8000<<OPNB_OUTSB)

/* -------------------- quality selection --------------------- */

/* sinwave entries */
/* used static memory = SIN_ENT * 4 (byte) */
#define SIN_ENT 2048

/* output level entries (envelope,sinwave) */
/* envelope counter lower bits */
#define ENV_BITS 16
/* envelope output entries */
#define EG_ENT   4096
/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
/* used static  memory = EG_ENT*4 (byte)                     */

#ifdef SEG_SUPPORT
#define EG_OFF   ((3*EG_ENT)<<ENV_BITS)  /* OFF          */
#define EG_UED   EG_OFF
#define EG_UST   ((2*EG_ENT)<<ENV_BITS)  /* UPSISE START */
#define EG_DED   EG_UST
#else
#define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
#define EG_DED   EG_OFF
#endif
#define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
#define EG_AED   EG_DST
#define EG_AST   0                       /* ATTACK START */

#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */

/* LFO table entries */
#define LFO_ENT 512

/* -------------------- local defines , macros --------------------- */
/* number of maximum envelope counter */
/* #define ENV_OFF ((EG_ENT<<ENV_BITS)-1) */

/* register number to channel number , slot offset */
#define OPN_CHAN(N) (N&3)
#define OPN_SLOT(N) ((N>>2)&3)
#define OPM_CHAN(N) (N&7)
#define OPM_SLOT(N) ((N>>3)&3)
/* slot number */
#define SLOT1 0
#define SLOT2 2
#define SLOT3 1
#define SLOT4 3

/* envelope phase */
#define ENV_MOD_OFF 0x00
#define ENV_MOD_RR  0x01
#define ENV_MOD_SR  0x02
#define ENV_MOD_DR  0x03
#define ENV_MOD_AR  0x04
#define ENV_SSG_SR  0x05
#define ENV_SSG_DR  0x06
#define ENV_SSG_AR  0x07

/* bit0 = right enable , bit1 = left enable (FOR YM2612) */
#define OPN_RIGHT  1
#define OPN_LEFT   2
#define OPN_CENTER 3

/* bit0 = left enable , bit1 = right enable */
#define OPM_LEFT   1
#define OPM_RIGHT  2
#define OPM_CENTER 3
/* */

/* YM2608 Rhythm Number */
#define RY_BD  0
#define RY_SD  1
#define RY_TOP 2
#define RY_HH  3
#define RY_TOM 4
#define RY_RIM 5

/* FM timer model */
#define FM_TIMER_SINGLE (0)
#define FM_TIMER_INTERVAL (1)

/* ---------- OPN / OPM one channel  ---------- */
typedef struct fm_slot {
    int *DT;                /* detune          :DT_TABLE[DT]       */
    int DT2;                /* multiple,Detune2:(DT2<<4)|ML for OPM*/
    int TL;                 /* total level     :TL << 8            */
    signed int TLL;         /* adjusted now TL                     */
    unsigned char KSR;      /* key scale rate  :3-KSR              */
    int *AR;                /* attack rate     :&AR_TABLE[AR<<1]   */
    int *DR;                /* decay rate      :&DR_TALBE[DR<<1]   */
    int *SR;                /* sustin rate     :&DR_TABLE[SR<<1]   */
    int  SL;                /* sustin level    :SL_TALBE[SL]       */
    int *RR;                /* release rate    :&DR_TABLE[RR<<2+2] */
    unsigned char SEG;      /* SSG EG type     :SSGEG              */
    unsigned char ksr;      /* key scale rate  :kcode>>(3-KSR)     */
    unsigned int mul;       /* multiple        :ML_TABLE[ML]       */
    unsigned int Cnt;       /* frequency count :                   */
    unsigned int Incr;      /* frequency step  :                   */
    /* envelope generator state */
    unsigned char evm;      /* envelope phase                      */
    signed int evc;         /* envelope counter                    */
    signed int eve;         /* envelope counter end point          */
    signed int evs;         /* envelope counter step               */
    signed int evsa;        /* envelope step for AR                */
    signed int evsd;        /* envelope step for DR                */
    signed int evss;        /* envelope step for SR                */
    signed int evsr;        /* envelope step for RR                */
    /* LFO */
    unsigned char ams;
    unsigned char pms;
}FM_SLOT;


typedef struct fm_chan {
    FM_SLOT SLOT[4];
    unsigned char PAN;          /* PAN NONE,LEFT,RIGHT or CENTER       */
    unsigned char ALGO;         /* algorythm                           */
    unsigned char FB;           /* feed back       :&FB_TABLE[FB<<8]   */
    int op1_out;                /* op1 output foe beedback             */
    /* algorythm state */
    int *connect1;              /* operator 1 connection pointer       */
    int *connect2;              /* operator 2 connection pointer       */
    int *connect3;              /* operator 3 connection pointer       */
    int *connect4;              /* operator 4 connection pointer       */
    /* phase generator state */
    unsigned int  fc;           /* fnum,blk        :calcrated          */
    unsigned char fn_h;         /* freq latch      :                   */
    unsigned char kcode;        /* key code        :                   */
} FM_CH;

/* OPN/OPM common state */
typedef struct fm_state {
    unsigned char index;        /* chip index (number of chip) */
    int clock;                  /* master clock  (Hz)  */
    int rate;                   /* sampling rate (Hz)  */
    int freqbase;               /* frequency base      */
    double TimerBase;           /* Timer base time     */
    unsigned char address;      /* address register    */
    unsigned char irq;          /* interrupt level     */
    unsigned char irqmask;      /* irq mask            */
    unsigned char status;       /* status flag         */
    unsigned int mode;          /* mode  CSM / 3SLOT   */
    int TA;                     /* timer a             */
    int TAC;                    /* timer a counter     */
    unsigned char TB;           /* timer b             */
    int TBC;                    /* timer b counter     */
    /* speedup customize */
    /* time tables */
    signed int DT_TABLE[8][32];     /* detune tables       */
    signed int AR_TABLE[94];    /* atttack rate tables */
    signed int DR_TABLE[94];    /* decay rate tables   */
    /* LFO */
    unsigned int LFOCnt;
    unsigned int LFOIncr;
    /* Extention Timer and IRQ handler */
    FM_TIMERHANDLER Timer_Handler;
    FM_IRQHANDLER   IRQ_Handler;
    /* timer model single / interval */
    unsigned char timermodel;
}FM_ST;

/* OPN 3slot struct */
typedef struct opn_3slot {
    unsigned int  fc[3];        /* fnum3,blk3  :calcrated */
    unsigned char fn_h[3];      /* freq3 latch            */
    unsigned char kcode[3];     /* key code    :          */
}FM_3SLOT;

/* adpcm type A and type B struct */
typedef struct adpcm_state {
  unsigned char flag;       /* port state */
  unsigned char flagMask;   /* arrived    */
  unsigned char now_data;
  unsigned int now_addr;
  unsigned int now_step;
  unsigned int step;
  unsigned int start;
  unsigned int end;
  unsigned int delta;
  int IL;
  int volume;
  int *pan;     /* &outd[OPN_xxxx] */
  int /*adpcmm,*/ adpcmx, adpcmd;
  int adpcml;           /* hiro-shi!! */

  /* leveling and re-sampling state for DELTA-T */
  int volume_w_step;   /* volume with step rate */
  int next_leveling;   /* leveling value        */
  int sample_step;     /* step of re-sampling   */
}ADPCM_CH;

/* OPN/A/B common state */
typedef struct opn_f {
    unsigned char type;     /* chip type         */
    FM_ST ST;               /* general state     */
    FM_3SLOT SL3;           /* 3 slot mode state */
    FM_CH *P_CH;            /* pointer of CH     */
    unsigned int FN_TABLE[2048]; /* fnumber -> increment counter */
} FM_OPN;

/* here's the virtual YM2203(OPN) (Used by YM2608 / YM2612)  */
typedef struct ym2203_f {
    FM_OPN OPN;             /* OPN state         */
/*  FMSAMPLE *Buf;*/            /* sound buffer      */
    FM_CH CH[3];            /* channel state     */
} YM2203;

/* here's the virtual YM2610 */
typedef struct ym2610_f {
    FM_OPN OPN;                     /* OPN state    */
/*  FMSAMPLE *Buf[YM2610_NUMBUF];*/ /* sound buffer */
    FM_CH CH[6];                    /* channel state */
    int address1;   /* address register1 */
    /**** ADPCM control ****/
    char *pcmbuf[2];
    unsigned int pcm_size[2];
    int *TL_adpcmb;
    ADPCM_CH adpcm[7];          /* normal ADPCM & deltaT ADPCM */
    unsigned int adpcmreg[2][0x30];
    int port0state, port0control, port0shift;
    int port1state, port1control, port1shift;
    unsigned char adpcm_arrivedEndAddress,adpcm_statusmask;
} YM2610;

/* here's the virtual YM2608 */
typedef YM2610 YM2608;

/* here's the virtual YM2612 */
typedef struct ym2612_f {
    FM_OPN OPN;                     /* OPN state       */
/*  FMSAMPLE *Buf[YM2612_NUMBUF];*/ /* sound buffer */
    FM_CH CH[6];                    /* channel state */
    int address1;   /* address register1 */
    /* dac output (YM2612) */
    int dacen;
    int dacout;
} YM2612;

/* here's the virtual YM2151(OPM)  */
typedef struct ym2151_f {
/*  FMSAMPLE *Buf[YM2151_NUMBUF];*//* sound buffers    */
    FM_ST ST;                   /* general state     */
    FM_CH CH[8];                /* channel state     */
    unsigned char NReg;         /* noise enable,freq */
    unsigned char pmd;          /* LFO pmd level     */
    unsigned char amd;          /* LFO amd level     */
    unsigned char ctw;          /* CT0,1 and waveform */
    unsigned int KC_TABLE[8*12*64+950];/* keycode,keyfunction -> count */
    void (*PortWrite)(int offset,int data);/*  callback when write CT0/CT1 */
} YM2151;

/* -------------------- tables --------------------- */

/* key scale level */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?