/*	
 *	clipmod.h
 *
 *	P/ECE MOD Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2002 Naoyuki Sawa
 *
 *	* Tue Nov 19 12:30:00 JST 2002 Naoyuki Sawa
 *	- 新規作成。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_MOD_H__
#define __CLIP_MOD_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/****************************************************************************
 *	定数・型定義
 ****************************************************************************/

#define MODBUFLEN 320 /* = 16000/50 … 1[tick](=1/50[sec])当たりのサンプル数 */

/*--------------- MODファイル形式 ---------------*/

/* MODファイルヘッダ内のサンプル情報 */
typedef struct _MODSAMPLE {
	char name[22];			/* + 0,22 */
	unsigned short length;		/* +22, 2 */
	unsigned char finetune;		/* +24, 1 */
	unsigned char volume;		/* +25, 1 */
	unsigned short repofs;		/* +26, 2 */
	unsigned short replen;		/* +28, 2 */
					/* =30    */
} MODSAMPLE;

///* パターン内のロー */
//typedef struct _MODROW {
//	unsigned int note[4];		/* + 0,16 */
//					/* =16   */
//} MODROW;
//→チャネル数可変になりました(2003/02/01)

///* MODファイルヘッダ内のパターン */
//typedef struct _MODPATTERN {
//	MODROW row[64];			/* +   0,1024 */
//					/* =1024      */
//} MODPATTERN;
//→チャネル数可変になりました(2003/02/01)

/* MODファイルの固定部分（ヘッダ） */
typedef struct _MODHEADER {
	char title[20];			/* +   0, 20 */
	MODSAMPLE sample[31];		/* +  20,930 */
	unsigned char seqlen;		/* + 950,  1 */
	unsigned char seqrep;		/* + 951,  1 */
	unsigned char sequence[128];	/* + 952,128 */
	char tag[4];			/* +1080,  4 */
					/* =1084     */
	/* MODPATTERN pattern[1〜64]                 */
	/* unsigned char smpdat[1〜31][2B〜128KB]    */
} MODHEADER;

/*--------------- ドライバ内部形式 ---------------*/

#define MODCHANS 16	/* サポートする最大チャネル数(MOD仕様では32) */
			/* この定数を変更した場合は、mod_init()のタグテーブルも追加してさい。 */

typedef struct _MODCHANNEL {
	/* smpno,volume,periodはchar,char,shortで充分なのですが、変更すると逆にコードサイズが増えます。
	 * MODドライバ本体は高速RAM上にあり、もう容量の余裕がないので、intのままにしておきます。
	 */
	int smpno;	/* サンプル番号(0〜31、ノートデータ内のサンプル番号を-1して格納します) */
	int volume;	/* ボリューム(0〜64、ボリュームスライド時に負値検査を行うので要符号！) */
	int period;	/* ピリオド値(0〜0x0fff、トーンスライド時に負値検査を行うので要符号！) */
	int effect;	/* エフェクト(ノートデータのビット11〜0をそのまま格納します)           */
	int offset;	/* サンプルオフセット(24.8bit、サンプルデータ先頭からのbyteオフセット) */
} MODCHANNEL;

typedef struct _MODDRIVER {
	MODHEADER* header;		/* ファイルヘッダアドレス                             */
	unsigned char* smpdat[31];	/* サンプルデータアドレス                             */
	unsigned int* pattern[64];	/* パターンアドレス                                   */
	MODCHANNEL channel[MODCHANS];	/* チャネル                                           */
	unsigned char chans;		/* チャネル数(1〜MODCHANS)                            */
	unsigned char seqno;		/* シーケンス番号(0〜126、127以上なら終了)            */
	unsigned char rowno;		/* ロー番号(0〜63、64なら次のシーケンスへ)            */
	unsigned char speed;		/* スピード設定値(1〜32)                              */
	unsigned char tempo;		/* テンポ設定値(33〜255)                              */
	unsigned short tick;		/* チック(tempoづつ増加、speed*125以上なら次のローへ) */
} MODDRIVER;

/****************************************************************************
 *	関数
 ****************************************************************************/

/* MODファイルの再生を開始します。
 * [in]
 *	data		MODデータの先頭アドレス。
 * [out]
 *	戻り値		再生開始に成功したら、 0を返します。
 *			再生開始できなければ、-1を返します。
 * [note]
 *	* MODデータの正／不正は、タグが「M.K.」かどうかだけをチェックしています。
 *	  基本的な4トラック31サンプルのMODでも、「M.K.」以外のタグを持つデータを指定した場合は、
 *	  再生を開始せずに-1を返すのでご注意ください。
 *	- 2003/02/01追記
 *	  1〜16チャネルまでのMODに対応しました。
 *	  「M.K.」の他、「1CHN〜9CHN」および「10CH」〜「16CH」形式のタグを持つデータが再生可能です。
 *	  MOD拡張仕様では「32CH」まで存在しますが、P/ECEで16チャネル以上を使うことはないと思います。
 *	* この関数は内部でstream_play()を呼び出しています。
 *	* stream_play()を呼ぶと、サウンド割り込みベクタがフックされます。
 *	  プログラム終了前に必ずmod_stop()を呼んで、ベクタを復元してください。
 */
int mod_play(const void* data);

/* MODファイルの再生を停止します。
 * [note]
 *	* 再生中でなければ、この関数は何もしません。
 */
void mod_stop();

/* mod_init()/mod_tick()は、MODサンプル展開だけを行う低レベル関数です。
 * * P/ECEで使う場合は、高レベルなmod_play()/mod_stop()を使ってください。
 *   mod_init()/mod_tick()を直接使う必要はありません。
 * * Windowsで利用する場合は、mod_init()/mod_tick()とWindowsサウンドAPIを
 *   組み合わせて使ってください。
 */
int mod_init(MODDRIVER* driver, const void* data);
int mod_tick(MODDRIVER* driver, short wbuff[/*MODBUFLEN*/]);

/* mod_tick()から呼ばれる関数。(clipfram.cで定義) */
int mod_seq(MODDRIVER* driver);
int mod_mix(MODDRIVER* driver, short wbuff[/*MODBUFLEN*/]);

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_MOD_H__*/
