1 //============================================================================= 2 // MuseScore 3 // Music Composition & Notation 4 // 5 // Copyright (C) 2002-2012 Werner Schweer 6 // 7 // This program is free software; you can redistribute it and/or modify 8 // it under the terms of the GNU General Public License version 2 9 // as published by the Free Software Foundation and appearing in 10 // the file LICENCE.GPL 11 //============================================================================= 12 13 #ifndef __NOTE_H__ 14 #define __NOTE_H__ 15 16 /** 17 \file 18 Definition of classes Note and NoteHead. 19 */ 20 21 #include "element.h" 22 #include "symbol.h" 23 #include "noteevent.h" 24 #include "pitchspelling.h" 25 #include "shape.h" 26 #include "key.h" 27 #include "sym.h" 28 29 namespace Ms { 30 31 class Tie; 32 class Chord; 33 class NoteEvent; 34 class Text; 35 class Score; 36 class Sym; 37 class MuseScoreView; 38 class Bend; 39 class AccidentalState; 40 class Accidental; 41 class NoteDot; 42 class Spanner; 43 class StaffType; 44 class NoteEditData; 45 enum class AccidentalType : unsigned char; 46 47 static const int MAX_DOTS = 4; 48 49 //--------------------------------------------------------- 50 // @@ NoteHead 51 //--------------------------------------------------------- 52 53 class NoteHead final : public Symbol { 54 Q_GADGET 55 public: 56 // keep in sync with noteHeadSchemeNames array in note.cpp 57 enum class Scheme : signed char { 58 ///.\{ 59 HEAD_AUTO = -1, 60 HEAD_NORMAL, 61 HEAD_PITCHNAME, 62 HEAD_PITCHNAME_GERMAN, 63 HEAD_SOLFEGE, 64 HEAD_SOLFEGE_FIXED, 65 HEAD_SHAPE_NOTE_4, 66 HEAD_SHAPE_NOTE_7_AIKIN, 67 HEAD_SHAPE_NOTE_7_FUNK, 68 HEAD_SHAPE_NOTE_7_WALKER, 69 HEAD_SCHEMES 70 ///\} 71 }; 72 // keep in sync with noteHeadGroupNames array in note.cpp 73 enum class Group : signed char { 74 ///.\{ 75 HEAD_NORMAL = 0, 76 HEAD_CROSS, 77 HEAD_PLUS, 78 HEAD_XCIRCLE, 79 HEAD_WITHX, 80 HEAD_TRIANGLE_UP, 81 HEAD_TRIANGLE_DOWN, 82 HEAD_SLASHED1, 83 HEAD_SLASHED2, 84 HEAD_DIAMOND, 85 HEAD_DIAMOND_OLD, 86 HEAD_CIRCLED, 87 HEAD_CIRCLED_LARGE, 88 HEAD_LARGE_ARROW, 89 HEAD_BREVIS_ALT, 90 91 HEAD_SLASH, 92 93 HEAD_SOL, 94 HEAD_LA, 95 HEAD_FA, 96 HEAD_MI, 97 HEAD_DO, 98 HEAD_RE, 99 HEAD_TI, 100 // not exposed from here 101 HEAD_DO_WALKER, 102 HEAD_RE_WALKER, 103 HEAD_TI_WALKER, 104 HEAD_DO_FUNK, 105 HEAD_RE_FUNK, 106 HEAD_TI_FUNK, 107 108 HEAD_DO_NAME, 109 HEAD_RE_NAME, 110 HEAD_MI_NAME, 111 HEAD_FA_NAME, 112 HEAD_SOL_NAME, 113 HEAD_LA_NAME, 114 HEAD_TI_NAME, 115 HEAD_SI_NAME, 116 117 HEAD_A_SHARP, 118 HEAD_A, 119 HEAD_A_FLAT, 120 HEAD_B_SHARP, 121 HEAD_B, 122 HEAD_B_FLAT, 123 HEAD_C_SHARP, 124 HEAD_C, 125 HEAD_C_FLAT, 126 HEAD_D_SHARP, 127 HEAD_D, 128 HEAD_D_FLAT, 129 HEAD_E_SHARP, 130 HEAD_E, 131 HEAD_E_FLAT, 132 HEAD_F_SHARP, 133 HEAD_F, 134 HEAD_F_FLAT, 135 HEAD_G_SHARP, 136 HEAD_G, 137 HEAD_G_FLAT, 138 HEAD_H, 139 HEAD_H_SHARP, 140 141 HEAD_CUSTOM, 142 HEAD_GROUPS, 143 HEAD_INVALID = -1 144 ///\} 145 }; 146 // keep in sync with noteHeadTypeNames array in note.cpp 147 enum class Type : signed char { 148 ///.\{ 149 HEAD_AUTO = -1, 150 HEAD_WHOLE = 0, 151 HEAD_HALF = 1, 152 HEAD_QUARTER = 2, 153 HEAD_BREVIS = 3, 154 HEAD_TYPES 155 ///\} 156 }; 157 158 Q_ENUM(Scheme); 159 Q_ENUM(Group); 160 Q_ENUM(Type); 161 Symbol(s)162 NoteHead(Score* s = 0) : Symbol(s) {} 163 NoteHead &operator=(const NoteHead&) = delete; clone()164 NoteHead* clone() const override { return new NoteHead(*this); } type()165 ElementType type() const override { return ElementType::NOTEHEAD; } 166 167 Group headGroup() const; 168 169 static QString scheme2userName(Scheme scheme); 170 static QString group2userName(Group group); 171 static QString type2userName(Type type); 172 static QString scheme2name(Scheme scheme); 173 static QString group2name(Group group); 174 static QString type2name(Type type); 175 static Scheme name2scheme(const QString& s); 176 static Group name2group(const QString& s); 177 static Type name2type(const QString& s); 178 }; 179 180 //--------------------------------------------------------- 181 // NoteVal 182 /// helper structure 183 /// \cond PLUGIN_API \private \endcond 184 //--------------------------------------------------------- 185 186 struct NoteVal { 187 int pitch { -1 }; 188 int tpc1 { Tpc::TPC_INVALID }; 189 int tpc2 { Tpc::TPC_INVALID }; 190 int fret { FRET_NONE }; 191 int string { STRING_NONE }; 192 NoteHead::Group headGroup { NoteHead::Group::HEAD_NORMAL }; 193 NoteValNoteVal194 NoteVal() {} NoteValNoteVal195 NoteVal(int p) : pitch(p) {} 196 }; 197 198 static const int INVALID_LINE = -10000; 199 200 //--------------------------------------------------------------------------------------- 201 // @@ Note 202 /// Graphic representation of a note. 203 // 204 // @P accidental Accidental note accidental (null if none) 205 // @P accidentalType int note accidental type 206 // @P dots array[NoteDot] list of note dots (some can be null, read only) 207 // @P dotsCount int number of note dots (read only) 208 // @P elements array[Element] list of elements attached to notehead 209 // @P fret int fret number in tablature 210 // @P ghost bool ghost note (guitar: death note) 211 // @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) 212 // @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) 213 // @P headType enum (NoteHeadType.HEAD_AUTO, .HEAD_BREVIS, .HEAD_HALF, .HEAD_QUARTER, .HEAD_WHOLE) 214 // @P hidden bool hidden, not played note (read only) 215 // @P line int notehead position (read only) 216 // @P mirror bool mirror notehead on x axis (read only) 217 // @P pitch int midi pitch 218 // @P play bool play note 219 // @P ppitch int actual played midi pitch (honoring ottavas) (read only) 220 // @P small bool small notehead 221 // @P string int string number in tablature 222 // @P subchannel int midi subchannel (for midi articulation) (read only) 223 // @P tieBack Tie note backward tie (null if none, read only) 224 // @P tieFor Tie note forward tie (null if none, read only) 225 // @P tpc int tonal pitch class, as per concert pitch setting 226 // @P tpc1 int tonal pitch class, non transposed 227 // @P tpc2 int tonal pitch class, transposed 228 // @P tuning float tuning offset in cent 229 // @P userDotPosition enum (Direction.AUTO, Direction.DOWN, Direction.UP) 230 // @P userMirror enum (DirectionH.AUTO, DirectionH.LEFT, DirectionH.RIGHT) 231 // @P veloOffset int 232 // @P veloType enum (Note.OFFSET_VAL, Note.USER_VAL) 233 //--------------------------------------------------------------------------------------- 234 235 class Note final : public Element { 236 Q_GADGET 237 public: 238 enum class ValueType : char { OFFSET_VAL, USER_VAL }; 239 Q_ENUM(ValueType); 240 241 private: 242 bool _ghost { false }; ///< ghost note (guitar: death note) 243 bool _hidden { false }; ///< marks this note as the hidden one if there are 244 ///< overlapping notes; hidden notes are not played 245 ///< and heads + accidentals are not shown 246 bool _dotsHidden { false }; ///< dots of hidden notes are hidden too 247 ///< except if only one note is dotted 248 bool _fretConflict { false }; ///< used by TAB staves to mark a fretting conflict: 249 ///< two or more notes on the same string 250 bool dragMode { false }; 251 bool _mirror { false }; ///< True if note is mirrored at stem. 252 bool _small { false }; 253 bool _play { true }; // note is not played if false 254 mutable bool _mark { false }; // for use in sequencer 255 bool _fixed { false }; // for slash notation 256 257 MScore::DirectionH _userMirror { MScore::DirectionH::AUTO }; ///< user override of mirror 258 Direction _userDotPosition { Direction::AUTO }; ///< user override of dot position 259 260 NoteHead::Scheme _headScheme { NoteHead::Scheme::HEAD_AUTO }; 261 NoteHead::Group _headGroup { NoteHead::Group::HEAD_NORMAL }; 262 NoteHead::Type _headType { NoteHead::Type::HEAD_AUTO }; 263 264 ValueType _veloType { ValueType::OFFSET_VAL }; 265 266 char _offTimeType { 0 }; // compatibility only 1 - user(absolute), 2 - offset (%) 267 char _onTimeType { 0 }; // compatibility only 1 - user, 2 - offset 268 269 int _subchannel { 0 }; ///< articulation 270 int _line { INVALID_LINE }; ///< y-Position; 0 - top line. 271 int _fret { -1 }; ///< for tablature view 272 int _string { -1 }; 273 mutable int _tpc[2] { Tpc::TPC_INVALID, Tpc::TPC_INVALID }; ///< tonal pitch class (concert/transposing) 274 mutable int _pitch { 0 }; ///< Note pitch as midi value (0 - 127). 275 276 int _veloOffset { 0 }; ///< velocity user offset in percent, or absolute velocity for this note 277 int _fixedLine { 0 }; // fixed line number if _fixed == true 278 qreal _tuning { 0.0 }; ///< pitch offset in cent, playable only by internal synthesizer 279 280 Accidental* _accidental { 0 }; 281 282 Tie* _tieFor { 0 }; 283 Tie* _tieBack { 0 }; 284 285 ElementList _el; ///< fingering, other text, symbols or images 286 QVector<NoteDot*> _dots; 287 NoteEventList _playEvents; 288 QVector<Spanner*> _spannerFor; 289 QVector<Spanner*> _spannerBack; 290 291 SymId _cachedNoteheadSym; // use in draw to avoid recomputing at every update 292 SymId _cachedSymNull; // additional symbol for some transparent notehead 293 294 QString _fretString; 295 296 void startDrag(EditData&) override; 297 QRectF drag(EditData&ed) override; 298 void endDrag(EditData&) override; 299 void editDrag(EditData &editData) override; 300 301 void verticalDrag(EditData& ed); 302 void horizontalDrag(EditData& ed); 303 304 void addSpanner(Spanner*); 305 void removeSpanner(Spanner*); 306 int concertPitchIdx() const; 307 void updateRelLine(int relLine, bool undoable); 308 bool isNoteName() const; 309 SymId noteHead() const; 310 311 void normalizeLeftDragDelta(Segment* seg, EditData &ed, NoteEditData* ned); 312 313 static QString tpcUserName(int tpc, int pitch, bool explicitAccidental); 314 315 public: 316 Note(Score* s = 0); 317 Note(const Note&, bool link = false); 318 ~Note(); 319 320 Note& operator=(const Note&) = delete; clone()321 virtual Note* clone() const override { return new Note(*this, false); } type()322 ElementType type() const override { return ElementType::NOTE; } 323 324 void undoUnlink() override; 325 326 qreal mag() const override; 327 328 void layout() override; 329 void layout2(); 330 //setter is used only in drumset tools to setup the notehead preview in the drumset editor and the palette setCachedNoteheadSym(SymId i)331 void setCachedNoteheadSym(SymId i) { _cachedNoteheadSym = i; } 332 void scanElements(void* data, void (*func)(void*, Element*), bool all = true) override; 333 void setTrack(int val) override; 334 335 int playTicks() const; 336 Fraction playTicksFraction() const; 337 338 qreal headWidth() const; 339 qreal headHeight() const; 340 qreal tabHeadWidth(const StaffType* tab = 0) const; 341 qreal tabHeadHeight(const StaffType* tab = 0) const; 342 QPointF stemDownNW() const; 343 QPointF stemUpSE() const; 344 qreal bboxXShift() const; 345 qreal noteheadCenterX() const; 346 qreal bboxRightPos() const; 347 qreal headBodyWidth() const; 348 headScheme()349 NoteHead::Scheme headScheme() const { return _headScheme; } headGroup()350 NoteHead::Group headGroup() const { return _headGroup; } headType()351 NoteHead::Type headType() const { return _headType; } 352 void setHeadScheme(NoteHead::Scheme val); 353 void setHeadGroup(NoteHead::Group val); 354 void setHeadType(NoteHead::Type t); 355 subtype()356 int subtype() const override { return int(_headGroup); } 357 QString subtypeName() const override; 358 359 void setPitch(int val); 360 void setPitch(int pitch, int tpc1, int tpc2); pitch()361 int pitch() const { return _pitch; } 362 int ottaveCapoFret() const; 363 int ppitch() const; ///< playback pitch 364 int epitch() const; ///< effective pitch tuning()365 qreal tuning() const { return _tuning; } setTuning(qreal v)366 void setTuning(qreal v) { _tuning = v; } 367 void undoSetTpc(int v); 368 int transposition() const; fixed()369 bool fixed() const { return _fixed; } setFixed(bool v)370 void setFixed(bool v) { _fixed = v; } fixedLine()371 int fixedLine() const { return _fixedLine; } setFixedLine(int v)372 void setFixedLine(int v) { _fixedLine = v; } 373 374 int tpc() const; tpc1()375 int tpc1() const { return _tpc[0]; } // non transposed tpc tpc2()376 int tpc2() const { return _tpc[1]; } // transposed tpc 377 QString tpcUserName(bool explicitAccidental = false) const; 378 379 void setTpc(int v); setTpc1(int v)380 void setTpc1(int v) { _tpc[0] = v; } setTpc2(int v)381 void setTpc2(int v) { _tpc[1] = v; } 382 void setTpcFromPitch(); 383 int tpc1default(int pitch) const; 384 int tpc2default(int pitch) const; 385 int transposeTpc(int tpc); 386 accidental()387 Accidental* accidental() const { return _accidental; } setAccidental(Accidental * a)388 void setAccidental(Accidental* a) { _accidental = a; } 389 390 AccidentalType accidentalType() const; 391 void setAccidentalType(AccidentalType type); 392 393 int line() const; setLine(int n)394 void setLine(int n) { _line = n; } 395 int physicalLine() const; 396 fret()397 int fret() const { return _fret; } setFret(int val)398 void setFret(int val) { _fret = val; } string()399 int string() const { return _string; } 400 void setString(int val); ghost()401 bool ghost() const { return _ghost; } setGhost(bool val)402 void setGhost(bool val) { _ghost = val; } fretConflict()403 bool fretConflict() const { return _fretConflict; } setFretConflict(bool val)404 void setFretConflict(bool val) { _fretConflict = val; } 405 406 void add(Element*) override; 407 void remove(Element*) override; 408 mirror()409 bool mirror() const { return _mirror; } setMirror(bool val)410 void setMirror(bool val) { _mirror = val; } 411 small()412 bool small() const { return _small; } 413 void setSmall(bool val); 414 play()415 bool play() const { return _play; } setPlay(bool val)416 void setPlay(bool val) { _play = val; } 417 tieFor()418 Ms::Tie* tieFor() const { return _tieFor; } tieBack()419 Ms::Tie* tieBack() const { return _tieBack; } setTieFor(Tie * t)420 void setTieFor(Tie* t) { _tieFor = t; } setTieBack(Tie * t)421 void setTieBack(Tie* t) { _tieBack = t; } 422 Note* firstTiedNote() const; 423 const Note* lastTiedNote() const; lastTiedNote()424 Note* lastTiedNote() { return const_cast<Note*>(static_cast<const Note*>(this)->lastTiedNote()); } 425 int unisonIndex() const; 426 void disconnectTiedNotes(); 427 void connectTiedNotes(); 428 chord()429 Chord* chord() const { return (Chord*)parent(); } setChord(Chord * a)430 void setChord(Chord* a) { setParent((Element*)a); } 431 void draw(QPainter*) const override; 432 433 void read(XmlReader&) override; 434 bool readProperties(XmlReader&) override; 435 void readAddConnector(ConnectorInfoReader* info, bool pasteMode) override; 436 void write(XmlWriter&) const override; 437 438 bool acceptDrop(EditData&) const override; 439 Element* drop(EditData&) override; 440 hidden()441 bool hidden() const { return _hidden; } setHidden(bool val)442 void setHidden(bool val) { _hidden = val; } dotsHidden()443 bool dotsHidden() const { return _dotsHidden; } setDotsHidden(bool val)444 void setDotsHidden(bool val) { _dotsHidden = val; } 445 446 NoteType noteType() const; 447 QString noteTypeUserName() const; 448 el()449 ElementList& el() { return _el; } el()450 const ElementList& el() const { return _el; } 451 subchannel()452 int subchannel() const { return _subchannel; } setSubchannel(int val)453 void setSubchannel(int val) { _subchannel = val; } 454 userMirror()455 MScore::DirectionH userMirror() const { return _userMirror; } setUserMirror(MScore::DirectionH d)456 void setUserMirror(MScore::DirectionH d) { _userMirror = d; } 457 userDotPosition()458 Direction userDotPosition() const { return _userDotPosition; } setUserDotPosition(Direction d)459 void setUserDotPosition(Direction d) { _userDotPosition = d; } 460 bool dotIsUp() const; // actual dot position 461 462 void reset() override; 463 veloType()464 ValueType veloType() const { return _veloType; } setVeloType(ValueType v)465 void setVeloType(ValueType v) { _veloType = v; } veloOffset()466 int veloOffset() const { return _veloOffset; } setVeloOffset(int v)467 void setVeloOffset(int v) { _veloOffset = v; } 468 469 void setOnTimeOffset(int v); 470 void setOffTimeOffset(int v); 471 472 int customizeVelocity(int velo) const; dot(int n)473 NoteDot* dot(int n) { return _dots[n]; } dots()474 const QVector<NoteDot*>& dots() const { return _dots; } dots()475 QVector<NoteDot*>& dots() { return _dots; } 476 477 int qmlDotsCount(); 478 void updateAccidental(AccidentalState*); 479 void updateLine(); 480 void setNval(const NoteVal&, Fraction = { -1, 1} ); playEvents()481 NoteEventList& playEvents() { return _playEvents; } playEvents()482 const NoteEventList& playEvents() const { return _playEvents; } noteEvent(int idx)483 NoteEvent* noteEvent(int idx) { return &_playEvents[idx]; } setPlayEvents(const NoteEventList & l)484 void setPlayEvents(const NoteEventList& l) { _playEvents = l; } 485 spannerFor()486 const QVector<Spanner*>& spannerFor() const { return _spannerFor; } spannerBack()487 const QVector<Spanner*>& spannerBack() const { return _spannerBack; } 488 addSpannerBack(Spanner * e)489 void addSpannerBack(Spanner* e) { if (!_spannerBack.contains(e)) _spannerBack.push_back(e); } removeSpannerBack(Spanner * e)490 bool removeSpannerBack(Spanner* e) { return _spannerBack.removeOne(e); } addSpannerFor(Spanner * e)491 void addSpannerFor(Spanner* e) { if (!_spannerFor.contains(e)) _spannerFor.push_back(e); } removeSpannerFor(Spanner * e)492 bool removeSpannerFor(Spanner* e) { return _spannerFor.removeOne(e); } 493 494 void transposeDiatonic(int interval, bool keepAlterations, bool useDoubleAccidentals); 495 496 void localSpatiumChanged(qreal oldValue, qreal newValue) override; 497 QVariant getProperty(Pid propertyId) const override; 498 bool setProperty(Pid propertyId, const QVariant&) override; 499 void undoChangeDotsVisible(bool v); 500 QVariant propertyDefault(Pid) const override; 501 QString propertyUserValue(Pid) const override; 502 mark()503 bool mark() const { return _mark; } setMark(bool v)504 void setMark(bool v) const { _mark = v; } 505 void setScore(Score* s) override; 506 void setDotY(Direction); 507 508 void addParentheses(); 509 510 static SymId noteHead(int direction, NoteHead::Group, NoteHead::Type, int tpc, Key key, NoteHead::Scheme scheme); 511 static SymId noteHead(int direction, NoteHead::Group, NoteHead::Type); 512 NoteVal noteVal() const; 513 514 Element* nextInEl(Element* e); 515 Element* prevInEl(Element* e); 516 Element* nextElement() override; 517 Element* prevElement() override; 518 virtual Element* lastElementBeforeSegment(); 519 Element* nextSegmentElement() override; 520 Element* prevSegmentElement() override; 521 522 QString accessibleInfo() const override; 523 QString screenReaderInfo() const override; 524 QString accessibleExtraInfo() const override; 525 526 Shape shape() const override; 527 std::vector<Note*> tiedNotes() const; 528 setOffTimeType(int v)529 void setOffTimeType(int v) { _offTimeType = v; } setOnTimeType(int v)530 void setOnTimeType(int v) { _onTimeType = v; } offTimeType()531 int offTimeType() const { return _offTimeType; } onTimeType()532 int onTimeType() const { return _onTimeType; } 533 }; 534 535 } // namespace Ms 536 #endif 537