view pmdwin.h @ 6:da588a3fb3cc

Make pmdwin a dynamically linked executable.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 08 Sep 2014 17:15:41 +0200
parents c55ea9478c80
children e3849cd10ad3
line wrap: on
line source

//=============================================================================
//	Professional Music Driver [P.M.D.] version 4.8
//			Programmed By M.Kajihara
//			Windows Converted by C60
//=============================================================================

#ifndef PMDWIN_H
#define PMDWIN_H

#include <stdint.h>
#include <stdlib.h>
#include <limits.h>
#include "opna.h"

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#ifndef __cplusplus
typedef unsigned char bool;
#endif
extern const int *const efftbl[];

#ifdef __cplusplus
extern "C" {
    void lfg_srand(unsigned int seed);
    unsigned int lfg_rand(void);
};
#endif


//=============================================================================
//	バージョン情報
//=============================================================================
#define	DLLVersion			 36		// 上1桁:major, 下2桁:minor version
#define	InterfaceVersion	117		// 上1桁:major, 下2桁:minor version


//=============================================================================
//	DLL の戻り値
//=============================================================================
#define	PMDWIN_OK				 	  0		// 正常終了
#define	ERR_OPEN_MUSIC_FILE			  1		// 曲 データを開けなかった
#define	ERR_WRONG_MUSIC_FILE		  2		// PMD の曲データではなかった
#define	ERR_WRONG_PARTNO			 30		// パート番号が不適
//#define	ERR_ALREADY_MASKED			 31		// 指定パートはすでにマスクされている
#define	ERR_NOT_MASKED				 32		// 指定パートはマスクされていない
#define	ERR_MUSIC_STOPPED			 33		// 曲が止まっているのにマスク操作をした
#define	ERR_EFFECT_USED				 34		// 効果音で使用中なのでマスクを操作できない
#define	ERR_OUT_OF_MEMORY			 99		// メモリを確保できなかった
#define	ERR_OTHER					999		// その他のエラー


//----------------------------------------------------------------------------
//	PMDWin専用の定義
//----------------------------------------------------------------------------
#define	SOUND_55K			  55555
#define	SOUND_55K_2			  55466
#define	SOUND_48K			  48000
#define	SOUND_44K			  44100
#define	SOUND_22K			  22050
#define	SOUND_11K			  11025
#define	DEFAULT_REG_WAIT	  15000
#define	MAX_PCMDIR				 64
#define	MAX_MEMOBUF			   1024

//----------------------------------------------------------------------------
//	その他定義
//----------------------------------------------------------------------------
//#define	nbufsample			  30000
#define nbufsample 8192
#define	OPNAClock		(3993600*2)

#define	NumOfFMPart			      6
#define	NumOfSSGPart		      3
#define	NumOFOPNARhythmPart	      1
#define	NumOfAllPart		(NumOfFMPart+NumOfSSGPart+NumOFOPNARhythmPart)

#pragma pack( push, enter_include1 )
#pragma pack(2)

typedef struct stereo16bittag
{
	short left;
} Stereo16bit;

#pragma pack( pop, enter_include1 )

//#define ver 		"4.8o"
//#define vers		0x48
//#define verc		"o"
//#define date		"Jun.19th 1997"

//#define max_part1	22		// 0クリアすべきパート数(for PMDPPZ)
#define max_part2	11		// 初期化すべきパート数  (for PMDPPZ)

#define mdata_def	64
#define voice_def	 8
#define effect_def	64

#define fmvd_init	0		// 98は88よりもFM音源を小さく


