//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "GlobalUnit.h"
#include "FxDef.h"
#include "AudioTrack.h"
#include "Compose.h"
#include "ContentPanelUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
/***************************************************************************************/
// 全局常量
/***************************************************************************************/
const char 	*g_strEffect[MAX_FX_NUM] = {
				"回声", "失真", "旋转", "混响", "压缩",
				"哇音", "合唱", "均衡", "移相", "变调" },
			*g_strEffectPreset[MAX_FX_NUM][3] = {
				{ "小", "中", "大" }, { "默认", "", "" },
				{ "慢", "中", "快" }, { "小", "中", "大" },
				{ "小", "中", "大" }, { "小", "中", "大" },
				{ "小", "中", "大" }, { "喇叭", "电话", "听筒" },
				{ "小", "中", "大" }, { "默认", "低八度", "高八度" } },
			*g_strEffectParamName[MAX_FX_NUM][6] = {
/*				{ "WetDryMix", "Feedback", "LeftDelay", "RightDelay", "", "" },
				{ "Gain", "Frequency", "Bandwidth", "Edge", "CutOff", "" },
				{ "Rate", "", "", "", "", "" },
				{ "InGain", "ReverbMix", "ReverbTime", "RTRatio", "", "" },
				{ "Gain", "Threshold", "Ratio", "Attack", "Release", "" },
				{ "DryMix", "WetMix", "Feedback", "Rate", "Range", "Frequency" },
				//{ "DryMix", "WetMix", "Feedback", "Rate", "MinDelay", "MaxDelay" },
				{ "WetDryMix", "Depth", "Feedback", "Frequency", "Delay", "" },
				{ "Center", "Bandwidth", "Gain", "", "", "" },
				{ "DryMix", "WetMix", "Feedback", "Rate", "Range", "Frequency" },
*/
				{ "干湿比", "反馈", "左延迟", "右延迟", "", "" },
				{ "增益", "频率", "波段", "边界", "临界值", "" },
				{ "速率", "", "", "", "", "" },
				{ "输入增益", "混响比", "混响时间", "混响速率", "", "" },
				{ "增益", "阀值", "速率", "启动", "释放", "" },
				{ "干声比", "湿声比", "反馈", "速率", "范围", "频率" },
				{ "干湿比", "深度", "反馈", "频率", "延迟", "" },
				{ "中心点", "波段", "增益", "", "", "" },
				{ "干声比", "湿声比", "反馈", "速率", "范围", "频率" },
				{ "半音阶", "", "", "", "", "" } };

const DWORD	 g_aAudioEffectTypes[MAX_FX_NUM] ={
				FX_ECHO, FX_DISTORTION, FX_ROTATE, FX_REVERB, FX_COMPRESSOR,
				FX_WAH, FX_CHORUS, FX_PARAMEQ, FX_PHASER, FX_PITCH }; //音效类型

const float	 g_aEffectParamLimit[MAX_FX_NUM][6][2] = {
				{ {0,100}, {0,100}, {1,2000}, {1,2000}, {0,0}, {0,0} },
				{ {-60,0}, {0,100}, {100,8000}, {100,8000}, {100,8000}, {0,0} },
				{ {0,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} },
				{ {-96,0}, {-96,0}, {0.001,3000}, {0.001,0.999}, {0,0}, {0,0} },
				{ {-60,60}, {-60,0}, {1,20}, {0.01,1000}, {0.01,5000}, {0,0} },
				{ {-2,2}, {-2,2}, {-1,1}, {0.001,9.999}, {0.001,9.999}, {1,999} },
				//{ {-2,2}, {-2,2}, {-1,1}, {1,6000}, {1,6000}, {1,1000} },
				{ {0,100}, {0,100}, {-99,99}, {0,10}, {0,20}, {0,0} },
				{ {80,16000}, {1,36}, {-15,15}, {0,0}, {0,0}, {0,0}  },
				{ {-2,2}, {-2,2}, {-1,1}, {0.001,9.999}, {0.001,9.999}, {1,999} },
				{ {-36,36}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} } };

/***************************************************************************************/
// 全局变量
/***************************************************************************************/
/*PTEffect	//g_aAudioEffects[MAX_FX_NUM],
			//g_aAudioEffects_SVD[MAX_FX_NUM],
			g_aAudioEffects_Clipboard[MAX_FX_NUM];
*/
/***************************************************************************************/
// 全局函数
/***************************************************************************************/
int GetFxPresetCount( int iFxType )
{
	if( iFxType==FX_DISTORTION )
		return 1;

	return 3;
}

