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

1044 lines
24 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GlobalUnit.h"
#include "StyleItem.h"
#include "Compose.h"
#include "Project.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
/***************************************************************************************/
// 全局变量
/***************************************************************************************/
int g_iMelodyKey = -1; //主旋律调号
float g_fMusicVolume = 1; //伴奏音量
bool g_bComposeMute = false; //伴奏静音
TTheme g_Theme; //主旋律对象
TOpus g_Opus; //全曲对象
TOpusStageList& g_lstOpusStages = g_Opus.StageList(); //曲式结构段落表
vector<UINT> g_lstPaidStyleIDs; //当前工程本次使用已支付风格ID列表
/***************************************************************************************/
// TCompose类函数
void TCompose::ClearStages()
{
while( m_lstStages.size()>0 ){
delete m_lstStages.back();
m_lstStages.pop_back();
}
m_nBarCount = 0;
}
void TCompose::Clear()
{
ClearStages();
m_idLoc = m_idStyle = -1;
}
TOpusStage* TCompose::CopyStageAt( int iStage )
{
if( iStage<0 || iStage>m_lstStages.size() )
return NULL;
TOpusStage *pSrcStage = m_lstStages[iStage],
*pNewStage = new TOpusStage( pSrcStage );
for( int j=0; j<pSrcStage->aBars.size(); j++ ){
pNewStage->aBars.push_back( new TBar( pSrcStage->aBars[j] ));
}
for( int j=0; j<pSrcStage->aTracks.size(); j++ ){
pNewStage->aTracks.push_back( new TTrack( pSrcStage->aTracks[j] ));
}
return pNewStage;
}
void TCompose::WriteProj( LOCSEGLIST& lstLocSeg, FILE* pFile )
{
fwrite(&m_idLoc, sizeof(UINT), 1, pFile);
fwrite(&m_idStyle, sizeof(UINT), 1, pFile);
SaveOpusStages( m_lstStages, lstLocSeg, pFile );
}
int TCompose::ReadProj( STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion )
{
fread(&m_idLoc, sizeof(UINT), 1, pFile);
fread(&m_idStyle, sizeof(UINT), 1, pFile);
int ret = LoadOpusStages( m_lstStages, aUnsolvedStyles, pFile, dwVersion );
if( E_PROJ_FATALERROR>(DWORD)ret ){
m_nBarCount = ret;
ret = E_PROJ_NOERROR;
}
else{
Clear();
}
return ret;
}
void TCompose::SetTempStyle( UINT idLoc, UINT idStyle, int idSet )
{
if( m_idLoc==idLoc && m_idStyle==idStyle ){
m_idLoc = -1;
m_idStyle = idSet;
}
for( int s=0; s<m_lstStages.size(); s++ ){
TOpusStage* pStage = m_lstStages[s];
for( int t=0; t<pStage->aTracks.size(); t++ ){
TTrack* pTrack = pStage->aTracks[t];
if( pTrack->iStyleLoc==idLoc && pTrack->iStyleId==idStyle ){
pTrack->iStyleLoc = -1;
pTrack->iStyleId = idSet;
}
}
}
}
void TCompose::Set( UINT idLoc, UINT idStyle, TOpusStageList& lstStages )
{
ClearStages();
m_idLoc = idLoc;
m_idStyle = idStyle;
for( int i=0; i<lstStages.size(); i++ ){
TOpusStage *pSrcStage = lstStages[i],
*pNewStage = new TOpusStage( pSrcStage );
int nBars = pSrcStage->aBars.size();
for( int j=0; j<nBars; j++ ){
pNewStage->aBars.push_back( new TBar( pSrcStage->aBars[j] ));
}
m_nBarCount += nBars;
for( int j=0; j<pSrcStage->aTracks.size(); j++ ){
pNewStage->aTracks.push_back( new TTrack( pSrcStage->aTracks[j] ));
}
m_lstStages.push_back( pNewStage );
}
}
void TCompose::Get( UINT& idLoc, UINT& idStyle, TOpusStageList& lstStages )
{
idLoc = m_idLoc;
idStyle = m_idStyle;
for( int i=0; i<m_lstStages.size(); i++ ){
lstStages.push_back( CopyStageAt(i) );
}
}
void TCompose::GetSpecBanks( vector<BYTE>& lstBank )
{
for( int s=0; s<m_lstStages.size(); s++ ){
TOpusStage* pStage = m_lstStages[s];
for( int t=0; t<pStage->aTracks.size(); t++ ){
TTrack* pTrack = pStage->aTracks[t];
if( pTrack->iBank!=0xFF ){
bool bAdd = true;
for( int b=0; b<lstBank.size(); b++ ){
if( pTrack->iBank==lstBank[b] ){
bAdd = false;
break;
}
}
if( bAdd )
lstBank.push_back( pTrack->iBank );
}
}
}
}
void TCompose::SetSpecBanks( BANKMAPLIST& lstMap )
{
for( int s=0; s<m_lstStages.size(); s++ ){
TOpusStage* pStage = m_lstStages[s];
for( int t=0; t<pStage->aTracks.size(); t++ ){
TTrack* pTrack = pStage->aTracks[t];
if( pTrack->iBank!=0xFF ){
for( int b=0; b<lstMap.size(); b++ ){
TBankMap* pMap = lstMap[b];
if( pTrack->iBank==pMap->iBankOld ){
pTrack->iBank = pMap->iBankNew;
break;
}
}
}
}
}
}
/***************************************************************************************/
// TTheme类函数
TTheme::TTheme() : TCompose()
{
m_bWeakup = false;
m_iKey = -1;
}
void TTheme::Clear()
{
TCompose::Clear();
m_iKey = -1;
m_bWeakup = false;
}
void TTheme::Set( UINT idLoc, UINT idStyle, TOpusStageList& lstStages )
{
TCompose::Set( idLoc, idStyle, lstStages );
m_iKey = g_iMelodyKey;
if( lstStages.size()>0 ){
TOpusStage* pSrcStage = m_lstStages[0];
if( m_bWeakup && pSrcStage->aBars.size()>1 ){
TOpusStage* pWeakStage = new TOpusStage( pSrcStage );
pWeakStage->aBars.push_back( pSrcStage->aBars[0] );
pSrcStage->aBars.erase( pSrcStage->aBars.begin() );
for( int j=0; j<pSrcStage->aTracks.size(); j++ ){
pWeakStage->aTracks.push_back( new TTrack( pSrcStage->aTracks[j] ));
}
m_lstStages.insert( m_lstStages.begin(), pWeakStage );
}
}
}
void TTheme::Set( TOpusStageList& lstStages )
{
TCompose::Set( m_idLoc, m_idStyle, lstStages );
}
void TTheme::Build( TBarList& lstBars, vector<int>&lstStages )
{
Clear();
m_iKey = g_iMelodyKey;
TStyleItem* pStyItem = g_pPreStyle;
int nSegNum[4];
vector<TSegmentItem*> aSegments[4];
memset( nSegNum, 0, sizeof(int)*4 );
if( pStyItem ){
if( pStyItem->pStyle ){
m_idLoc = pStyItem->pStyle->idLoc;
m_idStyle = pStyItem->pStyle->idStyle;
}
else{
m_idLoc = -1;
m_idStyle = 0;
}
if( pStyItem->aItems->Count==0 ){
TPROSTYLE* info = pStyItem->pStyle;
for( int s=0; s<SEGTYPE_TRACK; s++ ){
int rep = s<SEGTYPE_INTRO ? 1 : 2;
for( int r=0; r<rep; r++ ){
int numSeg = info->idLoc==0 ? info->pOrigin->detail.nSegNum[s]
: info->idLoc==1 ? info->pShare->nSegNum[s]
: info->pLocal->nSegNum[s];
int num = s<SEGTYPE_INTRO ? numSeg
: r==0 ? ( numSeg & 0x0F )
: ( numSeg>>4 );
if( num>0 ){
DWORD opts = OPT_DEL | OPT_VOL | (s<SEGTYPE_INTRO ? OPT_BRUSH : 0);
for( int i=0; i<num; i++ ){
int sn = r==0 ? i : i+4;
int vol = info->idLoc==0 ? 100
: info->idLoc==1 ? info->pShare->nSegVol[s][sn]
: info->pLocal->nSegVol[s][sn];
TSegmentItem* pSegItem = pStyItem->AddSegment( s, sn, opts, 0, -1, vol, false );
DWORD dwTrkOpt = OPT_DEL|OPT_FONTPROG|OPT_VOL;
if( s<SEGTYPE_INTRO )
dwTrkOpt |= OPT_TEXTURE;
for( int j=0; j<16; j++ ){
pSegItem->AddTrack( info, sn, j, dwTrkOpt, true );
}
if( pSegItem->aItems->Count>0 ){
if( s==SEGTYPE_INTRO ){
pSegItem->nBars = info->idLoc==0 ? info->pOrigin->detail.aIntroBars[sn]
: info->idLoc==1 ? info->pShare->aIEBars[0][sn]
: info->pLocal->aIEBars[0][sn];
}
else if( s==SEGTYPE_ENDING ){
pSegItem->nBars = info->idLoc==0 ? info->pOrigin->detail.aEndingBars[sn]
: info->idLoc==1 ? info->pShare->aIEBars[1][sn]
: info->pLocal->aIEBars[1][sn];
}
aSegments[s].push_back( pSegItem );
nSegNum[s]++;
}
else{
pStyItem->DeleteSegment( pSegItem );
}
}
}
}
}
}
else{
for( int i=0; i<pStyItem->aItems->Count; i++ ){
TSegmentItem* pSegment = (TSegmentItem*)pStyItem->aItems->Items[i];
int stype = pSegment->GetSegType();
aSegments[stype].push_back( pSegment );
nSegNum[stype]++;
}
}
}
if( lstStages.size()>1 && lstStages[0]==0 )
m_bWeakup = true;
else
m_bWeakup = false;
int iSegNo = 0, iBar = 0;
for( int i=0; i<lstStages.size(); i++ ){
TOpusStage* pStage = new TOpusStage;
pStage->iSegKey = g_iMelodyKey;
pStage->iSegType = SEGTYPE_VAR;
pStage->nVol = 100;
pStage->iSegNo = -1;
int nBar = lstStages[i] - iBar + 1;
for( int j=0; j<nBar; j++ ){
pStage->aBars.push_back( lstBars[iBar++] );
}
if( nSegNum[SEGTYPE_VAR]==0 ){
delete pStage;
}
else{
TSegmentItem* pSegment = aSegments[SEGTYPE_VAR][iSegNo];
pStage->nVol = pSegment->volume;
pStage->iSegNo = pSegment->iSegNo;
ProduceTracks( pStage, pSegment );
m_lstStages.push_back( pStage );
m_nBarCount += nBar;
if( nSegNum[SEGTYPE_FILL]>0 && nBar>1 && i<lstStages.size()-1 ){
int iFill = iSegNo % nSegNum[SEGTYPE_FILL];
TSegmentItem *pSegFill = aSegments[SEGTYPE_FILL][iFill];
TOpusStage * pFillStage = new TOpusStage;
pFillStage->iSegKey = g_iMelodyKey;
pFillStage->iSegType = SEGTYPE_FILL;
pFillStage->iSegNo = pSegFill->iSegNo;
pFillStage->nVol = pSegFill->volume;
pFillStage->aBars.push_back( pStage->aBars.back() );
pStage->aBars.pop_back();
ProduceTracks( pFillStage, pSegFill );
m_lstStages.push_back( pFillStage );
}
if( iBar>1 && iSegNo < nSegNum[SEGTYPE_VAR]-1 )
iSegNo = (iSegNo + 1) % nSegNum[SEGTYPE_VAR];
}
}
}
int TTheme::GetFirstChord()
{
int iStage = m_bWeakup ? 1 : 0;
return MAKELONG( m_lstStages[iStage]->aBars[0]->aChords.iType[0],
m_lstStages[iStage]->aBars[0]->aChords.iKey[0] );
}
int TTheme::GetLastChord()
{
return MAKELONG( m_lstStages.back()->aBars.back()->aChords.iType[g_nChordNumPerBar-1],
m_lstStages.back()->aBars.back()->aChords.iKey[g_nChordNumPerBar-1] );
}
void TTheme::WriteProj( LOCSEGLIST& lstLocSeg, FILE* pFile )
{
fwrite(&m_iKey, sizeof(int), 1, pFile);
fwrite(&m_bWeakup, sizeof(bool), 1, pFile);
TCompose::WriteProj( lstLocSeg, pFile );
}
int TTheme::ReadProj( STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion )
{
fread(&m_iKey, sizeof(int), 1, pFile);
fread(&m_bWeakup, sizeof(bool), 1, pFile);
return TCompose::ReadProj( aUnsolvedStyles, pFile, dwVersion );
}
/***************************************************************************************/
// TOpus类函数
TOpus::TOpus()
{
m_bModified = false;
m_iKeyBk = -1;
}
TOpus::~TOpus()
{
ClearBackup();
}
void TOpus::ClearBackup()
{
m_bModified = false;
m_iKeyBk = -1;
while( m_lstStagesBk.size()>0 ){
delete m_lstStagesBk.back();
m_lstStagesBk.pop_back();
}
}
void TOpus::Clear()
{
TCompose::Clear();
ClearBackup();
m_aStageBars.clear();
}
void TOpus::Set( UINT idLoc, UINT idStyle, TOpusStageList& lstStages )
{
TCompose::Set( idLoc, idStyle, lstStages );
CountBars();
}
void TOpus::WriteProj( LOCSEGLIST& lstLocSeg, FILE* pFile )
{
m_idLoc = (g_pUseStyle && g_pUseStyle->pStyle) ? g_pUseStyle->pStyle->idLoc : 0;
m_idStyle = (g_pUseStyle && g_pUseStyle->pStyle) ? g_pUseStyle->pStyle->idStyle : 0;
TCompose::WriteProj( lstLocSeg, pFile );
}
int TOpus::ReadProj( STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion )
{
int ret = TCompose::ReadProj( aUnsolvedStyles, pFile, dwVersion );
if( ret==E_PROJ_NOERROR ){
CountBars();
}
return ret;
}
void TOpus::Backup()
{
ClearBackup();
m_iKeyBk = g_iMelodyKey;
for( int i=0; i<m_lstStages.size(); i++ ){
TOpusStage *pNewStage = new TOpusStage;
TOpusStage *pBkStage = m_lstStages[i];
pNewStage->iSegKey = pBkStage->iSegKey;
pNewStage->iSegType = pBkStage->iSegType;
pNewStage->iSegNo = pBkStage->iSegNo;
pNewStage->nVol = pBkStage->nVol;
for( int j=0; j<pBkStage->aBars.size(); j++ ){
TBar* pBar = new TBar;
pBar->iBarKey = pBkStage->aBars[j]->iBarKey;
memcpy( &pBar->aChords,
&pBkStage->aBars[j]->aChords,
sizeof(TBarChords) );
pNewStage->aBars.push_back( pBar );
}
for( int j=0; j<pBkStage->aTracks.size(); j++ ){
TTrack * pTrack = new TTrack;
memcpy( pTrack, pBkStage->aTracks[j], sizeof(TTrack) );
pNewStage->aTracks.push_back( pTrack );
}
m_lstStagesBk.push_back( pNewStage );
}
m_bModified = false;
}
BOOL TOpus::CheckModified( int iCheckType )
{
if( iCheckType==CHECK_GET ){
return m_bModified;
}
m_bModified &= ~iCheckType;
if( iCheckType & CHECK_KEY ){
if( m_iKeyBk!=g_iMelodyKey ){
m_bModified |= CHECK_KEY;
}
}
if( !(m_bModified & CHECK_KEY) && ( iCheckType & CHECK_STAGE) ){
if( m_lstStagesBk.size()!=m_lstStages.size() ){
m_bModified |= CHECK_STAGE;
}
}
if( !(m_bModified & CHECK_STAGE) && (iCheckType & CHECK_STAGE || iCheckType & CHECK_TRACK
|| iCheckType & CHECK_CHORD )){
for( int i=0; i<m_lstStagesBk.size(); i++ ){
TOpusStage* pOpStage = m_lstStages[i];
TOpusStage* pBkStage = m_lstStagesBk[i];
if( !(m_bModified & CHECK_STAGE) && (iCheckType & CHECK_STAGE)
|| !(m_bModified & CHECK_CHORD) && iCheckType & CHECK_CHORD ){
if( pOpStage->aBars.size()!=pBkStage->aBars.size()
|| pOpStage->iSegType!=pBkStage->iSegType
|| pOpStage->nVol!=pBkStage->nVol
|| pOpStage->iSegKey!=pBkStage->iSegKey ){
m_bModified |= CHECK_STAGE;
}
else if(iCheckType & CHECK_CHORD && pBkStage->iSegType<=SEGTYPE_FILL ){
for( int j=0; j<pBkStage->aBars.size(); j++ ){
TBarChords* pOpBar = &pOpStage->aBars[j]->aChords;
TBarChords* pBkBar = &pBkStage->aBars[j]->aChords;
if( memcmp( pOpBar, pBkBar, sizeof(TBarChords ))){
m_bModified |= CHECK_CHORD;
break;
}
}
}
}
if( !(m_bModified & CHECK_TRACK) && (iCheckType & CHECK_TRACK) ){
if( pOpStage->aTracks.size()!=pBkStage->aTracks.size() ){
m_bModified |= CHECK_TRACK;
}
else{
for( int j=0; j<pBkStage->aTracks.size(); j++ ){
TTrack* pOpTrack = pOpStage->aTracks[j];
TTrack* pBkTrack = pBkStage->aTracks[j];
if( pOpTrack->iStyleId!=pBkTrack->iStyleId
|| pOpTrack->iStyleLoc!=pBkTrack->iStyleLoc
|| pOpTrack->iSegNo!=pBkTrack->iSegNo
|| pOpTrack->iChanNo!=pBkTrack->iChanNo
|| pOpTrack->iFile!=pBkTrack->iFile
|| pOpTrack->iBank!=pBkTrack->iBank
|| pOpTrack->iChanSpec!=pBkTrack->iChanSpec ){
m_bModified |= CHECK_TRACK;
break;
}
if( (iCheckType & CHECK_PROG) && pOpTrack->iProg!=pBkTrack->iProg ){
m_bModified |= CHECK_PROG;
break;
}
if( (iCheckType & CHECK_VOL) && pOpTrack->nVol!=pBkTrack->nVol ){
m_bModified |= CHECK_VOL;
break;
}
}
}
}
}
}
return m_bModified;
}
void TOpus::BuildStyleItem()
{
if( m_lstStages.empty() ){
g_pUseStyle = NULL;
return;
}
TPROSTYLE* info = GetStyleInfo( m_idLoc, m_idStyle );
TStyleItem* pSty = new TStyleItem( info, 0 );
for( int i=0; i<m_lstStages.size(); i++ ){
TOpusStage* pStage = m_lstStages[i];
int ind = 0;
DWORD opts = OPT_DEL|OPT_VOL;
if( pStage->iSegType<=SEGTYPE_FILL ){
ind = pSty->nSegNum[0] + pSty->nSegNum[1];
opts |= OPT_BRUSH;
}
else
ind = pSty->nSegNum[pStage->iSegType];
TSegmentItem* pSegItem = pSty->AddSegment( pStage->iSegType,
pStage->iSegNo,
opts,
pStage->aBars.size(),
ind,
pStage->nVol,
false );
opts = OPT_DEL|OPT_FONTPROG|OPT_VOL;
if( pStage->iSegType<=SEGTYPE_FILL )
opts |= OPT_TEXTURE;
for( int j=0; j<pStage->aTracks.size(); j++ ){
TTrack* pTrack = pStage->aTracks[j];
int idLoc = pTrack->iStyleLoc,
idStyle = pTrack->iStyleId;
TPROSTYLE* pStyle = GetStyleInfo( idLoc, idStyle );
if( !pStyle ){
DebugPrint( "风格文件已失效!\n" );
delete pTrack;
pStage->aTracks.erase( pStage->aTracks.begin() + j );
j--;
continue;
}
pSegItem->AddTrack( pStyle, pTrack, opts, false );
if( !info ){
pSty->pStyle = pStyle;
}
}
}
g_pUseStyle = pSty;
}
void TOpus::CopyStages( int iStartBar, int iEndBar, TOpusStageList* lstStages )
{
int iBar = iStartBar;
int iFirstBar, iSrcStage = FindStage( iBar, &iFirstBar );
while( iBar<=iEndBar ){
int nOffsetBar = iBar-iFirstBar;
TOpusStage* pOriStage = m_lstStages[iSrcStage];
int nCopyBar = pOriStage->aBars.size() - nOffsetBar;
if( nCopyBar>iEndBar-iBar+1 )
nCopyBar = iEndBar-iBar+1;
TOpusStage* pNewStage = new TOpusStage( pOriStage );
int iCopyEndBar = nOffsetBar + nCopyBar;
for( int i=nOffsetBar; i<iCopyEndBar; i++ ){
pNewStage->aBars.push_back( new TBar( pOriStage->aBars[i] ) );
}
for( int j=0; j<pOriStage->aTracks.size(); j++ ){
pNewStage->aTracks.push_back( new TTrack( pOriStage->aTracks[j] ));
}
lstStages->push_back( pNewStage );
iBar += nCopyBar;
iSrcStage++;
iFirstBar = iBar;
}
}
void TOpus::ChangeKey( int iBarStart, int iBarEnd, int iKey, int keys[] )
{
if( iBarStart<0 )
iBarStart = 0;
if( iBarEnd<0 )
iBarEnd = m_nBarCount - 1;
int iBar = iBarStart,
iFirstKey = -1;
while( iBar<=iBarEnd ){
int iFirstBar, iStage = FindStage( iBar, &iFirstBar );
TOpusStage* pStage = m_lstStages[iStage];
int iSetKey = keys!=NULL ? keys[iBar-iBarStart] : iKey;
if( iFirstKey<0 )
iFirstKey = iSetKey;
if( pStage->iSegType>=SEGTYPE_INTRO && iBar==iFirstBar ){
pStage->iSegKey = iSetKey;
iBar += pStage->aBars.size();
}
else{
int iStart = max( iBar, iFirstBar ),
iEnd = min( iBarEnd, (int)(iFirstBar + pStage->aBars.size() - 1) );
for( int i = iStart; i<=iEnd; i++ ){
TBar *pBar = pStage->aBars[i-iFirstBar];
int iDiff = iSetKey - pBar->iBarKey;
pBar->iBarKey = iSetKey;
for( int k=0; k<4; k++ ){
pBar->aChords.iKey[k] += iDiff;
if( pBar->aChords.iKey[k]>0x7F )
pBar->aChords.iKey[k] += KEY_NUM;
else if( pBar->aChords.iKey[k]>=KEY_NUM )
pBar->aChords.iKey[k] -= KEY_NUM;
}
}
iBar = iEnd + 1;
}
}
}
void TOpus::InsertStage( int iIns, TOpusStage* pStage )
{
int nBar = pStage->aBars.size();
if( iIns<0 || iIns>=StageCount() ){
m_lstStages.push_back( pStage );
int iBegin = m_nBarCount,
iEnd = iBegin + nBar - 1;
m_aStageBars.push_back( MAKELONG( iBegin, iEnd ) );
m_nBarCount += nBar;
}
else{
m_lstStages.insert( m_lstStages.begin()+iIns, pStage );
int iBegin = iIns==0 ? 0 : HIWORD(m_aStageBars[iIns-1]) + 1,
iEnd = iBegin + nBar - 1;
m_aStageBars.insert( m_aStageBars.begin()+iIns, MAKELONG( iBegin, iEnd ) );
for( int i=iIns+1; i<m_aStageBars.size(); i++ ){
iBegin = LOWORD(m_aStageBars[i]) + nBar;
iEnd = HIWORD(m_aStageBars[i]) + nBar;
m_aStageBars[i] = MAKELONG( iBegin, iEnd );
}
m_nBarCount += nBar;
}
}
void TOpus::RemoveStage( int iDel )
{
TOpusStage* pStage = m_lstStages[iDel];
int nBar = pStage->aBars.size();
delete pStage;
m_lstStages.erase( m_lstStages.begin() + iDel );
m_aStageBars.erase( m_aStageBars.begin() + iDel );
if( nBar>0 ){
for( int i=iDel; i<m_aStageBars.size(); i++ ){
int iBegin = LOWORD(m_aStageBars[i]) - nBar,
iEnd = HIWORD(m_aStageBars[i]) - nBar;
m_aStageBars[i] = MAKELONG( iBegin, iEnd );
}
m_nBarCount -= nBar;
}
}
void TOpus::CutStage( int iStage, int iCutBar )
{
int iFirstBar = LOWORD(m_aStageBars[iStage]),
iEndBar = HIWORD(m_aStageBars[iStage]);
if( iCutBar<=iFirstBar || iCutBar>iEndBar )
return;
TOpusStage* pOriStage = g_lstOpusStages[iStage];
TOpusStage* pCutStage = new TOpusStage;
pCutStage->iSegKey = pOriStage->iSegKey;
pCutStage->iSegNo = pOriStage->iSegNo;
pCutStage->iSegType = pOriStage->iSegType;
pCutStage->nVol = pOriStage->nVol;
for( int i=0; i<pOriStage->aTracks.size(); i++ ){
TTrack * pTrack = new TTrack( pOriStage->aTracks[i] );
pCutStage->aTracks.push_back( pTrack );
}
int nBarNum = pOriStage->aBars.size()-(iCutBar-iFirstBar);
for( int i=0; i<nBarNum; i++ ){
pCutStage->aBars.insert( pCutStage->aBars.begin(), pOriStage->aBars.back() );
pOriStage->aBars.pop_back();
}
m_lstStages.insert( m_lstStages.begin()+iStage+1, pCutStage );
m_aStageBars[iStage] = MAKELONG( iFirstBar, iCutBar-1 );
m_aStageBars.insert( m_aStageBars.begin()+iStage+1, MAKELONG(iCutBar, iEndBar) );
}
void TOpus::ChangeStageBar( int iStage, int nBar, bool bCount )
{
int iFirstBar = LOWORD(m_aStageBars[iStage]),
iEndBar = HIWORD(m_aStageBars[iStage]) + nBar;
m_aStageBars[iStage] = MAKELONG( iFirstBar, iEndBar );
if( bCount ){
for( int i=iStage+1; i<m_aStageBars.size(); i++ ){
int iBegin = LOWORD(m_aStageBars[i]) + nBar,
iEnd = HIWORD(m_aStageBars[i]) + nBar;
m_aStageBars[i] = MAKELONG( iBegin, iEnd );
}
m_nBarCount += nBar;
}
}
void TOpus::CountBars()
{
m_aStageBars.clear();
m_nBarCount = 0;
int iBegin = 0, iEnd = -1;
for( int i=0; i<m_lstStages.size(); i++ ){
TOpusStage* pStage = m_lstStages[i];
m_nBarCount += pStage->aBars.size();
iBegin = iEnd + 1;
iEnd += pStage->aBars.size();
m_aStageBars.push_back( MAKELONG( iBegin, iEnd ) );
}
}
int TOpus::FindStage( int iBar, int *piFirstBar )
{
if( iBar>=0 && iBar<m_nBarCount ){
for( int i=0; i<m_aStageBars.size(); i++ ){
int iSBegin = LOWORD(m_aStageBars[i]);
int iSEnd = HIWORD(m_aStageBars[i]);
if( iBar>=iSBegin && iBar<=iSEnd ){
if( piFirstBar )
*piFirstBar = iSBegin;
return i;
}
}
}
return -1;
}
int TOpus::StageFirstBar( int iStage )
{
if( iStage>=0 && iStage<m_aStageBars.size() ){
return LOWORD(m_aStageBars[iStage]);
}
return -1;
}
int TOpus::StageLastBar( int iStage )
{
if( iStage>=0 && iStage<m_aStageBars.size() ){
return HIWORD(m_aStageBars[iStage]);
}
return -1;
}
DWORD TOpus::StageRange( int iStage )
{
if( iStage>=0 && iStage<m_aStageBars.size() ){
return m_aStageBars[iStage];
}
return -1;
}
/***************************************************************************************/
// 全局函数
/***************************************************************************************/
int FindStage( int iBar, int *piFirstBar )
{
return g_Opus.FindStage( iBar, piFirstBar );
/* if( iBar>=0 && iBar<g_Opus.BarCount() ){
int nStageNum = g_lstOpusStages.size();
int nBarCount = 0;
for( int i=0; i<nStageNum; i++ ){
TOpusStage* pStage = g_lstOpusStages[i];
if( piFirstBar )
*piFirstBar = nBarCount;
nBarCount += pStage->aBars.size();
if( iBar<nBarCount ){
return i;
}
}
}
return -1;
*/
}
int FirstBar( int iStage )
{
return g_Opus.StageFirstBar( iStage );
/* if( iStage<0 || iStage>=g_lstOpusStages.size() )
return -1;
int nBarCount = 0;
for( int i=0; i<iStage; i++ ){
TOpusStage* pStage = g_lstOpusStages[i];
nBarCount += pStage->aBars.size();
}
return nBarCount;
*/
}
int GetBarCount()
{
return g_Opus.BarCount();
/* int nBarCount = 0;
for( int i=0; i<g_lstOpusStages.size(); i++ ){
TOpusStage* pStage = g_lstOpusStages[i];
nBarCount += pStage->aBars.size();
}
return nBarCount;
*/
}
int GetBarKey( int iBar )
{
int iFirstBar, iStage = FindStage( iBar, &iFirstBar );
if( iStage<0 )
return -1;
if( g_lstOpusStages[iStage]->iSegType>=SEGTYPE_INTRO )
return g_lstOpusStages[iStage]->iSegKey;
else
return g_lstOpusStages[iStage]->aBars[iBar-iFirstBar]->iBarKey;
}
TOpusStage* DuplicateStage( TOpusStage* pSrc )
{
TOpusStage* pNew = new TOpusStage( pSrc );
for( int j=0; j<pSrc->aBars.size(); j++ ){
pNew->aBars.push_back( new TBar( pSrc->aBars[j] ));
}
for( int j=0; j<pSrc->aTracks.size(); j++ ){
pNew->aTracks.push_back( new TTrack( pSrc->aTracks[j] ));
}
return pNew;
}
void ProduceTracks( TOpusStage* pStage, void* pSegItem )
{
TSegmentItem* pSeg = (TSegmentItem*)pSegItem;
for( int i=0; i<pSeg->aItems->Count; i++ ){
TTrackItem* pTrk = (TTrackItem*)pSeg->aItems->Items[i];
TTrack * pTrack = new TTrack( pTrk->pTrack );
pStage->aTracks.push_back( pTrack );
}
}
bool DiffStages( TOpusStage* pStage1, TOpusStage* pStage2, bool bPassSegNo,
bool bPassFile )
{
bool bDiff = true;
if( pStage1->iSegType==pStage2->iSegType
&& pStage1->iSegKey==pStage2->iSegKey
&& pStage1->nVol==pStage2->nVol
&& ( bPassSegNo || pStage1->iSegNo==pStage2->iSegNo )
&& pStage1->aTracks.size()==pStage2->aTracks.size() ){
bDiff = false;
if( !pStage1->aTracks.empty() ){
int num = pStage1->aTracks.size();
bool* aMatch = new bool[num];
memset( aMatch, false, sizeof(bool)*num );
for( int i=0; i<num; i++ ){
TTrack* pTrk1 = pStage1->aTracks[i];
bool bFound = false;
for( int j=0; j<num; j++ ){
TTrack* pTrk2 = pStage2->aTracks[j];
if( !aMatch[j] && pTrk1->iStyleId==pTrk2->iStyleId
&& pTrk1->iStyleLoc==pTrk2->iStyleLoc
&& pTrk1->iSegNo==pTrk2->iSegNo
&& pTrk1->iChanNo==pTrk2->iChanNo
&& pTrk1->iBank==pTrk2->iBank
&& pTrk1->iProg==pTrk2->iProg
&& pTrk1->nVol==pTrk2->nVol
&& ( bPassFile || pTrk1->iFile==pTrk2->iFile
|| pTrk1->iFile==0xFF
|| pTrk2->iFile==0xFF )){
bFound = true;
aMatch[j] = true;
break;
}
}
if( !bFound ){
bDiff = true;
break;
}
}
delete[] aMatch;
}
}
return bDiff;
}