LCOV - code coverage report
Current view: top level - src/engraving/dom - sig.h Coverage Total Hit
Test: filtered_coverage.info Lines: 100.0 % 34 34
Test Date: 2026-11-05 04:07:02

            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              : }
        

Generated by: LCOV version 2.0-1