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