1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2009-2019 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 __CHANGEMAP_H__
14 #define __CHANGEMAP_H__
15 
16 #include <QMultiMap>
17 
18 #include "fraction.h"
19 
20 /**
21  \file
22  Definition of class ChangeMap.
23 */
24 
25 namespace Ms {
26 
27 enum class ChangeMethod : signed char {
28       NORMAL,
29       EXPONENTIAL,
30       EASE_IN,
31       EASE_OUT,
32       EASE_IN_OUT      // and shake it all about
33       };
34 
35 enum class ChangeDirection : signed char {
36       INCREASING,
37       DECREASING
38       };
39 
40 //---------------------------------------------------------
41 ///   ChangeEvent
42 ///   item in ChangeMap
43 //---------------------------------------------------------
44 
45 enum class ChangeEventType : char { FIX, RAMP, INVALID };
46 
47 class ChangeEvent {
48       int value { 0 };
49       ChangeEventType type { ChangeEventType::INVALID };
50       Fraction length;
51       ChangeMethod method { ChangeMethod::NORMAL };
52       ChangeDirection direction { ChangeDirection::INCREASING };
53       int cachedStartVal   { -1 };
54       int cachedEndVal     { -1 };
55 
56    public:
ChangeEvent()57       ChangeEvent() {}
ChangeEvent(int vel)58       ChangeEvent(int vel) : value(vel), type(ChangeEventType::FIX) {}
ChangeEvent(Fraction s,Fraction e,int diff,ChangeMethod m,ChangeDirection d)59       ChangeEvent(Fraction s, Fraction e, int diff, ChangeMethod m, ChangeDirection d)
60             : value(diff), type(ChangeEventType::RAMP), length(e - s), method(m), direction(d) {}
61 
62       bool operator==(const ChangeEvent& event) const;
63       bool operator!=(const ChangeEvent& event) const { return !(operator==(event)); }
64 
65       friend class ChangeMap;
66       };
67 
68 //---------------------------------------------------------
69 //  ChangeMap
70 ///  List of changes in a value.
71 //---------------------------------------------------------
72 
73 typedef std::vector<std::pair<Fraction, Fraction>> EndPointsVector;
74 
75 class ChangeMap : public QMultiMap<Fraction, ChangeEvent> {
76       bool cleanedUp    { false };
77       static const int DEFAULT_VALUE  { 80 };   // TODO
78 
79       struct ChangeMethodItem {
80             ChangeMethod method;
81             const char* name;
82             };
83 
compareRampEvents(ChangeEvent & a,ChangeEvent & b)84       static bool compareRampEvents(ChangeEvent& a, ChangeEvent& b)     { return a.length > b.length; }
85 
86       void cleanupStage0();
87       void cleanupStage1();
88       void cleanupStage2(std::vector<bool>& startsInRamp, EndPointsVector& endPoints);
89       void cleanupStage3();
90 
91    public:
ChangeMap()92       ChangeMap() {}
93       int val(Fraction tick);
94       std::vector<std::pair<Fraction, Fraction>> changesInRange(Fraction stick, Fraction etick);
95 
96       void addFixed(Fraction tick, int value);
97       void addRamp(Fraction stick, Fraction etick, int change, ChangeMethod method, ChangeDirection direction);
98       void cleanup();
99 
100       void dump();
101 
102       static int interpolate(Fraction& eventTick, ChangeEvent& event, Fraction& tick);
103       static QString changeMethodToName(ChangeMethod method);
104       static ChangeMethod nameToChangeMethod(QString name);
105 
106       static const std::vector<ChangeMethodItem> changeMethodTable;
107       };
108 
109 }     // namespace Ms
110 #endif
111 
112