/*
 *	clipsndx.h
 *
 *	Sound Mixer
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2014 Naoyuki Sawa
 *
 *	* Mon Mar 24 10:56:48 JST 2014 Naoyuki Sawa
 *	- 1st リリース。
 *	- Sound Mixerを作成した理由は、下記の通りです。
 *	  以前にSound Manager(clipsndm.h,c)を作成したのですが、使いづらくあまり役立ちませんでした。
 *	  そこで、実際のアプリケーションで必要な機能に絞って、Sound Mixerを作成することにしました。
 *	- Sound Mixerは、サウンドシーケンサ(clipsnds.h,c)との併用を想定して作成しました。
 *	  フレーズ単位の音量制御は、サウンドシーケンサに任せます。
 *	  Sound Mixerは、サウンドチャネルのグループ単位で、多重の減衰量制御を行うことが主目的です。
 *	- 使用例は clip/test.pce/app.c を参照してください。
 *	* Sat Jun 21 20:45:00 JST 2014 Naoyuki Sawa
 *	- SndMxr_Init()とSndMxr_InitStatic()の引数nSndMxrChの範囲を、(1〜32)に制限しました。
 *	  SndMxr_GetSndChAtt()とSndMxr_GetSndChAttAll()に、引数iSndMxrChMaskを追加しました。
 */
#ifndef __CLIP_SNDX_H__
#define __CLIP_SNDX_H__

/****************************************************************************
 *	構造体
 ****************************************************************************/

/* Sound Mixerチャネル構造体 */
typedef struct _ST_SndMxrCh {
	int SndChMask;				/* + 0,4 サウンドチャネルマスク */
	unsigned char AttNow;			/* + 4,1 現在減衰量 (0=減衰無し。1以上の値の解釈はアプリケーション任意) */
	unsigned char AttTo;			/* + 5,1 目標減衰量 (0=減衰無し。1以上の値の解釈はアプリケーション任意) */
	unsigned char Rate;			/* + 6,1 減衰量変化速度 (SndMxr_Exec()一回毎に(Rate/Scale)の速度で変化) */
	unsigned char Scale;			/* + 7,1 減衰量変化速度 (SndMxr_Exec()一回毎に(Rate/Scale)の速度で変化) */
	unsigned char ErrTerm;			/* + 8,1 誤差項 */
						/* + 9,3 (パディング) */
} ST_SndMxrCh;					/* =12 */

/* Sound Mixer構造体 */
typedef struct _ST_SndMxr {
	unsigned char nSndMxrCh;		/* +0,1   Sound Mixerチャネル数 */
						/* +1,3   (パディング) */
	ST_SndMxrCh pSndMxrCh[0/*nSndMxrCh*/];	/* +4,12N Sound Mixerチャネル構造体配列 */
} ST_SndMxr;					/* =4+12N */

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

/* Sound Mixerを作成します。
 * [in]
 *	nSndMxrCh	Sound Mixerチャネル数 (1〜32)
 *	pSndChMask	サウンドチャネルマスク配列
 * [out]
 *	戻り値		Sound Mixer
 * [note]
 *	- pSndChMaskが指す内容が、Sound Mixer構造体の中にコピーされます。
 *	  アプリケーションは、SndMxr_Init()が処理を返した後、pSndChMaskを開放して構いません。
 *	- 当関数は、malloc()を使用して、Sound Mixer構造体のメモリを動的に確保します。
 *	  動的なメモリ確保を行いたくない場合は、当関数の代りに、SndMxr_InitStatic()を使用してください。
 *	- 引数nSndMxrChの上限を「32」と定めた理由は、以下の通りです。
 *	  SndMxr_GetSndChAtt()とSndMxr_GetSndChAttAll()の、引数iSndMxrChMaskが32ビットであるため、適用可能なSound Mixerチャネル番号の範囲は0〜31です。
 *	  もし、Sound Mixerチャネル番号32以上を作成できたとしても、適用することができません。
 *	  適用できないSound Mixerチャネルを作成しても無駄なので、エラーとすることにしました。
 */
ST_SndMxr* SndMxr_Init(int nSndMxrCh, const int pSndChMask[/*nSndMxrCh*/]);

/* 静的に確保したメモリを使用して、Sound Mixerを作成します。
 * [in]
 *	pSndMxr		静的に確保したメモリ
 *	nSndMxrCh	Sound Mixerチャネル数 (1〜32)
 *	pSndChMask	サウンドチャネルマスク配列
 * [note]
 *	- pSndChMaskが指す内容が、Sound Mixer構造体の中にコピーされます。
 *	  アプリケーションは、SndMxr_Init()が処理を返した後、pSndChMaskを開放して構いません。
 *	- 当関数を使用して作成したSound Mixerは、SndMxr_Free()による開放は不要です。
 * [使用例]
 *	│struct {
 *	│  ST_SndMxr   sndMxr;
 *	│  ST_SndMxrCh sndMxrCh[3];
 *	│} stSndMxr;
 *	│static const int TBL_SndMxr_SndChMask[3] = {(1<<0),(1<<0)|(1<<1)|(1<<2),-1};
 *	│SndMxr_InitStatic(&stSndMxr.sndMxr, 3, TBL_SndChMask);
 */
void SndMxr_InitStatic(ST_SndMxr* pSndMxr, int nSndMxrCh, const int pSndChMask[/*nSndMxrCh*/]);

