/***************************************************************************
                          MIDITime.h  -  description
                             -------------------
    begin                : Die Apr 8 2003
    copyright            : (C) 2003 by klaus frieler
    email                : kgf@omniversum.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef _LIBMELODY_MIDITIME_H
#define _LIBMELODY_MIDITIME_H
class MIDITime
{
public:
   MIDITime(){};
   MIDITime(uint m, uint b, uint t, uint s, uint tb, uint mpb):
      m_iMeasure(m),
      m_iBeat(b),
      m_iTicks(t),
      m_iSignature(s),
      m_iTicksPerBeat(tb),
      m_iMicroSecsPerBeat(mpb),
      m_iTotalTicks(0),
      m_dTotalTime(0)
      {
         calculate();
      }

   MIDITime(const MIDITime& midiT):
      m_iMeasure(midiT.m_iMeasure),
      m_iBeat(midiT.m_iBeat),
      m_iTicks(midiT.m_iTicks),
      m_iSignature(midiT.m_iSignature),
      m_iTicksPerBeat(midiT.m_iTicksPerBeat),
      m_iMicroSecsPerBeat(midiT.m_iMicroSecsPerBeat),
      m_iTotalTicks(midiT.m_iTotalTicks),
      m_dTotalTime(midiT.m_dTotalTime)
   {
   }
   ~MIDITime(){}

   MIDITime& operator=(const MIDITime & midiT)
   {
      set(midiT.m_iMeasure,
         midiT.m_iBeat,
         midiT.m_iTicks,
         midiT.m_iSignature,
         midiT.m_iTicksPerBeat,
         midiT.m_iMicroSecsPerBeat,
         midiT.m_iTotalTicks,
         midiT.m_dTotalTime);
         return *this;
   }
   void  set(uint measure, uint beat, uint ticks)
   {
      m_iMeasure           = measure;
      m_iBeat              = beat;
      m_iTicks             = ticks;
      calculate();
   }
   void  set(uint m, uint b, uint t, uint s, uint tb, uint mpb, uint tt, double tti)
   {
      m_iMeasure           = m;
      m_iBeat              = b;
      m_iTicks             = t;
      m_iSignature         = s;
      m_iTicksPerBeat      = tb;
      m_iMicroSecsPerBeat  = mpb;
      m_iTotalTicks        = tt;
      m_dTotalTime         = tti;
      
   }
   void  calculate()
   {
      m_iTotalTicks = m_iTicksPerBeat*(m_iMeasure * m_iSignature +m_iBeat)+m_iTicks;
      m_dTotalTime = (double)(m_iMicroSecsPerBeat+0.0)/m_iTicksPerBeat * m_iTotalTicks * 1e-6;
   }
   
   void set(const uint ticks)
   {
      uint totalBeats = ticks/m_iTicksPerBeat;
      m_iTotalTicks  =ticks;
      m_iMeasure  = totalBeats / m_iSignature;
      m_iBeat     = totalBeats % m_iSignature;
      m_iTicks    = ticks - (m_iMeasure * m_iSignature + m_iBeat) * m_iTicksPerBeat;
      m_dTotalTime = (double)(m_iMicroSecsPerBeat+0.0)/m_iTicksPerBeat * m_iTotalTicks * 1e-6;
   }
   
   MIDITime operator +(const MIDITime& midiT) const
   {
      MIDITime tmp = *this;
      tmp += midiT;
      return tmp;
   }
   void operator +=(const MIDITime& midiT)
   {
      m_dTotalTime  += midiT.m_dTotalTime;
      m_iTotalTicks += midiT.m_iTotalTicks;
      set(m_iTotalTicks);
   }
   void operator +=(const uint ticks)
   {
      m_iTotalTicks += ticks;
      m_dTotalTime = (double)(m_iMicroSecsPerBeat+0.0)/m_iTicksPerBeat * m_iTotalTicks * 1e-6;
      set(m_iTotalTicks);
   }
   
   MIDITime operator -(const MIDITime& midiT) const
   {
      MIDITime tmp = *this;
      tmp -= midiT;
      return tmp;
   }   
   void operator -=(const MIDITime& midiT)
   {
      m_dTotalTime  -= midiT.m_dTotalTime;
      m_iTotalTicks -= midiT.m_iTotalTicks;
      set(m_iTotalTicks);
   }

   int getDiffTicks(const MIDITime& midiT)
   {
      MIDITime tmp = *this - midiT;
      return tmp.getTotalTicks();      
   }
   double getDiffTime(const MIDITime& midiT)
   {
      MIDITime tmp = *this - midiT;
      return tmp.getTotalTime();
   }
   
   uint     getMeasure()          { return m_iMeasure;}
   uint     getBeat()             { return m_iBeat;}
   uint     getTicks()            { return m_iTicks;}
   uint     getSignature()        { return m_iSignature;}
   uint     getTicksPerBeat()     { return m_iTicksPerBeat;}
   uint     getTempo()            { return m_iMicroSecsPerBeat;}
   uint     getTotalTicks()       { return m_iTotalTicks;}
   double   getTotalTime()        { return m_dTotalTime;}

   void     setSignature(uint sig)  { m_iSignature          = sig;}
   void     setTicksPerBeat(uint tb){ m_iTicksPerBeat       = tb;}
   void     setTempo(uint mpb)      { m_iMicroSecsPerBeat   = mpb;}

   void     setProps(uint s, uint tb, uint mpb)
   {
         m_iSignature          = s;
         m_iTicksPerBeat       = tb;
         m_iMicroSecsPerBeat   = mpb;
   }
protected:
   uint     m_iMeasure;
   uint     m_iBeat;
   uint     m_iTicks;
   uint     m_iSignature;
   uint     m_iTicksPerBeat;
   uint     m_iMicroSecsPerBeat;

   uint     m_iTotalTicks;
   double   m_dTotalTime;
};
#endif
