Files
AC_Pro/AudioTrack.cpp
T
2026-06-13 00:05:19 +08:00

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 );
}
}
}