/*	
 *	clipmidi.h
 *
 *	P/ECE MIDI Driver
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2003 Naoyuki Sawa
 *
 *	* Tue Aug 30 22:28:00 JST 2003 Naoyuki Sawa
 *	- 新規作成。
 *	* Tue Sep 02 24:00:00 JST 2003 Naoyuki Sawa
 *	- 音色マップ対応。
 *	- リズムパート対応。
 *	- チャネル内和音対応。
 *	* Tue Sep 03 04:02:00 JST 2003 Naoyuki Sawa
 *	- テンポずれ修正。
 */
#ifndef __CLIP_MIDI_H__
#define __CLIP_MIDI_H__

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

#define MIDITRACKS	16		/* サポートする最大トラック数(調整可) */

/* 音色マップ構造体(アプリケーションから指定) */
typedef struct _MIDIMAP {
	unsigned char melody[128];	/* メロディー音色マップ(MIDIプログラムNo.(0〜127)→MODサンプルNo.(1〜32、0は無音)) */
	unsigned char rhythm[128];	/* リズム音色マップ(MIDIノートNo.(0〜127)→MODサンプルNo.(1〜32、0は無音)) */
} MIDIMAP;

/* MIDIトラック構造体(内部使用) */
typedef struct _MIDITRACK {
	const unsigned char* pos;	/* 演奏位置 */
	int delta;			/* デルタタイム */
	int running_status;		/* ランニングステータス */
} MIDITRACK;

/* MIDIチャネル構造体(内部使用) */
typedef struct _MIDICHANNEL {
	int program;			/* プログラムナンバー */
} MIDICHANNEL;

/* MODチャネル管理情報構造体(内部使用) */
typedef struct _MIDIVOICE {
	int age;			/* 0:停止/1〜:発声(発声中は毎回+1する) */
	int channel;			/* MIDIチャネル */
	int note;			/* ノートナンバー */
} MIDIVOICE;

/* MIDIドライバ構造体(内部使用) */
typedef struct _MIDIDRIVER {
	const MIDIMAP* map;		/* 音色マップ */
	int track_count;		/* トラック数 */
	int time_unit;			/* 時間単位(四分音符当りのデルタタイム) */
	int tempo;			/* テンポ(四分音符当りのマイクロ秒) */
	long long timer;		/* 経過時間の余り[usec] (時間計算はミリ秒単位なので、intでは足りない) */
	MIDITRACK track[MIDITRACKS];	/* トラック */
	MIDICHANNEL channel[16];	/* チャネル */
	MIDIVOICE voice[MODCHANS];	/* MODチャネル管理情報 */
	MODDRIVER mod;			/* MODドライバ(音源として利用) */
} MIDIDRIVER;

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

/*------------------------------ 高レベル関数 ------------------------------*/

/* 標準MIDIファイル(SMF)の再生を開始します。
 * [in]
 *	data		SMFデータの先頭アドレス。
 *	inst		音源として使用するMODデータの先頭アドレス。
 *	map		音色マップ定義データのアドレス。
 * [out]
 *	戻り値		再生開始に成功したら、 0を返します。
 *			再生開始できなければ、-1を返します。
 */
int midi_play(const void* data, const void* inst, const MIDIMAP* map);

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

