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) 2025 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 : #pragma once
23 :
24 : #include "global/realfn.h"
25 : #include "mpe/mpetypes.h"
26 :
27 : #include "../../dom/score.h"
28 : #include "../../dom/repeatlist.h"
29 : #include "../../dom/tempotimeline.h"
30 :
31 : #include "../../types/constants.h"
32 :
33 : namespace mu::engraving {
34 4364 : inline muse::mpe::timestamp_t timestampFromTicks(const Score* score, const int tick)
35 : {
36 4364 : return score->tempoTimeline().utick2utime(tick) * 1000000;
37 : }
38 :
39 731 : inline int timestampToTick(const Score* score, const muse::mpe::timestamp_t timestamp)
40 : {
41 731 : return score->tempoTimeline().utime2utick(timestamp / 1000000.f);
42 : }
43 :
44 : // Returns the pause at `tick` in microseconds, or 0
45 1623 : inline muse::mpe::duration_t pauseUs(const Score* score, const int tick, const int tickPositionOffset)
46 : {
47 1623 : const TempoTimeline& timeline = score->tempoTimeline();
48 1623 : const auto pauseIt = timeline.pauses().find(tick + tickPositionOffset);
49 1623 : if (pauseIt == timeline.pauses().end()) {
50 1618 : return 0;
51 : }
52 :
53 5 : double secs = pauseIt->second / timeline.tempoMultiplier().val;
54 5 : return muse::RealIsNull(secs) ? 0 : secs* 1000000;
55 : }
56 :
57 45 : inline muse::mpe::duration_t durationFromStartAndEndTick(const Score* score, const int startTick, const int endTick,
58 : const int tickPositionOffset)
59 : {
60 45 : muse::mpe::timestamp_t startTimestamp = timestampFromTicks(score, startTick + tickPositionOffset);
61 45 : muse::mpe::timestamp_t endTimestamp = timestampFromTicks(score, endTick + tickPositionOffset);
62 45 : muse::mpe::duration_t pause = pauseUs(score, endTick, tickPositionOffset);
63 :
64 45 : return endTimestamp - startTimestamp - pause;
65 : }
66 :
67 45 : inline muse::mpe::duration_t durationFromStartAndTicks(const Score* score, const int startTick, const int durationTicks,
68 : const int tickPositionOffset)
69 : {
70 45 : return durationFromStartAndEndTick(score, startTick, startTick + durationTicks, tickPositionOffset);
71 : }
72 :
73 1578 : inline muse::mpe::TimestampAndDuration timestampAndDurationFromStartAndDurationTicks(const Score* score,
74 : const int startTick, const int durationTicks,
75 : const int tickPositionOffset)
76 : {
77 1578 : int startTickWithOffset = startTick + tickPositionOffset;
78 1578 : muse::mpe::timestamp_t startTimestamp = timestampFromTicks(score, startTickWithOffset);
79 1578 : muse::mpe::timestamp_t endTimestamp = timestampFromTicks(score, startTickWithOffset + durationTicks);
80 1578 : muse::mpe::duration_t pause = pauseUs(score, startTick + durationTicks, tickPositionOffset);
81 1578 : muse::mpe::duration_t duration = endTimestamp - startTimestamp - pause;
82 :
83 1578 : return { startTimestamp, duration };
84 : }
85 :
86 675 : inline muse::mpe::duration_t durationFromTempoAndTicks(const double beatsPerSecond, const int durationTicks,
87 : const int ticksPerBeat = Constants::DIVISION)
88 : {
89 675 : float beatsNumber = static_cast<float>(durationTicks) / static_cast<float>(ticksPerBeat);
90 :
91 675 : return (beatsNumber / beatsPerSecond) * 1000000;
92 : }
93 :
94 4 : inline int ticksFromTempoAndDuration(const double beatsPerSecond, const muse::mpe::duration_t duration,
95 : const int ticksPerBeat = Constants::DIVISION)
96 : {
97 4 : return (duration * beatsPerSecond * ticksPerBeat) / 1000000;
98 : }
99 :
100 : static constexpr int CROTCHET_TICKS = Constants::DIVISION;
101 : static constexpr int QUAVER_TICKS = Constants::DIVISION / 2;
102 : static constexpr int SEMIQUAVER_TICKS = Constants::DIVISION / 4;
103 : static constexpr int DEMISEMIQUAVER_TICKS = Constants::DIVISION / 8;
104 :
105 : static const double PRESTISSIMO_BPS_BOUND = muse::RealRound(200 /*bpm*/ / 60.f /*secs*/, 2);
106 : static const double PRESTO_BPS_BOUND = muse::RealRound(168 /*bpm*/ / 60.f /*secs*/, 2);
107 : static const double ALLEGRO_BPS_BOUND = muse::RealRound(120 /*bpm*/ / 60.f /*secs*/, 2);
108 : static const double MODERATO_BPS_BOUND = muse::RealRound(108 /*bpm*/ / 60.f /*secs*/, 2);
109 : static const double ANDANTE_BPS_BOUND = muse::RealRound(76 /*bpm*/ / 60.f /*secs*/, 2);
110 : static const double ADAGIO_BPS_BOUND = muse::RealRound(66 /*bpm*/ / 60.f /*secs*/, 2);
111 : static const double LENTO_BPS_BOUND = muse::RealRound(40 /*bpm*/ / 60.f /*secs*/, 2);
112 : static const double GRAVE_BPS_BOUND = muse::RealRound(20 /*bpm*/ / 60.f /*secs*/, 2);
113 : }
|