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 : #ifndef MU_ENGRAVING_VELOCITYMAP_H
24 : #define MU_ENGRAVING_VELOCITYMAP_H
25 :
26 : #include <map>
27 :
28 : #include "global/allocator.h"
29 :
30 : #include "../../types/types.h"
31 :
32 : /**
33 : \file
34 : Definition of class VelocityMap.
35 : */
36 :
37 : namespace mu::engraving {
38 : //---------------------------------------------------------
39 : /// VelocityEvent
40 : /// item in VelocityMap
41 : //---------------------------------------------------------
42 :
43 : enum class VelocityEventType : char {
44 : DYNAMIC, HAIRPIN, INVALID
45 : };
46 :
47 : class VelocityEvent
48 : {
49 : public:
50 0 : VelocityEvent() {}
51 340 : VelocityEvent(int val)
52 340 : : m_value(val), m_type(VelocityEventType::DYNAMIC) {}
53 32 : VelocityEvent(Fraction s, Fraction e, int diff, ChangeMethod m, ChangeDirection d)
54 32 : : m_value(diff), m_type(VelocityEventType::HAIRPIN), m_length(e - s), m_method(m), m_direction(d) {}
55 :
56 : bool operator==(const VelocityEvent& event) const;
57 : bool operator!=(const VelocityEvent& event) const { return !(operator==(event)); }
58 :
59 : private:
60 : friend class VelocityMap;
61 :
62 : int m_value = 0;
63 : VelocityEventType m_type = VelocityEventType::INVALID;
64 : Fraction m_length;
65 : ChangeMethod m_method = ChangeMethod::NORMAL;
66 : ChangeDirection m_direction = ChangeDirection::INCREASING;
67 : int m_cachedStartVal = -1;
68 : int m_cachedEndVal = -1;
69 : };
70 :
71 : //---------------------------------------------------------
72 : // VelocityMap
73 : /// List of changes in a value.
74 : //---------------------------------------------------------
75 :
76 : typedef std::vector<std::pair<Fraction, Fraction> > EndPointsVector;
77 :
78 : class VelocityMap : public std::multimap<Fraction, VelocityEvent>
79 : {
80 : OBJECT_ALLOCATOR(engraving, VelocityMap)
81 : public:
82 1864 : VelocityMap() {}
83 : int val(Fraction tick) const;
84 : std::vector<std::pair<Fraction, Fraction> > changesInRange(Fraction stick, Fraction etick) const;
85 :
86 : void addDynamic(Fraction tick, int value);
87 : void addHairpin(Fraction stick, Fraction etick, int change, ChangeMethod method, ChangeDirection direction);
88 : void setup();
89 :
90 : static int interpolate(Fraction& eventTick, VelocityEvent& event, Fraction& tick);
91 :
92 : private:
93 :
94 : struct ChangeMethodItem {
95 : ChangeMethod method;
96 : const char* name;
97 : };
98 :
99 0 : static bool compareHairpinEvents(VelocityEvent& a, VelocityEvent& b) { return a.m_length > b.m_length; }
100 :
101 : void sortHairpins();
102 : void resolveHairpinCollisions();
103 : void resolveDynamicInsideHairpinCollisions();
104 : void adjustCollidingHairpinsLength(std::vector<bool>& startsInHairpin, EndPointsVector& endPoints);
105 : bool dynamicExistsOnTick(Fraction tick) const;
106 : VelocityEvent dynamicEventForTick(Fraction tick) const;
107 : void addMissingDynamicsAfterHairpins();
108 : void fillHairpinsCache();
109 :
110 : static constexpr int DEFAULT_VALUE = 80;
111 : static constexpr int MIN_VALUE = 1;
112 : static constexpr int MAX_VALUE = 127;
113 : static constexpr int STEP = 16;
114 : };
115 : } // namespace mu::engraving
116 : #endif
|