⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fm.c

📁 这个是延伸mame的在wince平台下的游戏模拟器的代码
💻 C
📖 第 1 页 / 共 5 页
字号:

#define ADPCMA_VOLUME_RATE  (8)  /* DELTA-T volume rate */
#define ADPCMB_VOLUME_RATE  (32) /* ADOCM volume rate */

#define ADPCMA_CURVE_DIVIDE 8    /* DELTA-T curve rate */
#define ADPCMB_CURVE_DIVIDE 1    /* ADPCM curve rate */
/*
**
** File: fm.c -- software implementation of FM sound generator
**
** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
**
** Version 0.34M
**
*/
/*
    no check:
		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
		YM2151 output pins (CT0 and CT1)
		YM2608/YM2610 Expansion status/Expansion interrupt
		YM2608 DELTA-T-ADPCM and RYTHM
		YM2610 DELTA-T-ADPCM with PCM port
		YM2610 PCM memory data access
	preliminary :
		key scale level rate (?)
		attack rate time rate , curve (?)
		decay  rate time rate , curve (?)
		self feedback calcration
		YM2610 ADPCM mixing level
	Problem :
		is sometime hiss noize heard ?

	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      */
/************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#ifndef __RAINE__
#include "driver.h"		/* use M.A.M.E. */
#else
#include "deftypes.h"		/* use RAINE */
#include "support.h"		/* use RAINE */
#endif
#include "ay8910.h"
#include "fm.h"

#ifndef PI
#define PI 3.14159265357989
#endif

#define ADPCM_SHIFT    (10)
#ifdef SIGNED_SAMPLES
	#define AUDIO_CONV(A) ((A))
	#define AUDIO_CONV16(A) ((A))
#else
	#define AUDIO_CONV(A) ((A)^0x80)
	#define AUDIO_CONV16(A) ((A)^0x8000)
#endif

/* ------------------------------------------------------------------ */
#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 */
#define OPN_OUTSB   (TL_BITS+2-16)		/* OPN output final shift 16bit */
#define OPN_OUTSB_8 (OPN_OUTSB+8)		/* OPN output final shift  8bit */
#define OPM_OUTSB   (TL_BITS+2-16) 		/* OPM output final shift 16bit */
#define OPM_OUTSB_8 (OPM_OUTSB+8) 		/* OPM output final shift  8bit */
/* limit minimum and maximum */
#define OPN_MAXOUT (0x7fff<<OPN_OUTSB)
#define OPN_MINOUT (-0x8000<<OPN_OUTSB)
#define OPM_MAXOUT (0x7fff<<OPM_OUTSB)
#define OPM_MINOUT (-0x8000<<OPM_OUTSB)

#define OPNBAD_MAXOUT (0x7fff)
#define OPNBAD_MINOUT (-0x8000)

/* -------------------- 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


/* ---------- 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 {
	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     */
	void *timer_a_timer;		/* timer for a         */
	void *timer_b_timer;		/* timer for b         */
	/* 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;
}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;

typedef struct adpcm_state {
  unsigned char flag;
  unsigned char flagMask;
  unsigned int now_addr;
  unsigned int step;
  unsigned int start;
  unsigned int end;
  unsigned int delta;
  int IL;
  int volume;
  int *pan;     /* &outd[OPN_xxxx] */
  int adpcmx, adpcmd;
}ADPCM_CH;

/* OPN/A/B common state */
typedef struct opn_f {
	unsigned char type;		/* chip type         */
	unsigned char index;	/* chip index (number of chip) */
	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 YM2608 */
typedef struct ym2608_f {
	FM_OPN OPN;						/* OPN state       */
/*	FMSAMPLE *Buf[YM2608_NUMBUF];*/	/* sound buffer */
	FM_CH CH[6];					/* channel state   */
	int address1;					/* additional address register */
	/* PCM Part   (YM2608) */
	int ADMode;		/* mode of ADPCM unit */
	int ADPAN;		/* PAN */
	int ADStart;	/* Start address */
	int ADStop;		/* Stop address */
	int ADDelta;	/* Playback sampling rate */
	int ADTL;		/* output level */
	int ADLimit;	/* Limit address */
	int ADData;		/* PCM data */
	/* Rhythm Part (YM2608) */
	int RTL;		/* Total level */
	int RPAN[6];	/* PAN */
	int RIL[6];		/* IL  */
} YM2608;

/* 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_justfinished,adpcm_statusmask;
} YM2610;

/* 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 */
/* !!!!! preliminary !!!!! */

#define DV (1/EG_STEP)
static const unsigned char KSL[32]=
{
#if 1
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
#else
 0.000/DV , 0.000/DV , 0.000/DV , 0.000/DV ,	/* OCT 0 */
 0.000/DV , 0.000/DV , 0.000/DV , 1.875/DV ,	/* OCT 1 */
 0.000/DV , 0.000/DV , 3.000/DV , 4.875/DV ,	/* OCT 2 */
 0.000/DV , 3.000/DV , 6.000/DV , 7.875/DV ,	/* OCT 3 */
 0.000/DV , 6.000/DV , 9.000/DV ,10.875/DV ,	/* OCT 4 */
 0.000/DV , 9.000/DV ,12.000/DV ,13.875/DV ,	/* OCT 5 */
 0.000/DV ,12.000/DV ,15.000/DV ,16.875/DV ,	/* OCT 6 */
 0.000/DV ,15.000/DV ,18.000/DV ,19.875/DV		/* OCT 7 */
#endif
};
#undef DV

/* OPN key frequency number -> key code follow table */
/* fnum higher 4bit -> keycode lower 2bit */
static const char OPN_FKTABLE[16]={0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};

static const int KC_TO_SEMITONE[16]={
	/*translate note code KC into more usable number of semitone*/
	0*64, 1*64, 2*64, 3*64,
	3*64, 4*64, 5*64, 6*64,
	6*64, 7*64, 8*64, 9*64,
	9*64,10*64,11*64,12*64
};

static const int DT2_TABLE[4]={ /* 4 DT2 values */
/*
 *   DT2 defines offset in cents from base note
 *
 *   The table below defines offset in deltas table...
 *   User's Manual page 22
 *   Values below were calculated using formula:  value = orig.val * 1.5625
 *
 * DT2=0 DT2=1 DT2=2 DT2=3
 * 0     600   781   950
 */
	0,    384,  500,  608
};

/* sustain lebel table (3db per step) */
/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
static const int SL_TABLE[16]={
 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
};
#undef SC

#ifdef TL_SAVE_MEM
  #define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
#else
  #define TL_MAX (EG_ENT*4) /* tl + ksr + envelope + sinwave */
#endif

/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
static int *TL_TABLE;

/* pointers to TL_TABLE with sinwave output offset */
static signed int *SIN_TABLE[SIN_ENT];

/* envelope output curve table */
#ifdef SEG_SUPPORT
/* attack + decay + SSG upside + OFF */
static int ENV_CURVE[3*EG_ENT+1];
#else
/* attack + decay + OFF */
static int ENV_CURVE[2*EG_ENT+1];
#endif
/* envelope counter conversion table when change Decay to Attack phase */
static int DRAR_TABLE[EG_ENT];

#define OPM_DTTABLE OPN_DTTABLE

⌨️ 快捷键说明

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