/*
 *	clipsnds.h
 *
 *	サウンドシーケンサ
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2014 Naoyuki Sawa
 *
 *	* Thu Oct 03 00:19:14 JST 2013 Naoyuki Sawa
 *	- 1st リリース。
 *	* Sat Oct 05 15:05:45 JST 2013 Naoyuki Sawa
 *	- パターンコマンドに、4バイトウェイトを追加しました。
 *	  4バイトウェイトにはオフセットが無く全範囲をカバーするので、手作業でデータを作成する時は4バイトウェイトだけを使用すると直感的に作成できます。
 *	  ただし1〜3バイトウェイトの方がメモリを節約できるので、ツールでデータを作成する時はウェイト時間によって1〜4バイトウェイトを生成してください。
 *	* Sun Jun 01 22:15:15 JST 2014 Naoyuki Sawa
 *	- SndSeqCmd_Vol,SndSeqCmd_Panのマクロ定義が間違っていたので、修正しました。
 */
#ifndef __CLIP_SNDS_H__
#define __CLIP_SNDS_H__

/****************************************************************************
 *	定数、構造体
 ****************************************************************************/

#define SndTrk_Max	31	/* トラック番号の最大値(この値も含む)。0以上で調整可能。 */			//ハードウェアに依存
#define SndPhr_Max	8191	/* フレーズ番号の最大値(この値も含む)。0以上で調整可能。 */			//ハードウェアに依存
#define SndVol_Max	128	/* ボリュームの最大値(この値も含む)。0以上で調整可能。 */			//ハードウェアに依存
#define SndPan_Max	128	/* パンの最大値(この値も含む)。0以上で調整可能。 */				//ハードウェアに依存

#define SndSeqCh_Max	15	/* サウンドシーケンサチャネル番号の最大値(この値も含む)。0以上で調整可能。 */	//アプリケーションに依存

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

/* 初期化情報 */
typedef struct _ST_SndSeqInfo {
	int  (*fnTime)();
	void (*fnPlay)(int iTrk, int iPhr, int iVol, int iPan);	/* ステレオ再生時は、iPanは無効値である。アプリケーション側は、フレーズ番号からモノラル/ステレオを判断し、ステレオ再生ならばiPanを無視せよ。 */
	void (*fnStop)(int iTrk);
	void (*fnVol)(int iTrk, int iVol);	/* ステレオ再生時は、左トラックのみ呼び出される。アプリケーション側で、モノラル再生中かステレオ再生中かを記憶し、必要に応じて右トラックのボリュームも連動させよ。 */
	void (*fnPan)(int iTrk, int iPan);	/* ステレオ再生時は、呼び出されることは無い。 */
	int  (*fnInf)(int iPhr);		/* このフレーズが、無限ループフレーズであるかを判断する。無限ループフレーズならば0以外を返すこと。無限ループフレーズとは、パターンを超えて継続するフレーズである。 */
} ST_SndSeqInfo;

/* トラック情報 */
typedef struct _ST_SndTrk {
	short iSndSeqCh;	/* 現在このトラックを制御しているサウンドシーケンサチャネル番号(0-SndSeqCh_Max)。(-1)ならば「このトラックはサウンドシーケンサによって制御されていない」と見なす。以降、この状態を「無制御」と称す。 */	//ステレオ再生時の情報は左トラックのみに格納する。右トラックは便宜上、無制御とする。パターンデータが正常ならば、この扱いで問題ない。
	short iPhr;		/* フレーズ番号(0-SndPhr_Max)。無制御ならば(-1)を格納する。 */																		//ステレオ再生時の情報は左トラックのみに格納する。右トラックは便宜上、無制御とする。
	short iVol;		/* ボリューム  (0-SndVol_Max)。無制御ならば(-1)を格納する。 */																		//ステレオ再生時の情報は左トラックのみに格納する。右トラックは便宜上、無制御とする。
	short iPan;		/* パン        (0-SndPan_Max)。無制御ならば(-1)を格納する。ステレオ再生時も(-1)を格納する。 */														//ステレオ再生時の情報は左トラックのみに格納する。右トラックは便宜上、無制御とする。
} ST_SndTrk;

/* サウンドシーケンサチャネル */
typedef struct _ST_SndSeqCh {
	const unsigned char* pData;	/* パターンデータの現在アドレス。(NULL=停止中) */
	int Wait;			/* ウェイトカウンタ[ms]。ウェイトコマンド実行時に(+)する。実時間経過時に(-)する。ウェイトカウンタが0以下ならば、コマンドを実行する。 */
} ST_SndSeqCh;

/* サウンドシーケンサ */
typedef struct _ST_SndSeq {
	const ST_SndSeqInfo* pSndSeqInfo;	/* 初期化情報 */
	int Time;				/* 前回時刻[ms] */
	ST_SndTrk SndTrk[SndTrk_Max + 1];	/* トラック情報 */
	ST_SndSeqCh SndSeqCh[SndSeqCh_Max + 1];	/* サウンドシーケンサチャネル */
} ST_SndSeq;

/****************************************************************************
 *	アプリケーション用関数
 ****************************************************************************/

void SndSeq_Init(const ST_SndSeqInfo* pSndSeqInfo);
void SndSeq_Exec();
void SndSeq_Play(int iSndSeqCh, const void* pData);
void SndSeq_Stop(int iSndSeqCh);
void SndSeq_StopAll();
void SndSeq_GetTrk(int iTrk, ST_SndTrk* pSndTrk);

/****************************************************************************
 *	パターンデータ定義用マクロ
 ****************************************************************************/

#define SndSeqCmd_End()				(0x00)																		/* パターン終了 */
#define SndSeqCmd_Wait1(ms)			(0x01),((unsigned char)((ms)-0x00001))														/* 1バイトウェイト */	//1バイトウェイトの範囲 = 0x00001+(0〜0x000000FF) [ms]
#define SndSeqCmd_Wait2(ms)			(0x02),((unsigned char)((ms)-0x00101)),((unsigned char)(((ms)-0x00101)>>8))									/* 2バイトウェイト */	//2バイトウェイトの範囲 = 0x00101+(0〜0x0000FFFF) [ms]
#define SndSeqCmd_Wait3(ms)			(0x03),((unsigned char)((ms)-0x10101)),((unsigned char)(((ms)-0x10101)>>8)),((unsigned char)(((ms)-0x10101)>>16))				/* 3バイトウェイト */	//3バイトウェイトの範囲 = 0x10101+(0〜0x00FFFFFF) [ms]
#define SndSeqCmd_Wait4(ms)			(0x04),((unsigned char) (ms)         ),((unsigned char)( (ms)         >>8)),((unsigned char)( (ms)         >>16)),((unsigned char)((ms)>>24))	/* 4バイトウェイト */	//4バイトウェイトの範囲 =         (0〜0xFFFFFFFF) [ms]
#define SndSeqCmd_Stop(trk)			(0x10),(trk)																	/* トラック停止 */
#define SndSeqCmd_PlayM(trk,phr,vol,pan)	(0x11),(trk),((unsigned char)(phr)),((unsigned char)((phr)>>8)),(vol),(pan)									/* モノラル再生 */
#define SndSeqCmd_PlayS(trk,phr,vol)		(0x12),(trk),((unsigned char)(phr)),((unsigned char)((phr)>>8)),(vol)										/* ステレオ再生 */
#define SndSeqCmd_Vol(trk,vol)			(0x20),(trk),(vol)																/* ボリューム更新 */
#define SndSeqCmd_Pan(trk,pan)			(0x21),(trk),(pan)																/* パン更新 */

#endif/*__CLIP_SNDS_H__*/
