//--------------------------------------------------------------------------- #include #pragma hdrstop #include "GlobalUnit.h" #include "Compose.h" #include "MidiTrack.h" //--------------------------------------------------------------------------- #pragma package(smart_init) /***************************************************************************************/ // 全局变量 /***************************************************************************************/ TMidi g_Midi; //MIDI轨道对象 TMidiTrackList& g_aMidiTracks = g_Midi.MidiTrackList(); //MIDI轨道列表 int g_iSelMidiTrack = -1; //当前处理的MIDI轨道 /***************************************************************************************/ // Midi类函数 void TMidi::ClearMidiTracks() { ClearMidiTrackNotes(); while( !m_lstMidiTracks.empty() ){ delete m_lstMidiTracks.back(); m_lstMidiTracks.pop_back(); } while( !m_aChnoUsed.empty() ){ delete m_aChnoUsed.back(); m_aChnoUsed.pop_back(); } m_nMidiFile = 0; } //--------------------------------------------------------------------------- void TMidi::ClearMidiTrackNotes() { for( int i=0; iaNotes.empty() ){ delete pTrack->aNotes.back(); pTrack->aNotes.pop_back(); } pTrack->ptMin = 0xFF; pTrack->ptMax = 0; } } //--------------------------------------------------------------------------- TMidiTrack* TMidi::FindMidiTrack( BYTE file, BYTE chno ) { for( int i=0; ifile==file && m_lstMidiTracks[i]->chno==chno ){ return m_lstMidiTracks[i]; } } return NULL; } //--------------------------------------------------------------------------- int TMidi::GetMidiTrackIndex( BYTE file, BYTE chno ) { for( int i=0; ifile==file && m_lstMidiTracks[i]->chno==chno ){ return i; } } return -1; } //--------------------------------------------------------------------------- void TMidi::SortMidiTracks() { /* ClearMidiTracks(); if( !g_pUseStyle ) return; TStyleItem* pStyleItem = g_pUseStyle; */ for( int i=0; iaTracks.size(); j++ ){ TTrack* pTrk = pStage->aTracks[j]; // BYTE ch = ( pTrk->iBank==0xFF || pTrk->iBank<0x80 ) ? pTrk->iChanNo // : pTrk->iChanSpec; TMidiTrack* pMT = GetValidMidiTrack( i, pTrk->iFile, pTrk->iChanSpec, pTrk->iBank, pTrk->iProg ); if( pTrk->iChanSpec!=pMT->chno || pTrk->iFile!=pMT->file ){ pTrk->iFile = pMT->file; pTrk->iChanSpec = pMT->chno; } } } #ifdef _DEBUG for( int k=0; kbank, pChannel->chno, pChannel->prog ); AnsiString strStages = " stages:"; for( int m=0; maStages.size(); m++ ){ strStages += " "; strStages += IntToStr( pChannel->aStages[m] ); } DebugPrint( "%s\n", strStages.c_str() ); } for( int m=0; mbank ); strStages += " used:"; for( int n=0; n<16; n++ ){ if( m_aChnoUsed[m]->chno & (1<file==file && pChUs->bank==bank ){ pCU = pChUs; break; } } if( !pCU ){ pCU = new TChnoUsed( bank, file ); AddChnoUsed( pCU ); } return pCU; } //--------------------------------------------------------------------------- BYTE TMidi::GetValidFile( BYTE bank, BYTE chno ) { WORD ch = ( 1<bank==bank && !(pChUs->chno & ch) ){ pCU = pChUs; break; } } if( !pCU ){ pCU = new TChnoUsed( bank, m_nMidiFile++ ); AddChnoUsed( pCU ); } pCU->chno |= ch; return pCU->file; } //--------------------------------------------------------------------------- TMidiTrack* TMidi::GetValidMidiTrack( int iStage, BYTE file, BYTE chno, BYTE bank, BYTE prog ) { vector aStages; aStages.push_back( iStage ); return GetValidMidiTrack( aStages, file, chno, bank, prog ); } //--------------------------------------------------------------------------- TMidiTrack* TMidi::GetValidMidiTrack( vector& lstStages, BYTE file, BYTE chno, BYTE bank, BYTE prog ) { TMidiTrack* pMidiTrack = NULL; vector aValidTracks; bool bVSTi = bank!=0xFF && bank>=0x80; if( file!=0xFF ){ TMidiTrack* pMT = FindMidiTrack( file, chno ); if( !pMT ){ pMidiTrack = new TMidiTrack( bank, chno, prog, file ); AddMidiTrack( pMidiTrack ); goto EXIT_LINE; } else if( pMT->bank==bank && (!bVSTi && ( pMT->chno==9 && chno==9 || pMT->chno!=9 && chno!=9 && pMT->prog==prog ) //GM的鼓通道或相同bank和prog || bVSTi && pMT->chno==chno ) //VSTi的通道相同 && pMT->ValidStages( lstStages ) ){ pMidiTrack = pMT; goto EXIT_LINE; } } for( int i=0; ibank && (!bVSTi && ( pMT->chno==9 && chno==9 || pMT->chno!=9 && chno!=9 && pMT->prog==prog ) //GM的鼓通道或相同bank和prog || bVSTi && pMT->chno==chno ) //VSTi的通道相同 && pMT->ValidStages( lstStages ) ){ pMidiTrack = pMT; goto EXIT_LINE; } } //未找到有效MidiTrack,新建 for( int i=0; ibank==bank ){ TChnoUsed* pCU = m_aChnoUsed[i]; if( bVSTi && ( pCU->chno & (1<chno & 0x200) || chno!=9 && (pCU->chno & 0xFDFF)!=0xFDFF ){ if( pCU->chno & (1<chno & (1<file ); AddMidiTrack( pMidiTrack ); goto EXIT_LINE; } } } EXIT_LINE: if( !pMidiTrack ){ pMidiTrack = new TMidiTrack( bank, chno, prog, m_nMidiFile++ ); AddMidiTrack( pMidiTrack ); } for( int i=0; iAddStage( lstStages[i] ); } return pMidiTrack; } //--------------------------------------------------------------------------- void TMidi::AddMidiTrack( TMidiTrack* pCh, int iInd ) { if( iInd>=0 && iIndfile ) m_nMidiFile = pCh->file+1; TChnoUsed* pCU = GetChnoUsed( pCh->file, pCh->bank ); pCU->chno |= ( 1 << pCh->chno ); } //--------------------------------------------------------------------------- void TMidi::AddChnoUsed( TChnoUsed* pCU ) { int m = 0; for( ; mbank > (char)pCU->bank ){ m_aChnoUsed.insert( m_aChnoUsed.begin()+m, pCU ); break; } } if( m==m_aChnoUsed.size() ) m_aChnoUsed.push_back( pCU ); } //--------------------------------------------------------------------------- void TMidi::DeleteMidiTrack( TMidiTrack* pCh ) { for( int i=0; ifile, pCh->bank ); pCU->chno &= ~( 1 << pCh->chno ); if( pCU->chno==0 ) DeleteChnoUsed( pCU ); delete pCh; m_lstMidiTracks.erase( m_lstMidiTracks.begin() + i ); break; } } } //--------------------------------------------------------------------------- void TMidi::DeleteChnoUsed( TChnoUsed* pCU ) { for( int i=0; iaStages.size()-1; j>=0; j-- ){ if( pMT->aStages[j]>iStage ) pMT->aStages[j]++; else if( pMT->aStages[j]==iStage ){ pMT->aStages.insert( pMT->aStages.begin()+j+1, iStage+1 ); break; } else break; } } } //--------------------------------------------------------------------------- void TMidi::InsertStage( int iStage ) { for( int i=0; iaStages.size()-1; j>=0; j-- ){ if( pMT->aStages[j]>=iStage ) pMT->aStages[j]++; else break; } } } //--------------------------------------------------------------------------- void TMidi::RemoveStage( int iStage, bool bSort ) { for( int i=0; iaStages.size()-1; j>=0; j-- ){ if( pMT->aStages[j]>iStage ){ if( bSort ) pMT->aStages[j]--; } else if( pMT->aStages[j]==iStage ) pMT->aStages.erase( pMT->aStages.begin()+j ); else break; } } } //--------------------------------------------------------------------------- int TMidi::ClearEmptyTrack() { int iFirstEmpty = -1; for( int i=m_lstMidiTracks.size()-1; i>=0; i-- ){ if( m_lstMidiTracks[i]->aStages.empty() ){ TMidiTrack* pMT = m_lstMidiTracks[i]; TChnoUsed* pCU = GetChnoUsed( pMT->file, pMT->bank ); pCU->chno &= ~( 1 << pMT->chno ); if( pCU->chno==0 ) DeleteChnoUsed( pCU ); delete pMT; m_lstMidiTracks.erase( m_lstMidiTracks.begin() + i ); iFirstEmpty = i; } } return iFirstEmpty; } //--------------------------------------------------------------------------- void TMidi::ChangMidiChno( int iMT, BYTE fiNew, BYTE chNew ) { TMidiTrack* pMT = m_lstMidiTracks[iMT]; for( int i=0; iaStages.size(); i++ ){ TOpusStage* pStage = g_lstOpusStages[pMT->aStages[i]]; for( int j=0; jaTracks.size(); j++ ){ TTrack* pTrack = pStage->aTracks[j]; if( pTrack->iFile==pMT->file && pTrack->iChanSpec==pMT->chno ){ pTrack->iFile = fiNew; pTrack->iChanSpec = chNew; break; } } } TChnoUsed* pCU = g_Midi.GetChnoUsed( pMT->file, pMT->bank ); pCU->chno &= ~( 1 << pMT->chno ); pMT->file = fiNew; pMT->chno = chNew; } //--------------------------------------------------------------------------- void TMidi::ChangeNotesVolume( int iMT, int iSBar, int iEBar, BYTE volume ) { TMidiTrack* pMT = m_lstMidiTracks[iMT]; int iTickS = iSBar * POINTS_PER_BAR, iTickE = iEBar * POINTS_PER_BAR; for( int i=0; iaNotes.size(); i++ ){ TMidiNote* pNote = pMT->aNotes[i]; if( pNote->tkOn < pNote->tkOff && pNote->tkOn < iTickE && pNote->tkOff > iTickS ){ pNote->volume = volume; } } } //--------------------------------------------------------------------------- TColor u_clrNote[64]; void TMidi::InitNoteColor() { int clrSeed[2][3] = {{52,101,100},{162,180,180}}; int r0 = clrSeed[0][0], r1 = clrSeed[1][0], g0 = clrSeed[0][1], g1 = clrSeed[1][1], b0 = clrSeed[0][2], b1 = clrSeed[1][2]; double dR = (r1-r0) / 64.0, dG = (g1-g0) / 64.0, dB = (b1-b0) / 64.0; u_clrNote[63] = RGB( r0, g0, b0 ); for (int i=62; i>0; i--){ r0 += dR; g0 += dG; b0 += dB; u_clrNote[i] = RGB( r0, g0, b0 ); } u_clrNote[0] = RGB( r1, g1, b1 ); } //--------------------------------------------------------------------------- TColor TMidi::GetNoteColor( int vol ) { return u_clrNote[vol>>1]; } //--------------------------------------------------------------------------- void TMidi::GetSpecBanks( vector& lstBank ) { for( int i=0; ibank!=0xFF ){ bool bAdd = true; for( int b=0; bbank==lstBank[b] ){ bAdd = false; break; } } if( bAdd ) lstBank.push_back( pMT->bank ); } } } //--------------------------------------------------------------------------- void TMidi::SetSpecBanks( BANKMAPLIST& lstMap ) { for( int i=0; ibank!=0xFF ){ for( int b=0; bbank==pMap->iBankOld ){ pMT->bank = pMap->iBankNew; break; } } } } } //--------------------------------------------------------------------------- void TMidi::WriteProj( FILE* pFile ) { int num = m_lstMidiTracks.size(); fwrite( &num, sizeof(int), 1, pFile ); for( int i=0; istate, sizeof(BYTE), 1, pFile ); fwrite( &pMT->volume, sizeof(BYTE), 1, pFile ); fwrite( &pMT->pan, sizeof(char), 1, pFile ); fwrite( &pMT->gain, sizeof(char), 1, pFile ); fwrite( &pMT->bank, sizeof(BYTE), 1, pFile ); fwrite( &pMT->chno, sizeof(BYTE), 1, pFile ); fwrite( &pMT->prog, sizeof(BYTE), 1, pFile ); fwrite( &pMT->file, sizeof(BYTE), 1, pFile ); } } // --------------------------------------------------------------------------- int TMidi::ReadProj( FILE* pFile, DWORD dwVersion ) { int num = 0; fread( &num, sizeof(int), 1, pFile ); for( int i=0; istate, sizeof(BYTE), 1, pFile ); fread( &pMT->volume, sizeof(BYTE), 1, pFile ); fread( &pMT->pan, sizeof(char), 1, pFile ); fread( &pMT->gain, sizeof(char), 1, pFile ); fread( &pMT->bank, sizeof(BYTE), 1, pFile ); fread( &pMT->chno, sizeof(BYTE), 1, pFile ); fread( &pMT->prog, sizeof(BYTE), 1, pFile ); fread( &pMT->file, sizeof(BYTE), 1, pFile ); AddMidiTrack( pMT ); } return 0; } // ---------------------------------------------------------------------------