#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <file_dlg.h>
#include <egb.h>
#include <mos.h>
#include <snd.h>
#include <math.h>
#include "wavhime.h"
#include "otolib.h"
#include "fft.h"

/* fade int & out */
int	fadeDialogId = -1 ;
int	fadeOkBtnId = -1 ;
int	fadePlayBtnId = -1 ;
int	fadeUndoBtnId = -1 ;
int	fadeFixBtnId = -1 ;
int	fadeCanBtnId = -1 ;
int	fadeMesId[37] = -1 ;
int	fadeSubDialogId = -1 ;
int	fadeNumId[4] = -1 ;
int	fadeBtnId[3] = -1 ;
int	fadeInfBtnId = -1 ;

/* trim */
int	trimDialogId = -1 ;
int	trimSubDialogId = -1 ;
int	trimMesId[21] = -1 ;
int	trimNumId[2] = -1 ;
int	trimOkBtnId = -1 ;
int	trimPlayBtnId = -1 ;
int	trimUndoBtnId = -1 ;
int	trimFixBtnId = -1 ;
int	trimInfBtnId = -1 ;
int	trimCanBtnId = -1 ;

/* fft */
int	fftDialogId = -1 ;
int	fftOkBtnId = -1 ;
int	fftInfBtnId = -1 ;
int	fftMesId[61] = -1 ;
int	fftCanBtnId = -1 ;
int	fftFileNameMesId = -1 ;
int	fftSubDialogId = -1 ;
int	fftChBtnId[2] = -1 ;
int	fftTimeNumId = -1 ;
int	fftSubDialogId2 = -1 ;
int	fftWaveBaseMesId = -1 ;
int	fftScaleMesId = -1 ;
int	fftSubDialogId3 = -1 ;
int	fftFreqMesId[2] = -1 ;
int	fftSpecBaseMesId = -1 ;
int	fftWinBtnId[4] = -1 ;
int	fftNBtnId[3] = -1 ;
int	fftFreqBtnId[3] = -1 ;
int	fftMulNumId = -1 ;
int	fftMulScrId = -1 ;
int	fftPointNumId = -1 ;

/* FADE IN & OUT */

static fadeMode = 0 ;

int	sndEffectFade()
{
	MMI_SendMessage( fadeDialogId, MM_ATTACH, 1, MMI_GetBaseObj() ) ;

	MTL_setFlagObj( fadeBtnId[fadeMode], (MS_UNSELECT | MS_TOGGLE) ) ;

	MMI_SendMessage( fadeDialogId, MM_SHOW, 0 ) ;	/* 全体を見せる */

	MMI_ExecSystem() ;		/* Dialog表示へ･･･イベントループ */

	MMI_SendMessage( fadeDialogId, MM_ERASE, 0 ) ;
	MMI_SendMessage( fadeDialogId, MM_DETACH, 0 ) ;

	return NOERR ;
}

/*	initDataIOTFAD:fadeOkBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fadeOkchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int var, min, max, delta, ptColumn ;
	int f ;
	int i, num[4] ;
	int ret ;
	int bit, kd, sz ;

	SetMouse16( 81, 0xf, 0x8 ) ;	/* マウスカーソルをウエイト表示 */
	setMsgColor( fadeMesId[0], EXE_COLOR ) ;

	if( tempFileCount == 0 )	/* テンポラリファイルの数が0なら */
	{
		ret = NO_DATA ;
		goto END_00 ;
	}
	else if( tempFileCount == 1 )	/* テンポラリファイルの数が1なら */
	{
		if( (ret = temp1_to_temp2()) != NOERR )		/* temp1をtemp2へ */
			goto END_00 ;
	}

	if( (ret = readWavDataInfo( &f, &bit, &kd, &sz )) != NOERR )
		goto END_00 ;

	for( i=0 ; i<4 ; i++ )
	{
		MMI_SendMessage( fadeNumId[i], MM_GETNUMBOX, 5,
							&var, &min, &max, &delta, &ptColumn ) ;
		num[i] = var * f / 100 ;
	}

	ret = fadeInFadeOut( num[0], num[1], num[2], num[3], fadeMode ) ;

