Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
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
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <map>
26 : #include <cassert>
27 :
28 : #include "global/allocator.h"
29 : #include "../types/types.h"
30 :
31 : namespace mu::engraving {
32 : int ticks_beat(int n);
33 :
34 : //-------------------------------------------------------------------
35 : // BeatType
36 : //-------------------------------------------------------------------
37 :
38 : enum class BeatType : unsigned char {
39 : DOWNBEAT, // 1st beat of measure (rtick == 0)
40 : COMPOUND_STRESSED, // e.g. eighth-note number 7 in 12/8
41 : SIMPLE_STRESSED, // e.g. beat 3 in 4/4
42 : COMPOUND_UNSTRESSED, // e.g. eighth-note numbers 4 or 10 in 12/8
43 : SIMPLE_UNSTRESSED, // "offbeat" e.g. beat 2 and 4 in 4/4 (i.e. the denominator unit)
44 : COMPOUND_SUBBEAT, // e.g. any other eighth-note in 12/8 (i.e. the denominator unit)
45 : SUBBEAT // does not fall on a beat
46 : };
47 :
48 : //-------------------------------------------------------------------
49 : // Time Signature Fraction (n/d - numerator/denominator)
50 : //-------------------------------------------------------------------
51 :
52 : class TimeSigFrac : public Fraction
53 : {
54 : OBJECT_ALLOCATOR(engraving, TimeSigFrac)
55 : public:
56 : using Fraction::Fraction;
57 34784 : constexpr TimeSigFrac(int n = 0, int d = 1)
58 34784 : : Fraction(n, d) {}
59 12139 : TimeSigFrac(const Fraction& f)
60 12139 : : TimeSigFrac(f.numerator(), f.denominator()) {}
61 :
62 : // isCompound? Note: 3/8, 3/16, ... are NOT considered compound.
63 25572 : bool isCompound() const { return numerator() > 3 /*&& denominator() >= 8*/ && numerator() % 3 == 0; }
64 :
65 : // isBeatedCompound? Note: Conductors will beat the simple unit at slow tempos (<60 compound units per minute)
66 : // However, the meter is still considered to be compound (at least for our purposes).
67 153 : bool isBeatedCompound(double tempo) const { return tempo2beatsPerMinute(tempo) >= 60.0; }
68 :
69 : int dUnitTicks() const;
70 5 : int ticksPerMeasure() const { return numerator() * dUnitTicks(); }
71 :
72 15131 : int dUnitsPerBeat() const { return isCompound() ? 3 : 1; }
73 4710 : int beatTicks() const { return dUnitTicks() * dUnitsPerBeat(); }
74 10268 : int beatsPerMeasure() const { return numerator() / dUnitsPerBeat(); }
75 :
76 : int subbeatTicks(int level) const;
77 : int maxSubbeatLevel() const;
78 :
79 7134 : bool isTriple() const { return beatsPerMeasure() % 3 == 0; }
80 3134 : bool isDuple() const { assert(!isTriple()); return beatsPerMeasure() % 2 == 0; } // note: always test isTriple() first
81 :
82 : // MuseScore stores tempos in quarter-notes-per-second, so conversions to conventional beats-per-minute format are provided here:
83 153 : double tempo2beatsPerMinute(double tempo) const { return tempo * denominator() * 15.0 / dUnitsPerBeat(); }
84 : double beatsPerMinute2tempo(double bpm) const { return bpm * dUnitsPerBeat() / (15.0 * denominator()); }
85 :
86 : BeatType rtick2beatType(int rtick) const;
87 : int rtick2subbeatLevel(int rtick) const; // returns negative value if not on a well-defined subbeat
88 :
89 : BeatType strongestBeatInRange(int rtick1, int rtick2, int* dUnitsCrossed = 0, int* subbeatTick = 0, bool saveLast = false) const; // range is exclusive
90 : int strongestSubbeatLevelInRange(int rtick1, int rtick2, int* subbeatTick = 0) const; // range is exclusive
91 :
92 1042 : int ticksPastDUnit(int rtick) const { return rtick % dUnitTicks(); } // returns 0 if rtick is exactly on a dUnit
93 1042 : int ticksToNextDUnit(int rtick) const { return dUnitTicks() - ticksPastDUnit(rtick); } // returns dUnitTicks() if rtick is on a dUnit
94 :
95 218 : int ticksPastBeat(int rtick) const { return rtick % beatTicks(); } // returns 0 if rtick is exactly on a beat
96 101 : int ticksToNextBeat(int rtick) const { return beatTicks() - ticksPastBeat(rtick); } // returns beatTicks() if rtick is on a beat
97 :
98 128 : int ticksPastSubbeat(int rtick, int level) const { return rtick % subbeatTicks(level); }
99 64 : int ticksToNextSubbeat(int rtick, int level) const { return subbeatTicks(level) - ticksPastSubbeat(rtick, level); }
100 : };
101 :
102 : //-------------------------------------------------------------------
103 : // Time Signature Event
104 : // Incomplete measures as for example pickup measures have
105 : // a nominal duration different from actual duration.
106 : //-------------------------------------------------------------------
107 :
108 : class SigEvent
109 : {
110 : public:
111 5299 : constexpr SigEvent()
112 5299 : : m_bar(0) {} ///< default SigEvent is invalid
113 3056 : SigEvent(const Fraction& s, int bar = 0)
114 3056 : : m_timesig(s), m_nominal(s), m_bar(bar) {}
115 2571 : SigEvent(const Fraction& s, const Fraction& ss, int bar = 0)
116 2571 : : m_timesig(s), m_nominal(ss), m_bar(bar) {}
117 :
118 : bool operator==(const SigEvent& e) const;
119 : bool valid() const { return m_timesig.isValid(); }
120 : String print() const { return m_timesig.toString(); }
121 24223 : TimeSigFrac timesig() const { return m_timesig; }
122 26 : void setTimesig(const TimeSigFrac& f) { m_timesig = f; }
123 2008 : TimeSigFrac nominal() const { return m_nominal; }
124 26 : void setNominal(const TimeSigFrac& f) { m_nominal = f; }
125 11288 : int bar() const { return m_bar; }
126 6372 : void setBar(int val) { m_bar = val; }
127 :
128 : private:
129 :
130 : TimeSigFrac m_timesig;
131 : TimeSigFrac m_nominal;
132 : int m_bar = 0; ///< precomputed value
133 : };
134 :
135 : //---------------------------------------------------------
136 : // SigList
137 : //---------------------------------------------------------
138 :
139 : class TimeSigMap : public std::map<int, SigEvent>
140 : {
141 4113 : OBJECT_ALLOCATOR(engraving, TimeSigMap)
142 :
143 : public:
144 17120 : TimeSigMap() {}
145 :
146 : static const TimeSigFrac DEFAULT_TIME_SIGNATURE;
147 :
148 : void add(int tick, const Fraction&);
149 : void add(int tick, const SigEvent& ev);
150 :
151 : void del(int tick);
152 :
153 : void clearRange(int tick1, int tick2);
154 :
155 : void dump() const;
156 :
157 : const SigEvent& timesig(int tick) const;
158 2138 : const SigEvent& timesig(const Fraction& f) const { return timesig(f.ticks()); }
159 :
160 : void tickValues(int t, int* bar, int* beat, int* tick) const;
161 : int bar2tick(int bar, int beat) const;
162 : String pos(int t) const;
163 :
164 : unsigned raster(unsigned tick, int raster) const;
165 : unsigned raster1(unsigned tick, int raster) const; // round down
166 : unsigned raster2(unsigned tick, int raster) const; // round up
167 : int rasterStep(unsigned tick, int raster) const;
168 :
169 : void normalize();
170 : };
171 : }
|