/* 音色マップ定義の例：
 *
 *	MIDIMAP map = {
 *		{
 *			[0 ... 127] = 1
 *		}, {
 *			2,2,2,2,2,2,2,2,2,2,	// 0-9
 *			2,2,2,2,2,2,2,2,2,2,	// 10-19
 *			2,2,2,2,2,2,2,2,2,2,	// 20-29
 *			2,2,2,2,2,		// 30-34
 *			0x83,			// 35 Acoustic Bass Drum
 *			0x83,			// 36 Bass Drum1
 *			2,			// 37 Side Stick
 *			0x82,			// 38 Acoustic Snare
 *			0x84,			// 39 Hand Clap
 *			0x82,			// 40 Electric Snare
 *			0x85,			// 41 Low Floor Tom
 *			2,			// 42 Closed Hi-Hat
 *			0x85,			// 43 High Floor Tom
 *			2,			// 44 Pedal Hi-Hat
 *			0x85,			// 45 Low Tom
 *			2,			// 46 Open Hi-Hat
 *			0x85,			// 47 Low-Mid Tom
 *			0x85,			// 48 Hi-Mid Tom
 *			2,			// 49 Crash Cymbal1
 *			0x85,			// 50 High Tom
 *			2,			// 51 Ride Cymbal1
 *			2,			// 52 Chinese Cymbal
 *			2,			// 53 Ride Bell
 *			2,			// 54 Tambourine
 *			2,			// 55 Splash Cymbal
 *			2,			// 56 Cowbell
 *			2,			// 57 Crash Cymbal2
 *			2,			// 58 Vibraslap
 *			2,			// 59 Ride Cymbal2
 *			2,			// 60 Hi Bongo
 *			2,			// 61 Low Bongo
 *			2,			// 62 Mute Hi Conga
 *			2,			// 63 Open Hi Conga
 *			0x85,			// 64 Low Conga
 *			2,			// 65 High Timbale
 *			2,			// 66 Low Timbale
 *			2,			// 67 High Agogo
 *			2,			// 68 Low Agogo
 *			2,			// 69 Cabasa
 *			2,			// 70 Maracas
 *			2,			// 71 Short Whistle
 *			2,			// 72 Long Whistle
 *			2,			// 73 Short Guiro
 *			2,			// 74 Long Guiro
 *			2,			// 75 Clavas
 *			2,			// 76 Hi Wood Block
 *			2,			// 77 Low Wood Block
 *			2,			// 78 Mute Cuica
 *			2,			// 79 Open Cuica
 *			2,			// 80 Mute Triangle
 *			2,			// 81 Open Triangle
 *			2,2,2,2,2,2,2,2,	// 82-89
 *			2,2,2,2,2,2,2,2,2,2,	// 90-99
 *			2,2,2,2,2,2,2,2,2,2,	// 100-109
 *			2,2,2,2,2,2,2,2,2,2,	// 110-119
 *			2,2,2,2,2,2,2,2		// 120-127
 *		}
 *	};
 *
 * ・MODファイルに次のようなサンプルを定義し、
 *	サンプル#1 ... ピアノ
 *	サンプル#2 ... スネアドラム
 *	サンプル#3 ... バスドラム
 *	サンプル#4 ... ハンドクラップ
 *	サンプル#5 ... タム
 *   メロディー音色は全てピアノに振り分け、リズム音色はスネア〜タムに振り分ける場合の例です。
 *
 * ・MODサンプルナンバーに0を指定すると、そのプログラムナンバー(メロディの場合)/ノートナンバー(リズムの場合)は鳴りません。
 *   この例では利用していません。
 *
 * ・MODサンプルナンバーは基本的に 0:無音/1〜32:MODサンプルナンバー で指定しますが、0x80を加えると音量が4倍になります。
 *   この例では、リズム音色の一部に利用しています。
 */

/*------------------------------ 中レベル関数 ------------------------------*/

/* mod_init()/mod_tick()は、MIDIサンプル展開だけを行う低レベル関数です。
 * * P/ECEで使う場合は、高レベルなmidi_play()/midi_stop()を使ってください。
 *   midi_init()/midi_tick()を直接使う必要はありません。
 */
int midi_init(MIDIDRIVER* driver, const void* data, const void* inst, const MIDIMAP* map);
int midi_tick(MIDIDRIVER* driver, short wbuff[/*MODBUFLEN*/]);

/*------------------------------ 低レベル関数 ------------------------------*/

/* mod_tick()から呼ばれる関数。 */
int midi_seq(MIDIDRIVER* driver);
int midi_mix(MIDIDRIVER* driver, short wbuff[/*MODBUFLEN*/]);

#endif /*__CLIP_MIDI_H__*/
