814 lines
20 KiB
C++
814 lines
20 KiB
C++
//---------------------------------------------------------------------------
|
|
#include <vcl.h>
|
|
#pragma hdrstop
|
|
|
|
#include "GlobalUnit.h"
|
|
#include "AudioTrack.h"
|
|
#include "Undo.h"
|
|
#include "Project.h"
|
|
//---------------------------------------------------------------------------
|
|
#pragma package(smart_init)
|
|
|
|
/***************************************************************************************/
|
|
// 全局变量
|
|
/***************************************************************************************/
|
|
|
|
TAudio g_Audio;
|
|
TAudioTrackList& g_aAudioTracks = g_Audio.AudioTracks(); //全曲音频轨道(最大4组)
|
|
int g_iSelAudio = 0; // 当前处理的音频轨
|
|
|
|
/***************************************************************************************/
|
|
// TAudio类函数
|
|
/***************************************************************************************/
|
|
|
|
void TAudio::CopyTrackList( int iStartBar, int nCopyBars, TAudioTrackList* lstAudio, bool bFx )
|
|
{
|
|
int iTrkStart = 1,
|
|
iTrkEnd = m_lstTracks.size();
|
|
|
|
if( g_iPreStage==0/*iTrkEnd==iTrkStart*/ )
|
|
iTrkStart = 0;
|
|
|
|
for( int i=iTrkStart; i<iTrkEnd; i++ ){
|
|
if( !m_lstTracks[i]->lstBars.empty() )
|
|
lstAudio->push_back( CopyTrack( i, iStartBar, nCopyBars, bFx ) );
|
|
}
|
|
}
|
|
|
|
TAudioTrack* TAudio::CopyTrack( int iTrack, int iStartBar, int nCopyBars, bool bFx, TAudioTrack* pDest )
|
|
{
|
|
TAudioTrack* pSrcTrack = m_lstTracks[iTrack],
|
|
*pDestTrack = pDest ? pDest : new TAudioTrack();
|
|
|
|
pDestTrack->state = pSrcTrack->state;
|
|
pDestTrack->volume = pSrcTrack->volume;
|
|
pDestTrack->pan = pSrcTrack->pan;
|
|
pDestTrack->gain = pSrcTrack->gain;
|
|
|
|
for( int i=0; i<nCopyBars; i++ ){
|
|
pDestTrack->lstBars.push_back( new TWaveBar( pSrcTrack->lstBars[iStartBar+i] ) );
|
|
}
|
|
|
|
if( bFx ){
|
|
for( int i=0; i<pSrcTrack->lstFxs.size(); i++ )
|
|
pDestTrack->lstFxs.push_back( new TAudioFx( pSrcTrack->lstFxs[i]) );
|
|
}
|
|
|
|
return pDestTrack;
|
|
}
|
|
|
|
void TAudio::ResetTracks( TAudioTrackList* lstAudio )
|
|
{
|
|
//处理音频
|
|
while( m_lstTracks.size()>1 ){
|
|
delete m_lstTracks.back();
|
|
m_lstTracks.pop_back();
|
|
}
|
|
|
|
for( int i=0; i<lstAudio->size(); i++ ){
|
|
//替换AudioTrack
|
|
TAudioTrack* pNewTrack = DuplicateAudioTrack( (*lstAudio)[i] );
|
|
m_lstTracks.push_back( pNewTrack );
|
|
|
|
AudioEffectsSet( i+1 );
|
|
}
|
|
|
|
/* if( m_lstTracks.size()>1 ){
|
|
m_lstTracks[0]->bHide = true;
|
|
}
|
|
*/
|
|
}
|
|
|
|
void TAudio::RestoreAudio( TOpusStageList* lstStages, TAudioTrackList* lstAudio, bool bUndo )
|
|
{
|
|
int iOrigStage = 0, iVarBar = 0;
|
|
|
|
TOpusStageList::iterator iterDest = lstStages->begin(),
|
|
iterSrc = g_lstOpusStages.begin();
|
|
int iDestBar(0), iSrcBar(0);//, iDVB(0), iSVB(0);
|
|
while( iterDest!=lstStages->end() && iterSrc!=g_lstOpusStages.end() ){
|
|
TOpusStage *pSrcStage = *iterSrc,
|
|
*pDestStage = *iterDest;
|
|
|
|
if( pSrcStage->iSegType<SEGTYPE_INTRO && pDestStage->iSegType<SEGTYPE_INTRO ){
|
|
int nBar = min( pSrcStage->aBars.size(), pDestStage->aBars.size() );
|
|
|
|
if( nBar==pSrcStage->aBars.size() ){
|
|
iterSrc++;
|
|
}
|
|
|
|
if( nBar==pDestStage->aBars.size() ){
|
|
iterDest++;
|
|
}
|
|
|
|
iDestBar += nBar;
|
|
iSrcBar += nBar;
|
|
}
|
|
else if( pSrcStage->iSegType<SEGTYPE_INTRO && pDestStage->iSegType>=SEGTYPE_INTRO ){ //undo情况
|
|
int nBar = pDestStage->aBars.size();
|
|
|
|
iDestBar += nBar;
|
|
iSrcBar += nBar;
|
|
iterDest++;
|
|
}
|
|
else if( pSrcStage->iSegType>=SEGTYPE_INTRO && pDestStage->iSegType<SEGTYPE_INTRO ){ //redo情况
|
|
//删掉音频
|
|
int nBar = pSrcStage->aBars.size();
|
|
for( int i=1; i<g_aAudioTracks.size(); i++ ){
|
|
RemoveWaveBars( i, iSrcBar, nBar );
|
|
}
|
|
|
|
iterSrc++;
|
|
}
|
|
else if( pSrcStage->iSegType==SEGTYPE_INTRO && pDestStage->iSegType==SEGTYPE_ENDING ){//redo情况
|
|
//删掉音频
|
|
int nBar = pSrcStage->aBars.size();
|
|
for( int i=1; i<g_aAudioTracks.size(); i++ ){
|
|
RemoveWaveBars( i,iSrcBar , nBar );
|
|
}
|
|
|
|
iterSrc++;
|
|
}
|
|
else if( pSrcStage->iSegType==SEGTYPE_ENDING && pDestStage->iSegType==SEGTYPE_INTRO ){//undo情况
|
|
int nBar = pDestStage->aBars.size();
|
|
|
|
iDestBar += nBar;
|
|
iSrcBar += nBar;
|
|
iterDest++;
|
|
}
|
|
else{ //前尾奏类型相同
|
|
//redo比较长度并插入空白或删除
|
|
if( !bUndo ){
|
|
if( pDestStage->aBars.size() > pSrcStage->aBars.size() ){
|
|
int nBar = pDestStage->aBars.size() - pSrcStage->aBars.size(),
|
|
iInsBar = iSrcBar + pSrcStage->aBars.size();
|
|
|
|
for( int i=1; i<g_aAudioTracks.size(); i++ ){
|
|
InsertAudioTrack( i, iInsBar, nBar, NULL );
|
|
}
|
|
|
|
iSrcBar += nBar;
|
|
}
|
|
else if( pDestStage->aBars.size() < pSrcStage->aBars.size() ){
|
|
int nBar = pSrcStage->aBars.size() - pDestStage->aBars.size(),
|
|
iDelBar = iSrcBar + pDestStage->aBars.size();
|
|
|
|
for( int i=1; i<g_aAudioTracks.size(); i++ ){
|
|
RemoveWaveBars( i, iDelBar, nBar );
|
|
}
|
|
|
|
iSrcBar -= nBar;
|
|
}
|
|
}
|
|
|
|
iSrcBar += pSrcStage->aBars.size();
|
|
iDestBar += pDestStage->aBars.size();
|
|
iterSrc++;
|
|
iterDest++;
|
|
}
|
|
}
|
|
|
|
while( iterDest!=lstStages->end() ){ //undo情况
|
|
int nBar = (*iterDest)->aBars.size();
|
|
|
|
iDestBar += nBar;
|
|
iterDest++;
|
|
}
|
|
|
|
//处理音频
|
|
if( lstAudio ){
|
|
for( int i=1; i<g_aAudioTracks.size(); i++ ){
|
|
if( bUndo ){ //替换WaveBars
|
|
TAudioTrack *pAT = g_aAudioTracks[i],
|
|
*pSrc = (*lstAudio)[i-1];
|
|
|
|
RemoveWaveBars( i, 0, pAT->lstBars.size() );
|
|
|
|
if( pSrc ){
|
|
for( int i=0; i<pSrc->lstBars.size(); i++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
memcpy( pWvBar->aVols, pSrc->lstBars[i], sizeof(DWORD)*POINTS_PER_BAR );
|
|
pAT->lstBars.push_back( pWvBar );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TAudio::WriteProj( FILE* pFile )
|
|
{
|
|
int num = m_lstTracks.size();
|
|
fwrite( &num, sizeof(int), 1, pFile );
|
|
|
|
for( int i=0; i<num; i++ ){
|
|
TAudioTrack* pAT = m_lstTracks[i];
|
|
|
|
int nBars = pAT->lstBars.size();
|
|
fwrite( &nBars, sizeof(int), 1, pFile );
|
|
|
|
// fwrite( &bHide, sizeof(BYTE), 1, pFile );
|
|
// fwrite( &bMute, sizeof(BYTE), 1, pFile );
|
|
fwrite( &pAT->state, sizeof(BYTE), 1, pFile );
|
|
fwrite( &pAT->volume, sizeof(BYTE), 1, pFile );
|
|
fwrite( &pAT->pan, sizeof(char), 1, pFile );
|
|
fwrite( &pAT->gain, sizeof(char), 1, pFile );
|
|
// fwrite( &iShow, sizeof(BYTE), 1, pFile );
|
|
|
|
int count = pAT->lstFxs.size();
|
|
fwrite( &count, sizeof(int), 1, pFile );
|
|
|
|
for( int j=0; j<count; j++ ){
|
|
TAudioFx* pFx = pAT->lstFxs[j];
|
|
fwrite( &pFx->iFx, sizeof(int), 1, pFile );
|
|
fwrite( &pFx->iPreset, sizeof(int), 1, pFile );
|
|
fwrite( &pFx->bBypass, sizeof(WORD), 1, pFile );
|
|
fwrite( &pFx->nParamSize, sizeof(WORD), 1, pFile );
|
|
if( pFx->nParamSize>0 )
|
|
fwrite( pFx->pParam, sizeof(float), pFx->nParamSize, pFile );
|
|
|
|
if( pFx->iFx >= FX_VST ){
|
|
VSTINFO* pVST = g_lstVSTFx[pFx->iFx-FX_VST];
|
|
DWORD uniqueID = pVST->uniqueID;
|
|
fwrite( &uniqueID, sizeof(DWORD), 1, pFile );
|
|
|
|
if( pFx->iPreset>=0 ){
|
|
uniqueID = pVST->aPlugins[pFx->iPreset]->id;
|
|
fwrite( &uniqueID, sizeof(DWORD), 1, pFile );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int TAudio::ReadProj( FILE* pFile, DWORD dwVersion )
|
|
{
|
|
WORD wMajVersion = HIWORD( dwVersion ),
|
|
wMinVersion = LOWORD( dwVersion );
|
|
int iError = E_PROJ_NOERROR;
|
|
|
|
int num;
|
|
fread( &num, sizeof(int), 1, pFile );
|
|
|
|
for( int i=0; i<num; i++ ){
|
|
int nBars;
|
|
fread( &nBars, sizeof(int), 1, pFile );
|
|
|
|
TAudioTrack* pAT = NULL;
|
|
if( i==0 ){
|
|
pAT = m_lstTracks[0];
|
|
}
|
|
else{
|
|
pAT = new TAudioTrack;
|
|
m_lstTracks.push_back( pAT );
|
|
}
|
|
|
|
for( int j=0; j<nBars; j++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
pAT->lstBars.push_back( pWvBar );
|
|
}
|
|
|
|
if( wMajVersion==5 && wMinVersion>=6 ){
|
|
fread( &pAT->state, sizeof(BYTE), 1, pFile );
|
|
fread( &pAT->volume, sizeof(BYTE), 1, pFile );
|
|
fread( &pAT->pan, sizeof(char), 1, pFile );
|
|
fread( &pAT->gain, sizeof(char), 1, pFile );
|
|
|
|
int count = 0;
|
|
fread( &count, sizeof(int), 1, pFile );
|
|
|
|
for( int j=0; j<count; j++ ){
|
|
int iFx, iPreset;
|
|
WORD bBypass, nParamSize;
|
|
float* pParam = NULL;
|
|
bool bAdd = true;
|
|
|
|
fread( &iFx, sizeof(int), 1, pFile );
|
|
fread( &iPreset, sizeof(int), 1, pFile );
|
|
fread( &bBypass, sizeof(WORD), 1, pFile );
|
|
fread( &nParamSize, sizeof(WORD), 1, pFile );
|
|
if( nParamSize>0 ){
|
|
pParam = new float[nParamSize];
|
|
fread( pParam, sizeof(float), nParamSize, pFile );
|
|
}
|
|
|
|
if( iFx >= FX_VST ){
|
|
DWORD uniqueID = 0, pluginID = 0;
|
|
fread( &uniqueID, sizeof(DWORD), 1, pFile );
|
|
|
|
if( iPreset>=0 )
|
|
fread( &pluginID, sizeof(int), 1, pFile );
|
|
|
|
bAdd = false;
|
|
for( int k=0; k<g_lstVSTFx.size(); k++ ){
|
|
if( uniqueID==g_lstVSTFx[k]->uniqueID ){
|
|
iFx = FX_VST + k;
|
|
|
|
if( iPreset<0 ){
|
|
bAdd = true;
|
|
}
|
|
else{
|
|
for( int p=0; p<g_lstVSTFx[k]->aPlugins.size(); p++ ){
|
|
if( g_lstVSTFx[k]->aPlugins[p]->id==pluginID ){
|
|
iPreset = p;
|
|
bAdd = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bAdd ){
|
|
TAudioFx* pFx = new TAudioFx( iFx, iPreset, pParam, nParamSize, bBypass );
|
|
pAT->lstFxs.push_back( pFx );
|
|
}
|
|
else{
|
|
iError |= E_PROJ_INVALIDFX;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
BYTE bHide, bMute, iShow;
|
|
fread( &bHide, sizeof(BYTE), 1, pFile );
|
|
fread( &bMute, sizeof(BYTE), 1, pFile );
|
|
fread( &pAT->volume, sizeof(BYTE), 1, pFile );
|
|
fread( &iShow, sizeof(BYTE), 1, pFile );
|
|
|
|
if( bHide )
|
|
pAT->Hide();
|
|
if( bMute )
|
|
pAT->Mute();
|
|
|
|
for( int k=0; k<MAX_FX_NUM; k++ ){
|
|
int count;
|
|
fread(&count, sizeof(int), 1, pFile);
|
|
|
|
for( int j=0; j<count; j++ ){
|
|
TEffect pAE;
|
|
fread( &pAE.iBarStart, sizeof(int), 1, pFile );
|
|
fread( &pAE.iPointStart, sizeof(int), 1, pFile );
|
|
fread( &pAE.iBarEnd, sizeof(int), 1, pFile );
|
|
fread( &pAE.iPointEnd, sizeof(int), 1, pFile );
|
|
fread( &pAE.iPreset, sizeof(int), 1, pFile );
|
|
fread( &pAE.bOn, sizeof(bool), 1, pFile );
|
|
if( pAE.bOn ){
|
|
pAE.aParams = new float[6];
|
|
fread( pAE.aParams, sizeof(float), 6, pFile );
|
|
}
|
|
|
|
if( pAE.iBarStart==0 && pAE.iBarEnd>=pAT->lstBars.size()-1 ){
|
|
int iType = g_aAudioEffectTypes[k];
|
|
|
|
if( iType!=FX_PITCH ){
|
|
int nSize = GetFxParamNum( iType );
|
|
float* pParams = new float[nSize];
|
|
int iPreset = pAE.iPreset;
|
|
|
|
int nPresetCount = GetFxPresetCount( iType );
|
|
|
|
if( pAE.bOn )
|
|
memcpy( pParams, pAE.aParams, sizeof(float)*nSize );
|
|
else{
|
|
if( iPreset>=nPresetCount )
|
|
iPreset = 0;
|
|
|
|
GetFxPreset( iType, iPreset, pParams );
|
|
}
|
|
|
|
TAudioFx* pFx = new TAudioFx( iType, iPreset, pParams, nSize, !pAE.bOn );
|
|
pAT->lstFxs.push_back( pFx );
|
|
}
|
|
}
|
|
else{
|
|
iError |= E_PROJ_INVALIDFX;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return iError;
|
|
}
|
|
|
|
/***************************************************************************************/
|
|
// 全局函数
|
|
/***************************************************************************************/
|
|
|
|
TAudioTrack* NewAudioTrack( int nBar, bool bAddUndo )
|
|
{
|
|
TAudioTrack* pTrack = NULL;
|
|
|
|
if( g_aAudioTracks.size()<MAX_AUDIOTRACK ){
|
|
pTrack = new TAudioTrack;
|
|
g_aAudioTracks.push_back( pTrack );
|
|
|
|
if( g_aAudioTracks.size()>1 ){
|
|
int iTrack = g_aAudioTracks.size()-1;
|
|
|
|
for( int i=0; i<nBar; i++ ){
|
|
TWaveBar* pBar = new TWaveBar;
|
|
pTrack->lstBars.push_back( pBar );
|
|
}
|
|
|
|
if( bAddUndo ){
|
|
f_MM_AudioNewTrack();
|
|
|
|
g_Undo.AddUndo( UNDO_TRKAUD_ADD, iTrack, 0, 0, NULL, NULL );
|
|
|
|
f_MM_AddUndoBefore( 0, NULL );
|
|
f_MM_AddUndoAfter( 1, &iTrack );
|
|
}
|
|
|
|
g_aAudioTracks[0]->Hide();
|
|
}
|
|
|
|
PostMessage( Application->MainFormHandle, UM_ENABLERECORD, 0, 0 );
|
|
}
|
|
|
|
return pTrack;
|
|
}
|
|
|
|
void DeleteAudioTrack( int iTrack, bool bAddUndo )
|
|
{
|
|
if( iTrack>0 && iTrack>=g_aAudioTracks.size() )
|
|
return;
|
|
|
|
int num = 1, iDelTrk = iTrack;
|
|
TAudioTrackList* aTracks = NULL;
|
|
// TAudioTrack* aTracks = NULL;
|
|
|
|
if( iTrack<0 ){
|
|
if( g_iPreStage==0 ){
|
|
if( g_aAudioTracks[0]->lstBars.empty() )
|
|
return;
|
|
else
|
|
iDelTrk = 0;
|
|
}
|
|
else if( g_aAudioTracks.size()<=1 )
|
|
return;
|
|
}
|
|
|
|
if( iDelTrk<0 ){
|
|
int nBars = g_Opus.BarCount();
|
|
num = g_aAudioTracks.size()-1;
|
|
|
|
if( bAddUndo ){
|
|
aTracks = new TAudioTrackList;
|
|
// aTracks = new TAudioTrack[num];
|
|
int* aTrks = new int[num];
|
|
|
|
for( int i=0; i<num; i++ )
|
|
aTrks[i] = i+1;
|
|
|
|
f_MM_AddUndoBefore( num, aTrks );
|
|
|
|
delete[] aTrks;
|
|
}
|
|
|
|
for( int i=num; i>0; i-- ){
|
|
if( bAddUndo )
|
|
// g_Audio.CopyTrack( i, 0, nBars, true, &aTracks[i-1] );
|
|
aTracks->insert( aTracks->begin(), DuplicateAudioTrack( g_aAudioTracks[i] ));
|
|
|
|
f_MM_AudioDeleteTrack( i );
|
|
delete g_aAudioTracks.back();
|
|
g_aAudioTracks.pop_back();
|
|
}
|
|
}
|
|
else{
|
|
if( bAddUndo ){
|
|
aTracks = new TAudioTrackList;
|
|
|
|
aTracks->push_back( DuplicateAudioTrack( g_aAudioTracks[iDelTrk] ));
|
|
f_MM_AddUndoBefore( 1, &iDelTrk );
|
|
}
|
|
|
|
f_MM_AudioDeleteTrack( iDelTrk );
|
|
delete g_aAudioTracks[iDelTrk];
|
|
|
|
if( iDelTrk==0 )
|
|
g_aAudioTracks[0] = new TAudioTrack;
|
|
else
|
|
g_aAudioTracks.erase( g_aAudioTracks.begin() + iDelTrk );
|
|
}
|
|
|
|
if( bAddUndo ){
|
|
int iUndoType = iTrack<0 ? UNDO_TRKAUD_DELALL : UNDO_TRKAUD_DEL;
|
|
g_Undo.AddUndo( iUndoType, iDelTrk, -1, -1, (void*)aTracks, NULL );
|
|
}
|
|
|
|
PostMessage( Application->MainFormHandle, UM_ENABLERECORD, 0, 0 );
|
|
//Application->MainForm->Perform( UM_ENABLERECORD, 0, 0 );
|
|
}
|
|
|
|
void DuplicateRawBars()
|
|
{
|
|
if( g_aAudioTracks.size()>1 || g_aAudioTracks[0]->lstBars.empty() )
|
|
return;
|
|
|
|
TAudioTrack* pRaw = g_aAudioTracks[0];
|
|
TAudioTrack* pAT = DuplicateAudioTrack( pRaw );
|
|
|
|
g_aAudioTracks.push_back( pAT );
|
|
|
|
pRaw->Hide();
|
|
pAT->Hide(false);
|
|
|
|
f_MM_AudioNewTrack();
|
|
f_MM_SetStreamVolume( 0x10+1, pAT->IsMute() ? 0.0 : ( pAT->volume / 100.0) );
|
|
MoveAudio( 0, 0, pRaw->lstBars.size(), 1, 0, MODE_INSERT | OPT_BARS );
|
|
|
|
AudioEffectsSet( g_aAudioTracks.size()-1 );
|
|
}
|
|
|
|
TAudioTrack* DuplicateAudioTrack( TAudioTrack* pSrc )
|
|
{
|
|
if( !pSrc )
|
|
return NULL;
|
|
|
|
TAudioTrack* pNew = new TAudioTrack( pSrc );
|
|
|
|
//复制bars
|
|
for( int i=0; i<pSrc->lstBars.size(); i++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
memcpy( pWvBar->aVols, pSrc->lstBars[i]->aVols, sizeof(DWORD)*POINTS_PER_BAR );
|
|
pNew->lstBars.push_back( pWvBar );
|
|
}
|
|
|
|
for( int i=0; i<pSrc->lstFxs.size(); i++ ){
|
|
TAudioFx* pFx = new TAudioFx( pSrc->lstFxs[i] );
|
|
pNew->lstFxs.push_back( pFx );
|
|
}
|
|
|
|
return pNew;
|
|
}
|
|
|
|
bool MoveAudio( int iSrcTrack, double dblStart, double dblEnd,
|
|
int iDestTrack, double dblInsert, int iOption )
|
|
{
|
|
bool bMoveBars = iOption & OPT_BARS,
|
|
bCountDown = false;
|
|
|
|
int iMode = iOption & 0x0F;
|
|
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 );
|
|
|
|
TAudioTrack *pSrcTrack = iSrcTrack<0 ? NULL : g_aAudioTracks[iSrcTrack],
|
|
*pDestTrack = iDestTrack<0 ? NULL : g_aAudioTracks[iDestTrack];
|
|
|
|
if( bMoveBars ){ //小节操作
|
|
int nBarCount = iEndBar - iStartBar,
|
|
iDelBar = iStartBar;
|
|
|
|
if( iMode==MODE_MOVE || iMode==MODE_COPY || iMode==MODE_INSERT ){
|
|
TWaveBarList lstCopyBars;
|
|
|
|
for( int i=iStartBar; i<iEndBar; i++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
if( pSrcTrack )
|
|
memcpy( pWvBar->aVols, pSrcTrack->lstBars[i]->aVols,
|
|
sizeof(DWORD)*POINTS_PER_BAR );
|
|
|
|
lstCopyBars.push_back( pWvBar );
|
|
}
|
|
|
|
InsertWaveBars( iDestTrack, iInsertBar, lstCopyBars );
|
|
|
|
if( iMode==MODE_MOVE && iInsertBar<iStartBar )
|
|
iDelBar += nBarCount;
|
|
|
|
f_MM_AudioMove( iDestTrack, dblInsert, iSrcTrack, dblStart, dblEnd, MODE_INSERT );
|
|
}
|
|
|
|
if( iMode == MODE_DELETE || iMode == MODE_MOVE ){
|
|
RemoveWaveBars( iSrcTrack, iDelBar, nBarCount );
|
|
|
|
f_MM_AudioMove( -1, 0, iSrcTrack, iDelBar, iDelBar+nBarCount, MODE_DELETE );
|
|
}
|
|
}
|
|
else{ //音频操作
|
|
if( iSrcTrack==iDestTrack && iStartBar==iInsertBar && iStartPoint==iInsertPoint ) //无需移动
|
|
return false;
|
|
|
|
int nPoints = (int)( (dblEnd-dblStart) * POINTS_PER_BAR + 0.5 );
|
|
double dblDelStart = dblStart, dblDelEnd = dblEnd;
|
|
DWORD* aWave = iMode==MODE_ERASE ? NULL : new DWORD[nPoints];
|
|
|
|
if( pSrcTrack ){
|
|
int iPoint = 0;
|
|
|
|
for( int i=iStartBar; i<=iEndBar; i++ ){
|
|
int iSP = 0, iEP = POINTS_PER_BAR;
|
|
if( i==iStartBar )
|
|
iSP = iStartPoint;
|
|
if( i==iEndBar )
|
|
iEP = iEndPoint;
|
|
|
|
if( iEP>iSP ){
|
|
int lenP = iEP - iSP;
|
|
if( iMode==MODE_MOVE || iMode==MODE_COPY )
|
|
memcpy( aWave + iPoint, pSrcTrack->lstBars[i]->aVols + iSP,
|
|
sizeof(DWORD) * lenP );
|
|
|
|
if( iMode==MODE_MOVE || iMode==MODE_ERASE )
|
|
memset( pSrcTrack->lstBars[i]->aVols + iSP, 0,
|
|
sizeof(DWORD) * lenP );
|
|
|
|
iPoint += lenP;
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( iMode==MODE_MOVE || iMode==MODE_COPY ){
|
|
if( iDestTrack==0 ){ //处理增加长度
|
|
double dblMinLen = dblInsert + dblEnd - dblStart;
|
|
if( dblMinLen > pDestTrack->lstBars.size() ){
|
|
int nBars = (int)dblMinLen;
|
|
if( dblMinLen - nBars > 0 )
|
|
nBars++;
|
|
|
|
for( int i=pDestTrack->lstBars.size(); i<nBars; i++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
pDestTrack->lstBars.push_back( pWvBar );
|
|
}
|
|
}
|
|
}
|
|
|
|
int iPoint = 0;
|
|
while( iPoint<nPoints ){
|
|
int iSP = 0, iEP = POINTS_PER_BAR;
|
|
|
|
if( iInsertPoint>0 ){
|
|
iSP = iInsertPoint;
|
|
|
|
if( iSP + nPoints - iPoint < POINTS_PER_BAR )
|
|
iEP = iSP + nPoints - iPoint;
|
|
}
|
|
else if( nPoints-iPoint < POINTS_PER_BAR ){
|
|
iEP = nPoints - iPoint;
|
|
}
|
|
|
|
if( iEP > iSP ){
|
|
int lenP = iEP - iSP;
|
|
memcpy( pDestTrack->lstBars[iInsertBar]->aVols + iInsertPoint,
|
|
aWave + iPoint, sizeof(DWORD) * lenP );
|
|
|
|
iInsertPoint = 0;
|
|
iInsertBar++;
|
|
iPoint += lenP;
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete[] aWave;
|
|
}
|
|
|
|
f_MM_AudioMove( iDestTrack, dblInsert, iSrcTrack, dblStart, dblEnd, iMode );
|
|
|
|
if( g_iSelAudio==0 )
|
|
PostMessage( Application->MainForm->Handle, UM_AUTORECOGNITION, iMode, 0 );
|
|
}
|
|
|
|
return bCountDown;
|
|
}
|
|
|
|
int CopyWave( int iTrack, int iStartBar, int iStartPoint,
|
|
int iEndBar, int iEndPoint, DWORD** aWave )
|
|
{
|
|
bool bT2A = *aWave==NULL;
|
|
int nSelPoints = ( iEndBar - iStartBar - 1) * POINTS_PER_BAR
|
|
+ (POINTS_PER_BAR - iStartPoint) + iEndPoint;
|
|
|
|
if( bT2A ){
|
|
*aWave = new DWORD[nSelPoints];
|
|
}
|
|
|
|
TAudioTrack* pTrack = g_aAudioTracks[iTrack];
|
|
int iPoint = 0;
|
|
|
|
for( int i=iStartBar; i<=iEndBar; i++ ){
|
|
int iSP = 0, iEP = POINTS_PER_BAR;
|
|
if( i==iStartBar )
|
|
iSP = iStartPoint;
|
|
if( i==iEndBar )
|
|
iEP = iEndPoint;
|
|
|
|
if( iEP>iSP ){
|
|
char *pSrc = (char*)( bT2A ? pTrack->lstBars[i]->aVols+iSP : (*aWave)+iPoint ),
|
|
*pDest = (char*)( bT2A ? (*aWave)+iPoint : pTrack->lstBars[i]->aVols+iSP );
|
|
|
|
memcpy( pDest, pSrc, sizeof(DWORD) * ( iEP - iSP ));
|
|
|
|
iPoint += iEP - iSP;
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return nSelPoints;
|
|
}
|
|
|
|
void RemoveWaveBars( int iTrack, int iStartBar, int nDelBars )
|
|
{
|
|
TAudioTrack* pTrack = g_aAudioTracks[iTrack];
|
|
|
|
for( int i=0; i<nDelBars; i++ ){
|
|
delete pTrack->lstBars[iStartBar];
|
|
pTrack->lstBars.erase( pTrack->lstBars.begin()+iStartBar );
|
|
}
|
|
}
|
|
|
|
void InsertWaveBars( int iTrack, int iInsertBar, TWaveBarList lstBars )
|
|
{
|
|
TAudioTrack* pTrack = g_aAudioTracks[iTrack];
|
|
|
|
if( pTrack->lstBars.size()>0 && iInsertBar < pTrack->lstBars.size() ){
|
|
for( int i=lstBars.size()-1; i>=0; i-- ){
|
|
pTrack->lstBars.insert( pTrack->lstBars.begin()+iInsertBar, lstBars[i] );
|
|
}
|
|
}
|
|
else{
|
|
for( int i=0; i<lstBars.size(); i++ ){
|
|
pTrack->lstBars.push_back( lstBars[i] );
|
|
}
|
|
}
|
|
}
|
|
|
|
void RestoreWaveBars( int iInsBar, int nBars, DWORD* aWave )
|
|
{
|
|
int nPoints = nBars * POINTS_PER_BAR;
|
|
|
|
for( int i=1; i<g_aAudioTracks.size(); i++ ){
|
|
DWORD* pW = aWave ? aWave + nPoints * ( i - 1 ) : NULL;
|
|
TWaveBarList lstWaveBars;
|
|
|
|
for( int j=0; j<nBars; j++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
|
|
if( pW )
|
|
memcpy( pWvBar->aVols, pW + j * POINTS_PER_BAR,
|
|
sizeof(DWORD)*POINTS_PER_BAR );
|
|
|
|
lstWaveBars.push_back( pWvBar );
|
|
}
|
|
|
|
InsertWaveBars( i, iInsBar, lstWaveBars );
|
|
}
|
|
}
|
|
|
|
TAudioTrack* CopyAudioTrack( int iTrack, int iStartBar, int nCopyBars )
|
|
{
|
|
TAudioTrack* pSrcTrack = g_aAudioTracks[iTrack],
|
|
*pDestTrack = new TAudioTrack(pSrcTrack);
|
|
|
|
for( int i=0; i<nCopyBars; i++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
memcpy( pWvBar->aVols, pSrcTrack->lstBars[iStartBar+i],
|
|
sizeof(DWORD)*POINTS_PER_BAR );
|
|
pDestTrack->lstBars.push_back( pWvBar );
|
|
}
|
|
|
|
return pDestTrack;
|
|
}
|
|
|
|
void InsertAudioTrack( int iTrack, int iInsertBar, int nBars, TAudioTrack* pSrcTrack, int iStartBar )
|
|
{
|
|
TAudioTrack* pDestTrack = g_aAudioTracks[iTrack];
|
|
|
|
if( pDestTrack->lstBars.size()>0 && iInsertBar < pDestTrack->lstBars.size() ){
|
|
for( int i=nBars-1; i>=0; i-- ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
|
|
if( pSrcTrack )
|
|
memcpy( pWvBar->aVols, pSrcTrack->lstBars[iStartBar+i], sizeof(DWORD)*POINTS_PER_BAR );
|
|
|
|
pDestTrack->lstBars.insert( pDestTrack->lstBars.begin()+iInsertBar, pWvBar );
|
|
}
|
|
}
|
|
else{
|
|
for( int i=0; i<nBars; i++ ){
|
|
TWaveBar* pWvBar = new TWaveBar;
|
|
|
|
if( pSrcTrack )
|
|
memcpy( pWvBar->aVols, pSrcTrack->lstBars[iStartBar+i], sizeof(DWORD)*POINTS_PER_BAR );
|
|
|
|
pDestTrack->lstBars.push_back( pWvBar );
|
|
}
|
|
}
|
|
}
|