void GetFxPreset( int iFxType, int iPreset, float fParams[] )
{
	if( iFxType==FX_ROTATE ){
		if( iPreset==0 ){
			fParams[0] = 0.2;
		}
		else if( iPreset==1 ){
			fParams[0] = 1.0;
		}
		else if( iPreset==2 ){
			fParams[0] = 2.28;
		}
	}
	else if( iFxType==FX_WAH ){
		fParams[0] = 0.5;
		fParams[1] = 1.5;
		fParams[2] = 0.5;

		if( iPreset==0 ){
			fParams[3] = 2;
			fParams[4] = 4.3;
			fParams[5] = 50;
		}
		else if( iPreset==1 ){

			fParams[3] = 5;
			fParams[4] = 5.3;
			fParams[5] = 50;
		}
		else if( iPreset==2 ){
			fParams[3] = 5;
			fParams[4] = 4.3;
			fParams[5] = 500;
		}
	}
	else if( iFxType==FX_PHASER ){
		fParams[0] = 0.999;
		fParams[1] = 0.999;
		fParams[3] = 1;

		if( iPreset==0 ){
			fParams[2] = 0.0;
			fParams[4] = 4.0;
			fParams[5] = 100;
		}
		else if( iPreset==1 ){
			fParams[2] = 0.6;
			fParams[4] = 4.0;
			fParams[5] = 40;
		}
		else if( iPreset==2 ){
			fParams[2] = 0.6;
			fParams[4] = 4.0;
			fParams[5] = 60;
		}
	}
	else if( iFxType==FX_CHORUS ){
 /*
		fParams[2] = 0.5;
		fParams[3] = 1;

		if( iPreset==0 ){
			fParams[0] = 1;
			fParams[1] = 0.3;
			fParams[4] = 5;
			fParams[5] = 1;
		}
		else if( iPreset==1 ){
			fParams[0] = 0.9;
			fParams[1] = -0.4;
			fParams[4] = 2;
			fParams[5] = 1;
		}
		else if( iPreset==2 ){
			fParams[0] = 0.3;
			fParams[1] = 0.4;
			fParams[4] = 10;
			fParams[5] = 5;
		}
*/
 		if( iPreset==0 ){
			fParams[0] = 25;
			fParams[1] = 10;
			fParams[2] = 10;
			fParams[3] = 1.1;
			fParams[4] = 10;
		}
		else if( iPreset==1 ){
			fParams[0] = 50;
			fParams[1] = 10;
			fParams[2] = 25;
			fParams[3] = 1.1;
			fParams[4] = 16;
		}
		else if( iPreset==2 ){
			fParams[0] = 65;
			fParams[1] = 20;
			fParams[2] = 45;
			fParams[3] = 5;
			fParams[4] = 16;
		}
	}
	else if( iFxType==FX_DISTORTION ){
		fParams[0] = -60;
		fParams[1] = 60;
		fParams[2] = 6466;
		fParams[3] = 1327;
		fParams[4] = 7080;
	}
	else if( iFxType==FX_REVERB ){
		fParams[0] = 0;
		fParams[3] = 0.001;

		if( iPreset==0 ){
			fParams[1] = -44;
			fParams[2] = 1428;
		}
		else if( iPreset==1 ){
			fParams[1] = -21;
			fParams[2] = 1573;
		}
		else if( iPreset==2 ){
			fParams[1] = -9;
			fParams[2] = 1573;
		}
	}
	else if( iFxType==FX_COMPRESSOR ){
		if( iPreset==0 ){
			fParams[0] = 0;
			fParams[1] = -12;
			fParams[2] = 6;
		}
		else if( iPreset==1 ){
			fParams[0] = 8;
			fParams[1] = -13;
			fParams[2] = 4;
		}
		else if( iPreset==2 ){
			fParams[0] = 15;
			fParams[1] = -15;
			fParams[2] = 2;
		}

		fParams[3] = 10;
		fParams[4] = 200;
	}
	else if( iFxType==FX_ECHO ){
		fParams[0] = 20;
		fParams[1] = 6;

		if( iPreset==0 ){
			if( g_iMelodyTimeSignature==3 )
				fParams[2] = fParams[3] = g_dblTimePerBar / g_nChordNumPerBar / 3;
			else
				fParams[2] = fParams[3] = g_dblTimePerBar / g_nChordNumPerBar / 2;
		}
		else if( iPreset==1 ){
			if( g_iMelodyTimeSignature==3 )
				fParams[2] = g_dblTimePerBar / g_nChordNumPerBar / 3;
			else
				fParams[2] = g_dblTimePerBar / g_nChordNumPerBar / 2;

			fParams[3] = g_dblTimePerBar / g_nChordNumPerBar;
		}
		else if( iPreset==2 ){
			fParams[2] = g_dblTimePerBar / g_nChordNumPerBar;
			fParams[3] = g_dblTimePerBar / g_nChordNumPerBar * 2;
		}

		if( fParams[2]>2000 )
			fParams[2] = 2000;
//		fParams[3] = 500;
	}
	else if( iFxType==FX_PARAMEQ ){
		if( iPreset==0 ){
			fParams[0] = 2220;
			fParams[1] = 14;
			fParams[2] = 10;
		}
		else if( iPreset==1 ){
			fParams[0] = 932;
			fParams[1] = 20;
			fParams[2] = 6;
		}
		else if( iPreset==2 ){
			fParams[0] = 1110;
			fParams[1] = 11;
			fParams[2] = 6;
		}
	}
	else if( iFxType==FX_PITCH ){
		if( iPreset==1 )
			fParams[0] = -12;
		else if( iPreset==2 )
			fParams[0] = 12;
		else
			fParams[0] = 0;
	}
}

int GetFxParamNum( int iFxType )
{
	int num = 0;

	switch( iFxType ){
		case FX_ROTATE:
		case FX_PITCH:
			num = 1;
			break;
/*
		case FX_VOLUME:
			num = 2;
			break;
*/
		case FX_PARAMEQ:
			num = 3;
			break;

		case FX_REVERB:
		case FX_ECHO:
			num = 4;
			break;

		case FX_DISTORTION:
		case FX_COMPRESSOR:
		case FX_CHORUS:
			num = 5;
			break;

		case FX_WAH:
		case FX_PHASER:
			num = 6;
			break;
	}

	return num;
}

float Pos2Param( int iFx, int iParam, int Pos )
{
	float fMin = g_aEffectParamLimit[iFx][iParam][0],
		fMax = g_aEffectParamLimit[iFx][iParam][1];

	return fMin + ( fMax - fMin ) * ( Pos / 100.0 );
}

