/*
 *	clipadp.h
 *
 *	2-bit ADPCM Decoder
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2013 Naoyuki Sawa
 *
 *	* Wed Dec 20 00:13:10 JST 2006 Naoyuki Sawa
 *	- 作成開始。
 *	* Wed Dec 20 17:31:02 JST 2006 Naoyuki Sawa
 *	- 1st リリース。
 *	* Thu Dec 21 11:18:32 JST 2006 Naoyuki Sawa
 *	- ADPCMCHANNEL構造体を扱い易く並び替えて、ASM版adpcm_mix1()を最適化しました。
 *	* Thu Mar 01 01:53:43 JST 2007 Naoyuki Sawa
 *	- adpcm_stat()を追加しました。
 *	* Mon Jul 15 20:32:11 JST 2013 Naoyuki Sawa
 *	- ADPCMCHANNEL構造体を並び替え、volフィールドを追加しました。
 *	- 音量設定機能に対応するため、adpcm_att()関数を追加しました。
 *	- 高速RAMを節約するため、係数テーブルをframadp.cからclipadp.cへ移動しました。
 */
#ifndef __CLIP_ADP_H__
#define __CLIP_ADP_H__

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

#ifdef  PIECE
#define ADPCM_ASM
#endif/*PIECE*/

/* PCEWAVEINFO.type の独自拡張 */
#define PW_TYPE_2BITADPCM	3
#define PW_TYPE_ADPCM_X		(PW_TYPE_2BITADPCM|PW_TYPE_VR|PW_TYPE_ADP_INI)
#define PW_TYPE_ADPCM_X_NI	(PW_TYPE_2BITADPCM|PW_TYPE_VR)

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

/* アセンブラコードから直接参照するため、レイアウト固定です!! */
//typedef struct _ADPCMCHANNEL {
//	int loop;			/* + 0,4: 0=停止, 1～=残りループ回数, -1=無限ループ */
//	int pcm;			/* + 4,4: 出力PCM値 */
//	short data;			/* + 8,2: 入力ADPCM値のバッファ */
//	short delta;			/* +10,2: ⊿値 */
//	short progress;			/* +12,2: 進行カウンタ */
//	short rate;			/* +14,2: サンプリングレート */
//	int len;			/* +16,4: 残り出力サンプル数 */
//	const unsigned char* ptr;	/* +20,4: ADPCMデータ走査位置 */
//	int init_len;			/* +24,4: 残り出力サンプル数のリセット値 */
//	const unsigned char* init_ptr;	/* +28,4: ADPCMデータ走査位置のリセット値 */
//} ADPCMCHANNEL;				/* =32 */
//↓* Thu Dec 21 11:18:32 JST 2006 Naoyuki Sawa
//↓- ADPCMCHANNEL構造体を扱い易く並び替えて、ASM版adpcm_mix1()を最適化しました。
//typedef struct _ADPCMCHANNEL {
//	int pcm;			/* + 0,4: 出力PCM値 */
//	short data;			/* + 4,2: 入力ADPCM値のバッファ */
//	short delta;			/* + 6,2: ⊿値 */
//	short progress;			/* + 8,2: 進行カウンタ */
//	short rate;			/* +10,2: サンプリングレート */
//	int len;			/* +12,4: 残り出力サンプル数 */
//	const unsigned char* ptr;	/* +16,4: ADPCMデータ走査位置 */
//	int loop;			/* +20,4: 0=停止, 1～=残りループ回数, -1=無限ループ */
//	int init_len;			/* +24,4: 残り出力サンプル数のリセット値 */
//	const unsigned char* init_ptr;	/* +28,4: ADPCMデータ走査位置のリセット値 */
//} ADPCMCHANNEL;				/* =32 */
//↓* Mon Jul 15 20:32:11 JST 2013 Naoyuki Sawa
//↓- ADPCMCHANNEL構造体のフィールドを並び替えました。理由は、以下のとおりです:
//↓  1. これまでadpcm_mix1()にて、rateは書き戻し不要であるのに、書き戻していた無駄がありました。
//↓     書き戻し不要なフィールドを後ろにまとめて並び替え、rateを書き戻さないように改良しました。
//↓  2. 音量設定機能に対応するため、volフィールドを追加しました。
//↓     既存のloopフィールドをint⇒shortに縮小し、余った隙間にvolフィールドを追加しました。
//↓     従って、ADPCMCHANNEL構造体全体のサイズは、これまでと変わっていません。
//↓     ※補足 loopフィールドを縮小したため、loop値として32768～-2の値は使用できなくなりました。
//↓            実際にloop値として上記のような値を使うことはまず無いので、大丈夫と思います。
typedef struct _ADPCMCHANNEL {
	const unsigned char* ptr;	/* + 0,4: ADPCMデータ走査位置 */
	int len;			/* + 4,4: 残り出力サンプル数 */
	int pcm;			/* + 8,4: 出力PCM値 */
	short data;			/* +12,2: 入力ADPCM値のバッファ */
	short delta;			/* +14,2: ⊿値 */
	short progress;			/* +16,2: 進行カウンタ */
	short rate;			/* +18,2: サンプリングレート */
	short vol;			/* +20,2: 音量 */
	short loop;			/* +22,2: 0=停止, 1～=残りループ回数, -1=無限ループ */
	const unsigned char* init_ptr;	/* +24,4: ADPCMデータ走査位置のリセット値 */
	int init_len;			/* +28,4: 残り出力サンプル数のリセット値 */
} ADPCMCHANNEL;				/* =32 */

