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