/******************************************************************************
;	WORK AREA
******************************************************************************/
typedef struct PMDworktag {
	int		partb;				//	処理中パート番号
	int		tieflag;			//	&のフラグ(1 : tie)
	int		volpush_flag;		//	次の1音音量down用のflag(1 : voldown)
	int		rhydmy;				//	R part ダミー演奏データ
	int		fmsel;				//	FM 表(=0)か裏(=0x100)か flag
	int		omote_key[3];		//	FM keyondata表
	int		ura_key[3];			//	FM keyondata裏
	int		loop_work;			//	Loop Work
	bool	ppsdrv_flag;		//	ppsdrv を使用するか?flag(ユーザーが代入)
	int		lastTimerAtime;		//	一個前の割り込み時のTimerATime値
	int		music_flag;			//	B0:次でMSTART 1:次でMSTOP のFlag
	int		slotdetune_flag;	//	FM3 Slot Detuneを使っているか
	int		slot3_flag;			//	FM3 Slot毎 要効果音モードフラグ
	int		fm3_alg_fb;			//	FM3chの最後に定義した音色のalg/fb
	int		af_check;			//	FM3chのalg/fbを設定するかしないかflag
	int		lfo_switch;			//	局所LFOスイッチ
} PMDWORK;


typedef struct effworktag {
	int		*effadr;			//	effect address
	int		eswthz;				//	トーンスゥイープ周波数
	int		eswtst;				//	トーンスゥイープ増分
	int		effcnt;				//	effect count
	int		eswnhz;				//	ノイズスゥイープ周波数
	int		eswnst;				//	ノイズスゥイープ増分
	int		eswnct;				//	ノイズスゥイープカウント
	int		effon;				//	効果音 発音中
	int		psgefcnum;			//	効果音番号
} EFFWORK;


