MuseScore  3.4
Music composition and notation
sig.h
Go to the documentation of this file.
1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2009 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __AL_SIG_H__
14 #define __AL_SIG_H__
15 
16 #include "fraction.h"
17 
18 namespace Ms {
19 
20 class XmlWriter;
21 class XmlReader;
22 
23 int ticks_beat(int n);
24 
25 //-------------------------------------------------------------------
26 // BeatType
27 //-------------------------------------------------------------------
28 
29 enum class BeatType : char {
30  DOWNBEAT, // 1st beat of measure (rtick == 0)
31  COMPOUND_STRESSED, // e.g. eighth-note number 7 in 12/8
32  SIMPLE_STRESSED, // e.g. beat 3 in 4/4
33  COMPOUND_UNSTRESSED, // e.g. eighth-note numbers 4 or 10 in 12/8
34  SIMPLE_UNSTRESSED, // "offbeat" e.g. beat 2 and 4 in 4/4 (i.e. the denominator unit)
35  COMPOUND_SUBBEAT, // e.g. any other eighth-note in 12/8 (i.e. the denominator unit)
36  SUBBEAT // does not fall on a beat
37  };
38 
39 //-------------------------------------------------------------------
40 // Time Signature Fraction (n/d - numerator/denominator)
41 //-------------------------------------------------------------------
42 
43 class TimeSigFrac : public Fraction {
44 
45  public:
46  using Fraction::Fraction;
47  constexpr TimeSigFrac(int n = 0, int d = 1) : Fraction(n, d) {}
48  TimeSigFrac(const Fraction& f) : TimeSigFrac(f.numerator(), f.denominator()) {}
49  TimeSigFrac(const TimeSigFrac& f) : TimeSigFrac(f.numerator(), f.denominator()) {}
50 
51  // isCompound? Note: 3/8, 3/16, ... are NOT considered compound.
52  bool isCompound() const { return numerator() > 3 /*&& denominator() >= 8*/ && numerator() % 3 == 0; }
53 
54  // isBeatedCompound? Note: Conductors will beat the simple unit at slow tempos (<60 compound units per minute)
55  // However, the meter is still considered to be compound (at least for our purposes).
56  bool isBeatedCompound(qreal tempo) const { return tempo2beatsPerMinute(tempo) >= 60.0; }
57 
58  int dUnitTicks() const;
59  int ticksPerMeasure() const { return numerator() * dUnitTicks(); }
60 
61  int dUnitsPerBeat() const { return isCompound() ? 3 : 1; }
62  int beatTicks() const { return dUnitTicks() * dUnitsPerBeat(); }
63  int beatsPerMeasure() const { return numerator() / dUnitsPerBeat(); }
64 
65  int subbeatTicks(int level) const;
66  int maxSubbeatLevel() const;
67 
68  bool isTriple() const { return beatsPerMeasure() % 3 == 0; }
69  bool isDuple() const { Q_ASSERT(!isTriple()); return beatsPerMeasure() % 2 == 0; } // note: always test isTriple() first
70 
71  // MuseScore stores tempos in quarter-notes-per-second, so conversions to conventional beats-per-minute format are provided here:
72  qreal tempo2beatsPerMinute(qreal tempo) const { return tempo * denominator() * 15.0 / dUnitsPerBeat(); }
73  qreal beatsPerMinute2tempo(qreal bpm) const { return bpm * dUnitsPerBeat() / (15.0 * denominator()); }
74 
75  BeatType rtick2beatType(int rtick) const;
76  int rtick2subbeatLevel(int rtick) const; // returns negative value if not on a well-defined subbeat
77 
78  BeatType strongestBeatInRange(int rtick1, int rtick2, int* dUnitsCrossed = 0, int* subbeatTick = 0, bool saveLast = false) const; // range is exclusive
79  int strongestSubbeatLevelInRange(int rtick1, int rtick2, int* subbeatTick = 0) const; // range is exclusive
80 
81  int ticksPastDUnit(int rtick) const { return rtick % dUnitTicks(); } // returns 0 if rtick is exactly on a dUnit
82  int ticksToNextDUnit(int rtick) const { return dUnitTicks() - ticksPastDUnit(rtick); } // returns dUnitTicks() if rtick is on a dUnit
83 
84  int ticksPastBeat(int rtick) const { return rtick % beatTicks(); } // returns 0 if rtick is exactly on a beat
85  int ticksToNextBeat(int rtick) const { return beatTicks() - ticksPastBeat(rtick); } // returns beatTicks() if rtick is on a beat
86 
87  int ticksPastSubbeat(int rtick, int level) const { return rtick % subbeatTicks(level); }
88  int ticksToNextSubbeat(int rtick, int level) const { return subbeatTicks(level) - ticksPastSubbeat(rtick, level); }
89  };
90 
91 //-------------------------------------------------------------------
92 // Time Signature Event
93 // Incomplete measures as for example pickup measures have
94 // a nominal duration different from actual duration.
95 //-------------------------------------------------------------------
96 
97 class SigEvent {
100  int _bar;
101 
102  public:
103  int read(XmlReader&, int fileDivision);
104  void write(XmlWriter&, int) const;
105 
106  constexpr SigEvent() : _bar(0) {}
107  SigEvent(const Fraction& s, int bar = 0)
108  : _timesig(s), _nominal(s), _bar(bar) {}
109  SigEvent(const Fraction& s, const Fraction& ss, int bar = 0)
110  : _timesig(s), _nominal(ss), _bar(bar) {}
111  SigEvent(const SigEvent& e);
112 
113  bool operator==(const SigEvent& e) const;
114  bool valid() const { return _timesig.isValid(); }
115  QString print() const { return _timesig.print(); }
116  TimeSigFrac timesig() const { return _timesig; }
117  TimeSigFrac nominal() const { return _nominal; }
118  void setNominal(const Fraction& f) { _nominal = f; }
119  int bar() const { return _bar; }
120  void setBar(int val) { _bar = val; }
121  };
122 
123 //---------------------------------------------------------
124 // SigList
125 //---------------------------------------------------------
126 
127 class TimeSigMap : public std::map<int, SigEvent > {
128  void normalize();
129 
130  public:
132 
133  void add(int tick, const Fraction&);
134  void add(int tick, const SigEvent& ev);
135 
136  void del(int tick);
137 
138  void clearRange(int tick1, int tick2);
139 
140  void read(XmlReader&, int fileDiv);
141  void write(XmlWriter&) const;
142  void dump() const;
143 
144  const SigEvent& timesig(int tick) const;
145  const SigEvent& timesig(const Fraction& f) const { return timesig(f.ticks()); }
146 
147  void tickValues(int t, int* bar, int* beat, int* tick) const;
148  int bar2tick(int bar, int beat) const;
149  QString pos(int t) const;
150 
151  unsigned raster(unsigned tick, int raster) const;
152  unsigned raster1(unsigned tick, int raster) const; // round down
153  unsigned raster2(unsigned tick, int raster) const; // round up
154  int rasterStep(unsigned tick, int raster) const;
155  };
156 
157 } // namespace Ms
158 #endif
bool isBeatedCompound(qreal tempo) const
Definition: sig.h:56
SigEvent(const Fraction &s, const Fraction &ss, int bar=0)
Definition: sig.h:109
int ticksPastSubbeat(int rtick, int level) const
Definition: sig.h:87
void setBar(int val)
Definition: sig.h:120
Definition: xml.h:67
bool isCompound() const
Definition: sig.h:52
TimeSigFrac(const Fraction &f)
Definition: sig.h:48
bool isTriple(const ReducedFraction &barFraction)
Definition: importmidi_meter.cpp:33
TimeSigFrac _timesig
Definition: sig.h:98
constexpr TimeSigFrac(int n=0, int d=1)
Definition: sig.h:47
QString print() const
Definition: fraction.h:243
SigEvent(const Fraction &s, int bar=0)
Definition: sig.h:107
constexpr SigEvent()
default SigEvent is invalid
Definition: sig.h:106
Definition: sig.h:43
int _bar
precomputed value
Definition: sig.h:100
constexpr Fraction()
Definition: fraction.h:59
const SigEvent & timesig(const Fraction &f) const
Definition: sig.h:145
TimeSigFrac(const TimeSigFrac &f)
Definition: sig.h:49
bool isCompound(const ReducedFraction &barFraction)
Definition: importmidi_meter.cpp:18
TimeSigFrac nominal() const
Definition: sig.h:117
int beatTicks() const
Definition: sig.h:62
int ticks_beat(int n)
Definition: sig.cpp:22
void setNominal(const Fraction &f)
Definition: sig.h:118
TimeSigFrac timesig() const
Definition: sig.h:116
qreal tempo2beatsPerMinute(qreal tempo) const
Definition: sig.h:72
int dUnitsPerBeat() const
Definition: sig.h:61
qreal beatsPerMinute2tempo(qreal bpm) const
Definition: sig.h:73
Definition: aeolus.cpp:26
int ticksPastDUnit(int rtick) const
Definition: sig.h:81
Definition: xml.h:218
TimeSigMap()
Definition: sig.h:131
int ticksToNextSubbeat(int rtick, int level) const
Definition: sig.h:88
Definition: xmlwriter.h:26
QString print() const
Definition: sig.h:115
int ticks() const
Definition: fraction.h:228
BeatType
Definition: sig.h:29
bool isTriple() const
Definition: sig.h:68
bool valid() const
Definition: sig.h:114
int ticksToNextDUnit(int rtick) const
Definition: sig.h:82
int bar() const
Definition: sig.h:119
Definition: xmlreader.h:28
int ticksPerMeasure() const
Definition: sig.h:59
bool isValid() const
Definition: fraction.h:80
int beatsPerMeasure() const
Definition: sig.h:63
Definition: fraction.h:46
Definition: sig.h:97
TimeSigFrac _nominal
Definition: sig.h:99
Definition: sig.h:127
bool isDuple() const
Definition: sig.h:69
int ticksToNextBeat(int rtick) const
Definition: sig.h:85
int ticksPastBeat(int rtick) const
Definition: sig.h:84