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 : #include "interval.h"
24 : #include "../types/types.h"
25 :
26 : namespace mu::engraving {
27 1164 : Interval::Interval(int diatonic, int chromatic)
28 1164 : : diatonic(diatonic), chromatic(chromatic)
29 : {
30 1164 : }
31 :
32 359 : Interval::Interval(int chromatic)
33 359 : : diatonic(chromatic2diatonic(chromatic)), chromatic(chromatic)
34 : {
35 359 : }
36 :
37 : //---------------------------------------------------------
38 : // flip
39 : //---------------------------------------------------------
40 :
41 10561 : void Interval::flip()
42 : {
43 10561 : diatonic = -diatonic;
44 10561 : chromatic = -chromatic;
45 10561 : }
46 :
47 : //---------------------------------------------------------
48 : // reduce
49 : //---------------------------------------------------------
50 :
51 0 : void Interval::reduce()
52 : {
53 0 : diatonic = diatonic % 7;
54 0 : chromatic = chromatic % 12;
55 0 : }
56 :
57 0 : Interval Interval::reduced()
58 : {
59 0 : Interval interval(diatonic, chromatic);
60 0 : interval.reduce();
61 0 : return interval;
62 : }
63 :
64 : //---------------------------------------------------------
65 : // isZero
66 : //---------------------------------------------------------
67 :
68 26158 : bool Interval::isZero() const
69 : {
70 26158 : return diatonic == 0 && chromatic == 0;
71 : }
72 :
73 84 : Interval Interval::fromOrnamentInterval(OrnamentInterval ornInt)
74 : {
75 84 : Interval resultingInterval = Interval(0, 0);
76 :
77 84 : resultingInterval.diatonic = static_cast<int>(ornInt.step);
78 :
79 84 : int cromaticSteps = 0;
80 84 : switch (ornInt.step) {
81 0 : case IntervalStep::UNISON:
82 0 : cromaticSteps = 0;
83 0 : break;
84 68 : case IntervalStep::SECOND:
85 68 : cromaticSteps = 2;
86 68 : break;
87 5 : case IntervalStep::THIRD:
88 5 : cromaticSteps = 4;
89 5 : break;
90 11 : case IntervalStep::FOURTH:
91 11 : cromaticSteps = 5;
92 11 : break;
93 0 : case IntervalStep::FIFTH:
94 0 : cromaticSteps = 7;
95 0 : break;
96 0 : case IntervalStep::SIXTH:
97 0 : cromaticSteps = 9;
98 0 : break;
99 0 : case IntervalStep::SEVENTH:
100 0 : cromaticSteps = 11;
101 0 : break;
102 0 : case IntervalStep::OCTAVE:
103 0 : cromaticSteps = 12;
104 0 : break;
105 0 : default:
106 0 : break;
107 : }
108 :
109 84 : if (ornInt.isPerfect()) {
110 11 : switch (ornInt.type) {
111 0 : case IntervalType::DIMINISHED:
112 0 : cromaticSteps -= 1;
113 0 : break;
114 11 : case IntervalType::AUGMENTED:
115 11 : cromaticSteps += 1;
116 11 : break;
117 0 : default:
118 0 : break;
119 : }
120 : } else {
121 73 : switch (ornInt.type) {
122 0 : case IntervalType::DIMINISHED:
123 0 : cromaticSteps -= 2;
124 0 : break;
125 22 : case IntervalType::MINOR:
126 22 : cromaticSteps -= 1;
127 22 : break;
128 0 : case IntervalType::AUGMENTED:
129 0 : cromaticSteps += 1;
130 0 : break;
131 51 : default:
132 51 : break;
133 : }
134 : }
135 :
136 84 : resultingInterval.chromatic = cromaticSteps;
137 :
138 84 : return resultingInterval;
139 : }
140 :
141 : const std::array<Interval, 26> Interval::allIntervals {
142 : // diatonic - chromatic
143 : Interval(0, 0), // 0 Perfect Unison
144 : Interval(0, 1), // 1 Augmented Unison
145 :
146 : Interval(1, 0), // 2 Diminished Second
147 : Interval(1, 1), // 3 Minor Second
148 : Interval(1, 2), // 4 Major Second
149 : Interval(1, 3), // 5 Augmented Second
150 :
151 : Interval(2, 2), // 6 Diminished Third
152 : Interval(2, 3), // 7 Minor Third
153 : Interval(2, 4), // 8 Major Third
154 : Interval(2, 5), // 9 Augmented Third
155 :
156 : Interval(3, 4), // 10 Diminished Fourth
157 : Interval(3, 5), // 11 Perfect Fourth
158 : Interval(3, 6), // 12 Augmented Fourth
159 :
160 : Interval(4, 6), // 13 Diminished Fifth
161 : Interval(4, 7), // 14 Perfect Fifth
162 : Interval(4, 8), // 15 Augmented Fifth
163 :
164 : Interval(5, 7), // 16 Diminished Sixth
165 : Interval(5, 8), // 17 Minor Sixth
166 : Interval(5, 9), // 18 Major Sixth
167 : Interval(5, 10), // 19 Augmented Sixth
168 :
169 : Interval(6, 9), // 20 Diminished Seventh
170 : Interval(6, 10), // 21 Minor Seventh
171 : Interval(6, 11), // 22 Major Seventh
172 : Interval(6, 12), // 23 Augmented Seventh
173 :
174 : Interval(7, 11), // 24 Diminished Octave
175 : Interval(7, 12) // 25 Perfect Octave
176 : };
177 :
178 361 : int Interval::chromatic2diatonic(int semitones)
179 : {
180 : static constexpr int il[12] = {
181 : 0, // Perfect Unison
182 : 3, // Minor Second
183 : 4, // Major Second
184 : 7, // Minor Third
185 : 8, // Major Third
186 : 11, // Perfect Fourth
187 : 12, // Augmented Fourth
188 : 14, // Perfect Fifth
189 : 17, // Minor Sixth
190 : 18, // Major Sixth
191 : 21, // Minor Seventh
192 : 22, // Major Seventh
193 : // 25 Perfect Octave
194 : };
195 361 : bool down = semitones < 0;
196 361 : if (down) {
197 248 : semitones = -semitones;
198 : }
199 361 : int val = semitones % 12;
200 361 : int octave = semitones / 12;
201 361 : int intervalIndex = il[val];
202 361 : int steps = allIntervals[intervalIndex].diatonic;
203 361 : steps = steps + octave * 7;
204 361 : return down ? -steps : steps;
205 : }
206 : }
|