//	演奏中のデータエリア
typedef struct qqtag {
	uchar	*address;			//	2 エンソウチュウ ノ アドレス
	uchar	*partloop;			//	2 エンソウ ガ オワッタトキ ノ モドリサキ
	int		leng;				//	1 ノコリ LENGTH
	int		qdat;				//	1 gatetime (q/Q値を計算した値)
	uint	fnum;				//	2 エンソウチュウ ノ BLOCK/FNUM
	int		detune;				//	2 デチューン
	int		lfodat;				//	2 LFO DATA
	int		porta_num;			//	2 ポルタメントの加減値(全体)
	int		porta_num2;			//	2 ポルタメントの加減値(一回)
	int		porta_num3;			//	2 ポルタメントの加減値(余り)
	int		volume;				//	1 VOLUME
	int		shift;				//	1 オンカイ シフト ノ アタイ
	int		delay;				//	1 LFO	[DELAY] 
	int		speed;				//	1	[SPEED]
	int		step;				//	1	[STEP]
	int		time;				//	1	[TIME]
	int		delay2;				//	1	[DELAY_2]
	int		speed2;				//	1	[SPEED_2]
	int		step2;				//	1	[STEP_2]
	int		time2;				//	1	[TIME_2]
	int		lfoswi;				//	1 LFOSW. B0/tone B1/vol B2/同期 B3/porta
								//	         B4/tone B5/vol B6/同期
	int		volpush;			//	1 Volume PUSHarea
	int		mdepth;				//	1 M depth
	int		mdspd;				//	1 M speed
	int		mdspd2;				//	1 M speed_2
	int		envf;				//	1 PSG ENV. [START_FLAG] / -1でextend
	int		eenv_count;			//	1 ExtendPSGenv/No=0 AR=1 DR=2 SR=3 RR=4
	int		eenv_ar;			//	1 	/AR		/旧pat
	int		eenv_dr;			//	1	/DR		/旧pv2
	int		eenv_sr;			//	1	/SR		/旧pr1
	int		eenv_rr;			//	1	/RR		/旧pr2
	int		eenv_sl;			//	1	/SL
	int		eenv_al;			//	1	/AL
	int		eenv_arc;			//	1	/ARのカウンタ	/旧patb
	int		eenv_drc;			//	1	/DRのカウンタ
	int		eenv_src;			//	1	/SRのカウンタ	/旧pr1b
	int		eenv_rrc;			//	1	/RRのカウンタ	/旧pr2b
	int		eenv_volume;		//	1	/Volume値(0〜15)/旧penv
	int		extendmode;			//	1 B1/Detune B2/LFO B3/Env Normal/Extend
	int		fmpan;				//	1 FM Panning + AMD + PMD
	int		psgpat;				//	1 PSG PATTERN [TONE/NOISE/MIX]
	int		voicenum;			//	1 音色番号
	int		loopcheck;			//	1 ループしたら1 終了したら3
	int		carrier;			//	1 FM Carrier
	int		slot1;				//	1 SLOT 1 ノ TL
	int		slot3;				//	1 SLOT 3 ノ TL
	int		slot2;				//	1 SLOT 2 ノ TL
	int		slot4;				//	1 SLOT 4 ノ TL
	int		slotmask;			//	1 FM slotmask
	int		neiromask;			//	1 FM 音色定義用maskdata
	int		lfo_wave;			//	1 LFOの波形
	int		partmask;			//	1 PartMask b0:通常 b1:効果音 b2:NECPCM用
								//	   b3:none b4:PPZ/ADE用 b5:s0時 b6:m b7:一時
	int		keyoff_flag;		//	1 KeyoffしたかどうかのFlag
	int		volmask;			//	1 音量LFOのマスク
	int		qdata;				//	1 qの値
	int		qdatb;				//	1 Qの値
	int		hldelay;			//	1 HardLFO delay
	int		hldelay_c;			//	1 HardLFO delay Counter
	int		_lfodat;			//	2 LFO DATA
	int		_delay;				//	1 LFO	[DELAY] 
	int		_speed;				//	1		[SPEED]
	int		_step;				//	1		[STEP]
	int		_time;				//	1		[TIME]
	int		_delay2;			//	1		[DELAY_2]
	int		_speed2;			//	1		[SPEED_2]
	int		_step2;				//	1		[STEP_2]
	int		_time2;				//	1		[TIME_2]
	int		_mdepth;			//	1 M depth
	int		_mdspd;				//	1 M speed
	int		_mdspd2;			//	1 M speed_2
	int		_lfo_wave;			//	1 LFOの波形
	int		_volmask;			//	1 音量LFOのマスク
	int		mdc;				//	1 M depth Counter (変動値)
	int		mdc2;				//	1 M depth Counter
	int		_mdc;				//	1 M depth Counter (変動値)
	int		_mdc2;				//	1 M depth Counter
	int		onkai;				//	1 演奏中の音階データ (0ffh:rest)
	int		sdelay;				//	1 Slot delay
	int		sdelay_c;			//	1 Slot delay counter
	int		sdelay_m;			//	1 Slot delay Mask
	int		alg_fb;				//	1 音色のalg/fb
	int		keyon_flag;			//	1 新音階/休符データを処理したらinc
	int		qdat2;				//	1 q 最低保証値
	int		onkai_def;			//	1 演奏中の音階データ (転調処理前 / ?fh:rest)
	int		shift_def;			//	1 マスター転調値
	int		qdat3;				//	1 q Random
} QQ;


