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 "glissandosrenderer.h"
24 :
25 : #include "dom/glissando.h"
26 :
27 : #include "playback/renderingcontext.h"
28 : #include "playback/utils/expressionutils.h"
29 :
30 : using namespace mu::engraving;
31 : using namespace muse;
32 : using namespace muse::mpe;
33 :
34 5 : static std::vector<int> pitchSteps(const Note* note)
35 : {
36 5 : const Glissando* glissando = nullptr;
37 5 : for (const Spanner* spanner : note->spannerFor()) {
38 5 : if (spanner->isGlissando()) {
39 5 : glissando = toGlissando(spanner);
40 5 : break;
41 : }
42 : }
43 :
44 5 : if (!glissando) {
45 0 : return {};
46 : }
47 :
48 5 : std::vector<int> pitchSteps;
49 5 : Glissando::pitchSteps(glissando, pitchSteps);
50 :
51 5 : return pitchSteps;
52 5 : }
53 :
54 1 : muse::mpe::duration_t GlissandosRenderer::discreteGlissandoStepDuration(const Note* note, const duration_t noteDuration)
55 : {
56 1 : const std::vector<int> steps = pitchSteps(note);
57 1 : if (steps.empty()) {
58 0 : return 0;
59 : }
60 :
61 1 : return noteDuration / static_cast<float>(steps.size());
62 1 : }
63 :
64 4 : void GlissandosRenderer::renderDiscreteGlissando(const Note* note, NominalNoteCtx& ctx, mpe::PlaybackEventList& result)
65 : {
66 4 : const std::vector<int> steps = pitchSteps(note);
67 4 : if (steps.empty()) {
68 0 : return;
69 : }
70 :
71 4 : const size_t stepsCount = steps.size();
72 4 : const float durationStep = ctx.duration / static_cast<float>(stepsCount);
73 4 : size_t firstStep = 0;
74 :
75 4 : if (note->tieBack()) {
76 1 : mpe::ArticulationMeta& meta = ctx.articulations.at(ArticulationType::DiscreteGlissando).meta;
77 1 : meta.timestamp += durationStep;
78 1 : meta.overallDuration -= durationStep;
79 1 : firstStep = 1;
80 : }
81 :
82 25 : for (size_t i = firstStep; i < stepsCount; ++i) {
83 21 : NominalNoteCtx noteCtx(ctx);
84 21 : noteCtx.duration = durationStep;
85 21 : noteCtx.timestamp += i * durationStep;
86 21 : noteCtx.pitchLevel += steps.at(i) * mpe::PITCH_LEVEL_STEP;
87 :
88 21 : const int utick = timestampToTick(noteCtx.chordCtx.score, noteCtx.timestamp);
89 21 : noteCtx.dynamicLevel = ctx.chordCtx.playbackCtx->appliableDynamicLevel(note->track(), utick);
90 :
91 21 : updateArticulationBoundaries(ArticulationType::DiscreteGlissando,
92 : noteCtx.timestamp,
93 : noteCtx.duration,
94 : noteCtx.articulations);
95 :
96 21 : result.emplace_back(buildNoteEvent(noteCtx));
97 21 : }
98 25 : }
99 :
100 3 : void GlissandosRenderer::renderContinuousGlissando(const Note*, NominalNoteCtx& ctx, muse::mpe::PlaybackEventList& result)
101 : {
102 3 : result.emplace_back(buildNoteEvent(ctx));
103 6 : }
|