typedef struct _ADPCMDRIVER {
	int nch;			/* チャネル数 */
	ADPCMCHANNEL* pch/*[nch]*/;	/* チャネル構造体 */
} ADPCMDRIVER;


/* clipadp.c */
extern const short adpcm_tbl[4/*ADPCM値*/][2];	//{{2013/07/15追加:高速RAMを節約するため、係数テーブルをframadp.cからclipadp.cへ移動しました。}}

/* framadp.c */
void adpcm_mix1(ADPCMCHANNEL* pch, int mixbuf[/*ADPCMBUFLEN*/]);
void adpcm_mix2(short wbuff[/*ADPCMBUFLEN*/], int mixbuf[/*ADPCMBUFLEN*/]);

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

/* 2-bit ADPCM Decoderを起動します。
 * [in]
 *	nch		チャネル数。
 * [note]
 *	* adpcm_play()を使う前にadpcm_init()を呼び出して、2-bit ADPCM Decoderを起動しておいてください。
 *	* この関数は、内部でstream_play()を呼び出しています。
 *	  stream_play()を呼ぶと、サウンド割り込みベクタがフックされます。
 *	  プログラム終了前にadpcm_exit()を呼び出して、ベクタを復元してください。
 *	  ただし、ライブラリが終了時に自動的にフックを復元するので、adpcm_exit()を呼ばずに終了しても安全です。
 */
void adpcm_init(int nch);

/* 2-bit ADPCM Decoderを停止します。
 * [note]
 *	* 2-bit ADPCM Decoderが起動していなければ、この関数は何も行いません。
 */
void adpcm_exit();

/* 2-bit ADPCM形式のppdデータを再生します。
 * [in]
 *	ch		チャネル番号。(1～nch-1)
 *	data		2-bit ADPCM形式のppdデータ。(ファイルイメージの先頭アドレス)
 *	loop		1～ = ループ回数, -1 = 無限ループ。
 * [note]
 *	* この関数の使い方は、sound_play()と同じです。
 *	  clippce.hのsound_play()のコメントを参照してください。
 *	* この関数は、2-bit ADPCM形式のppdデータの再生にのみ利用できます。
 *	  2-bit ADPCM形式以外のppdを指定すると、エラー終了します。
 *	  2-bit ADPCM形式以外のppdを再生するには、sound_play()を利用してください。
 */
void adpcm_play(int ch, const void* data, int loop);

/* 2-bit ADPCM形式のppdデータ再生を停止します。
 * [in]
 *	ch		チャネル番号。(1～nch-1)
 * [note]
 *	* 指定されたチャネルが再生中でない場合は、この関数は何も行いません。
 */
void adpcm_stop(int ch);

/* 指定された2-bit ADPCMチャネルが、再生中か停止中かを調べます。
 * [in]
 *	ch		チャネル番号。(1～nch-1)
 * [out]
 *	戻り値		再生中ならば0以外の値を返します。
 *			停止中ならば0を返します。
 * [note]
 *	* 2007/03/01現在の実装は、ADPCMCHANNEL.loopの値をそのまま返しているので、
 *	  戻り値は、{0=停止, 1～=残りループ回数, -1=無限ループ} となっています。
 *	  ただし、今後もし実装を変更した場合に、戻り値が変わる可能性があります。
 *	  戻り値を、上のように仮定してコーディングしないよう、注意してください。
 */
int adpcm_stat(int ch);

//{{2013/07/15追加
/* 指定された2-bit ADPCMチャネルの、減衰量を設定します。
 * [in]
 *	ch		チャネル番号。(1～nch-1)
 *	att		減衰量。(0～64)
 * [note]
 *	* 減衰量は 減衰無し:0～64:消音 です。
 *	  数値範囲は、P/ECE APIのpceWaveSetMasterAtt()とpceWaveSetChAtt()に倣いました。
 *	- pceWaveSetMasterAtt()とpceWaveSetChAtt()のAPIリファレンスには、最大:0～127:最小 と書いてありますが、
 *	  実際の動作は、減衰無し:0～64:消音 であり、64以上は全て消音です。
 *	  ⇒ /usr/PIECE/sysdev/pcekn/snd.c volcalc() 参照
 *	  本関数も、pceWaveSetMasterAtt()とpceWaveSetChAtt()の実際の動作に倣い、0～64 で指定することしました。
 */
void adpcm_att(int ch, int att);
//}}2013/07/15追加

#endif /*__CLIP_ADP_H__*/