typedef struct OpenWorktag {
	QQ *MusPart[NumOfAllPart];	// パートワークのポインタ
	uchar	*mmlbuf;			//	Musicdataのaddress+1
	uchar	*tondat;			//	Voicedataのaddress
	uchar	*efcdat;			//	FM  Effecdataのaddress
	uchar	*prgdat_adr;		//	曲データ中音色データ先頭番地
	ushort	*radtbl;			//	R part offset table 先頭番地
	uchar	*rhyadr;			//	R part 演奏中番地
	int		rhythmmask;			//	Rhythm音源のマスク x8c/10hのbitに対応
	int		fm_voldown;			//	FM voldown 数値
	int		ssg_voldown;		//	PSG voldown 数値
	int		rhythm_voldown;		//	RHYTHM voldown 数値
	int		prg_flg;			//	曲データに音色が含まれているかflag
	int		status;				//	status1
	int		status2;			//	status2
	int		tempo_d;			//	tempo (TIMER-B)
	int		tempo_d_push;		//	tempo (TIMER-B) / 保存用
	int		syousetu_lng;		//	小節の長さ
	int		opncount;			//	最短音符カウンタ
	int		TimerAtime;			//	TimerAカウンタ
	int		effflag;			//	PSG効果音発声on/off flag(ユーザーが代入)
	int		psnoi;				//	PSG noise周波数
	int		psnoi_last;			//	PSG noise周波数(最後に定義した数値)
	int		rshot_dat;			//	リズム音源 shot flag
	int		rdat[6];			//	リズム音源 音量/パンデータ
	int		rhyvol;				//	リズムトータルレベル
	int		kshot_dat;			//	SSGリズム shot flag
	int		play_flag;			//	play flag
	int		slot_detune1;		//	FM3 Slot Detune値 slot1
	int		slot_detune2;		//	FM3 Slot Detune値 slot2
	int		slot_detune3;		//	FM3 Slot Detune値 slot3
	int		slot_detune4;		//	FM3 Slot Detune値 slot4
	int		TimerB_speed;		//	TimerBの現在値(=ff_tempoならff中)
	int		syousetu;			//	小節カウンタ
	int		port22h;			//	OPN-PORT 22H に最後に出力した値(hlfo)
	int		tempo_48;			//	現在のテンポ(clock=48 tの値)
	int		tempo_48_push;		//	現在のテンポ(同上/保存用)
	int		_fm_voldown;		//	FM voldown 数値 (保存用)
	int		_ssg_voldown;		//	PSG voldown 数値 (保存用)
	int		_rhythm_voldown;	//	RHYTHM voldown 数値 (保存用)
	int		ch3mode;			//	ch3 Mode
	int		TimerAflag;			//	TimerA割り込み中?フラグ(@不要?)
	int		TimerBflag;			//	TimerB割り込み中?フラグ(@不要?)

	// for PMDWin
	int		rate;				//	PCM 出力周波数(11k, 22k, 44k, 55k)
	bool	fmcalc55k;							// FM で 55kHz 合成をするか?
} OPEN_WORK;

//=============================================================================
//	PMDWin class
//=============================================================================

#ifdef __cplusplus
class PMDWIN
{
public:
	// IPCMMUSICDRIVER
	bool init(void);
	int music_load3(uchar *musdata, unsigned int size);
	void music_start(void);
	void music_stop(void);
	int getloopcount(void);
	bool getlength(uint *length, uint *loop);
	int getpos(void);
	void setpos(int pos);
	void getpcmdata(short *buf, int nsamples);
    unsigned int getstatus(char *buf, size_t bufsize);
    void setdevmask(uint8_t mask);
    void setchanmask(uint32_t mask);
	
	// IFMPMD
    void setpcmrate(unsigned int rate);
	void setfmcalc55k(bool flag);
	void setpos2(int pos);
	int getpos2(void);
	
	// IPMDWIN
	int maskon(unsigned int ch);
	int maskoff(unsigned int ch);
	void setfmvoldown(int voldown);
	void setssgvoldown(int voldown);
	void setrhythmvoldown(int voldown);
	int getfmvoldown(void);
	int getfmvoldown2(void);
	int getssgvoldown(void);
	int getssgvoldown2(void);
	int getrhythmvoldown(void);
	int getrhythmvoldown2(void);
	char* _getmemo(char *dest, uchar *musdata, int size, int al);
	char* _getmemo3(char *dest, uchar *musdata, int size, int al);
	char* getmemo(char *dest, uchar *musdata, int size, int al);
	char* getmemo3(char *dest, uchar *musdata, int size, int al);
	OPEN_WORK* getopenwork(void);
	QQ* getpartwork(unsigned int ch);
	
private:
	OPNA       opna;
	
	OPEN_WORK open_work;
	QQ FMPart[NumOfFMPart], SSGPart[NumOfSSGPart], RhythmPart;
	
	PMDWORK pmdwork;
	EFFWORK effwork;
	Stereo16bit	wavbuf2[nbufsample];
	
