MIDITempo.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "MIDITrack.hxx"
00025 #include "MIDISong.hxx"
00026 #include "MIDITempo.hxx"
00027
00028 #include <CLAM/MIDIDataTypes.hxx>
00029
00030 namespace MIDI
00031 {
00032
00033 class TempoImpl
00034
00035 {
00036 friend class Tempo;
00037 private:
00038 Song* mSong;
00039 Track* mTrack;
00040 Track::EventIterator mIterator;
00041 int mUsPerQ;
00042 bool mHasTempo;
00043
00044
00045
00046
00047
00048 int mLastTicks;
00049 int mLastTime;
00050
00051 TempoImpl(Song* song = 0,Track* track = 0)
00052 {
00053 Init(song,track);
00054 }
00055
00056 void Init(Song* song = 0,Track* track = 0)
00057 {
00058 mHasTempo=false;
00059 mSong = song;
00060 mTrack = track;
00061 if (mSong && mTrack==0)
00062 {
00063 for (int i=0;i<mSong->Tracks();i++)
00064 {
00065 Track* t = mSong->GetTrack(i);
00066 if (t->HasTempoEvents())
00067 {
00068 mTrack = t;
00069 break;
00070 }
00071 }
00072 }
00073 if (mTrack)
00074 {
00075 mHasTempo=true;
00076 mIterator = mTrack->Begin();
00077 }
00078 mUsPerQ = 500000;
00079 mLastTime = 0;
00080 mLastTicks = 0;
00081 }
00082
00083 Milliseconds TicksToTime(Ticks t)
00084 {
00085 if(!mHasTempo)
00086 {
00087
00088 return (Milliseconds)((double)t*480.0/(double)mSong->GetTicksPerQ());
00089 }
00090
00091 int i = 0;
00092
00093
00094 while (mIterator!=mTrack->End())
00095 {
00096 const Event &ev = **mIterator;
00097 if ( ev[0]==0xFF && ev[1]==0x51)
00098 {
00099 break;
00100 }
00101 mIterator++;
00102 }
00103
00104
00105
00106
00107 if (mIterator==mTrack->End() || ((*mIterator)->GetTicks()>t))
00108 {
00109 mIterator = mTrack->Begin();
00110 mUsPerQ = 500000;
00111 mLastTime = 0;
00112 mLastTicks = 0;
00113 }
00114
00115 std::list<Event*>::const_iterator prevIterator = mIterator;
00116
00117
00118
00119
00120
00121 while (mIterator!=mTrack->End())
00122 {
00123 const Event &ev = **mIterator;
00124 if ( ev[0]==0xFF && ev[1]==0x51 )
00125 {
00126 if (ev.GetTicks()>t)
00127 {
00128 break;
00129 }
00130
00131 MetaEvent* ev = (MetaEvent*) *mIterator;
00132
00133
00134
00135
00136 mLastTime +=
00137 ( (TInt64(ev->GetTicks() - mLastTicks) * TInt64(mUsPerQ)) /
00138 (TInt64(mSong->GetTicksPerQ())*TInt64(1000)) );
00139
00140 mUsPerQ =
00141 (ev->mData[0]<<16) |
00142 (ev->mData[1]<<8) |
00143 (ev->mData[0]);
00144
00145 mLastTicks = ev->GetTicks();
00146
00147 prevIterator = mIterator;
00148 }
00149 mIterator++;
00150 i++;
00151 }
00152
00153
00154 mIterator = prevIterator;
00155
00156
00157
00158
00159 return mLastTime + Milliseconds(
00160 (TInt64(t - mLastTicks) * TInt64(mUsPerQ)) /
00161 (TInt64(mSong->GetTicksPerQ())*TInt64(1000)));
00162 }
00163 };
00164
00165 Tempo::Tempo(Song* song,Track* track)
00166 {
00167 mImpl = new TempoImpl(song,track);
00168 }
00169
00170 Tempo::~Tempo()
00171 {
00172 delete mImpl;
00173 }
00174
00175 void Tempo::Init(Song* song,Track* track)
00176 {
00177 mImpl->Init(song,track);
00178 }
00179
00180 Milliseconds Tempo::TicksToTime(Ticks t)
00181 {
00182 return mImpl->TicksToTime(t);
00183 }
00184
00185 };
00186