END_00: ;
	setMsgColor( fadeMesId[0], MOJI_COLOR ) ;
	SetMouse16( 80, 0xf, 0x8 ) ;	/* マウスカーソルを元に */

	if( ret )
		errorCheck( ret ) ;

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */

	return NOERR ;
}

/*	initDataIOTFAD:fadePlayBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fadePlay(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	setMsgColor( fadeMesId[1], EXE_COLOR ) ;

	sndPlay() ;

	setMsgColor( fadeMesId[1], MOJI_COLOR ) ;

	return NOERR ;
}

/*	initDataIOTFAD:fadeUndoBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fadeUndo(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	setMsgColor( fadeMesId[2], EXE_COLOR ) ;

	unDo() ;

	setMsgColor( fadeMesId[2], MOJI_COLOR ) ;

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */

	return NOERR ;
}

/*	initDataIOTFAD:fadeFixBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fadeFix(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	delTemp2() ;
	return NOERR ;
}

/*	initDataIOTFAD:fadeInfBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fadeInf(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	/* ダイアログを使えないようにする */
	MTL_setAtrObj( fadeDialogId, MS_DSPONLYL40 ) ;

	sndInf() ;

	/* ダイアログを使えるように戻す */
	MTL_resetAtrObj( fadeDialogId, (~MS_DSPONLYL40) ) ;

	return NOERR ;
}

/*	initDataIOTFAD:fadeCanBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fadeCanchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	MMI_SetHaltFlag( TRUE ) ;
	return NOERR ;
}

/*	initDataIOTFAD:fadeBtnId[0]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIOTFAD:fadeBtnId[1]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIOTFAD:fadeBtnId[2]:MJ_TICONL40の呼び出し関数	*/
int	fadeModeSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int i ;

	for( i=0 ; i<3 ; i++ )
	{
		if( kobj == fadeBtnId[i] )
		{
			MTL_setFlagObj( fadeBtnId[i], MS_UNSELECT ) ;
			MTL_resetFlagObj( fadeBtnId[fadeMode],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
			MMI_SendMessage( fadeBtnId[fadeMode], MM_SHOW, 0 ) ;
			fadeMode = i ;
		}
	}
	return NOERR ;
}


/* trimming */

int	sndEffectTrim()
{
	MMI_SendMessage( trimDialogId, MM_ATTACH, 1, MMI_GetBaseObj() ) ;
	MMI_SendMessage( trimDialogId, MM_SHOW, 0 ) ;	/* 全体を見せる */

	MMI_ExecSystem() ;		/* Dialog表示へ･･･イベントループ */

	MMI_SendMessage( trimDialogId, MM_ERASE, 0 ) ;
	MMI_SendMessage( trimDialogId, MM_DETACH, 0 ) ;

	return NOERR ;
}

/*	initDataIWVTRM:trimOkBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	trimOkchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int var, min, max, delta, ptColumn ;
	int f, bit, kd, sz ;
	int i, num[2] ;
	int ret ;

	SetMouse16( 81, 0xf, 0x8 ) ;	/* マウスカーソルをウエイト表示 */
	setMsgColor( trimMesId[0], EXE_COLOR ) ;

	if( tempFileCount == 0 )	/* テンポラリファイルの数が0なら */
	{
		ret = NO_DATA ;
		goto END_00 ;
	}
	else if( tempFileCount == 1 )	/* テンポラリファイルの数が1なら */
	{
		if( (ret = temp1_to_temp2()) != NOERR )		/* temp1をtemp2へ */
			goto END_00 ;
	}

	if( (ret = readWavDataInfo( &f, &bit, &kd, &sz )) != NOERR )
		goto END_00 ;

	for( i=0 ; i<2 ; i++ )
	{
		MMI_SendMessage( trimNumId[i], MM_GETNUMBOX, 5,
							&var, &min, &max, &delta, &ptColumn ) ;
		num[i] = ( (double)var ) * f / 100 ;
	}

	ret = sndTrimming( num[0], num[1] ) ;

END_00: ;
	setMsgColor( trimMesId[0], MOJI_COLOR ) ;
	SetMouse16( 80, 0xf, 0x8 ) ;	/* マウスカーソルを元に */

	if( ret > 0 )
		errorCheck( ret ) ;
	else if( ret == -1 )
	{
		unDo() ;
		errorCheck2( "この設定では音声データが消滅します｡" ) ;
	}

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */

	return NOERR ;
}

