1 /*
2  * MidiTime.cpp - Class that encapsulates the position of a note/event in terms of
3  *   its bar, beat and tick.
4  *
5  * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net
6  *
7  * This file is part of LMMS - https://lmms.io
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public
20  * License along with this program (see COPYING); if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301 USA.
23  *
24  */
25 
26 #include "MidiTime.h"
27 
28 #include "MeterModel.h"
29 
TimeSig(int num,int denom)30 TimeSig::TimeSig( int num, int denom ) :
31 	m_num(num),
32 	m_denom(denom)
33 {
34 }
35 
TimeSig(const MeterModel & model)36 TimeSig::TimeSig( const MeterModel &model ) :
37 	m_num(model.getNumerator()),
38 	m_denom(model.getDenominator())
39 {
40 }
41 
42 
numerator() const43 int TimeSig::numerator() const
44 {
45 	return m_num;
46 }
47 
denominator() const48 int TimeSig::denominator() const
49 {
50 	return m_denom;
51 }
52 
53 
54 
55 
MidiTime(const tact_t tact,const tick_t ticks)56 MidiTime::MidiTime( const tact_t tact, const tick_t ticks ) :
57 	m_ticks( tact * s_ticksPerTact + ticks )
58 {
59 }
60 
MidiTime(const tick_t ticks)61 MidiTime::MidiTime( const tick_t ticks ) :
62 	m_ticks( ticks )
63 {
64 }
65 
toNearestTact() const66 MidiTime MidiTime::toNearestTact() const
67 {
68 	if( m_ticks % s_ticksPerTact >= s_ticksPerTact/2 )
69 	{
70 		return ( getTact() + 1 ) * s_ticksPerTact;
71 	}
72 	return getTact() * s_ticksPerTact;
73 }
74 
75 
toAbsoluteTact() const76 MidiTime MidiTime::toAbsoluteTact() const
77 {
78 	return getTact() * s_ticksPerTact;
79 }
80 
81 
operator +=(const MidiTime & time)82 MidiTime& MidiTime::operator+=( const MidiTime& time )
83 {
84 	m_ticks += time.m_ticks;
85 	return *this;
86 }
87 
88 
operator -=(const MidiTime & time)89 MidiTime& MidiTime::operator-=( const MidiTime& time )
90 {
91 	m_ticks -= time.m_ticks;
92 	return *this;
93 }
94 
95 
getTact() const96 tact_t MidiTime::getTact() const
97 {
98 	return m_ticks / s_ticksPerTact;
99 }
100 
101 
nextFullTact() const102 tact_t MidiTime::nextFullTact() const
103 {
104 	return (m_ticks + (s_ticksPerTact-1)) / s_ticksPerTact;
105 }
106 
107 
setTicks(tick_t ticks)108 void MidiTime::setTicks( tick_t ticks )
109 {
110 	m_ticks = ticks;
111 }
112 
113 
getTicks() const114 tick_t MidiTime::getTicks() const
115 {
116 	return m_ticks;
117 }
118 
119 
operator int() const120 MidiTime::operator int() const
121 {
122 	return m_ticks;
123 }
124 
125 
ticksPerBeat(const TimeSig & sig) const126 tick_t MidiTime::ticksPerBeat( const TimeSig &sig ) const
127 {
128 	// (number of ticks per bar) divided by (number of beats per bar)
129 	return ticksPerTact(sig) / sig.numerator();
130 }
131 
132 
getTickWithinBar(const TimeSig & sig) const133 tick_t MidiTime::getTickWithinBar( const TimeSig &sig ) const
134 {
135 	return m_ticks % ticksPerTact(sig);
136 }
137 
getBeatWithinBar(const TimeSig & sig) const138 tick_t MidiTime::getBeatWithinBar( const TimeSig &sig ) const
139 {
140 	return getTickWithinBar(sig) / ticksPerBeat(sig);
141 }
142 
getTickWithinBeat(const TimeSig & sig) const143 tick_t MidiTime::getTickWithinBeat( const TimeSig &sig ) const
144 {
145 	return getTickWithinBar(sig) % ticksPerBeat(sig);
146 }
147 
148 
frames(const float framesPerTick) const149 f_cnt_t MidiTime::frames( const float framesPerTick ) const
150 {
151 	if( m_ticks >= 0 )
152 	{
153 		return static_cast<f_cnt_t>( m_ticks * framesPerTick );
154 	}
155 	return 0;
156 }
157 
158 
fromFrames(const f_cnt_t frames,const float framesPerTick)159 MidiTime MidiTime::fromFrames( const f_cnt_t frames, const float framesPerTick )
160 {
161 	return MidiTime( static_cast<int>( frames / framesPerTick ) );
162 }
163 
164 
ticksPerTact()165 tick_t MidiTime::ticksPerTact()
166 {
167 	return s_ticksPerTact;
168 }
169 
170 
ticksPerTact(const TimeSig & sig)171 tick_t MidiTime::ticksPerTact( const TimeSig &sig )
172 {
173 	return DefaultTicksPerTact * sig.numerator() / sig.denominator();
174 }
175 
176 
stepsPerTact()177 int MidiTime::stepsPerTact()
178 {
179 	int steps = ticksPerTact() / DefaultBeatsPerTact;
180 	return qMax( 1, steps );
181 }
182 
183 
setTicksPerTact(tick_t tpt)184 void MidiTime::setTicksPerTact( tick_t tpt )
185 {
186 	s_ticksPerTact = tpt;
187 }
188 
189 
stepPosition(int step)190 MidiTime MidiTime::stepPosition( int step )
191 {
192 	return step * ticksPerTact() / stepsPerTact();
193 }
194