diff --git a/include/MidiTime.h b/include/MidiTime.h index 788e6fb57..ce5ead739 100644 --- a/include/MidiTime.h +++ b/include/MidiTime.h @@ -27,125 +27,76 @@ #ifndef MIDI_TIME_H #define MIDI_TIME_H -#include "lmms_basics.h" -#include "export.h" +#include +#include "export.h" +#include "lmms_basics.h" + +// note: 1 "Tact" = 1 Measure const int DefaultTicksPerTact = 192; const int DefaultStepsPerTact = 16; const int DefaultBeatsPerTact = DefaultTicksPerTact / DefaultStepsPerTact; +class MeterModel; + +class EXPORT TimeSig +{ +public: + // in a time signature, + // the numerator represents the number of beats in a measure. + // the denominator indicates which type of note represents a beat. + // example: 6/8 means 6 beats in a measure, where each beat has duration equal to one 8th-note. + TimeSig( int num, int denom ); + TimeSig( const MeterModel &model ); + int numerator() const; + int denominator() const; +private: + int m_num; + int m_denom; +}; + + class EXPORT MidiTime { public: - MidiTime( const tact_t tact, const tick_t ticks ) : - m_ticks( tact * s_ticksPerTact + ticks ) - { - } + MidiTime( const tact_t tact, const tick_t ticks ); + MidiTime( const tick_t ticks = 0 ); + MidiTime( const MidiTime& time ); - MidiTime( const tick_t ticks = 0 ) : - m_ticks( ticks ) - { - } + MidiTime toNearestTact() const; + MidiTime toAbsoluteTact() const; - MidiTime( const MidiTime& time ) : - m_ticks( time.m_ticks ) - { - } + MidiTime& operator=( const MidiTime& time ); + MidiTime& operator+=( const MidiTime& time ); + MidiTime& operator-=( const MidiTime& time ); - MidiTime toNearestTact() const - { - if( m_ticks % s_ticksPerTact >= s_ticksPerTact/2 ) - { - return ( getTact() + 1 ) * s_ticksPerTact; - } - return getTact() * s_ticksPerTact; - } + // return the tact, rounded down and 0-based + tact_t getTact() const; + // return the tact, rounded up and 0-based + tact_t nextFullTact() const; - MidiTime toAbsoluteTact() const - { - return getTact() * s_ticksPerTact; - } + void setTicks( tick_t ticks ); + tick_t getTicks() const; - MidiTime& operator=( const MidiTime& time ) - { - m_ticks = time.m_ticks; - return *this; - } + operator int() const; - MidiTime& operator+=( const MidiTime& time ) - { - m_ticks += time.m_ticks; - return *this; - } - - MidiTime& operator-=( const MidiTime& time ) - { - m_ticks -= time.m_ticks; - return *this; - } - - tact_t getTact() const - { - return m_ticks / s_ticksPerTact; - } - - tact_t nextFullTact() const - { - if( m_ticks % s_ticksPerTact == 0 ) - { - return m_ticks / s_ticksPerTact; - } - return m_ticks / s_ticksPerTact + 1; - } - - void setTicks( tick_t ticks ) - { - m_ticks = ticks; - } - - tick_t getTicks() const - { - return m_ticks; - } - - operator int() const - { - return m_ticks; - } + tick_t ticksPerBeat( const TimeSig &sig ) const; + // Remainder ticks after bar is removed + tick_t getTickWithinBar( const TimeSig &sig ) const; + // Returns the beat position inside the bar, 0-based + tick_t getBeatWithinBar( const TimeSig &sig ) const; + // Remainder ticks after bar and beat are removed + tick_t getTickWithinBeat( const TimeSig &sig ) const; // calculate number of frame that are needed this time - f_cnt_t frames( const float framesPerTick ) const - { - if( m_ticks >= 0 ) - { - return static_cast( m_ticks * framesPerTick ); - } - return 0; - } - - static MidiTime fromFrames( const f_cnt_t frames, const float framesPerTick ) - { - return MidiTime( static_cast( frames / framesPerTick ) ); - } - - - static tick_t ticksPerTact() - { - return s_ticksPerTact; - } - - static int stepsPerTact() - { - int steps = ticksPerTact() / DefaultBeatsPerTact; - return qMax( 1, steps ); - } - - static void setTicksPerTact( tick_t _tpt ) - { - s_ticksPerTact = _tpt; - } + f_cnt_t frames( const float framesPerTick ) const; + static MidiTime fromFrames( const f_cnt_t frames, const float framesPerTick ); + static tick_t ticksPerTact(); + static tick_t ticksPerTact( const TimeSig &sig ); + static int stepsPerTact(); + static void setTicksPerTact( tick_t tpt ); private: tick_t m_ticks; diff --git a/include/Song.h b/include/Song.h index 3f52cbbb1..7c65641ec 100644 --- a/include/Song.h +++ b/include/Song.h @@ -111,22 +111,18 @@ public: inline int ticksPerTact() const { - return DefaultTicksPerTact * - m_timeSigModel.getNumerator() / - m_timeSigModel.getDenominator(); + return MidiTime::ticksPerTact(m_timeSigModel); } // Returns the beat position inside the bar, 0-based inline int getBeat() const { - return ( currentTick() - currentTact() * ticksPerTact() ) / - ( ticksPerTact() / m_timeSigModel.getNumerator() ); + return getPlayPos().getBeatWithinBar(m_timeSigModel); } // the remainder after bar and beat are removed inline int getBeatTicks() const { - return ( currentTick() - currentTact() * ticksPerTact() ) % - ( ticksPerTact() / m_timeSigModel.getNumerator() ); + return getPlayPos().getTickWithinBeat(m_timeSigModel); } inline int getTicks() const { @@ -136,10 +132,6 @@ public: { return currentFrame(); } - inline bool isTempoAutomated() - { - return m_tempoModel.isAutomated(); - } inline bool isPaused() const { return m_paused; @@ -186,6 +178,14 @@ public: { return m_playPos[pm]; } + inline const PlayPos & getPlayPos( PlayModes pm ) const + { + return m_playPos[pm]; + } + inline const PlayPos & getPlayPos() const + { + return getPlayPos(m_playMode); + } void updateLength(); tact_t length() const diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e974d151f..6d6ae4d98 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -82,6 +82,7 @@ set(LMMS_SRCS core/midi/MidiController.cpp core/midi/MidiOss.cpp core/midi/MidiPort.cpp + core/midi/MidiTime.cpp core/midi/MidiWinMM.cpp PARENT_SCOPE diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index e8a91c77d..2aaf5665a 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -163,7 +163,7 @@ void ProjectRenderer::run() //skip first empty buffer Engine::mixer()->nextBuffer(); - Song::PlayPos & pp = Engine::getSong()->getPlayPos( + const Song::PlayPos & pp = Engine::getSong()->getPlayPos( Song::Mode_PlaySong ); m_progress = 0; const int sl = ( Engine::getSong()->length() + 1 ) * 192; diff --git a/src/core/midi/MidiTime.cpp b/src/core/midi/MidiTime.cpp new file mode 100644 index 000000000..b80c31b85 --- /dev/null +++ b/src/core/midi/MidiTime.cpp @@ -0,0 +1,200 @@ +/* + * MidiTime.cpp - Class that encapsulates the position of a note/event in terms of + * its bar, beat and tick. + * + * Copyright (c) 2004-2014 Tobias Doerffel = s_ticksPerTact/2 ) + { + return ( getTact() + 1 ) * s_ticksPerTact; + } + return getTact() * s_ticksPerTact; +} + + +MidiTime MidiTime::toAbsoluteTact() const +{ + return getTact() * s_ticksPerTact; +} + + +MidiTime& MidiTime::operator=( const MidiTime& time ) +{ + m_ticks = time.m_ticks; + return *this; +} + + +MidiTime& MidiTime::operator+=( const MidiTime& time ) +{ + m_ticks += time.m_ticks; + return *this; +} + + +MidiTime& MidiTime::operator-=( const MidiTime& time ) +{ + m_ticks -= time.m_ticks; + return *this; +} + + +tact_t MidiTime::getTact() const +{ + return m_ticks / s_ticksPerTact; +} + + +tact_t MidiTime::nextFullTact() const +{ + return (m_ticks + (s_ticksPerTact-1)) / s_ticksPerTact; +} + + +void MidiTime::setTicks( tick_t ticks ) +{ + m_ticks = ticks; +} + + +tick_t MidiTime::getTicks() const +{ + return m_ticks; +} + + +MidiTime::operator int() const +{ + return m_ticks; +} + + +tick_t MidiTime::ticksPerBeat( const TimeSig &sig ) const +{ + // (number of ticks per bar) divided by (number of beats per bar) + return ticksPerTact(sig) / sig.numerator(); +} + + +tick_t MidiTime::getTickWithinBar( const TimeSig &sig ) const +{ + return m_ticks % ticksPerTact(sig); +} + +tick_t MidiTime::getBeatWithinBar( const TimeSig &sig ) const +{ + return getTickWithinBar(sig) / ticksPerBeat(sig); +} + +tick_t MidiTime::getTickWithinBeat( const TimeSig &sig ) const +{ + return getTickWithinBar(sig) % ticksPerBeat(sig); +} + + +f_cnt_t MidiTime::frames( const float framesPerTick ) const +{ + if( m_ticks >= 0 ) + { + return static_cast( m_ticks * framesPerTick ); + } + return 0; +} + + +MidiTime MidiTime::fromFrames( const f_cnt_t frames, const float framesPerTick ) +{ + return MidiTime( static_cast( frames / framesPerTick ) ); +} + + +tick_t MidiTime::ticksPerTact() +{ + return s_ticksPerTact; +} + + +tick_t MidiTime::ticksPerTact( const TimeSig &sig ) +{ + return DefaultTicksPerTact * sig.numerator() / sig.denominator(); +} + + +int MidiTime::stepsPerTact() +{ + int steps = ticksPerTact() / DefaultBeatsPerTact; + return qMax( 1, steps ); +} + + +void MidiTime::setTicksPerTact( tick_t tpt ) +{ + s_ticksPerTact = tpt; +}