/*	initDataIWVTRM:trimPlayBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	trimPlay(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	setMsgColor( trimMesId[1], EXE_COLOR ) ;

	sndPlay() ;

	setMsgColor( trimMesId[1], MOJI_COLOR ) ;

	return NOERR ;
}

/*	initDataIWVTRM:trimUndoBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	trimUndo(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	setMsgColor( trimMesId[2], EXE_COLOR ) ;

	unDo() ;

	setMsgColor( trimMesId[2], MOJI_COLOR ) ;

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */

	return NOERR ;
}

/*	initDataIWVTRM:trimFixBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	trimFix(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	delTemp2() ;
	return NOERR ;
}

/*	initDataIWVTRM:trimInfBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	trimInf(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	/* ダイアログを使えないようにする */
	MTL_setAtrObj( trimDialogId, MS_DSPONLYL40 ) ;

	sndInf() ;

	/* ダイアログを使えるように戻す */
	MTL_resetAtrObj( trimDialogId, (~MS_DSPONLYL40) ) ;

	return NOERR ;
}

/*	initDataIWVTRM:trimCanBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	trimCanchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	MMI_SetHaltFlag( TRUE ) ;
	return NOERR ;
}


/* fft */

static int fftChMode = 0 ;
static int fftNMode = 1 ;
static int fftWinMode = 1 ;
static int fftMul = 1 ;
static int fftFreqMode = 0 ;

static int fftFreq = 44100 ;
static int fftOffset = 0 ;

int	sndEffectFft( char *name )
{
	int bit, kd, sz ;
	int var, min, max, delta, ptColumn ;
	int time ;

	if( ( readWavDataInfo1( &fftFreq, &bit, &kd, &sz ) ) != NOERR )
		return NOERR ;

	MMI_SendMessage( fftDialogId, MM_ATTACH, 1, MMI_GetBaseObj() ) ;

	MMI_SendMessage( fftFileNameMesId , MM_SETMSG , 1 , name ) ;
	MTL_setFlagObj( fftChBtnId[fftChMode], (MS_UNSELECT | MS_TOGGLE) ) ;
	MTL_setFlagObj( fftNBtnId[fftNMode], (MS_UNSELECT | MS_TOGGLE) ) ;
	MTL_setFlagObj( fftWinBtnId[fftWinMode], (MS_UNSELECT | MS_TOGGLE) ) ;
	MTL_setFlagObj( fftFreqBtnId[fftFreqMode], (MS_UNSELECT | MS_TOGGLE) ) ;

	// オフセット調節
	time = ( (double)fftOffset ) / fftFreq * 100 ;
	MMI_SendMessage( fftTimeNumId, MM_GETNUMBOX, 5,
						&var, &min, &max, &delta, &ptColumn ) ;
	MMI_SendMessage( fftTimeNumId, MM_SETNUMBOX, 5,
						time, min, max, delta, ptColumn ) ;

	MMI_SendMessage( fftDialogId, MM_SHOW, 0 ) ;	/* 全体を見せる */

	MMI_ExecSystem() ;		/* Dialog表示へ･･･イベントループ */

	MMI_SendMessage( fftDialogId, MM_ERASE, 0 ) ;
	MMI_SendMessage( fftDialogId, MM_DETACH, 0 ) ;

	return NOERR ;
}

/*	initDataIWVFFT:fftOkBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fftOkchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int ret ;

	SetMouse16( 81, 0xf, 0x8 ) ;	/* マウスカーソルをウエイト表示 */
	setMsgColor( fftMesId[0], EXE_COLOR ) ;

	if( tempFileCount == 0 )	/* テンポラリファイルの数が0なら */
	{
		ret = NO_DATA ;
		goto END_00 ;
	}

	else if( tempFileCount == 1 )	/* テンポラリファイルの数が1なら */
	{
		if( (ret = temp1_to_temp2()) != NOERR )		/* temp1をtemp2へ */
			goto END_00 ;
	}

	ret = sndFft( fftOffset, fftChMode, fftNMode+8, fftWinMode,
											 fftMul, fftFreqMode ) ;

