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 : #pragma once
23 :
24 : #include "mpe/events.h"
25 :
26 : #include "../dom/chord.h"
27 : #include "../dom/note.h"
28 : #include "../dom/sig.h"
29 :
30 : #include "utils/arrangementutils.h"
31 : #include "utils/pitchutils.h"
32 : #include "playbackcontext.h"
33 :
34 : namespace mu::engraving {
35 : struct RenderingContext {
36 : muse::mpe::timestamp_t nominalTimestamp = 0;
37 : muse::mpe::duration_t nominalDuration = 0;
38 : muse::mpe::dynamic_level_t nominalDynamicLevel = 0;
39 : int nominalPositionStartTick = 0;
40 : int nominalPositionEndTick = 0;
41 : int nominalDurationTicks = 0;
42 : int positionTickOffset = 0;
43 :
44 : BeatsPerSecond beatsPerSecond = 0;
45 : TimeSigFrac timeSignatureFraction;
46 :
47 : muse::mpe::ArticulationMap commonArticulations;
48 :
49 : const Score* score = nullptr;
50 : const muse::mpe::ArticulationsProfilePtr profile;
51 : const PlaybackContextPtr playbackCtx;
52 :
53 2679 : bool isValid() const
54 : {
55 2679 : return score
56 2679 : && profile
57 2679 : && playbackCtx
58 5358 : && beatsPerSecond > 0
59 2679 : && nominalDuration > 0
60 5358 : && nominalDurationTicks > 0;
61 : }
62 : };
63 :
64 1151 : inline RenderingContext buildRenderingCtx(const Chord* chord, const int tickPositionOffset,
65 : const muse::mpe::ArticulationsProfilePtr profile, const PlaybackContextPtr playbackCtx,
66 : const muse::mpe::ArticulationMap& articulations = {})
67 : {
68 1151 : int chordPosTick = chord->tick().ticks();
69 1151 : int chordDurationTicks = chord->actualTicks().ticks();
70 1151 : int chordPosTickWithOffset = chordPosTick + tickPositionOffset;
71 :
72 1151 : const Score* score = chord->score();
73 :
74 1151 : auto chordTnD = timestampAndDurationFromStartAndDurationTicks(score, chordPosTick, chordDurationTicks, tickPositionOffset);
75 :
76 1151 : BeatsPerSecond bps = score->multipliedTempoAtUtick(chordPosTickWithOffset);
77 1151 : TimeSigFrac timeSignatureFraction = score->sigmap()->timesig(chordPosTick).timesig();
78 :
79 1151 : RenderingContext ctx{ chordTnD.timestamp,
80 1151 : chordTnD.duration,
81 1151 : playbackCtx->appliableDynamicLevel(chord->track(), chordPosTickWithOffset),
82 : chordPosTick,
83 1151 : chordPosTick + chordDurationTicks,
84 : chordDurationTicks,
85 : tickPositionOffset,
86 : bps,
87 : timeSignatureFraction,
88 : articulations,
89 : score,
90 : profile,
91 2302 : playbackCtx };
92 :
93 1151 : return ctx;
94 : }
95 :
96 : struct NominalNoteCtx {
97 : voice_idx_t voiceIdx = 0;
98 : staff_idx_t staffIdx = 0;
99 : muse::mpe::timestamp_t timestamp = 0;
100 : muse::mpe::duration_t duration = 0;
101 : BeatsPerSecond tempo = 0;
102 : muse::mpe::dynamic_level_t dynamicLevel = 0;
103 : float userVelocityFraction = 0.f;
104 :
105 : muse::mpe::pitch_level_t pitchLevel = 0;
106 :
107 : RenderingContext chordCtx;
108 : muse::mpe::ArticulationMap articulations;
109 :
110 1558 : explicit NominalNoteCtx(const Note* note, const RenderingContext& ctx)
111 1558 : : voiceIdx(note->voice()),
112 1558 : staffIdx(note->staffIdx()),
113 1558 : timestamp(ctx.nominalTimestamp),
114 1558 : duration(ctx.nominalDuration),
115 1558 : tempo(ctx.beatsPerSecond),
116 1558 : dynamicLevel(ctx.nominalDynamicLevel),
117 1558 : userVelocityFraction(note->userVelocityFraction()),
118 1558 : pitchLevel(notePitchLevel(note->playingTpc(),
119 : note->playingOctave(),
120 : note->playingTuning())),
121 1558 : chordCtx(ctx),
122 1558 : articulations(ctx.commonArticulations)
123 : {
124 1558 : }
125 : };
126 :
127 1747 : inline muse::mpe::NoteEvent buildNoteEvent(const NominalNoteCtx& ctx, const muse::mpe::PitchCurve& pitchCurve = {})
128 : {
129 1747 : return muse::mpe::NoteEvent(ctx.timestamp,
130 1747 : ctx.duration,
131 1747 : static_cast<muse::mpe::voice_layer_idx_t>(ctx.voiceIdx),
132 1747 : static_cast<muse::mpe::staff_layer_idx_t>(ctx.staffIdx),
133 1747 : ctx.pitchLevel,
134 1747 : ctx.dynamicLevel,
135 1747 : ctx.articulations,
136 1747 : ctx.tempo.val,
137 1747 : ctx.userVelocityFraction,
138 1747 : pitchCurve);
139 : }
140 : }
|