	char	*pos2;						// buf に余っているサンプルの先頭位置
	int		us2;						// buf に余っているサンプル数
	uint64_t upos;					    // 演奏開始からの時間(μs)
	uchar mdataarea[mdata_def*1024];
	uchar pmdstatus[9];

protected:
	int uRefCount;		// 参照カウンタ
	void opnint_start(void);
	void data_init(void);
	void opn_init(void);
	void mstop(void);
	void mstop_f(void);
	void silence(void);
	void mstart(void);
	void mstart_f(void);
	void play_init(void);
	void setint(void);
	void calc_tb_tempo(void);
	void calc_tempo_tb(void);
	void settempo_b(void);
	void TimerA_main(void);
	void TimerB_main(void);
	void mmain(void);
	void syousetu_count(void);
	void fmmain(QQ *qq);
	void psgmain(QQ *qq);
	void rhythmmain(QQ *qq);
	uchar *rhythmon(QQ *qq, uchar *bx, int al, int *result);
	void eff_main(int al);
	void effplay(void);
	void efffor(const int *si);
	void effend(void);
	void effsweep(void);

	int silence_fmpart(QQ *qq);
	void keyoff(QQ *qq);
	void keyoffp(QQ *qq);
	void kof1(QQ *qq);
	int ssgdrum_check(QQ *qq, int al);
    uchar *commands(QQ *qq, uchar *si);
	uchar *commandsp(QQ *qq, uchar *si);
	uchar *commandsr(QQ *qq, uchar *si);
	uchar *special_0c0h(QQ *qq, uchar *si, uchar al);
	uchar *_vd_fm(QQ *qq, uchar *si);
	uchar *_vd_ssg(QQ *qq, uchar *si);
	uchar *_vd_rhythm(QQ *qq, uchar *si);
	uchar *comt(uchar *si);
	uchar *comat(QQ *qq, uchar *si);
	uchar *comatm(QQ *qq, uchar *si);
	uchar *comstloop(QQ *qq, uchar *si);
	uchar *comedloop(QQ *qq, uchar *si);
	uchar *comexloop(QQ *qq, uchar *si);
	uchar *extend_psgenvset(QQ *qq, uchar *si);
	void lfoinit(QQ *qq, int al);
	void lfoinitp(QQ *qq, int al);
	uchar *lfoset(QQ *qq, uchar *si);
	uchar *psgenvset(QQ *qq, uchar *si);
	uchar *rhykey(uchar *si);
	uchar *rhyvs(uchar *si);
	uchar *rpnset(uchar *si);
	uchar *rmsvs(uchar *si);
	uchar *rmsvs_sft(uchar *si);
	uchar *rhyvs_sft(uchar *si);

	uchar *vol_one_up_psg(QQ *qq, uchar *si);
	uchar *vol_one_down(QQ *qq, uchar *si);
	uchar *portap(QQ *qq, uchar *si);
	uchar *psgnoise_move(uchar *si);
	uchar *mdepth_count(QQ *qq, uchar *si);
	uchar *toneadr_calc(QQ *qq, int dl);
	void neiroset(QQ *qq, int dl);

	int oshift(QQ *qq, int al);
	int oshiftp(QQ *qq, int al);
	void fnumset(QQ *qq, int al);
	void fnumsetp(QQ *qq, int al);
	uchar *panset(QQ *qq, uchar *si);
	uchar *panset_ex(QQ *qq, uchar *si);
	void panset_main(QQ *qq, int al);
	uchar calc_panout(QQ *qq);
	uchar *calc_q(QQ *qq, uchar *si);
	void fm_block_calc(int *cx, int *ax);
	int ch3_setting(QQ *qq);
	void cm_clear(int *ah, int *al);
	void ch3mode_set(QQ *qq);
	void ch3_special(QQ *qq, int ax, int cx);
	void volset(QQ *qq);
	void volsetp(QQ *qq);
	void otodasi(QQ *qq);
	void otodasip(QQ *qq);
	void keyon(QQ *qq);
	void keyonp(QQ *qq);
	int lfo(QQ *qq);
	uchar *lfoswitch(QQ *qq, uchar *si);
	void lfoinit_main(QQ *qq);
	void lfo_change(QQ *qq);
	void lfo_exit(QQ *qq);
	void lfin1(QQ *qq);
	void lfo_main(QQ *qq);
	void fmlfo_sub(QQ *qq, int al, int bl, uchar *vol_tbl);
	void volset_slot(int dh, int dl, int al);
	void porta_calc(QQ *qq);
    int soft_env(QQ *qq);
    int soft_env_main(QQ *qq);
    int soft_env_sub(QQ *qq);
    int ext_ssgenv_main(QQ *qq);
    void esm_sub(QQ *qq, int ah);
	void md_inc(QQ *qq);

