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