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 : #include "bendinfoconverter.h"
23 :
24 : #include <engraving/dom/note.h>
25 :
26 : using namespace mu::engraving;
27 :
28 : namespace mu::iex::guitarpro {
29 121 : ImportedBendInfo BendInfoConverter::fillBendInfo(const Note* note, const PitchValues& pitchValues)
30 : {
31 : enum class PitchValuesDiff {
32 : NONE,
33 : SAME_PITCH_AND_TIME,
34 : SAME_PITCH_DIFF_TIME,
35 : INCREASED_PITCH_SAME_TIME,
36 : INCREASED_PITCH_DIFF_TIME,
37 : DECREASED_PITCH_DIFF_TIME
38 : };
39 :
40 : using pvd = PitchValuesDiff;
41 :
42 121 : ImportedBendInfo importedInfo;
43 : PitchValuesDiff currentPitchDiff;
44 121 : PitchValuesDiff previousPitchDiff = PitchValuesDiff::NONE;
45 :
46 231 : auto pitchDiff = [](const PitchValue& prev, const PitchValue& cur) {
47 231 : if (prev.pitch == cur.pitch) {
48 86 : return prev.time == cur.time ? pvd::SAME_PITCH_AND_TIME : pvd::SAME_PITCH_DIFF_TIME;
49 : }
50 :
51 145 : if (prev.time == cur.time) {
52 0 : return pvd::INCREASED_PITCH_SAME_TIME;
53 : }
54 :
55 145 : return prev.pitch < cur.pitch ? pvd::INCREASED_PITCH_DIFF_TIME : pvd::DECREASED_PITCH_DIFF_TIME;
56 : };
57 :
58 140 : auto addPrebendOrHold = [&importedInfo](const PitchValue& start) {
59 140 : importedInfo.timeOffsetFromStart = start.time;
60 140 : importedInfo.pitchOffsetFromStart = start.pitch;
61 140 : if (start.pitch > 0) {
62 64 : importedInfo.type = BendType::PREBEND;
63 : }
64 261 : };
65 :
66 352 : for (size_t i = 0; i < pitchValues.size() - 1; i++) {
67 231 : currentPitchDiff = pitchDiff(pitchValues[i], pitchValues[i + 1]);
68 231 : if (currentPitchDiff == pvd::SAME_PITCH_AND_TIME) {
69 0 : continue;
70 : }
71 :
72 231 : if (currentPitchDiff == previousPitchDiff && !importedInfo.segments.empty()) {
73 17 : BendSegment& lastSegment = importedInfo.segments.back();
74 17 : lastSegment.middleTime = pitchValues[i + 1].time; // there is no "hold" in bend, cause both segments go same direction
75 17 : lastSegment.endTime = pitchValues[i + 1].time;
76 17 : lastSegment.endPitch = pitchValues[i + 1].pitch;
77 17 : continue;
78 17 : }
79 :
80 214 : switch (currentPitchDiff) {
81 0 : case pvd::NONE:
82 : case pvd::SAME_PITCH_AND_TIME:
83 0 : break;
84 :
85 86 : case pvd::SAME_PITCH_DIFF_TIME:
86 : case pvd::INCREASED_PITCH_SAME_TIME:
87 : {
88 86 : if (importedInfo.segments.empty()) {
89 43 : addPrebendOrHold(pitchValues[i]);
90 : } else {
91 43 : BendSegment& lastSegment = importedInfo.segments.back();
92 43 : lastSegment.middleTime = lastSegment.endTime;
93 43 : lastSegment.endTime = pitchValues[i + 1].time;
94 43 : lastSegment.endPitch = pitchValues[i + 1].pitch;
95 : }
96 :
97 86 : break;
98 : }
99 :
100 128 : case pvd::INCREASED_PITCH_DIFF_TIME:
101 : case pvd::DECREASED_PITCH_DIFF_TIME:
102 : {
103 128 : if (importedInfo.segments.empty()) {
104 97 : addPrebendOrHold(pitchValues[i]);
105 : }
106 :
107 128 : BendSegment newSegment;
108 128 : newSegment.startPitch = pitchValues[i].pitch;
109 128 : newSegment.endPitch = pitchValues[i + 1].pitch;
110 128 : newSegment.startTime = pitchValues[i].time;
111 128 : newSegment.middleTime = pitchValues[i + 1].time;
112 128 : newSegment.endTime = pitchValues[i + 1].time;
113 128 : importedInfo.segments.push_back(newSegment);
114 128 : break;
115 : }
116 : }
117 :
118 214 : previousPitchDiff = currentPitchDiff;
119 : }
120 :
121 121 : importedInfo.note = note;
122 121 : if (!importedInfo.segments.empty()) {
123 97 : importedInfo.segments.back().endTime = PitchValue::MAX_TIME;
124 : }
125 :
126 249 : for (auto& seg : importedInfo.segments) {
127 128 : if (seg.endTime - seg.middleTime == 1) {
128 9 : seg.middleTime = seg.endTime;
129 : }
130 : }
131 :
132 190 : if (importedInfo.segments.size() == 1 && importedInfo.type == BendType::NORMAL_BEND
133 190 : && importedInfo.segments.front().pitchDiff() == GP_PITCH_PER_QUARTERTONE) {
134 14 : importedInfo.type = BendType::SLIGHT_BEND;
135 : }
136 :
137 121 : return importedInfo;
138 0 : }
139 : } // namespace mu::iex::guitarpro
|