/* ====================================
     zmd2mid keyon,keyoffサブルーチン
   ==================================== */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Putcode.h"
#include "structs.h"
#include "bend.h"

#include "config.h"

void initCurrentNote(void);
DWORD keyonoff2(UBYTE *MTrk,UBYTE *tie,UBYTE *harm,UWORD step,UWORD gate,
		DWORD *gate_old,WORD velo,DWORD trk,DWORD delay,
		UBYTE *L0,BYTE KEYOFF,MODDAT M,PORTDAT port,WORD *bend,
		WORD *port_now,WORD *special_tie,
		WORD *extMOD_now,ARCCDAT A,EIGHTH E,BYTE *AB,UBYTE sw,BYTE TIEMODE,
		WORD vol,FADEDAT *F,BYTE ABspc,
		UBYTE ID[4],BYTE runstatus);
DWORD keyoff(UBYTE *MTrk,UBYTE *harm_old,UBYTE *harm_old2,DWORD gate_old,DWORD trk);
void bend_old_chg(WORD newbend);
void arcc_old_chg(BYTE newarcc,UBYTE tie);
void mod_old_chg(UBYTE tie);
void R_w_chg(BYTE r);
#ifdef AAA
int bendreset(unsigned char *MTrk,int *bend,int portsign,int *port_now,
		int *special_tie,int *extMOD_now,int *gate_old,int trk);
void mod_reset(unsigned char tie);
#endif


int harmchk(UBYTE harm[],UBYTE harm2[]);
void sort(UBYTE *harm,UBYTE num);
DWORD portament(UBYTE *MTrk,DWORD *gate_old,PORTDAT port,DWORD *cor,
		WORD *bend,WORD *port_now,WORD *special_tie,WORD *extMOD_now,BYTE ABspc,DWORD trk);
DWORD effect(UBYTE *MTrk,DWORD *gate_old,DWORD start,DWORD final,UBYTE sw,
		MODDAT M,PORTDAT port,DWORD *cor,
		ARCCDAT A,EIGHTH E,FADEDAT *F,DWORD vol,
		DWORD *Etime,/* int bfirst,*/ WORD *bend, WORD *port_now,
		WORD *special_tie,WORD *extMOD_now,
		BYTE ABspc,BYTE KEYON,UBYTE *harm,DWORD delay,DWORD velo,DWORD trk,
		UBYTE ID[4],BYTE runstatus);
DWORD fadeout(UBYTE *MTrk,DWORD *gate_old,FADEDAT *F,
		DWORD vol,DWORD trk,
		UBYTE ID[4],BYTE runstatus);
void bresenham(DWORD start,DWORD end,DWORD delta,WORD *adding,UBYTE *correct,BYTE *sign);


extern DWORD wavedatanum[],wavelooppoint[];
extern WORD *wavetable[];
extern BYTE wavelooptype[];


static DWORD total=0;
static DWORD AFT_old=0;
static DWORD lastkeyon = 0;					/* 最後のkeyonからの経過時間 */
static DWORD bend_old=0 /*,bfirst=0*/ ;		/* @Bnum で変更したベンド値 */
static DWORD eigMODm_old=0,eigARCm_old=0,eigAFTm_old=0;
static DWORD extMODc=0,extARCCc=0;			/* 拡張MOD/ARCC用内部カウンタ */
static DWORD tempMOD=0,tempARCC=0;			/* 拡張MOD/ARCC用内部状態保存変数(カウンタ) */
static DWORD extMODtime=0,extARCCtime=0;	/* 拡張MOD/ARCC 次のパラメータ変化のクロック(ディ例を除いた分) */
static DWORD nowMOD=0,nowARCC=0;			/* 非同期時のカウンタ */
static WORD  extMODcur=0,extARCCcur=0;		/* 拡張MOD/ARCC用bresenham work */
static BYTE /* extMODv=0,*/extARCCv=0;		/* 拡張ARCC用内部状態保存変数(絶対ARCC値) */
static BYTE eMOD=0,eARC=0,eAFT=0;			/* 1/8depth 実行中？ */
static BYTE KEYON2=0;						/* MOD/ARCC用:リセット後keyonまで0 */
static BYTE R_old=0;						/* 直前に演奏したのは休符か@wか */
static DWORD MODspc = 0, ARCCspc = 0;		/* 拡張MOD/ARCCの変更間隔 */
static UBYTE currentNote[16];				/* 現在発音中のノート */

void initCurrentNote()
{
	currentNote[0] = 0xFF;
}

/* ========================
     音符、休符を処理する
   ======================== */