END_00: ;

	unDo() ;

	setMsgColor( fftMesId[0], MOJI_COLOR ) ;
	SetMouse16( 80, 0xf, 0x8 ) ;	/* マウスカーソルを元に */

	if( ret > 0 )
		errorCheck( ret ) ;
	else if( ret == -1 )
	{
		errorCheck2( "観測点がデータの外にでます｡" ) ;
	}
	else if( ret == -ILLIGAL_DATA )
	{
		errorCheck2( "規格外のサンプリングレートです｡" ) ;
	}

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */

	return NOERR ;
}

/*	initDataIWVFFT:fftInfBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fftInf(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	/* ダイアログを使えないようにする */
	MTL_setAtrObj( fftDialogId, MS_DSPONLYL40 ) ;

	sndInf() ;

	/* ダイアログを使えるように戻す */
	MTL_resetAtrObj( fftDialogId, (~MS_DSPONLYL40) ) ;

	return NOERR ;
}

/*	initDataIWVFFT:fftCanBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	fftCanchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	sndFft_end() ;		// メモリ解放

	MMI_SetHaltFlag( TRUE ) ;
	return NOERR ;
}

/*	initDataIWVFFT:fftChBtnId[0]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftChBtnId[1]:MJ_TICONL40の呼び出し関数	*/
int	fftChSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int i ;

	for( i=0 ; i<2 ; i++ )
	{
		if( kobj == fftChBtnId[i] )
		{
			MTL_setFlagObj( fftChBtnId[i], MS_UNSELECT ) ;
			MTL_resetFlagObj( fftChBtnId[fftChMode],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
			MMI_SendMessage( fftChBtnId[fftChMode], MM_SHOW, 0 ) ;
			fftChMode = i ;
		}
	}
	return NOERR ;
}

/*	initDataIWVFFT:fftNBtnId[0]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftNBtnId[1]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftNBtnId[2]:MJ_TICONL40の呼び出し関数	*/
int	fftNSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int i ;

	for( i=0 ; i<3 ; i++ )
	{
		if( kobj == fftNBtnId[i] )
		{
			MTL_setFlagObj( fftNBtnId[i], MS_UNSELECT ) ;
			MTL_resetFlagObj( fftNBtnId[fftNMode],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
			MMI_SendMessage( fftNBtnId[fftNMode], MM_SHOW, 0 ) ;
			fftNMode = i ;
		}
	}
	return NOERR ;
}

/*	initDataIWVFFT:fftWinBtnId[0]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftWinBtnId[1]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftWinBtnId[2]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftWinBtnId[3]:MJ_TICONL40の呼び出し関数	*/
int	fftWinSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int i ;

	for( i=0 ; i<4 ; i++ )
	{
		if( kobj == fftWinBtnId[i] )
		{
			MTL_setFlagObj( fftWinBtnId[i], MS_UNSELECT ) ;
			MTL_resetFlagObj( fftWinBtnId[fftWinMode],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
			MMI_SendMessage( fftWinBtnId[fftWinMode], MM_SHOW, 0 ) ;
			fftWinMode = i ;
		}
	}
	return NOERR ;
}

/*	initDataIWVFFT:fftMulScrId:MJ_SCRLL40の呼び出し関数	*/
int	fftMulSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int var, min, max, len, page ;
	int var2, min2, max2, delta2, ptColumn2 ;

	MMI_SendMessage( kobj, MM_GETSCROLL, 5,
										&var, &min, &max, &len, &page ) ;

	fftMul = 1 << var ;

	MMI_SendMessage( fftMulNumId, MM_GETNUMBOX, 5,
							&var2, &min2, &max2, &delta2, &ptColumn2 ) ;
	MMI_SendMessage( fftMulNumId, MM_SETNUMBOX, 5,
							fftMul, min2, max2, delta2, ptColumn2 ) ;
	MMI_SendMessage( fftMulNumId, MM_SHOW, 0 ) ;

	sndFftWave( fftMul ) ;

	return NOERR ;
}

