Mercurial > pmdwin
diff pmdwin.h @ 0:c55ea9478c80
Hello Gensokyo!
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 21 May 2013 10:29:21 +0200 |
parents | |
children | e3849cd10ad3 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pmdwin.h @@ -0,0 +1,521 @@ +//============================================================================= +// 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