1044 lines
24 KiB
C++
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;
|
|
}
|
|
|