/*	initDataIWVFFT:fftFreqBtnId[0]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftFreqBtnId[1]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIWVFFT:fftFreqBtnId[2]:MJ_TICONL40の呼び出し関数	*/
int	fftFreqSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int i ;

	for( i=0 ; i<3 ; i++ )
	{
		if( kobj == fftFreqBtnId[i] )
		{
			MTL_setFlagObj( fftFreqBtnId[i], MS_UNSELECT ) ;
			MTL_resetFlagObj( fftFreqBtnId[fftFreqMode],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
			MMI_SendMessage( fftFreqBtnId[fftFreqMode], MM_SHOW, 0 ) ;
			fftFreqMode = i ;
		}
	}

	sndFftSpecDsp( fftFreqMode ) ;

	return NOERR ;
}

/*	initDataIWVFFT:fftTimeNumId:MJ_NUMBOXL40の呼び出し関数	*/
/*	initDataIWVFFT:fftPointNumId:MJ_NUMBOXL40の呼び出し関数	*/
int	fftOffsetSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int var, min, max, delta, ptColumn ;
	int var2, min2, max2, delta2, ptColumn2 ;
	int time ;

	if( kobj == fftTimeNumId )
	{
		MMI_SendMessage( fftTimeNumId, MM_GETNUMBOX, 5,
						&var, &min, &max, &delta, &ptColumn ) ;

		fftOffset = ( (double)var ) / 100 * fftFreq ;

		MMI_SendMessage( fftPointNumId, MM_GETNUMBOX, 5,
						&var2, &min2, &max2, &delta2, &ptColumn2 ) ;
		MMI_SendMessage( fftPointNumId, MM_SETNUMBOX, 5,
						fftOffset, min2, max2, delta2, ptColumn2 ) ;
		MMI_SendMessage( fftPointNumId, MM_SHOW, 0 ) ;
	}
	else
	{
		MMI_SendMessage( fftPointNumId, MM_GETNUMBOX, 5,
						&var2, &min2, &max2, &delta2, &ptColumn2 ) ;

		fftOffset = var2 ;
		time = ( (double)var2 ) / fftFreq * 100 ;

		MMI_SendMessage( fftTimeNumId, MM_GETNUMBOX, 5,
						&var, &min, &max, &delta, &ptColumn ) ;
		MMI_SendMessage( fftTimeNumId, MM_SETNUMBOX, 5,
						time, min, max, delta, ptColumn ) ;
		MMI_SendMessage( fftTimeNumId, MM_SHOW, 0 ) ;
	}

	return NOERR ;
}





/* 実行ルーチン */
/* 引数はデータ数 */
static int fadeInFadeOut( int num0, int num1, int num2, int num3, int mode )
{
	int i ;
	int x1, x2, y1, y2, ret ;
	int fq, bit, kd, sz ;
	int sndLength ;
	int p0, p1, p2, p3, div ;

	if( (ret = readWavData_init( &fq, &bit, &kd, &sz )) != NOERR )
	{
		return ret ;
	}

	sndLength = sz / ( kd * bit/8 ) ;
	if( kd == 1 )mode = 0 ;

	if( (ret = writeWavData_init( fq, bit, kd, sz )) != NOERR )
	{
		readWavData_end() ;
		return ret ;
	}

	p0 = num0 ;
	p1 = p0 + num1 ;
	p3 = sndLength - num3 ;
	p2 = p3 - num2 ;

	for( i=0 ; i<sndLength ; i++ )
	{
		if( (ret = readWavData( i, &x1, &x2 )) != NOERR )
		{
			writeWavData_end() ;
			return ret ;
		}

		if( i < p0 )
		{
			y1 = 0 ;
			y2 = 0 ;
		}
		else if( i < p1 )
		{
			div = num1 >> 8 ;
			if( div == 0 )div = 1 ;
			y1 = x1 * (( i - p0 ) >> 8) / div ;
			y2 = x2 * (( i - p0 ) >> 8) / div ;
		}
		else
		{
			y1 = x1 ;
			y2 = x2 ;
		}

		if( i > p3 )
		{
			y1 = 0 ;
			y2 = 0 ;
		}
		else if( i > p2 )
		{
			div = num2 >> 8 ;
			if( div == 0 )div = 1 ;
			y1 = y1 * (( p3 - i ) >> 8) / div ;
			y2 = y2 * (( p3 - i ) >> 8) / div ;
		}

		switch( mode )
		{
		case 0:
				x1 = y1 ;
				x2 = y2 ;
				break ;
		case 1:
				x1 = y1 ;
				break ;
		case 2:
				x2 = y2 ;
				break ;
		}

		if( (ret = writeWavData( x1, x2 )) != NOERR )
		{
			readWavData_end() ;
			return ret ;
		}
	}
	writeWavData_end() ;
	readWavData_end() ;

	return NOERR ;
}