/* Sound Mixerを開放します。
 * [in]
 *	pSndMxr		Sound Mixer
 *			本関数のみ、pSndMxr引数にNULLを指定可能です。
 *			「SndMxr_Free(NULL)」の呼び出しは安全であり、何も行いません。
 * [note]
 *	- アプリケーション終了直前ならば、明示的にSound Mixerを開放する必要はありません。
 *	  Sound Mixerはメモリリソースのみ使用し、割り込みフック等は行っていないからです。
 */
#define SndMxr_Free free

/* Sound Mixerの周期処理を行います。
 * [in]
 *	pSndMxr		Sound Mixer
 * [note]
 *	- 各Sound Mixerチャネルの減衰量変化処理を行います。
 *	- アプリケーションが定期的に、当関数を呼び出してください。
 *	  アプリケーションのメインループから呼び出しても構いませんし、割り込み処理から呼び出しても構いません。
 *	- 周期時間はアプリケーション定義ですが、10〜100ms程度が適切です。
 *	  どのぐらいスムーズに減衰量を変化させたいかによって、調整してください。
 */
void SndMxr_Exec(ST_SndMxr* pSndMxr);

/* Sound Mixerチャネルの減衰量変化を開始します。
 * [in]
 *	pSndMxr		Sound Mixer
 *	iSndMxrCh	Sound Mixerチャネル番号 (0〜(nSndMxrCh-1))
 *	AttTo		目標減衰量 (0=減衰無し。1以上の値の解釈はアプリケーション任意)
 *	Rate		減衰量変化速度 (SndMxr_Exec()一回毎に(Rate/Scale)の速度で変化)
 *	Scale		減衰量変化速度 (SndMxr_Exec()一回毎に(Rate/Scale)の速度で変化)
 * [note]
 *	- Rate,又は,Scaleの片方にでも0を指定すると、即変化します。
 */
void SndMxr_SetMxrChAtt(ST_SndMxr* pSndMxr, int iSndMxrCh, int AttTo, int Rate, int Scale);

/* サウンドチャネルの減衰量を取得します。
 * [in]
 *	pSndMxr		Sound Mixer
 *	iSndMxrChMask	適用するSound Mixerチャネルのビットマスク (bit0=Sound Mixerチャネル0,bit1=Sound Mixerチャネル1,...,bit31=Sound Mixerチャネル31)
 *	iSndCh		サウンドチャネル番号 (0〜31)
 * [out]
 *	戻り値		減衰量 (0=減衰無し。1以上の値の解釈はアプリケーション任意)
 * [note]
 *	- 引数iSndMxrChMaskの中の、Sound Mixerチャネル数よりも大きいビットは、無視します。
 *	  従って、全てのSound Mixerチャネルを適用する場合は、引数iSndMxrChMaskに(-1)を指定してください。
 *	- 当モジュールが扱う、サウンドチャネル番号の範囲は、(0〜31)に固定です。
 *	  ハードウェアやアプリケーションによって、サウンドチャネル数がもっと少ない事も有りますが、
 *	  当関数はそれらを考慮せず、サウンドチャネル番号の範囲を(0〜31)と仮定して処理を行います。
 *	  サウンドチャネルマスクが32ビット有り、サウンドチャネル番号(0〜31)に対応可能だからです。
 *	- 必要以上のサウンドチャネル番号が存在することの、実装上のオーバーヘッドは、ほぼありません。
 *	  必要以上のサウンドチャネル番号を、アプリケーションが参照しなければ、動作に影響ありません。
 *	- 個別のサウンドチャネルの減衰量を取得する場合は、SndMxr_GetSndChAtt()を使用するのが簡単ですが、
 *	  全てのサウンドチャネルの減衰量を取得する場合は、SndMxr_GetSndChAttAll()を使用する方が効率が良いです。
 */
int SndMxr_GetSndChAtt(ST_SndMxr* pSndMxr, int iSndMxrChMask, int iSndCh);

/* 全てのサウンドチャネルの減衰量を取得します。
 * [in]
 *	pSndMxr		Sound Mixer
 *	iSndMxrChMask	適用するSound Mixerチャネルのビットマスク (bit0=Sound Mixerチャネル0,bit1=Sound Mixerチャネル1,...,bit31=Sound Mixerチャネル31)
 *	AttSum		全てのサウンドチャネルの減衰量を格納するための配列
 * [out]
 *	戻り値		AttSumに、全てのサウンドチャネルの減衰量を格納する
 * [note]
 *	- 引数iSndMxrChMaskの中の、Sound Mixerチャネル数よりも大きいビットは、無視します。
 *	  従って、全てのSound Mixerチャネルを適用する場合は、引数iSndMxrChMaskに(-1)を指定してください。
 *	- 当モジュールが扱う、サウンドチャネル数は、32個に固定です。
 *	  固定である理由は、SndMxr_GetSndChAtt()のコメントを参照してください。
 *	- 個別のサウンドチャネルの減衰量を取得する場合は、SndMxr_GetSndChAtt()を使用するのが簡単ですが、
 *	  全てのサウンドチャネルの減衰量を取得する場合は、SndMxr_GetSndChAttAll()を使用する方が効率が良いです。
 */
void SndMxr_GetSndChAttAll(ST_SndMxr* pSndMxr, int iSndMxrChMask, unsigned char AttSum[/*32*/]);

#endif/*__CLIP_SNDX_H__*/
