-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
note.h
512 lines (412 loc) · 18.9 KB
/
note.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __NOTE_H__
#define __NOTE_H__
/**
\file
Definition of classes Note and NoteHead.
*/
#include "containers.h"
#include "engravingitem.h"
#include "symbol.h"
#include "noteevent.h"
#include "pitchspelling.h"
#include "shape.h"
#include "key.h"
#include "iengravingconfiguration.h"
#include "modularity/ioc.h"
namespace mu::engraving {
class Factory;
}
namespace Ms {
class Tie;
class Chord;
class NoteEvent;
class Text;
class Score;
class MuseScoreView;
class Bend;
class AccidentalState;
class Accidental;
class NoteDot;
class Spanner;
class StaffType;
class NoteEditData;
enum class AccidentalType;
static constexpr int MAX_DOTS = 4;
//---------------------------------------------------------
// @@ NoteHead
//---------------------------------------------------------
class NoteHead final : public Symbol
{
public:
NoteHead(Note* parent = 0);
NoteHead(const NoteHead&) = default;
NoteHead& operator=(const NoteHead&) = delete;
NoteHead* clone() const override { return new NoteHead(*this); }
NoteHeadGroup headGroup() const;
};
//---------------------------------------------------------
// NoteVal
/// helper structure
/// \cond PLUGIN_API \private \endcond
//---------------------------------------------------------
struct NoteVal {
int pitch { -1 };
int tpc1 { Tpc::TPC_INVALID };
int tpc2 { Tpc::TPC_INVALID };
int fret { INVALID_FRET_INDEX };
int string { INVALID_STRING_INDEX };
NoteHeadGroup headGroup { NoteHeadGroup::HEAD_NORMAL };
NoteVal() {}
NoteVal(int p)
: pitch(p) {}
};
static const int INVALID_LINE = -10000;
//---------------------------------------------------------------------------------------
// @@ Note
/// Graphic representation of a note.
//
// @P accidental Accidental note accidental (null if none)
// @P accidentalType int note accidental type
// @P dots array[NoteDot] list of note dots (some can be null, read only)
// @P dotsCount int number of note dots (read only)
// @P elements array[EngravingItem] list of elements attached to notehead
// @P fret int fret number in tablature
// @P ghost bool ghost note (guitar: death note)
// @P headScheme enum (NoteHeadScheme.HEAD_AUTO, .HEAD_NORMAL, .HEAD_PITCHNAME, .HEAD_PITCHNAME_GERMAN, .HEAD_SHAPE_NOTE_4, .HEAD_SHAPE_NOTE_7_AIKIN, .HEAD_SHAPE_NOTE_7_FUNK, .HEAD_SHAPE_NOTE_7_WALKER, .HEAD_SOLFEGE, .HEAD_SOLFEGE_FIXED)
// @P headGroup enum (NoteHeadGroup.HEAD_NORMAL, .HEAD_BREVIS_ALT, .HEAD_CROSS, .HEAD_DIAMOND, .HEAD_DO, .HEAD_FA, .HEAD_LA, .HEAD_MI, .HEAD_RE, .HEAD_SLASH, .HEAD_SOL, .HEAD_TI, .HEAD_XCIRCLE, .HEAD_TRIANGLE)
// @P headType enum (NoteHeadType.HEAD_AUTO, .HEAD_BREVIS, .HEAD_HALF, .HEAD_QUARTER, .HEAD_WHOLE)
// @P hidden bool hidden, not played note (read only)
// @P line int notehead position (read only)
// @P mirror bool mirror notehead on x axis (read only)
// @P pitch int midi pitch
// @P play bool play note
// @P ppitch int actual played midi pitch (honoring ottavas) (read only)
// @P isSmall bool small notehead
// @P string int string number in tablature
// @P subchannel int midi subchannel (for midi articulation) (read only)
// @P tieBack Tie note backward tie (null if none, read only)
// @P tieFor Tie note forward tie (null if none, read only)
// @P tpc int tonal pitch class, as per concert pitch setting
// @P tpc1 int tonal pitch class, non transposed
// @P tpc2 int tonal pitch class, transposed
// @P tuning float tuning offset in cent
// @P userDotPosition enum (Direction.AUTO, Direction.DOWN, Direction.UP)
// @P userMirror enum (DirectionH.AUTO, DirectionH.LEFT, DirectionH.RIGHT)
// @P veloOffset int
// @P veloType enum (Note.OFFSET_VAL, Note.USER_VAL)
//---------------------------------------------------------------------------------------
class Note final : public EngravingItem
{
public:
enum class SlideType {
Undefined = 0,
Shift, // connects 2 notes
Legato, // connects 2 notes and adds a slur
Plop, // from up to note
Lift, // from down to note
Doit, // from note to up
Fall, // from note to down
};
struct Slide {
SlideType type { SlideType::Undefined };
Note* startNote = nullptr; // note to start slide (for 2 notes slides)
Note* endNote = nullptr; // note to end slide (for 2 notes slides)
bool isValid() const { return type != SlideType::Undefined; }
bool is(SlideType t) const { return t == type; }
uint32_t slideToNoteLenght{ 40 };
};
private:
bool _ghost { false }; ///< ghost note
bool _deadNote { false }; ///< dead note
bool _hidden { false }; ///< marks this note as the hidden one if there are
///< overlapping notes; hidden notes are not played
///< and heads + accidentals are not shown
bool _dotsHidden { false }; ///< dots of hidden notes are hidden too
///< except if only one note is dotted
bool _fretConflict { false }; ///< used by TAB staves to mark a fretting conflict:
///< two or more notes on the same string
bool dragMode { false };
bool _mirror { false }; ///< True if note is mirrored at stem.
bool m_isSmall { false };
bool _play { true }; // note is not played if false
mutable bool _mark { false }; // for use in sequencer
bool _fixed { false }; // for slash notation
DirectionH _userMirror { DirectionH::AUTO }; ///< user override of mirror
DirectionV _userDotPosition { DirectionV::AUTO }; ///< user override of dot position
NoteHeadScheme _headScheme { NoteHeadScheme::HEAD_AUTO };
NoteHeadGroup _headGroup { NoteHeadGroup::HEAD_NORMAL };
NoteHeadType _headType { NoteHeadType::HEAD_AUTO };
VeloType _veloType { VeloType::OFFSET_VAL };
int _offTimeType { 0 }; // compatibility only 1 - user(absolute), 2 - offset (%)
int _onTimeType { 0 }; // compatibility only 1 - user, 2 - offset
int _subchannel { 0 }; ///< articulation
int _line { INVALID_LINE }; ///< y-Position; 0 - top line.
int _fret { -1 }; ///< for tablature view
int _string { -1 };
mutable int _tpc[2] { Tpc::TPC_INVALID, Tpc::TPC_INVALID }; ///< tonal pitch class (concert/transposing)
mutable int _pitch { 0 }; ///< Note pitch as midi value (0 - 127).
int _veloOffset { 0 }; ///< velocity user offset in percent, or absolute velocity for this note
int _fixedLine { 0 }; // fixed line number if _fixed == true
qreal _tuning { 0.0 }; ///< pitch offset in cent, playable only by internal synthesizer
Accidental* _accidental { 0 };
Tie* _tieFor { 0 };
Tie* _tieBack { 0 };
Slide _attachedSlide; // slide which starts from note
Slide* _relatedSlide = nullptr; // slide which goes to note
Symbol* _leftParenthesis = nullptr;
Symbol* _rightParenthesis = nullptr;
bool _hasHeadParentheses = false;
bool _isHammerOn = false;
bool _harmonic = false;
ElementList _el; ///< fingering, other text, symbols or images
std::vector<NoteDot*> _dots;
NoteEventList _playEvents;
std::vector<Spanner*> _spannerFor;
std::vector<Spanner*> _spannerBack;
SymId _cachedNoteheadSym; // use in draw to avoid recomputing at every update
SymId _cachedSymNull; // additional symbol for some transparent notehead
QString _fretString;
friend class mu::engraving::Factory;
Note(Chord* ch = 0);
Note(const Note&, bool link = false);
void startDrag(EditData&) override;
mu::RectF drag(EditData& ed) override;
void endDrag(EditData&) override;
void editDrag(EditData& editData) override;
void verticalDrag(EditData& ed);
void horizontalDrag(EditData& ed);
void addSpanner(Spanner*);
void removeSpanner(Spanner*);
int concertPitchIdx() const;
void updateRelLine(int relLine, bool undoable);
bool isNoteName() const;
SymId noteHead() const;
void normalizeLeftDragDelta(Segment* seg, EditData& ed, NoteEditData* ned);
static QString tpcUserName(int tpc, int pitch, bool explicitAccidental);
public:
~Note();
Note& operator=(const Note&) = delete;
virtual Note* clone() const override { return new Note(*this, false); }
Chord* chord() const { return (Chord*)explicitParent(); }
void setParent(Chord* ch);
// Score Tree functions
EngravingObject* scanParent() const override;
EngravingObject* scanChild(size_t idx) const override;
size_t scanChildCount() const override;
void undoUnlink() override;
qreal mag() const override;
EngravingItem* elementBase() const override;
void layout() override;
void layout2();
//setter is used only in drumset tools to setup the notehead preview in the drumset editor and the palette
void setCachedNoteheadSym(SymId i) { _cachedNoteheadSym = i; }
void scanElements(void* data, void (* func)(void*, EngravingItem*), bool all = true) override;
void setTrack(track_idx_t val) override;
int playTicks() const;
Fraction playTicksFraction() const;
qreal headWidth() const;
qreal headHeight() const;
qreal tabHeadWidth(const StaffType* tab = 0) const;
qreal tabHeadHeight(const StaffType* tab = 0) const;
mu::PointF stemDownNW() const;
mu::PointF stemUpSE() const;
qreal bboxXShift() const;
qreal noteheadCenterX() const;
qreal bboxRightPos() const;
qreal headBodyWidth() const;
qreal outsideTieAttachX(bool up) const;
NoteHeadScheme headScheme() const { return _headScheme; }
void updateHeadGroup(const NoteHeadGroup headGroup);
NoteHeadGroup headGroup() const { return _headGroup; }
NoteHeadType headType() const { return _headType; }
void setHeadScheme(NoteHeadScheme val);
void setHeadGroup(NoteHeadGroup val);
void setHeadType(NoteHeadType t);
int subtype() const override { return int(_headGroup); }
QString subtypeName() const override;
void setPitch(int val);
void setPitch(int pitch, int tpc1, int tpc2);
int pitch() const { return _pitch; }
int ottaveCapoFret() const;
int ppitch() const; ///< playback pitch
int epitch() const; ///< effective pitch
int octave() const;
int playingOctave() const;
qreal tuning() const { return _tuning; }
void setTuning(qreal v) { _tuning = v; }
void undoSetTpc(int v);
int transposition() const;
bool fixed() const { return _fixed; }
void setFixed(bool v) { _fixed = v; }
int fixedLine() const { return _fixedLine; }
void setFixedLine(int v) { _fixedLine = v; }
int tpc() const;
int tpc1() const { return _tpc[0]; } // non transposed tpc
int tpc2() const { return _tpc[1]; } // transposed tpc
QString tpcUserName(bool explicitAccidental = false) const;
void setTpc(int v);
void setTpc1(int v) { _tpc[0] = v; }
void setTpc2(int v) { _tpc[1] = v; }
void setTpcFromPitch();
int tpc1default(int pitch) const;
int tpc2default(int pitch) const;
int transposeTpc(int tpc) const;
int playingTpc() const;
Accidental* accidental() const { return _accidental; }
void setAccidental(Accidental* a) { _accidental = a; }
AccidentalType accidentalType() const;
void setAccidentalType(AccidentalType type);
int line() const;
void setLine(int n) { _line = n; }
int fret() const { return _fret; }
void setFret(int val) { _fret = val; }
int string() const { return _string; }
void setString(int val);
bool ghost() const { return _ghost; }
void setGhost(bool val) { _ghost = val; }
bool deadNote() const { return _deadNote; }
void setDeadNote(bool deadNote) { _deadNote = deadNote; }
bool fretConflict() const { return _fretConflict; }
void setFretConflict(bool val) { _fretConflict = val; }
void add(EngravingItem*) override;
void remove(EngravingItem*) override;
bool mirror() const { return _mirror; }
void setMirror(bool val) { _mirror = val; }
bool isSmall() const { return m_isSmall; }
void setSmall(bool val);
bool play() const { return _play; }
void setPlay(bool val) { _play = val; }
Ms::Tie* tieFor() const { return _tieFor; }
Ms::Tie* tieBack() const { return _tieBack; }
void setTieFor(Tie* t) { _tieFor = t; }
void setTieBack(Tie* t) { _tieBack = t; }
Note* firstTiedNote() const;
const Note* lastTiedNote() const;
Note* lastTiedNote() { return const_cast<Note*>(static_cast<const Note*>(this)->lastTiedNote()); }
int unisonIndex() const;
void disconnectTiedNotes();
void connectTiedNotes();
void draw(mu::draw::Painter*) const override;
void read(XmlReader&) override;
bool readProperties(XmlReader&) override;
void readAddConnector(ConnectorInfoReader* info, bool pasteMode) override;
void write(XmlWriter&) const override;
bool acceptDrop(EditData&) const override;
EngravingItem* drop(EditData&) override;
bool hidden() const { return _hidden; }
void setHidden(bool val) { _hidden = val; }
bool dotsHidden() const { return _dotsHidden; }
void setDotsHidden(bool val) { _dotsHidden = val; }
NoteType noteType() const;
QString noteTypeUserName() const;
ElementList& el() { return _el; }
const ElementList& el() const { return _el; }
int subchannel() const { return _subchannel; }
void setSubchannel(int val) { _subchannel = val; }
DirectionH userMirror() const { return _userMirror; }
void setUserMirror(DirectionH d) { _userMirror = d; }
DirectionV userDotPosition() const { return _userDotPosition; }
void setUserDotPosition(DirectionV d) { _userDotPosition = d; }
bool dotIsUp() const; // actual dot position
void reset() override;
VeloType veloType() const { return _veloType; }
void setVeloType(VeloType v) { _veloType = v; }
int veloOffset() const { return _veloOffset; }
void setVeloOffset(int v) { _veloOffset = v; }
void setOnTimeOffset(int v);
void setOffTimeOffset(int v);
int customizeVelocity(int velo) const;
NoteDot* dot(int n) { return _dots[n]; }
const std::vector<NoteDot*>& dots() const { return _dots; }
std::vector<NoteDot*>& dots() { return _dots; }
int qmlDotsCount();
void updateAccidental(AccidentalState*);
void updateLine();
void setNval(const NoteVal&, Fraction = { -1, 1 });
NoteEventList& playEvents() { return _playEvents; }
const NoteEventList& playEvents() const { return _playEvents; }
NoteEvent* noteEvent(int idx) { return &_playEvents[idx]; }
void setPlayEvents(const NoteEventList& l) { _playEvents = l; }
const std::vector<Spanner*>& spannerFor() const { return _spannerFor; }
const std::vector<Spanner*>& spannerBack() const { return _spannerBack; }
void addSpannerBack(Spanner* e)
{
if (!mu::contains(_spannerBack, e)) {
_spannerBack.push_back(e);
}
}
bool removeSpannerBack(Spanner* e) { return mu::remove(_spannerBack, e); }
void addSpannerFor(Spanner* e)
{
if (!mu::contains(_spannerFor, e)) {
_spannerFor.push_back(e);
}
}
bool removeSpannerFor(Spanner* e) { return mu::remove(_spannerFor, e); }
void transposeDiatonic(int interval, bool keepAlterations, bool useDoubleAccidentals);
void localSpatiumChanged(qreal oldValue, qreal newValue) override;
mu::engraving::PropertyValue getProperty(Pid propertyId) const override;
bool setProperty(Pid propertyId, const mu::engraving::PropertyValue&) override;
mu::engraving::PropertyValue propertyDefault(Pid) const override;
bool mark() const { return _mark; }
void setMark(bool v) const { _mark = v; }
void setScore(Score* s) override;
void setDotY(DirectionV);
void setHeadHasParentheses(bool hasParentheses);
static SymId noteHead(int direction, NoteHeadGroup, NoteHeadType, int tpc, Key key, NoteHeadScheme scheme);
static SymId noteHead(int direction, NoteHeadGroup, NoteHeadType);
NoteVal noteVal() const;
EngravingItem* nextInEl(EngravingItem* e);
EngravingItem* prevInEl(EngravingItem* e);
EngravingItem* nextElement() override;
EngravingItem* prevElement() override;
virtual EngravingItem* lastElementBeforeSegment();
EngravingItem* nextSegmentElement() override;
EngravingItem* prevSegmentElement() override;
QString accessibleInfo() const override;
QString screenReaderInfo() const override;
QString accessibleExtraInfo() const override;
Shape shape() const override;
std::vector<Note*> tiedNotes() const;
void setOffTimeType(int v) { _offTimeType = v; }
void setOnTimeType(int v) { _onTimeType = v; }
int offTimeType() const { return _offTimeType; }
int onTimeType() const { return _onTimeType; }
const Slide& slide() const { return _attachedSlide; }
void attachSlide(const Slide& s) { _attachedSlide = s; }
void setRelatedSlide(Slide* pSlide) { _relatedSlide = pSlide; }
bool hasRelatedSlide() const { return !!_relatedSlide; }
const Slide& relatedSlide() const { return *_relatedSlide; }
bool isSlideToNote() const;
bool isSlideOutNote() const;
bool isSlideStart() const;
bool isSlideEnd() const;
void relateSlide(Note& start) { _relatedSlide = &start._attachedSlide; }
bool isHammerOn() const { return _isHammerOn; }
void setIsHammerOn(bool hammerOn) { _isHammerOn = hammerOn; }
void setHarmonic(bool val) { _harmonic = val; }
bool harmonic() const { return _harmonic; }
};
} // namespace Ms
#endif