static int sndTrimming( int num0, int num1 )
{
	int i ;
	int x1, x2, ret ;
	int fq, bit, kd, sz ;
	int sndLength ;

	if( (ret = readWavData_init( &fq, &bit, &kd, &sz )) != NOERR )
	{
		return ret ;
	}

	sndLength = sz / ( kd * bit/8 ) - num0 - num1 ;
	if( sndLength <= 0 )
	{
		readWavData_end() ;
		return -1 ;
	}

	if( (ret = writeWavData_init( fq, bit, kd, sndLength*kd*bit/8 )) != NOERR )
	{
		readWavData_end() ;
		return ret ;
	}

//	for( i=0 ; i<(sndLength+num0) ; i++ )
	for( i=num0 ; i<(sndLength+num0) ; i++ )
	{
		if( (ret = readWavData( i, &x1, &x2 )) != NOERR )
		{
			writeWavData_end() ;
			return ret ;
		}

//		if( i >= num0 )
//		{
			if( (ret = writeWavData( x1, x2 )) != NOERR )
			{
				readWavData_end() ;
				return ret ;
			}
//		}
	}
	writeWavData_end() ;
	readWavData_end() ;

	return NOERR ;
}

// ワーク & バッファ
static char *fftBuffer ;
static double *fftReal, *fftImag ;
static double *fftWin ;
static char *fftWork ;
static int *fftData ;

static int sndFftDataFlg = 0 ;	/* 1:ワーク&データ確保 0:なにもない状態 */
static int sndFftFreq ;			/* サンプリングレート */
static int sndFftEx ;			/* 2のNじょう */

static int sndFft( int ofst, int chMode, int ex, int winMode,
												 int mul, int dspMode )
{
	int i ;
	int x1, x2, ret ;
	int fq, bit, kd, sz ;
	int sndLength ;
	int length, size ;

	sndFftEx = ex ;
	length = 1 << ex ;

	// ワークエリアの確保
	if( sndFftDataFlg )
		TL_free( fftBuffer ) ;
	sndFftDataFlg = 0 ;

	size = length*sizeof( double )* 3 + sizeof( double )*length*3
	     + length*sizeof( int ) ;

	if( (fftBuffer = (char *)TL_malloc( size )) == NULL )
		return OUT_OF_MEMORY ;

	if(TL_checkMemory(1) * 4096 < MinMem)	/*	必要とする動作メモリのcheck	*/
	{
		TL_free( fftBuffer ) ;
		return OUT_OF_MEMORY ;
	}

	fftReal = (double *)fftBuffer ;
	fftImag = fftReal + length ;
	fftWin  = fftImag + length ;
	fftWork = (char *)(fftWin + length) ;
	fftData = (int *)( fftWork + sizeof( double )*length*3 ) ;

	if( (ret = readWavData_init( &fq, &bit, &kd, &sz )) != NOERR )
	{
		TL_free( fftBuffer ) ;
		return ret ;
	}

	if( (fq != 44100) && (fq != 22050) && (fq != 11025) )
	{
		readWavData_end() ;
		TL_free( fftBuffer ) ;
		MMI_SendMessage( fftSubDialogId2, MM_SHOW, 0 ) ;
		MMI_SendMessage( fftSubDialogId3, MM_SHOW, 0 ) ;
        return -ILLIGAL_DATA ;		// 規格外のサンプリングレート
    }

	if( kd == 1 )chMode = 0 ;
	sndFftFreq = fq ;

	sndLength = sz / ( kd * bit/8 ) - ofst ;
	if( sndLength <= 0 )
	{
		readWavData_end() ;
		TL_free( fftBuffer ) ;
		MMI_SendMessage( fftSubDialogId2, MM_SHOW, 0 ) ;
		MMI_SendMessage( fftSubDialogId3, MM_SHOW, 0 ) ;
		return -1 ;
	}

	for( i=0 ; i<length ; i++ )
	{
		if( (ret = readWavData( i + ofst, &x1, &x2 )) != NOERR )
		{
			writeWavData_end() ;
			TL_free( fftBuffer ) ;
			return ret ;
		}

		switch( chMode )
		{
		case 0:
				fftData[i] = x1 ;
				break ;
		case 1:
				fftData[i] = x2 ;
				break ;
		}
	}
	sndFftDataFlg = 1 ;

	sndFftWave( mul ) ;
	sndFftSpec( winMode ) ;
	sndFftSpecDsp( dspMode ) ;

	readWavData_end() ;
	return NOERR ;
}

