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 "tremolometaparser.h"
24 :
25 : #include "dom/tremolosinglechord.h"
26 : #include "dom/tremolotwochord.h"
27 : #include "dom/chord.h"
28 :
29 : #include "mpe/mpetypes.h"
30 : #include "../../renderingcontext.h"
31 :
32 : using namespace mu::engraving;
33 : using namespace muse;
34 :
35 29 : static mpe::ArticulationType toArticulationType(TremoloType type)
36 : {
37 29 : switch (type) {
38 7 : case TremoloType::R8:
39 : case TremoloType::C8:
40 7 : return mpe::ArticulationType::Tremolo8th;
41 6 : case TremoloType::R16:
42 : case TremoloType::C16:
43 6 : return mpe::ArticulationType::Tremolo16th;
44 16 : case TremoloType::R32:
45 : case TremoloType::C32:
46 16 : return mpe::ArticulationType::Tremolo32nd;
47 0 : case TremoloType::R64:
48 : case TremoloType::C64:
49 : // Playback currently caps tremolo subdivisions at 64th; 128th and 256th
50 : // tremolos intentionally reuse the 64th articulation pattern.
51 : case TremoloType::R128:
52 : case TremoloType::C128:
53 : case TremoloType::R256:
54 : case TremoloType::C256:
55 0 : return mpe::ArticulationType::Tremolo64th;
56 0 : case TremoloType::BUZZ_ROLL:
57 0 : return mpe::ArticulationType::TremoloBuzz;
58 0 : case TremoloType::INVALID_TREMOLO:
59 0 : break;
60 : }
61 :
62 0 : return mpe::ArticulationType::Undefined;
63 : }
64 :
65 28 : void TremoloSingleMetaParser::doParse(const EngravingItem* item, const RenderingContext& ctx, mpe::ArticulationMap& result)
66 : {
67 28 : IF_ASSERT_FAILED(item->type() == ElementType::TREMOLO_SINGLECHORD) {
68 0 : return;
69 : }
70 :
71 28 : const TremoloSingleChord* tremolo = item_cast<const TremoloSingleChord*>(item);
72 :
73 28 : mpe::ArticulationType type = toArticulationType(tremolo->tremoloType());
74 28 : if (type == mpe::ArticulationType::Undefined) {
75 0 : return;
76 : }
77 :
78 28 : int overallDurationTicks = ctx.nominalDurationTicks;
79 :
80 28 : const mpe::ArticulationPattern& pattern = ctx.profile->pattern(type);
81 28 : if (pattern.empty()) {
82 0 : return;
83 : }
84 :
85 28 : mpe::ArticulationMeta articulationMeta;
86 28 : articulationMeta.type = type;
87 28 : articulationMeta.pattern = pattern;
88 28 : articulationMeta.timestamp = ctx.nominalTimestamp;
89 28 : articulationMeta.overallDuration = timestampFromTicks(ctx.score, ctx.nominalPositionStartTick + overallDurationTicks)
90 28 : - ctx.nominalTimestamp;
91 :
92 28 : appendArticulationData(std::move(articulationMeta), result);
93 28 : }
94 :
95 1 : void TremoloTwoMetaParser::doParse(const EngravingItem* item, const RenderingContext& ctx, mpe::ArticulationMap& result)
96 : {
97 1 : IF_ASSERT_FAILED(item->type() == ElementType::TREMOLO_TWOCHORD) {
98 0 : return;
99 : }
100 :
101 1 : const TremoloTwoChord* tremolo = item_cast<const TremoloTwoChord*>(item);
102 :
103 1 : const Chord* chord2 = tremolo->chord2();
104 1 : IF_ASSERT_FAILED(chord2) {
105 0 : return;
106 : }
107 :
108 1 : if (chord2->tick().ticks() == ctx.nominalPositionStartTick) {
109 0 : return;
110 : }
111 :
112 1 : mpe::ArticulationType type = toArticulationType(tremolo->tremoloType());
113 1 : if (type == mpe::ArticulationType::Undefined) {
114 0 : return;
115 : }
116 :
117 1 : int overallDurationTicks = ctx.nominalDurationTicks;
118 1 : if (tremolo->chord1() && tremolo->chord2()) {
119 1 : overallDurationTicks = tremolo->chord1()->actualTicks().ticks() + tremolo->chord2()->actualTicks().ticks();
120 : }
121 :
122 1 : const mpe::ArticulationPattern& pattern = ctx.profile->pattern(type);
123 1 : if (pattern.empty()) {
124 0 : return;
125 : }
126 :
127 1 : mpe::ArticulationMeta articulationMeta;
128 1 : articulationMeta.type = type;
129 1 : articulationMeta.pattern = pattern;
130 1 : articulationMeta.timestamp = ctx.nominalTimestamp;
131 1 : articulationMeta.overallDuration = timestampFromTicks(ctx.score, ctx.nominalPositionStartTick + overallDurationTicks)
132 1 : - ctx.nominalTimestamp;
133 :
134 1 : appendArticulationData(std::move(articulationMeta), result);
135 1 : }
|