int Param2Pos( int iFx, int iParam, float fParam )
{
	float fMin = g_aEffectParamLimit[iFx][iParam][0],
		fMax = g_aEffectParamLimit[iFx][iParam][1];

	return (int)( (fParam-fMin) / ( fMax-fMin ) * 100);
}

void AudioEffectsClear( int iWave, bool bApply )
{
	TAudioTrack* pAT = g_aAudioTracks[iWave];

	while( !pAT->lstFxs.empty() ){
		TAudioFx* pFx = pAT->lstFxs.back();

		if( bApply )
			f_MM_AudioMoveFx( iWave, pAT->lstFxs.size()-1, -1 );

		delete pFx;
		pAT->lstFxs.pop_back();
	}
}

HRESULT AudioApplyEffect( int iWave, int ind, TAudioFx* pFx )
{
	UINT pluginID = 0;
	char* strVSTFile = NULL;

	if( pFx->iFx>=FX_VST ){
		VSTINFO* pVST = g_lstVSTFx[pFx->iFx-FX_VST];
		strVSTFile = pVST->strFileName;

		if( pFx->iPreset>=0 && !pVST->aPlugins.empty() ){
			pluginID = pVST->aPlugins[pFx->iPreset]->id;
		}
	}

	Screen->Cursor = crHourGlass;

	HRESULT hr = f_MM_AudioAddFx( iWave, pFx->iFx, strVSTFile, pluginID, false );
	if( hr==S_OK ){
		if( !pFx->bBypass || pFx->iFx>=FX_VST )
			f_MM_AudioSetFxParam( iWave, ind, pFx->pParam, pFx->nParamSize );

		if( pFx->bBypass )
			f_MM_AudioSetFxParam( iWave, ind, NULL, 0 );
	}

	Screen->Cursor = crDefault;

	return hr;
}

void AudioEffectsDefault( int iWave, bool bApply )
{
	AudioEffectsClear( iWave, bApply );

	TAudioTrack* pTrack = g_aAudioTracks[iWave];

	int nBarCount = pTrack->lstBars.size();

	if( nBarCount>0 ){
		int nSize = GetFxParamNum( FX_REVERB );
		float* pParams = new float[nSize];

		GetFxPreset( FX_REVERB, 1, pParams );

		TAudioFx* pFx = new TAudioFx( FX_REVERB, 1, pParams, nSize );
		pTrack->lstFxs.push_back( pFx );

		if( bApply )
			AudioEffectsSet( iWave );
	}
}

void AudioEffectsSet( int iWave )
{
	TAudioTrack* pAT = g_aAudioTracks[iWave];

	for( int i=0; i<pAT->lstFxs.size(); i++ ){
		TAudioFx* pFx = pAT->lstFxs[i];

		if( S_OK!=AudioApplyEffect( iWave, i, pFx ) ){
			delete pFx;
			pAT->lstFxs.erase( pAT->lstFxs.begin()+i );
			i--;
		}
	}
}

