Files
2026-06-13 00:05:19 +08:00

1312 lines
30 KiB
C++

//---------------------------------------------------------------------------
#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;
}
*/