static int sndFft_end()
{
	if( sndFftDataFlg )
		TL_free( fftBuffer ) ;
	sndFftDataFlg = 0 ;
	return NOERR ;
}

static int sndFftWave( int mul )
{
	extern char	*guiEgbPtr ;			/*	EGB のワークアドレス	*/

	HYPER hyp ;
	int x0, y0 ;
	int length ;
	int i, d ;
	static char *dsp[] = {
								"0      8      16msec.",
								"0      4      8msec.",
								"0      2      4msec.",
								"0      1      2msec.",
								"0     0.5     1msec."
							} ;
	char para[ 2 + 4*512 ] ;

	if( sndFftDataFlg == 0 )
		return NOERR ;

	length = 1 << sndFftEx ;

	MMI_SendMessage( fftWaveBaseMesId, MM_GETHYPER, 1, &hyp ) ;
	x0 = hyp.fr.lupx ;
	y0 = hyp.fr.lupy ;

	switch( sndFftEx )
	{
	case 8:	WORD( para ) = 256 ;
			for( i=0 ; i<256 ; i++ )
			{
				WORD( para + 2 + 4*i ) = x0 + i*2 ;
				d = - fftData[i]*50*mul / 32768 ;
				if( d < -50 )d = -50 ;
				if( d >  50 )d =  50 ;
				WORD( para + 2 + 4*i + 2 ) = y0 - d ;
			}
			break ;
	case 9:	WORD( para ) = 512 ;
			for( i=0 ; i<512 ; i++ )
			{
				WORD( para + 2 + 4*i ) = x0 + i ;
				d = - fftData[i]*50*mul / 32768 ;
				if( d < -50 )d = -50 ;
				if( d >  50 )d =  50 ;
				WORD( para + 2 + 4*i + 2 ) = y0 - d ;
			}
			break ;
	case 10: WORD( para ) = 512 ;
			for( i=0 ; i<512 ; i++ )
			{
				WORD( para + 2 + 4*i ) = x0 + i ;
				d = - fftData[i*2]*50*mul / 32768 ;
				if( d < -50 )d = -50 ;
				if( d >  50 )d =  50 ;
				WORD( para + 2 + 4*i + 2 ) = y0 - d ;
			}
			break ;
	}

//	switch( sndFftFreq / 11025 * length / 256 )
	switch( sndFftFreq / 11025 * 1024 / length )
	{
	case 1 :
		MMI_SendMessage( fftScaleMesId, MM_SETMSG, 1, dsp[0] ) ;
		break ;
	case 2 :
		MMI_SendMessage( fftScaleMesId, MM_SETMSG, 1, dsp[1] ) ;
		break ;
	case 4 :
		MMI_SendMessage( fftScaleMesId, MM_SETMSG, 1, dsp[2] ) ;
		break ;
	case 8 :
		MMI_SendMessage( fftScaleMesId, MM_SETMSG, 1, dsp[3] ) ;
		break ;
	case 16 :
		MMI_SendMessage( fftScaleMesId, MM_SETMSG, 1, dsp[4] ) ;
		break ;
	}

	EGB_color(guiEgbPtr,0,15);
	EGB_paintMode(guiEgbPtr,0x222);
	EGB_writeMode(guiEgbPtr,0);

	MG_mosDisp( 0 ) ;
	MMI_SendMessage( fftSubDialogId2, MM_SHOW, 0 ) ;
	EGB_connect(guiEgbPtr,para);
	MG_mosDisp( 1 ) ;

	return NOERR ;
}