DWORD keyonoff2(UBYTE *MTrk,UBYTE *tie,UBYTE *harm,UWORD step,UWORD gate,
		DWORD *gate_old,WORD velo,DWORD trk,DWORD delay,
		UBYTE *L0,BYTE KEYOFF,MODDAT M,PORTDAT port,WORD *bend,
		WORD *port_now,WORD *special_tie,
		WORD *extMOD_now,ARCCDAT A,EIGHTH E,BYTE *AB,UBYTE sw,BYTE TIEMODE,
		WORD vol,FADEDAT *F,BYTE ABspc,
		UBYTE ID[4],BYTE runstatus)
{
	static DWORD Mdepth_last=0,TIEorg=0 /* ,PORTorg=0 */;
	static BYTE Mtype_old=2,ARCCtype_old=2;	/* KEYON:keyon時１ */
	static BYTE ABPORTflg = 0;	/* ABPORTflg:port/bend before? */
	static BYTE harm__;	/* harm__: 真に直前に(MML表記で)鳴らした音階
				 * harm__2:前回と今回の(真の)音階の差 */

	UBYTE *MTrk_ = MTrk;
	DWORD i,cor=0,j,k,Etime[8],KEYON=0,harm__2=0,delay_,stepgate;
	BYTE ABflg = 0;		/*:autobend now?*/

	const DWORD TIEdata[25]={ -8192,-7513,-6830,-6147,-5464,-4781,
							-4098,-3415,-2732,-2049,-1366,-683,
							0,683, 1366, 2049, 2732, 3415, 4098,
							 4781, 5464, 6147, 6830, 7513, 8191 };

	/* bfirst = bend_old; */	/* del 138 */
	port.delay += total;				/* adding */
	if (step < gate) {
		gate = 0xFFFF;			/* こういう奴がいて文句を言われた */
	}
	if (harm[0] == 0x80 && *tie && harm[9] != 0xFF) {
		strncpy(&harm[0],&harm[9],8);	/* TIE中のnote */
	}

	if (*tie && 
		((harm[0] != 0xFF && harm[1] != 0xFF) ||
		(harm[9] != 0xFF && harm[10] != 0xFF) ) ) {	/* 和音中は一時的にスペシャルタイ解除 */
			TIEMODE = 0;
	}

	if (!(sw&1)) {
		M.Mdepth = 0;
	}
	if (Mtype_old != M.Mtype) {			/* 波形タイプを切り替えた */
		*extMOD_now = extMODc = extMODtime = tempMOD = 0;
		extMODcur = 0;
		/* extMODdepth = 0 */
		/* extMODv = M.Mdepth; */
		nowMOD = total;
		Mtype_old = M.Mtype;
	}
	if (ARCCtype_old != A.ARCCtype) {
		/* WORD j; */
		extARCCc = tempARCC = extARCCtime = 0;
		extARCCcur = 0;
		/* extARCCv = A.ARCCr; */	/* del v1.51 */

		if (A.ARCCtype < 8) {		/* add this block in v1.51 */
			extARCCv = A.ARCCr;
		} else {
			extARCCv = (A.ARCCv > 0)?
				wavetable[A.ARCCtype][0] : -wavetable[A.ARCCtype][0];
			extARCCv += A.ARCCn;
		}

		nowARCC = total;
		ARCCtype_old = A.ARCCtype;
	}

	if (E.eigMODm || E.eigARCm || E.eigAFTm) {		/* 1/8depth */
		j = step >> 3;
		cor = (step & 7) << 6;
		Etime[0] = total;
		k = cor;
		for (i = 1; i <= 7; i++) {
			Etime[i] = Etime[i - 1] + j;
			cor += k;
			if (cor > 0xFF) {
				cor -= 0x100;
				Etime[i]++;
			}
		}
		/* cor = 0; */

		if (eigMODm_old != E.eigMODm) {		/* タイ途中で@m,@a,@z 1/8 が */ 
			eigMODm_old = E.eigMODm;	/* 変更になった場合 */
			eMOD = 0;
		}
		if (eigARCm_old != E.eigARCm) {
			eigARCm_old = E.eigARCm;
			eARC = 0;
		}
		if (eigAFTm_old != E.eigAFTm) {
			eigAFTm_old = E.eigAFTm;
			eAFT = 0;
		}
	}

	if (abs(port.sign) == 1) {					/* ポルタメントなら */
		if (!port.delta  && !port.correct && *tie) {
				/* 同じ音階へのport.なら:なんちゅう仕様じゃ… */
			TIEMODE = 1;		/* 一時的にスペシャルタイ設定 */
			port.delta = port.correct = port.sign = 0;
		}
		if (*tie)  {
			/* bfirst = *bend; */	/* del138 */
		}
		/* if (TIEMODE) { */		/* 何半音分動くかを求める */
			harm__2  = (total + step - port.delay) * port.delta;
			cor      = (total + step - port.delay) * port.correct;
			cor     /= 0x100;
			harm__2 += cor * port.sign;
			harm__2 /= 683;
		/* } */
	}
/* ================================================================================= */


	if (gate == 0xFFFF) {	/* 今回TIEなら */
		stepgate = step;
		delay_ = 0;
	} else {
		stepgate = gate;
		delay_ = delay;
	}

	if (!M.Msync && harm[0] != 0x80) {
		nowMOD = total;
	}
	if (!A.ARCCsync && harm[0] != 0x80) {
		nowARCC = total;
	}


	if (R_old == 'w') {
		KEYON = 1;
	} else {
		if (*tie) {					/* 前回TIEなら */
			BYTE illnote = 0;
			if (harm[1] != 0xFF) {	/* 被接続和音TIEのdelay == 0 ('ceg',6& 'ega') v1.49.2*/
				delay_ = 0;
			}
			if (Mdepth_last != M.Mdepth) {		/* TIE途中@m変更 */
				M.Mdelay = total;
			}
			if ( TIEMODE ) {
				if ( harm__ != harm[0] ) {	/* 違う音階のTIE */
					illnote = 1;		/* この辺は手抜きだな... */
				}
			} else {				/* その内まとめます */
				if (L0[0] != 0xFF) {
					/* if (harmchk(harm,L0)) { */
					if (harmchk(harm,L0) &&
						harm[9] != 0xFF && harmchk(harm,&harm[9])) {
						illnote = 1;
					/* } else if (harm[9] != 0xFF && harmchk(harm,&harm[9])) { */
					/* 	illnote = 1; */
					}
				} else {
					if (harmchk(harm,&harm[9])) {
						illnote = 1;
					}
				}
			}
			if (illnote) {
/* keyoff */
				if (!KEYOFF && harm[0] != 0x80 && !TIEMODE) {
					DWORD wf =  keyoff(MTrk,&harm[9],&harm[0],*gate_old,trk);
/*fprintf(stderr,"(1)");*/
					MTrk += wf;
					if (wf) {
						*gate_old = 0;
					}
				}
/* keyon */		if (harm[0] != 0x80) {
					*port_now = 0;
					if (TIEMODE) {
									/* if (harm__ != harm[0] ) { */	/* 仮対応 */
									/* *bend = PORTorg + TIEdata[harm[0]-TIEorg+12]; */
						*special_tie = TIEdata[harm[0]-TIEorg+12];	/* 1.38 */
									/* } */
									/* bfirst += *bend; */ 	/* 仮対応 */ /* del1.38 */
						MTrk += bendchg(MTrk,gate_old,*bend,
										*port_now,*special_tie,*extMOD_now,trk);
						KEYON = 0;
/* printf("0[b=%d p=%d s=%d]",*bend,*port_now,*special_tie); */
									/* TIEorg=harm[0]; */
					} else {
						/*
							MTrk += bendreset(MTrk,bend,port.sign,
									port_now,special_tie,extMOD_now,gate_old,trk);
						*/
						MTrk += bendchg(MTrk,gate_old,*bend,
										*port_now,*special_tie,*extMOD_now,trk);
						KEYON = 1;
						TIEorg = harm[0];				/* add1.38 */
						strncpy(&harm[9],&harm[0],8);	/* TIE中のnote */
/* printf("1[b=%d p=%d s=%d]",*bend,*port_now,*special_tie); */
					}
				}
				harm__2 += harm[0] - harm__;	/* harm__2 は前と今の音階の差 */

			} else {	/* 同じ音階のTIE */
				/* keyoffを保留 */
				/* TIEorg=harm[0]; */
				if (harm[0] != 0x80) {
					/* int flg = ( (!port.delay && port.sign) || (ABPORTflg && !port.sign) )? 1 : 0; */
					const BYTE chgbendflg =
							( (!port.delay && port.sign) || (*AB && TIEMODE) )? 1 : 0;
/*
if (!port.delay && port.sign) {
printf("[1]");
}
if (ABPORTflg && !port.sign) {
printf("[2]");
}
*/
					if (ABPORTflg && !chgbendflg) {
												/* 前回オートベンド/portだったなら */
/* printf("q[b=%d p=%d s=%d]",*bend,*port_now,*special_tie); */
					/*
						MTrk += bendreset(MTrk,bend,port.sign,port_now,
											special_tie,extMOD_now,gate_old,trk);
					*/
						MTrk += bendchg(MTrk,gate_old,*bend,
										*port_now,*special_tie,*extMOD_now,trk);

												/* とりあえずベンドの最終値を出力させる */
					}
/* add 1.28 */	/* del 1.38 */					/* if (port.sign && bfirst != bend_old) { */
/* add 1.38 */		if (TIEMODE) {
												/* bend += harm__2 * 683; */
												/* *bend = PORTorg + TIEdata[harm[0]-TIEorg+12]; */
						*port_now = 0;
						*special_tie = TIEdata[harm[0] - TIEorg + 12];
/* printf("A[b=%d p=%d s=%d]",*bend,*port_now,*special_tie); */
						/* } */
												/* bfirst += *bend; */ 	/* 仮対応 */ /* del1.38 */
					} else if (port.sign) {		/* @b0,1366c& @b1366,0c */
						*port_now = 0;
/* printf("B[b=%d p=%d s=%d],AB=%d",*bend,*port_now,*special_tie,*AB); */
					}
					/* if ( (!port.delay && port.sign) || (ABPORTflg && !port.sign)) { */
					/* if (flg || TIEMODE) { */
					if (chgbendflg) {			/* タイ直後の１ベンド目としての更新が必要なら */
							/* (TIEMODE && !port.delay)) { */
						/*
						MTrk += bendreset(MTrk,bend,port.sign,port_now,
											special_tie,extMOD_now,gate_old,trk);
						*/
						MTrk += bendchg(MTrk,gate_old,*bend,
										*port_now,*special_tie,*extMOD_now,trk);
/* printf("C[]"); */
					}
					/* } */
					KEYON = 0;
				}
			}
			harm__2 -= harm[0] - harm__;		/* 最後での辻褄合わせ */

		} else {			/* 直前はTIEでないなら */
/*del1.38*/		/* *bend -= *extMOD_now; */	/* これでベンドを戻す処理に引っ掛かる */
			*special_tie = 0;	/* add1.38*/
			if (!M.Msync) {		/* とりあえず拡張MOD/ARCC カウンタクリア */
				*extMOD_now = extMODc = extMODcur = tempMOD = extMODtime = 0;
				/* extMODv = 0; */
				/* extMODdepth = 0; */
			}
			if (!A.ARCCsync) {
				if (harm[0] != 0x80) {
					extARCCc = extARCCcur = tempARCC = extARCCtime = 0;
					/* extARCCv = 0; */
					extARCCv = A.ARCCr;
				}
				/* nowARCC = total; */
			}
			if (gate == 0xFFFF) {			/* これからTIE開始なら */
				/* *tie = 1; */					/* TIEflagON */ /*後回し v1.38 */
				if (harm[0] != 0x80) {		/* 対処療法 */
					TIEorg = harm[0];
				} else 	if (L0[0] != 0xFF) {
					TIEorg = L0[0];
				} else {
					TIEorg = harm[9];
				}
			}
/* keyon */
			if (harm[0] != 0x80) {
				WORD i = 128;
				*port_now = 0;
/* printf("C[b=%d p=%d s=%d]",*bend,*port_now,*special_tie); */
			/*
				MTrk += bendreset(MTrk,bend,port.sign,port_now,special_tie,
									extMOD_now,gate_old,trk);
			*/
				MTrk += bendchg(MTrk,gate_old,*bend,
								*port_now,*special_tie,*extMOD_now,trk);
				if (gate == 0xFFFF) {
					/* PORTorg = *bend; */
					/* PORTorg = (*AB)? 0 : *bend; */	/* change 1.37 */ /* del1.38*/
				}
				if ( !M.Mmode && M.Mdepth) {
					MTrk += MODchg(MTrk,gate_old,0,trk);	/* Modulation off */
				}
				if (sw & 2) {
					if (A.ARCCmode) {
						if (A.ARCCv != -128) {
							i = A.ARCCn;		/* ユーザ波形/拡張ARCC */
							if (!A.ARCCdelay) {
								if ( A.ARCCtype >= 8 && (extARCCc == extARCCtime) ) {
									i = extARCCv;
								} else {
									WORD j;
									if (E.eigARCm) {			/* 1/8depth mode */
										j = E.eigARC[0];
									} else if (A.ARCCtype >= 8) {	/* add 1.51 */
										j = (A.ARCCv > 0)?
											 wavetable[A.ARCCtype][tempARCC] :
											-wavetable[A.ARCCtype][tempARCC];
									} else {
										j = A.ARCCv;
									}
/* printf("{j=%d}",j); */
#ifdef AAA	/* ユーザー波形対策・・・やってないのは手抜きです */
						if ( (tempARCC >= 0) && (extARCCc >= extARCCtime) ) {
							WORD i;
							if ( A.ARCCtype && tempARCC < wavedatanum[A.ARCCtype] ) {
								/* reject bend in case (UserWave && 1shot(done) && TIE) */
								if (++ARCCspc >= ABspc || now == final) {
									ARCCspc = 0;
									MTrk += ARCCchg(MTrk,gate_old,
										A.ARCCc,extARCCv,trk);
								}
							}
							i = (A.ARCCv > 0)?
								A.ARCCn + wavetable[A.ARCCtype][tempARCC] :
								A.ARCCn - wavetable[A.ARCCtype][tempARCC];
#endif
									if (A.ARCCtype == 3 || A.ARCCtype >= 8) {	/* delay0で波形が変わる対策 */
										i += j;
									} else if (j < 0) {
										i -= j;
									}
								}
							}



							if (i > 127) {
								i = 127;
							} else if (i < 0) {
								i = 0;
							}
						}
					} else {
						if (A.ARCCv != -128) {
							i = A.ARCCr;		/* normalARCC */
						} else if (E.eigARCm) {	/* 1/8depth mode */
							i = E.eigARC[0];
						}
					}
					if (i != 128) {
						if (!A.ARCCsync || !KEYON2) {	/* add v1.51 */
							/* 非同期モード時は、最初のキーオン以降リセットコードを送らない */
							MTrk += ARCCchg(MTrk,gate_old,A.ARCCc,i,trk);
						}
/* printf("(I=%d)",i); */
#ifdef A
						if (A.ARCCtype >= 8) {	/* add this block in v1.51 */
							extARCCv = i;
						}
#endif
					}
				}
				strncpy(&harm[9],&harm[0],8);	/* TIE中のnote */
				/* *gate_old = 0; */		/* stepgate-delay*(i-1); */

				i = 0 - 1;
				while (harm[++i] != 0xFF) {
					BYTE j = 0 - 1;
					while (L0[++j] != 0xFF) {
						if (harm[i] == L0[j]) {
							BYTE k;
							for (k = i; k < 8 - 1; k++) {
								harm[k] = harm[k + 1];
							}
						}
					}
				}

				KEYON = 1;
				delay_ = delay;		/* 今回初めてTIEの場合を考慮 */
			}
		}
	}


	if (abs(port.sign) == 2) {					/* オートベンドなら */
		if ( (harm[0] == 0x80) || (*AB) ) {	/* *AB: @b0,683c&c のため */
			port.sign = 0;
		} else {
			DWORD i = total + step - port.delay;
			/* bfirst = port.delta; */ /* del138 */	/* オートベンド用 ポルタメントのフォーマットに直す */
			*bend = port.delta;
			*port_now = 0;			/* @b0,683c& @b683,0,24c */
			if (i > 0) {
				UBYTE pc;
				bresenham( port.delta,port.correct+port.delta,i,
						&port.delta,&pc,&port.sign );
				port.correct = pc;
				/* *AB = 1; */
				/* ABflg = 1; */ /* loop out */
			} else {
				/* printf( "まだ未サポートのオートベンド。\n"); */
				port.sign = 0;
			}
			if ( !(*tie && !TIEMODE) && port.delay ) {	/* @j0/1 c&@b683,0,24c */
														/* @j0/1 @b683,0,24c */
				MTrk += bendchg(MTrk,gate_old,*bend,
								*port_now,*special_tie,*extMOD_now,trk);
			}
		}
		ABflg = 1;
	}
	if (gate == 0xFFFF) {		/* TIEなら */
		*tie = 1;
	}

	if (*AB) {
		port.sign = 0;
	}
	if ( harm[0] != 0x80 || M.Mdepth || A.ARCCmode || F->sign) {
		MTrk += effect(MTrk,gate_old,total,total+stepgate-1,sw,
				M,port,&cor,A,E,F,vol,
				&Etime[0],/* bfirst,*/ bend, port_now, special_tie,
				extMOD_now,
				ABspc,KEYON,harm,delay_,velo,trk,
				ID,runstatus);
	} else {
		*gate_old += stepgate;			/* for 高速化 */
	}

	if (R_old == 'w') {
		R_w_chg(' ');
	} else {
		if (harm[0] == 0x80 && L0[0] != 0xFF) {		/* *0&中で且つ休符が来たら */
			BYTE i = 0 - 1,j;						/* *0&の発音を通常発音の管理にする */
			while (L0[++i] != 0xFF) {
				if (harm[0] == 0x80) {
					harm[0] = L0[i];
				} else {
					for (j = 0; j < 8; j++) {
						if (harm[j] == L0[i]) {
							break;
						} else if (harm[j] == 0xFF) {
							harm[j]     = L0[i];
							harm[j + 1] = 0xFF;
							break;
						}
					}
				}
				for (j = 9; j < 9 + 8; j++) {
					if (harm[j] == L0[i]) {
						break;
					} else if (harm[j] == 0xFF) {
						harm[j]     = L0[i];
						harm[j + 1] = 0xFF;
						break;
					}
				}
			}
			L0[0] = 0xFF;
		}

		if (gate == 0xFFFF) {
			total += step;
			if (!KEYOFF && harm[0] == 0x80 && L0[0] != 0xFF) {	/* *0&中休符&なら中止 */
				DWORD wf = keyoff(MTrk,&L0[0],&harm[0],*gate_old,trk);
/*fprintf(stderr,"(2)");*/
				MTrk += wf;
				if (wf) {
					*gate_old = 0;
				}
				L0[0] = 0xFF;
			}
			*AB = ABflg;
		} else {
			/* total += gate; */
			/* keyoffする */
			if (!KEYOFF) {
				/* if ( (!*tie && harm[0]!=0x80)||(*tie) ) */
				if (harm[0] != 0x80) {
					if (L0[0] == 0xFF) {
						int wf = 0;
						MTrk += wf = keyoff(MTrk,&harm[9],NULL,*gate_old,trk);
/*fprintf(stderr,"(3)");*/
						harm[0] = harm[9] = 0xFF;
						if (wf) {
							*gate_old = 0;
						}
					} else {
						if (harm[0] != 0xFF) {
/*fprintf(stderr,"(4)");*/
							MTrk += keyoff(MTrk,&harm[0],NULL,*gate_old,trk);
							harm[0] = 0xFF;
							*gate_old = 0;
						}
						/* if (L0[0] != 0xFF) { */
							MTrk += keyoff(MTrk,&L0[0],&harm[0],*gate_old,trk);
							L0[0] = 0xFF;
						/* } */
					}
					/* *gate_old = 0; */
				/* } else if (!KEYOFF && L0[0] != 0xFF) { */	/* *0&中休符&なら中止 */
				} else if (L0[0] != 0xFF) {	/* *0&中休符&なら中止 */
/*fprintf(stderr,"(5)");*/
					MTrk += keyoff(MTrk,&L0[0],NULL,*gate_old,trk);
					L0[0] = 0xFF;
					*gate_old = 0;
				}
			}

			if ( (harm[0] != 0x80 || M.Mmode || A.ARCCmode || F->sign) &&
				 (stepgate < step) ) {
				i = harm[0];
				harm[0] = 0x80;
					/* step中gateだけ発音したからその残り分だけ(休符扱いで)待つ */
				MTrk += effect(MTrk,gate_old,total+stepgate,total+step-1,sw,
						M,port,&cor,A,E,F,vol,
						&Etime[0],/* bfirst, */ bend, port_now, special_tie,
						extMOD_now,
						ABspc,KEYON,harm,delay_,velo,trk,
						ID,runstatus);
					harm[0] = i;
			} else {
				*gate_old += step - stepgate;		/* for 高速化 */
			}

			*tie = total = *AB = eMOD = eARC = eAFT = eigMODm_old = eigARCm_old = eigAFTm_old = 0;
			*port_now = 0;
		}
		Mdepth_last = M.Mdepth;
		ABPORTflg = port.sign;
		harm__ = (TIEMODE && !port.sign)? harm[0] : harm[0] + harm__2;
						/* 前回tieなら: harm__ = harm__ + harm__2
						 * さもなくば : harm__ = harm[0] + harm__2 */
	/* printf("c:TIEMODE=%d harm[0]=%d harm__=%d harm__2=%d\n",TIEMODE,harm[0],harm__,harm__2); */
	}
	return MTrk - MTrk_;
}



/* ================================
     同じ和音かどうかチェックする
   ================================ */

int harmchk(UBYTE harm[],UBYTE harm2[])
{
	UBYTE i,j;
	int  k = 1;

	for (i = 0; i <= 7; i++)
		if (harm[i] == 0xFF) break;
	sort(harm,i);
	for (j = 0; j <= 7; j++)
		if (harm2[j] == 0xFF) break;

	if (i == j) {
		sort(harm2,j);
		if (!strncmp(harm,harm2,i)) k = 0;		/* 一致 */
	}
	return k;
}


/* ====================
     和音をソートする
   ==================== */

void sort(UBYTE *harm,UBYTE num)
{
	BYTE j;

	for (j = 1; j < num; j++) {
		BYTE i = j - 1;
		const UBYTE key = harm[j];

		while (i >= 0 && harm[i] > key) {
			harm[i + 1] = harm[i];
			i--;
		}
		harm[i + 1] = key;
	}
}



/* =======================
     keyoff サブルーチン
   ======================= */

DWORD keyoff(UBYTE *MTrk,UBYTE *harm_old,UBYTE *no_keyoff_array,
				DWORD gate_old,DWORD trk)
{
	UBYTE *MTrk_ = MTrk;

/*
if (no_keyoff_array != NULL) {
fprintf(stderr,"[[%.2x %.2x %.2x]]",*no_keyoff_array, no_keyoff_array[1],no_keyoff_array[2]);
}
*/
	while ( (char)*harm_old >= 0 ) {
		const UBYTE targetNote = *harm_old++;
		UBYTE *noKeyoff = no_keyoff_array;
		int isKeyOff = 1;

		if (noKeyoff != NULL) {
			while ((char)*noKeyoff >= 0) {
				if (*noKeyoff++ == targetNote) {
					isKeyOff = 0;
					break;
				}
			}
		}
		if (isKeyOff) {
			UBYTE *n;

/*fprintf(stderr,"[off %.2x]",targetNote);*/
			MTrk += Putcode(MTrk,gate_old,0x90+(unsigned char)trk,
							targetNote,0);
			gate_old = 0;

			for (n = currentNote; (*n != targetNote && (char)*n >= 0); n++)
				;
			while ((char)*n >= 0) {
				*n = *(n + 1);
				n++;
			}
/*fprintf(stderr,"{{%.2x %.2x %.2x}}",*currentNote, currentNote[1],currentNote[2]); */
		}
	}


	return MTrk - MTrk_;
}



/* ==============================
     キーオン中の挙動を再現する	  Modulation,Portament,ARCC,After touch (normal,1/8depth)
   ============================== */

DWORD effect(UBYTE *MTrk,DWORD *gate_old,DWORD start,DWORD final,UBYTE sw,
		MODDAT M,PORTDAT port,DWORD *cor,
		ARCCDAT A,EIGHTH E,FADEDAT *F,DWORD vol,
		DWORD *Etime,/* int bfirst,*/ WORD *bend, WORD *port_now,
		WORD *special_tie,WORD *extMOD_now,
		BYTE ABspc,BYTE KEYON,UBYTE *harm,DWORD delay,DWORD velo,DWORD trk,
		UBYTE ID[4],BYTE runstatus)
{
	UBYTE *MTrk_ = MTrk;
	DWORD time=0,KEYONtime=start,now,
		Mdelay_bak=M.Mdelay,ARCCdelay_bak=A.ARCCdelay;
	BYTE KEYONno = 0;
	WORD Mdepth_bak=M.Mdepth;
	BYTE ARCCv_bak=A.ARCCv;
	BYTE Mcond = 0;		/* -1:normal MOD ok 1:拡張MOD ok 0:none */
	BYTE Acond = 0;		/* -1:normal ARC ok 1:拡張ARC ok 0:none */
	static WORD extMODdelta,extARCCdelta;
	static UBYTE extMODcorrect,extARCCcorrect;
	static BYTE extMODsign,extARCCsign;
/*
printf("==================================================================\n");
*/

#ifdef AAA
	if (sw&1) {
		if (!M.Mmode) {
			if ( M.Mdepth>0 ) {			/* normalモジュレーション */
				Mcond = -1;
			}
		} else {
			if ( (M.Mmode)&&(nowMOD >= M.Mdelay) ) {	/* 拡張モジュレーション */
				Mcond = 1;
			}
		}
	}
#endif
/* printf("M=[%d/%d]",M.Mdepth, sw); */
	if ( (M.Mdepth > 0) && (sw & 1) ) {
		if (!M.Mmode) {				/* normalModulation処理 */
			Mcond = -1;
		} else 	{					/* 拡張Modulation */
			Mcond = 1;
		}
/* printf("%d ",Mcond); */
	}								/* 1/8 mod の判定は後で行う... add v1.62 */

	if ( (A.ARCCv != -128) && (sw & 2) ) {
		if (!A.ARCCmode) {				/* normalARCC処理 */
			Acond = -1;
		} else 	{					/* 拡張ARCC */
			Acond = 1;
		}
	}


	for (now = start; now <= final; nowMOD++,nowARCC++,lastkeyon++,now++) {
		if (harm[0] != 0x80) {
			while ( now == KEYONtime && KEYON ) {					/* keyon */
				UBYTE *n = currentNote;
				int isKeyOn = 1;

				if ( KEYONno > 7 || harm[KEYONno] == 0xFF ) {		/* もう発音する音がない */
					KEYON = 0;
					break;
				}

/*fprintf(stderr,"[ON %.2x]",harm[KEYONno]);*/
				while ( (char)*n >= 0 ) {
					if (harm[KEYONno] == *n++) {
						isKeyOn = 0;
						break;
					}
				}
				if (isKeyOn) {
					MTrk += Putcode(MTrk,*gate_old,0x90+trk,harm[KEYONno],velo);
					lastkeyon = *gate_old = 0;

					for (n = currentNote; (char)*n >= 0; n++)
						;
					*n = harm[KEYONno];
					*(n + 1) = 0xFF;
				}
/*fprintf(stderr,"{%.2x %.2x %.2x}", currentNote[0],currentNote[1],currentNote[2]);*/
				KEYONno++;
				KEYONtime += delay;
				KEYON2 = 1;
			}

			if ( now == Etime[time] ) {
				if ( E.eigMODm && eMOD >= 0 && (sw & 1) ) {		/* 1/8モジュレーション */
/* printf("%d-%d ",M.Mmode,E.eigMOD[time]); */
					if (!M.Mmode) {
						MTrk += MODchg(MTrk,gate_old,E.eigMOD[time],trk);
					} else {
						M.Mdepth = E.eigMOD[time];	/* 拡張1/8 */
						M.Mdelay = now;
						if (!M.Msync) {		/* ヤボを承知で */
							if ( (time > 1  && E.eigMOD[time - 1] == E.eigMOD[time]) ||		/* add these conditions: v1.62 */
								 (time == 0 && E.eigMOD[0]        == E.eigMOD[7])) {
							} else {
								*extMOD_now = extMODc = extMODcur = tempMOD = extMODtime = 0;
								nowMOD = 0;
							}
						}
						Mcond = 1;
					}
					eMOD = 1;
				}
				if ( E.eigARCm && eARC >= 0 && (sw & 2) ) {	/* 1/8 ARCC(normal)*/
					if (!A.ARCCmode) {
						MTrk += ARCCchg(MTrk,gate_old,A.ARCCc,E.eigARC[time],trk);
					} else {
						A.ARCCv = E.eigARC[time];	/* 拡張1/8 */
						A.ARCCdelay = now;
						if (!A.ARCCsync) {	/* ヤボを承知で */
							if ( (time > 1  && E.eigARC[time - 1] == E.eigARC[time]) ||		/* add these conditions: v1.62 */
								 (time == 0 && E.eigARC[0]        == E.eigARC[7])) {
								extARCCc = extARCCcur = tempARCC = extARCCtime = 0;
								nowARCC = 0;
							}
						}
					}
					eARC = 1;
				}
				if ( E.eigAFTm && eAFT >= 0 &&			/* 1/8 after touch */
					(sw & 8) && (AFT_old != E.eigAFT[time]) ) {
					MTrk += Putcode2(MTrk,*gate_old,0xD0+trk,E.eigAFT[time]);
					*gate_old = 0;
					AFT_old = E.eigAFT[time];
					eAFT = 1;
				}
				time++;
			}
		}

		if (port.sign && port.delay <= now) {	/* ポルタメント処理 */
			if (port.delay == now) {
				*cor = 0;
				/* *bend = bfirst; */	/* del 1.37 */
				portament(MTrk,gate_old,port,cor,bend,
					port_now,special_tie,extMOD_now,0,trk); /* 初期化 */
			}
			if (now == final) {
				ABspc = 1;	/* 最後だけはbend処理をskipしない */
			}
			MTrk += portament(MTrk,gate_old,port,cor,bend,
				port_now,special_tie,extMOD_now,ABspc,trk);
		}

		if (KEYON2) {
/* printf("!"); */
			if ( Mcond < 0 && lastkeyon == M.Mdelay ) {	/* normalモジュレーション処理 */
				MTrk += MODchg(MTrk,gate_old,M.Mdepth,trk);
			}
			if ( Acond < 0 && now == A.ARCCdelay ) {	/* normalARCC処理 */
				MTrk += ARCCchg(MTrk,gate_old,A.ARCCc,A.ARCCv,trk);
/* printf("[V=%d]\n",A.ARCCv); */
			}

			/* if ( (M.Mmode)&&(M.Mdepth)&& */
			if ( Mcond > 0) {				/* 拡張モジュレーション */
				DWORD Mdepth_ = (M.Mmode == 1)? 1067 * M.Mdepth / 100 : M.Mdepth;
				if (nowMOD < M.Mdelay && (!eMOD && !eARC)) {		/* eMOD/eARC: add v1.62 */
				/*    MTrk += ARCCchg(MTrk,gate_old,A.ARCCc,A.ARCCn,trk); */
				/*    MTrk += bendchg(MTrk,gate_old,*bend,*extMOD_now,trk); */
				} else {
					if (nowMOD == M.Mdelay) {
						MODspc = 0;
					}
					switch (M.Mtype) {
						case 0:		/* 鋸歯波 */
						case 2:		/* 三角波 */
						case 3:		/* 鋸歯波シングル */
							if (extMODtime == 0) {
								extMODtime = (M.Mtype == 2)?
									M.Mspeed : (M.Mspeed << 1); /* changed 1.37 */
								bresenham(0,Mdepth_,extMODtime,
									&extMODdelta,&extMODcorrect,&extMODsign);
								extMODcur = 0;
							}

							if (M.Mmode) {
								if (++MODspc >= ABspc || now == final) {
									MODspc = 0;
									MTrk += bendchg(MTrk,gate_old,
										*bend,*port_now,*special_tie,
										*extMOD_now,trk);
								}
							}
							if (extMODc >= extMODtime) {
								extMODcur = 0;
								switch (M.Mtype) {
									case 0:
										bresenham(-Mdepth_,Mdepth_,(M.Mspeed << 2),
											&extMODdelta,&extMODcorrect,&extMODsign);
										*extMOD_now -= Mdepth_ * 2;
										extMODtime += (M.Mspeed << 2);
										break;
									case 2:
										bresenham(0,-Mdepth_*2*extMODsign,(M.Mspeed << 1),
											&extMODdelta,&extMODcorrect,&extMODsign);
										extMODtime += (M.Mspeed << 1);
										break;
									case 3:
										M.Mmode = 0;	/* もう波形は動かない */
										Mcond = 0;
											break;
								}
							}
							if (M.Mmode) {
								*extMOD_now += extMODdelta;
								extMODcur += extMODcorrect;
								if (extMODcur > 0xFF) {
									extMODcur  -= 0x100;
									*extMOD_now += extMODsign;
								}
							}
							break;
						case 1:		/* 矩形波 */
							if ( extMODc >= extMODtime ) {
/* printf("[%d %d %d]",extMODc, extMODtime, tempMOD); */
								MTrk += bendchg(MTrk,gate_old,
										*bend,*port_now,*special_tie,
										*extMOD_now,trk);
								if (extMODc == 0 && extMODtime == 0) {
									*extMOD_now += Mdepth_;
									tempMOD++;
								} else if ( (++tempMOD)&1 ) {
									/* extMODdepth += Mdepth_ * 2; */
									/* *bend += Mdepth_ * 2; */
									*extMOD_now += Mdepth_ * 2;
								} else {
									/* extMODdepth -= Mdepth_ * 2; */
									/* *bend -= Mdepth_ * 2; */
									*extMOD_now -= Mdepth_ * 2;
								}
								extMODtime += (M.Mspeed << 1);
								/* printf("[%d]",*bend); */
							}
				/*
							if (extMODtime == 0) {
								*extMOD_now = -Mdepth_;
							}
				*/
							break;
						default:		/* ユーザー登録波形 */
							if ( (tempMOD >= 0) && (extMODc >= extMODtime) ) {
								if ( M.Mtype && tempMOD < wavedatanum[M.Mtype] ) {
									/* reject bend in case (UserWave && 1shot(done) && TIE) */
									*extMOD_now = (M.Mmode == 1)?
										1067 * wavetable[M.Mtype][tempMOD] / 100 :
										wavetable[M.Mtype][tempMOD];
									if (++MODspc >= ABspc || now == final) {
										MODspc = 0;
										MTrk += bendchg(MTrk,gate_old,
											*bend,*port_now,*special_tie,
										*extMOD_now,trk);
									}
								}
								extMODtime += M.Mspeed;
								if ( ++tempMOD >= wavedatanum[M.Mtype] ) {
									switch (wavelooptype[M.Mtype]) {
										case 0:	/* ワンショット */
											M.Mmode = 0; /* もう波形変化なし */
											Mcond = 0;
											break;
										case 1:	/* リピート */
											tempMOD = wavelooppoint[M.Mtype];
											/* ループポイントから */
											break;
										case 2:	/* オルタニブ */
											tempMOD = -tempMOD + 2;
											break;
										}
									}
							} else if ( (tempMOD < 0) && (extMODc >= extMODtime) ) {
								*extMOD_now = (M.Mmode == 1)?
									1067 * wavetable[M.Mtype][-tempMOD] / 100 :
									wavetable[M.Mtype][-tempMOD];
								if (++MODspc >= ABspc || now == final) {
									MODspc = 0;
									MTrk += bendchg(MTrk,gate_old,
										*bend,*port_now,*special_tie,*extMOD_now,trk);
								}
								tempMOD++;	/* オルタニブ:戻る時の処理 */
								extMODtime += M.Mspeed;
							}
							break;
					}
					extMODc++;
				}
			}

/* printf("mode,v,sw,nA,Ad=%d,%d,%d,%d,%d\n",A.ARCCmode,A.ARCCv,sw,nowARCC,A.ARCCdelay); */
			if ( Acond > 0 ) {		/* 拡張ARCC */
				if (nowARCC < A.ARCCdelay) {
					MTrk += ARCCchg(MTrk,gate_old,A.ARCCc,A.ARCCn,trk);
/* printf("[n=%d]",A.ARCCn); */
				} else {
					if (nowARCC == A.ARCCdelay) {	/* add this block in v1.51 */
						ARCCspc = 0;
						if (A.ARCCtype >= 8) {
							int i;
							i = (A.ARCCv > 0)?
								A.ARCCn + wavetable[A.ARCCtype][tempARCC] :
								A.ARCCn - wavetable[A.ARCCtype][tempARCC];
							if (i > 127) {
								i = 127;
							} else if (i < 0) {
								i = 0;
							}
							extARCCv = i;		/* for overflow */
						}
/* printf("[spc=0]"); */
					}
					switch (A.ARCCtype) {
						case 0:		/* 鋸歯波 */
						case 2:		/* 三角波 */
						case 3:		/* 鋸歯波シングル */
							if (extARCCtime == 0) {
								extARCCtime = (A.ARCCtype == 2)? 2 : 4;
								extARCCtime *= A.ARCCspeed;
								extARCCcur = 0;
								if (A.ARCCv > 0 ) {
									bresenham(A.ARCCr,A.ARCCr-A.ARCCv,extARCCtime,
										&extARCCdelta,&extARCCcorrect,&extARCCsign);
									extARCCv = A.ARCCn;
								} else {
									WORD i;
									bresenham(A.ARCCr+A.ARCCv,A.ARCCr-1,extARCCtime,
										&extARCCdelta,&extARCCcorrect,&extARCCsign);
									i = A.ARCCn + A.ARCCv;
									if (i > 127) {
										i = 127;
									} else if (i < 0) {
										i = 0;
									}
									extARCCv = i;
								}
							}
							if (A.ARCCmode) {
								if (++ARCCspc >= ABspc || now == final) {
									ARCCspc = 0;
									MTrk += ARCCchg(MTrk,gate_old,
									A.ARCCc,extARCCv,trk);
								}
							}
							if (extARCCc >= extARCCtime) {
								extARCCcur = 0;
								switch (A.ARCCtype) {
									WORD i;
									case 0:
										i = extARCCv + A.ARCCv;
										if (i>127) {
											i = 127;
										} else if (i < 0) {
											i = 0;
										}
										extARCCv = i;
										extARCCtime += (A.ARCCspeed << 2);
										break;
									case 2:
/* printf("extARCCv=%d,extARCCv=%d,A.ARCCv*extARCCsign=%d,A.ARCCspeed=%d\n",extARCCv,extARCCv,A.ARCCv*extARCCsign,A.ARCCspeed)

; */
/* 本当はこれを使わないとマズイが...ちと訳あって下のやつを使ってます。
										bresenham(extARCCv,extARCCv-A.ARCCv*extARCCsign,
											A.ARCCspeed * 2,
											&extARCCdelta,&extARCCcorrect,&extARCCsign);
*/
										extARCCdelta = -extARCCdelta;
										extARCCsign = -extARCCsign;

										extARCCtime += (A.ARCCspeed << 1);
										break;
									case 3:
										A.ARCCmode = 0; /* もう波形は動かない */
										Acond = 0;
										break;
								}
							}
							if (A.ARCCmode) {
								WORD i;
								i = extARCCv + extARCCdelta;
								extARCCcur += extARCCcorrect;
								if (extARCCcur > 0xFF) {
									extARCCcur -= 0x100;
									i += extARCCsign;
								}
								if (i > 127) {
									i = 127;
								} else if (i < 0) {
									i = 0;
								}
								extARCCv = i;
							}
							break;
						case 1:		/* 矩形波 */
							if ( extARCCc >= (A.ARCCspeed << 1) * tempARCC ) {
								WORD i;
								MTrk += ARCCchg(MTrk,gate_old,A.ARCCc,extARCCv,trk);
								if ( (++tempARCC) & 1 ) {
									i = extARCCv + A.ARCCv;
								} else {
									i = extARCCv - A.ARCCv;
								}
								if (i > 127) {
									i = 127;
								} else if (i < 0) {
									i = 0;
								}
								extARCCv = i;
							}
							if (tempARCC == 0) {
								if (A.ARCCv > 0) {
									WORD i = A.ARCCn - A.ARCCv;
									if (i > 127) {
										i = 127;
									} else if (i < 0) {
										i = 0;
									}
									extARCCv = i;
								} else
									extARCCv = A.ARCCn;
							}
							break;
						default:		/* ユーザー登録波形 */
							if ( tempARCC >= 0 && extARCCc >= extARCCtime ) {
								WORD i;
								if ( A.ARCCtype && tempARCC < wavedatanum[A.ARCCtype] ) {
									/* reject bend in case (UserWave && 1shot(done) && TIE) */
									if (++ARCCspc >= ABspc || now == final) {
										ARCCspc = 0;
										MTrk += ARCCchg(MTrk,gate_old,
											A.ARCCc,extARCCv,trk);
/* printf("[ev=%d]",extARCCv); */
									}
								}
/* printf("[t=%d]",tempARCC); */
								i = (A.ARCCv > 0)?
									A.ARCCn + wavetable[A.ARCCtype][tempARCC] :
									A.ARCCn - wavetable[A.ARCCtype][tempARCC];
								if (i > 127) {
									i = 127;
								} else if (i < 0) {
									i = 0;
								}
								extARCCv = i;		/* for overflow */
								extARCCtime += A.ARCCspeed;
/* printf("[i=%d]",i); */
/* printf("{j=%d] ",tempARCC); */
								if ( ++tempARCC >= wavedatanum[A.ARCCtype] ) {
									switch (wavelooptype[A.ARCCtype]) {
										case 0:	/* ワンショット */
											A.ARCCmode = 0; /* もう波形変化なし */
											Acond = 0;
											break;
										case 1:	/* リピート */
											tempARCC = wavelooppoint[A.ARCCtype];
												/* ループポイントから */
											break;
										case 2:	/* オルタニティブ */
											tempARCC = -tempARCC + 2;
											break;
									}
								}
							} else if ( tempARCC < 0 && extARCCc >= extARCCtime ) {
								WORD i;
								if (++ARCCspc >= ABspc || now == final) {
									ARCCspc = 0;
									MTrk += ARCCchg(MTrk,gate_old,
										A.ARCCc,extARCCv,trk);
								}
								i = A.ARCCn + wavetable[A.ARCCtype][-tempARCC];
								if (i > 127) {
									i = 127;
								} else if (i < 0) {
									i = 0;
								}
								extARCCv = i;
								tempARCC++;	/* オルタニティブ:戻る時の処理 */
								extARCCtime += A.ARCCspeed;
							}
							break;
					}
					extARCCc++;
				}
			}
		}
		if (F->sign) {				/* フェードアウト処理 */
			MTrk += fadeout(MTrk,gate_old,F,vol,trk,ID,runstatus);
			if ( (F->volcor <= 0) && (F->sign == -1) ) {
				(*gate_old) += final - now;
				now = final + 1;
			}
		}
		(*gate_old)++;
	}
	eMOD = -eMOD;
	eARC = -eARC;
	eAFT = -eAFT;
	M.Mdepth = Mdepth_bak;		/* 拡張の1/8で書き換えたので、戻す */
	M.Mdelay = Mdelay_bak;
	A.ARCCv  = ARCCv_bak;
	A.ARCCdelay = ARCCdelay_bak;

	return MTrk - MTrk_;
}



/* ========================
     ポルタメント中の処理
   ======================== */

DWORD portament(UBYTE *MTrk,DWORD *gate_old,PORTDAT port,DWORD *cor,
		WORD *bend,WORD *port_now,WORD *special_tie,WORD *extMOD_now,BYTE ABspc,DWORD trk)
{
	UBYTE *MTrk_ = MTrk;
	static BYTE space;

	if (!ABspc) space = 0;
	    else {
		if (++space >= ABspc) {
			MTrk += bendchg(MTrk,gate_old,*bend,
					*port_now,*special_tie,*extMOD_now,trk);
			space = 0;
		}
		*port_now += port.delta;
		*cor += port.correct;
		if (*cor > 0xFF) {
			*cor      -= 0x100;
			*port_now += port.sign;
		}
	}
	return MTrk - MTrk_;
}


/* ========================
     フェードアウトの処理
   ======================== */

DWORD fadeout(UBYTE *MTrk,DWORD *gate_old,FADEDAT *F,
		DWORD vol,DWORD trk,UBYTE ID[4],BYTE runstatus)
{
	/* static int fadecor; */
	UBYTE *MTrk_ = MTrk;

	if (F->delay > 0) {
		(F->delay)--;
	} else {
		F->volcor += F->delta;
		F->cor    += F->correct;
		if (F->cor > 0xFF) {
			/* DWORD j = (vol * F->volcor) >> 7; */
			F->cor -= 0x100;
			F->volcor += F->sign;
			if (F->volcor > 128) {
				F->volcor = 128;
			/*  else if (F->volcor<0) F->volcor=0; */
			} else {
				DWORD i = ((F->volcor)*vol) >> 7;
				if (i > 127) {
					i = 127;
				} else if (i < 0) {
					i = 0;
				}
				if (!F->target) {
					if ( volchk() ) MTrk += volchg(MTrk,gate_old,i,trk);
				} else {
					UBYTE data[4] = {0,0,0,0};
					if (ID[0] == 0x41) {	/* Roland */
						switch (ID[2]) {
							case 0x16:	/* MT32 alltrk fadein/out */
								data[0] = 0x10;
								data[2] = 0x16;
								data[3] = F->volcor;
								MTrk += put_ex(MTrk,gate_old,ID,
										data,4,1,runstatus);
								break;
							case 0x42:	/* GS alltrk fadein/out */
							case 0x45:
								data[0] = 0x40;
								data[2] = 0x04;
								data[3] = F->volcor;
								MTrk += put_ex(MTrk,gate_old,ID,
										data,4,1,runstatus);
								break;
							default:
								break;
						}
					} else if (ID[0] == 0x43) {	/* YAMAHA */
								data[0] = 0x00;
								data[2] = 0x04;
								data[3] = F->volcor;
								MTrk += put_ex(MTrk,gate_old,ID,
										data,4,2,runstatus);
								/* break; */
					}
				}
			}
		}
	}

	return MTrk - MTrk_;
}


/* =============
     bresenham
   ============= */

void bresenham(DWORD start,DWORD end,DWORD delta,WORD *adding,UBYTE *correct,BYTE *sign)
{
	DWORD i = end - start , j;

	*sign = (i >= 0)?  1 : -1;
	*adding = i / delta;
	j = i % delta;
	j = abs(j);
	j <<= 8;	/* j *= 256 */
	*correct = j / delta;
	if (j % delta) (*correct)++;
}


/* ====================================================
     外部でbendを変更した時、それをkeyonoff.cに伝える
   ==================================================== */

void bend_old_chg(WORD newbend)
{
	bend_old = newbend;
}


/* ====================================================
     外部でARCCを変更した時、それをkeyonoff.cに伝える
   ==================================================== */

void arcc_old_chg(BYTE newarcc,UBYTE tie)
{
	extARCCc = tempARCC = extARCCtime = 0;
	extARCCcur = 0;
	extARCCv = newarcc;
	/* extARCCv = 0; */
	if (!tie) {
		KEYON2 = 0;
	}
	nowARCC = total;
}


/* ==========================================================
     外部でmodulationを変更した時、それをkeyonoff.cに伝える
   ========================================================== */

/* void mod_old_chg(WORD newmod,UBYTE tie) */
void mod_old_chg(UBYTE tie)
{
	extMODc = tempMOD = extMODtime = 0;
	extMODcur = 0;
	/* extMODv = newmod; */
	if (!tie) {
		KEYON2 = 0;
	}
	nowMOD = total;
}


/* ======================================
     R/@wの切り替えをkeyonoff.cに伝える
   ====================================== */
void R_w_chg(BYTE r)
{
	R_old = r;			/* 直前に演奏したのは休符か@wか */
}



/* ===========================================
     KEYON時、必要ならベンドのリセットをする
   =========================================== */

#ifdef AAA
int bendreset(unsigned char *MTrk,int *bend,int portsign,
		int *port_now, int *special_tie, int *extMOD_now,
		int *gate_old,int trk)
{
	int MTrk_ = 0;

#ifdef AAA
	if (*bend != ( portsign? bfirst : bend_old )) {
		*bend = portsign? bfirst : bend_old;	/* ベンドを戻す */
	}
#endif
	MTrk_ = bendchg(MTrk,gate_old,*bend,*port_now,
			*special_tie,*extMOD_now,trk);

	return MTrk_;
}
#endif

#ifdef AAA
/* ========================================
   「モジュレーションonの時、keyonまで
     モジュレーション動作保留」flagの設定
   ======================================== */

void mod_reset(unsigned char tie)
{
	if (!tie) {
		KEYON2 = 0;
	}
}
#endif