	uchar *hlfo_set(QQ *qq, uchar *si);
	uchar *vol_one_up_fm(QQ *qq, uchar *si);
	uchar *porta(QQ *qq, uchar *si);
	uchar *slotmask_set(QQ *qq, uchar *si);
	uchar *slotdetune_set(QQ *qq, uchar *si);
	uchar *slotdetune_set2(QQ *qq, uchar *si);
	uchar *volmask_set(QQ *qq, uchar *si);
	uchar *fm_mml_part_mask(QQ *qq, uchar *si);
	uchar *ssg_mml_part_mask(QQ *qq, uchar *si);
	uchar *rhythm_mml_part_mask(QQ *qq, uchar *si);
	uchar *_lfoswitch(QQ *qq, uchar *si);
	uchar *_volmask_set(QQ *qq, uchar *si);
	uchar *tl_set(QQ *qq, uchar *si);
	uchar *fb_set(QQ *qq, uchar *si);
	void neiro_reset(QQ *qq);
	void swap(int *a, int *b);
};
#endif

//============================================================================
//	DLL Export Functions
//============================================================================

#ifdef __cplusplus
extern "C" {
#endif

#ifdef WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif

DLLEXPORT int getversion(void);
DLLEXPORT bool pmdwininit(void);
DLLEXPORT void pmdwinfree(void);
DLLEXPORT void setpcmrate(unsigned int rate);
DLLEXPORT int music_load3(uchar *musdata, int size);
DLLEXPORT void music_start(void);
DLLEXPORT void music_stop(void);
DLLEXPORT void getpcmdata(short *buf, int nsamples);
DLLEXPORT void setfmcalc55k(bool flag);
DLLEXPORT unsigned int getstatus(char *buf, size_t bufsize);
DLLEXPORT void setdevmask(uint8_t mask);
DLLEXPORT void setchanmask(uint32_t mask);
DLLEXPORT char * getmemo(char *dest, uchar *musdata, int size, int al);
DLLEXPORT char * getmemo3(char *dest, uchar *musdata, int size, int al);
DLLEXPORT int maskon(unsigned int ch);
DLLEXPORT int maskoff(unsigned int ch);
DLLEXPORT void setfmvoldown(int voldown);
DLLEXPORT void setssgvoldown(int voldown);
DLLEXPORT void setrhythmvoldown(int voldown);
DLLEXPORT int getfmvoldown(void);
DLLEXPORT int getfmvoldown2(void);
DLLEXPORT int getssgvoldown(void);
DLLEXPORT int getssgvoldown2(void);
DLLEXPORT int getrhythmvoldown(void);
DLLEXPORT int getrhythmvoldown2(void);
DLLEXPORT void setpos(int pos);
DLLEXPORT void setpos2(int pos);
DLLEXPORT int getpos(void);
DLLEXPORT int getpos2(void);
DLLEXPORT bool getlength(uint *length, uint *loop);
DLLEXPORT int getloopcount(void);
DLLEXPORT OPEN_WORK * getopenwork(void);
DLLEXPORT QQ * getpartwork(unsigned int ch);

#ifdef __cplusplus
}
#endif


#endif // PMDWIN_H