static int sndFftSpec( int winMode )
{
	int i ;
	int length ;

	length = 1 << sndFftEx ;

	sndFftWin( winMode, length ) ;

	for( i=0 ; i<length ; i++ )
	{
		fftReal[i] = fftWin[i] * fftData[i] ;
		fftImag[i] = 0 ;
	}

	fft_1( fftWork, fftReal, fftImag, sndFftEx, 1 );

	return NOERR ;
}

static int sndFftWin( int mode, int n )
{
	int i ;

	switch( mode )
	{
	case 0:	for( i=0 ; i<n ; i++ )	// ハニング
			{
				fftWin[i] = .5 - .5 * cos( 2 * _PI * i / n ) ;
			}
			break ;

	case 1:	for( i=0 ; i<n ; i++ )	// ハミング
			{
				fftWin[i] = .54 - .46 * cos( 2 * _PI * i / n ) ;
			}
			break ;

	case 2:	for( i=0 ; i<n ; i++ )	// ブラックマン
			{
				fftWin[i] = .42 - .5 * cos( 2 * _PI * i / n )
							+ .08 * cos( 4 * _PI * i / n ) ;
			}
			break ;

	case 3:	for( i=0 ; i<n ; i++ )	// 方形窓
			{
				fftWin[i] = 1 ;
			}
			break ;
	}

	return NOERR ;
}

static int sndFftSpecDsp( int dspMode )
{
	extern char	*guiEgbPtr ;			/*	EGB のワークアドレス	*/

	HYPER hyp ;
	int x0, y0 ;
	int i, step, total, dspExp ;
	int length ;
	static char *dsp[][2] = {
								{ "10k", "20kHz" },
								{ "5k",  "10kHz" },
								{ "  ",  "5kHz"  }
							} ;
	int max, db[512] ;
	char para[ 2 + 4*512 ] ;

	if( sndFftDataFlg == 0 )
		return NOERR ;

	length = 1 << sndFftEx ;

	for( i=0 ; i<(length >> 1) ; i++ )
	{
		db[i] = log10(fftReal[i] * fftReal[i] + fftImag[i] * fftImag[i]) * 20;
	}		/* スケールの関係からdBの2倍の値を取る */

	max = db[0] ;
	for( i=0 ; i<(length >> 1) ; i++ )
	{
		if( db[i] > max )max = db[i] ;
	}

	MMI_SendMessage( fftSpecBaseMesId, MM_GETHYPER, 1, &hyp ) ;
	x0 = hyp.fr.lupx ;
	y0 = hyp.fr.lupy ;

	dspExp = 1 << dspMode ;
	step = sndFftFreq / 11025 * 128 ;
	step = step * dspExp ;
	total = (length >> 1) ;

	switch( sndFftFreq )
	{
	case 44100:
		total = total / dspExp ;
		break ;
	case 22050:
		if( dspExp >= 4 )
		{
			total = total / 2 ;
		}
		break ;
	case 11025:
		break ;
	}

	WORD( para ) = total ;
	for( i=0 ; i<total ; i++ )
	{
		WORD( para + 2 + 4*i ) = x0 + i * step / (length >> 1) ;
		db[i] = db[i] - max + 159 ;
		if( db[i] > 159 )db[i] = 159 ;
		if( db[i] < 0 )db[i] = 0 ;
		WORD( para + 2 + 4*i + 2 ) = y0 - db[i] ;
	}

	MMI_SendMessage( fftFreqMesId[0], MM_SETMSG, 1, dsp[dspMode][0] ) ;
	MMI_SendMessage( fftFreqMesId[1], MM_SETMSG, 1, dsp[dspMode][1] ) ;

	EGB_color(guiEgbPtr,0,15);
	EGB_paintMode(guiEgbPtr,0x222);
	EGB_writeMode(guiEgbPtr,0);

	MG_mosDisp( 0 ) ;
	MMI_SendMessage( fftSubDialogId3, MM_SHOW, 0 ) ;
	EGB_connect(guiEgbPtr,para);
	MG_mosDisp( 1 ) ;

	return NOERR ;
}