/*
void AudioEffectsDefault( int iWave, bool bApply )
{
	AudioEffectsClear( iWave, bApply );

	TAudioTrack* pTrack = g_aAudioTracks[iWave];

	int nBarCount = pTrack->lstBars.size();

	if( nBarCount>0 ){
		TEffect* pAE = new TEffect;
		pAE->iBarStart = 0;
		pAE->iPointStart = 0;
		pAE->iBarEnd = nBarCount;
		pAE->iPointEnd = 0;
		pAE->bOn = true;
		pAE->iPreset = 1; //中等
		pAE->aParams = new float[6];
		GetFxPreset( g_aAudioEffectTypes[3], 1, pAE->aParams );

		pTrack->lstEffects[3] = pAE;

		if( bApply ){
			f_MM_AudioFx( iWave, 0, -1, g_aAudioEffectTypes[3], pAE->aParams );
		}
	}
}

void AudioEffectsClear( int iWave, bool bApply )
{
	TAudioTrack* pTrack = g_aAudioTracks[iWave];

	//清空音效
	for( int i=0; i<MAX_FX_NUM; i++ ){
		TEffect * pE = pTrack->lstEffects[i];

		if( pE ){
			if( bApply )
				f_MM_AudioFx( iWave, 0, -1, g_aAudioEffectTypes[i], NULL );

			while( pE ){
				TEffect *pTemp = pE->pNext;
				delete pE;
				pE = pTemp;
			}

			pTrack->lstEffects[i] = NULL;
		}
	}
}

bool AudioEffectsSort( int iWave, int iFx )
{
	TAudioTrack* pTrack = g_aAudioTracks[iWave];

	int nBarCount = pTrack->lstBars.size();
	int iFxStart = iFx, iFxEnd = iFx;
	if( iFx<0 ){
		iFxStart = 0;
		iFxEnd = MAX_FX_NUM-1;
	}

	bool bCountDown = false;
	for( int i=iFxStart; i<=iFxEnd; i++ ){
		TEffect *pAE = pTrack->lstEffects[i],
				*pHead = pAE,
				*pPrev = NULL;

		bool bHead = pHead!=NULL;
		while( pAE ){
			DWORD dwStart = pAE->iBarStart * POINTS_PER_BAR + pAE->iPointStart,
				  dwEnd = pAE->iBarEnd * POINTS_PER_BAR + pAE->iPointEnd;

			//清除关闭或短时效果
			if( !pAE->bOn || dwStart+4 >= dwEnd ){
				TEffect* pNext = pAE->pNext;

				if( pPrev )	pPrev->pNext = pNext;
				if( pHead==pAE ) pHead = pNext;

				delete pAE;
				pAE = pNext;

				continue;
			}

			if( pAE->pNext ){
					DWORD dwNextStart = pAE->pNext->iBarStart * POINTS_PER_BAR
															+ pAE->pNext->iPointStart,
						  dwNextEnd = pAE->pNext->iBarEnd * POINTS_PER_BAR
															+ pAE->pNext->iPointEnd;

					//清除关闭或短时效果
					if( !pAE->pNext->bOn || dwNextStart+4 >= dwNextEnd ){
						TEffect *pTemp = pAE->pNext;
						pAE->pNext = pTemp->pNext;
						delete pTemp;

						continue;
					}
					else{
						if( dwNextStart - dwEnd <= 4 ){
							if( !memcmp( pAE->aParams, pAE->pNext->aParams, 6*sizeof(float) )){
								pAE->iBarEnd = pAE->pNext->iBarEnd;
								pAE->iPointEnd = pAE->pNext->iPointEnd;

								TEffect *pTemp = pAE->pNext;
								pAE->pNext = pTemp->pNext;
								delete pTemp;

								continue;
							}
							else{
								pAE->iBarEnd = (dwNextStart - 1) / POINTS_PER_BAR;
								pAE->iPointEnd = (dwNextStart - 1) % POINTS_PER_BAR;
							}
						}
					}
			}

			if( pAE->iBarEnd==nBarCount-1 && pAE->iPointEnd==POINTS_PER_BAR-1 ){
				pAE->iBarEnd = nBarCount;
				pAE->iPointEnd = 0;
			}

			pPrev = pAE;
			pAE = pAE->pNext;
		}

		pTrack->lstEffects[i] = pHead;

		if( bHead && !pHead )
			bCountDown = true;
	}

	return bCountDown;
}

void AudioEffectsSet( int iWave, bool bOn )
{
	TAudioTrack* pTrack = g_aAudioTracks[iWave];

	for( int i=0; i<MAX_FX_NUM; i++ ){
		TEffect * pE = pTrack->lstEffects[i];
		int iFxType = g_aAudioEffectTypes[i];

		if( bOn ){
			while( pE ){
				double dblStart = pE->iBarStart + (double)pE->iPointStart / POINTS_PER_BAR,
						dblEnd = -1;

				if( pE->iBarEnd<g_aAudioTracks[iWave]->lstBars.size() )
					dblEnd = pE->iBarEnd + (double)pE->iPointEnd / POINTS_PER_BAR;

				f_MM_AudioFx( iWave, dblStart, dblEnd, iFxType, pE->aParams );

				pE = pE->pNext;
			}
		}
		else{
			f_MM_AudioFx( iWave, 0, -1, iFxType, NULL );
		}
	}
}

bool AudioEffectsMove( int iSrc, double dblStart, double dblEnd, int iDest, double dblInsert,  int iMode )
{
	int iStartBar = (int)dblStart,
		iEndBar = (int)dblEnd,
		iInsertBar = (int)dblInsert,
		iStartPoint = (int)( (dblStart-iStartBar) * POINTS_PER_BAR + 0.5 ),
		iEndPoint = (int)( (dblEnd-iEndBar) * POINTS_PER_BAR + 0.5 ),
		iInsertPoint = (int)( (dblInsert-iInsertBar) * POINTS_PER_BAR + 0.5 );

	int iDelStartBar = iStartBar,
		iDelStartPoint = iStartPoint,
		iDelEndBar = iEndBar,
		iDelEndPoint = iEndPoint,
		iDelStart = iStartBar * POINTS_PER_BAR + iStartPoint,
		iDelEnd = iEndBar * POINTS_PER_BAR + iEndPoint;

	if( iMode==MODE_MOVE && ( iInsertBar<iStartBar || iInsertBar==iStartBar
											&& iInsertPoint<=iStartPoint )){
		int nLen = ( iEndBar-iStartBar ) * POINTS_PER_BAR + iEndPoint - iStartPoint;

		iDelStart += nLen;
		iDelEnd += nLen;

		iDelStartBar = iDelStart / POINTS_PER_BAR;
		iDelStartPoint = iDelStart % POINTS_PER_BAR;
		iDelEndBar = iDelEnd / POINTS_PER_BAR;
		iDelEndPoint = iDelEnd % POINTS_PER_BAR;
	}

	TAudioTrack *pSrcTrack = iSrc<0 ? NULL : g_aAudioTracks[iSrc],
				*pDestTrack = g_aAudioTracks[iDest];

	if( iDest>=0 )
		AudioEffectsSet( iDest, false );
	if( iSrc>=0 && iSrc!=iDest )
		AudioEffectsSet( iSrc, false );

	bool bCountDown = false;
	for(int i = 0; i < MAX_FX_NUM; i++){
		PTEffect pBackupHead = NULL, // 记录备份链表头地址
				 pBackupLast = NULL; // 记录备份链表尾地址

		if( iMode==MODE_MOVE || iMode==MODE_COPY  || iMode==MODE_INSERT ){
			if( pSrcTrack ){
				PTEffect pAE = pSrcTrack->lstEffects[i];
				//备份
				while( pAE ) {
					if(pAE->iBarStart > iEndBar || pAE->iBarStart==iEndBar
												&& pAE->iPointStart>=iEndPoint ){
						break;
					}
					else if(pAE->iBarEnd > iStartBar || pAE->iBarEnd==iStartBar
														&& pAE->iPointEnd > iStartPoint ) {
						TEffect *pNewLast = new TEffect( pAE );

						if(pBackupHead == NULL) {
							pBackupHead = pNewLast;
							pBackupLast = pNewLast;
						}
						else {
							pBackupLast->pNext = pNewLast;
							pBackupLast = pNewLast;
						}

						if(pAE->iBarStart < iStartBar || pAE->iBarStart==iStartBar
															&& pAE->iPointStart < iStartPoint ) {
							// 相对位置
							pNewLast->iBarStart = iInsertBar;
							pNewLast->iPointStart = iInsertPoint;
						}
						else {
							pNewLast->iBarStart = pAE->iBarStart - iStartBar + iInsertBar;
							pNewLast->iPointStart = pAE->iPointStart - iStartPoint + iInsertPoint;

							if( pNewLast->iPointStart<0 ){
								pNewLast->iPointStart += POINTS_PER_BAR;
								pNewLast->iBarStart--;
							}
							else if( pNewLast->iPointStart>=POINTS_PER_BAR ){
								pNewLast->iPointStart -= POINTS_PER_BAR;
								pNewLast->iBarStart++;
							}
						}

						int iEB = iInsertBar - iStartBar,
							iEP = iInsertPoint - iStartPoint;

						if( pAE->iBarEnd < iEndBar || pAE->iBarEnd==iEndBar
													&& pAE->iPointEnd < iEndPoint ){
							iEB += pAE->iBarEnd;
							iEP += pAE->iPointEnd;
						}
						else{
							iEB += iEndBar;
							iEP += iEndPoint;
						}

						pNewLast->iBarEnd = iEB;
						pNewLast->iPointEnd = iEP;

						if( pNewLast->iPointEnd < 0 ){
							pNewLast->iPointEnd += POINTS_PER_BAR;
							pNewLast->iBarEnd--;
						}
						else if( pNewLast->iPointEnd >= POINTS_PER_BAR ){
							pNewLast->iPointEnd -= POINTS_PER_BAR;
							pNewLast->iBarEnd++;
						}
					}

					pAE = pAE->pNext;
				}
			}

			// 插入并记录插入点
			PTEffect pAE = pDestTrack->lstEffects[i],
					pPrev = NULL,
					pNext = NULL;

			while(pAE) {
				if( iInsertBar < pAE->iBarStart	|| iInsertBar==pAE->iBarStart
													&& iInsertPoint<=pAE->iPointStart ){
					pNext = pAE;
					break;
				}
				else if( iInsertBar > pAE->iBarEnd || iInsertBar==pAE->iBarEnd
													&& iInsertPoint > pAE->iPointEnd ){
					pPrev = pAE;
				}
				else{
					// 拆分
					TEffect *pNewEffect 	= new TEffect( pAE );
					pNewEffect->iBarStart 	= iInsertBar;
					pNewEffect->iPointStart = iInsertPoint;
					pNewEffect->pNext 		= pAE->pNext;

					pAE->iBarEnd = iInsertBar;
					pAE->iPointEnd = iInsertPoint - 1;
					pAE->pNext = pNewEffect;

					if( pAE->iPointEnd<0 ){
						pAE->iPointEnd += POINTS_PER_BAR;
						pAE->iBarEnd--;
					}

					pPrev = pAE;
					pNext = pNewEffect;

					break;
				}

				pAE = pAE->pNext;
			}

			if( pBackupHead ){
				if( pPrev ){
					pPrev->pNext = pBackupHead;
				}
				else{
					pDestTrack->lstEffects[i] = pBackupHead;
				}

				pBackupLast->pNext = pNext;
			}

			// 修正
			int nBar = iEndBar - iStartBar,
				nPoint = iEndPoint - iStartPoint;
			pAE = pNext;
			while(pAE) {
				if( !(iMode==MODE_INSERT && pAE==pNext && !pBackupHead && pAE->iBarStart==iInsertBar
															&& pAE->iPointStart==iInsertPoint )){
					pAE->iBarStart += nBar;
					pAE->iPointStart += nPoint;

					if( pAE->iPointStart<0 ){
						pAE->iPointStart += POINTS_PER_BAR;
						pAE->iBarStart--;
					}
					else if( pAE->iPointStart>=POINTS_PER_BAR ){
						pAE->iPointStart -= POINTS_PER_BAR;
						pAE->iBarStart++;
					}
				}

				pAE->iBarEnd += nBar;
				pAE->iPointEnd += nPoint;

				if( pAE->iPointEnd < 0 ){
					pAE->iPointEnd += POINTS_PER_BAR;
					pAE->iBarEnd--;
				}
				else if( pAE->iPointEnd >= POINTS_PER_BAR ){
					pAE->iPointEnd -= POINTS_PER_BAR;
					pAE->iBarEnd++;
				}

				pAE = pAE->pNext;
			}
		}

		// 删除
		if( iMode==MODE_DELETE || iMode==MODE_MOVE ){
			PTEffect pAE = pSrcTrack->lstEffects[i],
					pPrev = NULL,
					pNext = NULL;

			while( pAE ) {
				int iAEStart = pAE->iBarStart * POINTS_PER_BAR + pAE->iPointStart,
					iAEEnd = pAE->iBarEnd * POINTS_PER_BAR + pAE->iPointEnd;

				if( iAEStart>=iDelStart && iAEEnd<=iDelEnd ){
					if( pPrev )
						pPrev->pNext = pAE->pNext;
					else
						pSrcTrack->lstEffects[i] = pAE->pNext;

					PTEffect pTemp = pAE;
					pAE = pAE->pNext;
					delete pTemp;

					continue;
				}
				else if( iAEStart < iDelStart ){
					pPrev = pAE;

					if( iAEEnd > iDelStart ){
						if( iAEEnd > iDelEnd ){ //拆分
							TEffect* pBreak = new TEffect( pAE );
							pBreak->iBarStart = iDelEndBar;
							pBreak->iPointStart = iDelEndPoint;

							pBreak->pNext = pAE->pNext;
							pAE->pNext = pBreak;
						}

						pAE->iBarEnd = iDelStartBar;
						pAE->iPointEnd = iDelStartPoint;
					}
				}
				else if( iAEEnd > iDelStart ){
					if( iAEStart < iDelEnd ){
						pAE->iBarStart = iDelEndBar;
						pAE->iPointStart = iDelEndPoint;
					}

					pNext = pAE;
					break;
				}

				pAE = pAE->pNext;
			}

			if( pNext ){
				// 修正
				int nBar = iEndBar - iStartBar,
					nPoint = iEndPoint - iStartPoint;
				pAE = pNext;
				while(pAE) {
					pAE->iBarStart -= nBar;
					pAE->iPointStart -= nPoint;

					if( pAE->iPointStart<0 ){
						pAE->iPointStart += POINTS_PER_BAR;
						pAE->iBarStart--;
					}
					else if( pAE->iPointStart>=POINTS_PER_BAR ){
						pAE->iPointStart -= POINTS_PER_BAR;
						pAE->iBarStart++;
					}

					pAE->iBarEnd -= nBar;
					pAE->iPointEnd -= nPoint;

					if( pAE->iPointEnd < 0 ){
						pAE->iPointEnd += POINTS_PER_BAR;
						pAE->iBarEnd--;
					}
					else if( pAE->iPointEnd >= POINTS_PER_BAR ){
						pAE->iPointEnd -= POINTS_PER_BAR;
						pAE->iBarEnd++;
					}

					pAE = pAE->pNext;
				}
			}
			else if( !pPrev ){
				pSrcTrack->lstEffects[i] = NULL;
			}
		}

		if( iDest>=0 )
			bCountDown |= AudioEffectsSort( iDest, i );
		if( iSrc>=0 && iSrc!=iDest )
			bCountDown |= AudioEffectsSort( iSrc, i );
	}

	if( iDest>=0 )
		AudioEffectsSet( iDest, true );
	if( iSrc>=0 && iSrc!=iDest )
		AudioEffectsSet( iSrc, true );

	return bCountDown;
}

void ClearAudioEffects( TEffect* lstEffects[] )
{
	//清空音效
	for( int i=0; i<MAX_FX_NUM; i++ ){
		TEffect * pE = lstEffects[i];

		if( pE ){
			while( pE ){
				TEffect *pTemp = pE->pNext;
				delete pE;
				pE = pTemp;
			}

			lstEffects[i] = NULL;
		}
	}
}

void CopyAudioEffects( TEffect* lstDest[], TEffect* lstSrc[], double dblStart, double dblEnd )
{
	int iStartBar = (int)dblStart,
		iEndBar = (int)dblEnd,
		iStartPoint = (int)( (dblStart-iStartBar) * POINTS_PER_BAR + 0.5 ),
		iEndPoint = (int)( (dblEnd-iEndBar) * POINTS_PER_BAR + 0.5 );

	if( !lstDest || !lstSrc || iEndBar<iStartBar
						|| iEndBar==iStartBar && iEndPoint<=iStartPoint )
		return;

	for(int i = 0; i < MAX_FX_NUM; i++){
		PTEffect pBackupHead = NULL, // 记录备份链表头地址
				 pBackupLast = NULL; // 记录备份链表尾地址
		PTEffect pAE = lstSrc[i];

		//备份
		while( pAE ) {
			if( pAE->iBarStart > iEndBar || pAE->iBarStart==iEndBar
										&& pAE->iPointStart>=iEndPoint ){
				break;
			}
			else if(pAE->iBarEnd > iStartBar || pAE->iBarEnd==iStartBar
												&& pAE->iPointEnd > iStartPoint ) {
				TEffect *pNewLast = new TEffect( pAE );

				if( pBackupHead == NULL ){
					pBackupHead = pNewLast;
					pBackupLast = pNewLast;
				}
				else{
					pBackupLast->pNext = pNewLast;
					pBackupLast = pNewLast;
				}

				if( pAE->iBarStart < iStartBar || pAE->iBarStart==iStartBar
													&& pAE->iPointStart < iStartPoint ){
					// 相对位置
					pNewLast->iBarStart = 0;
					pNewLast->iPointStart = 0;
				}
				else {
					pNewLast->iBarStart = pAE->iBarStart - iStartBar;
					pNewLast->iPointStart = pAE->iPointStart - iStartPoint;

					if( pNewLast->iPointStart<0 ){
						pNewLast->iPointStart += POINTS_PER_BAR;
						pNewLast->iBarStart--;
					}
					else if( pNewLast->iPointStart>=POINTS_PER_BAR ){
						pNewLast->iPointStart -= POINTS_PER_BAR;
						pNewLast->iBarStart++;
					}
				}

				if( pAE->iBarEnd < iEndBar || pAE->iBarEnd==iEndBar
											&& pAE->iPointEnd < iEndPoint ){
					pNewLast->iBarEnd = pAE->iBarEnd - iStartBar;
					pNewLast->iPointEnd = pAE->iPointEnd - iStartPoint;
				}
				else{
					pNewLast->iBarEnd = iEndBar - iStartBar;
					pNewLast->iPointEnd = iEndPoint - iStartPoint;
				}

				if( pNewLast->iPointEnd < 0 ){
					pNewLast->iPointEnd += POINTS_PER_BAR;
					pNewLast->iBarEnd--;
				}
				else if( pNewLast->iPointEnd >= POINTS_PER_BAR ){
					pNewLast->iPointEnd -= POINTS_PER_BAR;
					pNewLast->iBarEnd++;
				}
			}

			pAE = pAE->pNext;
		}

		lstDest[i] = pBackupHead;
	}
}

void InsertAudioEffetcts( TEffect* lstDest[], TEffect* lstSrc[], double dblInsert, double dblLen )
{
	if( !lstDest )
		return;

	int iInsertBar = (int)dblInsert,
		iInsertPoint = (int)( (dblInsert-iInsertBar) * POINTS_PER_BAR + 0.5 ),
		nLenBar = (int)dblLen,
		nLenPoint = (int)( (dblLen-nLenBar) * POINTS_PER_BAR + 0.5 );

	for(int i = 0; i < MAX_FX_NUM; i++){
		PTEffect pSetHead = NULL, // 记录备份链表头地址
				 pSetTail = NULL; // 记录备份链表尾地址

		if( lstSrc && lstSrc[i] ){
			PTEffect pTemp = lstSrc[i];
			while( pTemp ){
				TEffect *pAE = new TEffect( pTemp );

				pAE->iBarStart += iInsertBar;
				pAE->iPointStart += iInsertPoint;

				if( pAE->iPointStart<0 ){
					pAE->iPointStart += POINTS_PER_BAR;
					pAE->iBarStart--;
				}
				else if( pAE->iPointStart>=POINTS_PER_BAR ){
					pAE->iPointStart -= POINTS_PER_BAR;
					pAE->iBarStart++;
				}

				pAE->iBarEnd += iInsertBar;
				pAE->iPointEnd += iInsertPoint;

				if( pAE->iPointEnd < 0 ){
					pAE->iPointEnd += POINTS_PER_BAR;
					pAE->iBarEnd--;
				}
				else if( pAE->iPointEnd >= POINTS_PER_BAR ){
					pAE->iPointEnd -= POINTS_PER_BAR;
					pAE->iBarEnd++;
				}

				if( pSetHead == NULL ){
					pSetHead = pAE;
					pSetTail = pAE;
				}
				else{
					pSetTail->pNext = pAE;
					pSetTail = pSetTail->pNext;
				}

				pTemp = pTemp->pNext;
			}
		}

		// 插入并记录插入点
		PTEffect pAE = lstDest[i],
				pPrev = NULL,
				pNext = NULL;

		while(pAE) {
			if( iInsertBar < pAE->iBarStart	|| iInsertBar==pAE->iBarStart
												&& iInsertPoint<=pAE->iPointStart ){
				pNext = pAE;
				break;
			}
			else if( iInsertBar > pAE->iBarEnd || iInsertBar==pAE->iBarEnd
												&& iInsertPoint > pAE->iPointEnd ){
				pPrev = pAE;
			}
			else{
				// 拆分
				TEffect *pNewEffect 	= new TEffect( pAE );
				pNewEffect->iBarStart 	= iInsertBar;
				pNewEffect->iPointStart = iInsertPoint;
				pNewEffect->pNext 		= pAE->pNext;

				pAE->iBarEnd = iInsertBar;
				pAE->iPointEnd = iInsertPoint;
				pAE->pNext = pNewEffect;

				if( pAE->iPointEnd<0 ){
					pAE->iPointEnd += POINTS_PER_BAR;
					pAE->iBarEnd--;
				}

				pPrev = pAE;
				pNext = pNewEffect;

				break;
			}

			pAE = pAE->pNext;
		}

		if( pSetHead ){
			if( pPrev )
				pPrev->pNext = pSetHead;
			else
				lstDest[i] = pSetHead;

			pSetTail->pNext = pNext;
		}

		// 修正
		pAE = pNext;
		while(pAE) {
			pAE->iBarStart += nLenBar;
			pAE->iPointStart += nLenPoint;

			if( pAE->iPointStart<0 ){
				pAE->iPointStart += POINTS_PER_BAR;
				pAE->iBarStart--;
			}
			else if( pAE->iPointStart>=POINTS_PER_BAR ){
				pAE->iPointStart -= POINTS_PER_BAR;
				pAE->iBarStart++;
			}

			pAE->iBarEnd += nLenBar;
			pAE->iPointEnd += nLenPoint;

			if( pAE->iPointEnd < 0 ){
				pAE->iPointEnd += POINTS_PER_BAR;
				pAE->iBarEnd--;
			}
			else if( pAE->iPointEnd >= POINTS_PER_BAR ){
				pAE->iPointEnd -= POINTS_PER_BAR;
				pAE->iBarEnd++;
			}

			pAE = pAE->pNext;
		}

		SortAudioEffects( &lstDest[i] );
	}
}

void SortAudioEffects( TEffect** lstEffect )
{
	TEffect *pAE = *lstEffect,
			*pHead = pAE,
			*pPrev = NULL;

	while( pAE ){
		DWORD dwStart = pAE->iBarStart * POINTS_PER_BAR + pAE->iPointStart,
			  dwEnd = pAE->iBarEnd * POINTS_PER_BAR + pAE->iPointEnd;

		//清除关闭或短时效果
		if( !pAE->bOn || dwStart+4 >= dwEnd ){
			TEffect* pNext = pAE->pNext;

			if( pPrev )	pPrev->pNext = pNext;
			if( pHead==pAE ) pHead = pNext;

			delete pAE;
			pAE = pNext;

			continue;
		}

		if( pAE->pNext ){
				DWORD dwNextStart = pAE->pNext->iBarStart * POINTS_PER_BAR
														+ pAE->pNext->iPointStart,
					  dwNextEnd = pAE->pNext->iBarEnd * POINTS_PER_BAR
														+ pAE->pNext->iPointEnd;

				//清除关闭或短时效果
				if( !pAE->pNext->bOn || dwNextStart+4 >= dwNextEnd ){
					TEffect *pTemp = pAE->pNext;
					pAE->pNext = pTemp->pNext;
					delete pTemp;

					continue;
				}
				else{
					if( dwNextStart - dwEnd <= 4 ){
						if( !memcmp( pAE->aParams, pAE->pNext->aParams, 6*sizeof(float) )){
							pAE->iBarEnd = pAE->pNext->iBarEnd;
							pAE->iPointEnd = pAE->pNext->iPointEnd;

							TEffect *pTemp = pAE->pNext;
							pAE->pNext = pTemp->pNext;
							delete pTemp;

							continue;
						}
						else{
							pAE->iBarEnd = (dwNextStart - 1) / POINTS_PER_BAR;
							pAE->iPointEnd = (dwNextStart - 1) % POINTS_PER_BAR;
						}
					}
				}
		}

		pPrev = pAE;
		pAE = pAE->pNext;
	}

	*lstEffect = pHead;
}

void RemoveAudioEffects( TEffect* lstEffects[], double dblStart, double dblEnd )
{
	int iStartBar = (int)dblStart,
		iEndBar = (int)dblEnd,
		iStartPoint = (int)( (dblStart-iStartBar) * POINTS_PER_BAR + 0.5 ),
		iEndPoint = (int)( (dblEnd-iEndBar) * POINTS_PER_BAR + 0.5 ),
		iDelStart = iStartBar * POINTS_PER_BAR + iStartPoint,
		iDelEnd = iEndBar * POINTS_PER_BAR + iEndPoint;

	for(int i = 0; i < MAX_FX_NUM; i++){
		PTEffect pAE = lstEffects[i],
				pPrev = NULL,
				pNext = NULL;

		while( pAE ) {
			int iAEStart = pAE->iBarStart * POINTS_PER_BAR + pAE->iPointStart,
				iAEEnd = pAE->iBarEnd * POINTS_PER_BAR + pAE->iPointEnd;

			if( iAEStart>=iDelStart && iAEEnd<=iDelEnd ){
				if( pPrev )
					pPrev->pNext = pAE->pNext;
				else
					lstEffects[i] = pAE->pNext;

				PTEffect pTemp = pAE;
				pAE = pAE->pNext;
				delete pTemp;

				continue;
			}
			else if( iAEStart < iDelStart ){
				pPrev = pAE;

				if( iAEEnd > iDelStart ){
					if( iAEEnd > iDelEnd ){ //拆分
						TEffect* pBreak = new TEffect( pAE );
						pBreak->iBarStart = iEndBar;
						pBreak->iPointStart = iEndPoint;

						pBreak->pNext = pAE->pNext;
						pAE->pNext = pBreak;
					}

					pAE->iBarEnd = iStartBar;
					pAE->iPointEnd = iStartPoint;
				}
			}
			else if( iAEEnd > iDelStart ){
				if( iAEStart < iDelEnd ){
					pAE->iBarStart = iEndBar;
					pAE->iPointStart = iEndPoint;
				}

				pNext = pAE;
				break;
			}

			pAE = pAE->pNext;
		}

		if( pNext ){
			// 修正
			int nBar = iEndBar - iStartBar,
				nPoint = iEndPoint - iStartPoint;
			pAE = pNext;
			while(pAE) {
				pAE->iBarStart -= nBar;
				pAE->iPointStart -= nPoint;

				if( pAE->iPointStart<0 ){
					pAE->iPointStart += POINTS_PER_BAR;
					pAE->iBarStart--;
				}
				else if( pAE->iPointStart>=POINTS_PER_BAR ){
					pAE->iPointStart -= POINTS_PER_BAR;
					pAE->iBarStart++;
				}

				pAE->iBarEnd -= nBar;
				pAE->iPointEnd -= nPoint;

				if( pAE->iPointEnd < 0 ){
					pAE->iPointEnd += POINTS_PER_BAR;
					pAE->iBarEnd--;
				}
				else if( pAE->iPointEnd >= POINTS_PER_BAR ){
					pAE->iPointEnd -= POINTS_PER_BAR;
					pAE->iBarEnd++;
				}

				pAE = pAE->pNext;
			}
		}
		else if( !pPrev ){
			lstEffects[i] = NULL;
		}
	}
}

TEffect* DuplicateEffects( TEffect* pSrcHead )
{
	TEffect *pDestHead = NULL,
			*pAE = pSrcHead,
			*pPrev = NULL;

	while( pAE ){
		TEffect* pNew = new TEffect( pAE );
		if( !pPrev ){
			pDestHead = pPrev = pNew;
		}
		else{
			pPrev->pNext = pNew;
			pPrev = pNew;
		}

		pAE = pAE->pNext;
	}

	return pDestHead;
}
*/
