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
|
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2012 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#ifndef __NOTE_H__
#define __NOTE_H__
/**
\file
Definition of classes Note and NoteHead.
*/
#include "element.h"
#include "symbol.h"
#include "noteevent.h"
#include "pitchspelling.h"
class QPainter;
namespace Ms {
class Tie;
class Chord;
class NoteEvent;
class Text;
class Score;
class Sym;
class MuseScoreView;
class Bend;
class AccidentalState;
class Accidental;
class NoteDot;
class Spanner;
class StaffType;
enum class SymId;
enum class AccidentalType : char;
static const int MAX_DOTS = 3;
//---------------------------------------------------------
// @@ NoteHead
//---------------------------------------------------------
class NoteHead : public Symbol {
Q_OBJECT
Q_ENUMS(Group)
Q_ENUMS(Type)
public:
enum class Group : signed char {
HEAD_NORMAL = 0,
HEAD_CROSS,
HEAD_DIAMOND,
HEAD_TRIANGLE,
HEAD_MI,
HEAD_SLASH,
HEAD_XCIRCLE,
HEAD_DO,
HEAD_RE,
HEAD_FA,
HEAD_LA,
HEAD_TI,
HEAD_SOL,
HEAD_BREVIS_ALT,
HEAD_CUSTOM,
HEAD_GROUPS,
HEAD_INVALID = -1
};
enum class Type : signed char {
HEAD_AUTO = -1,
HEAD_WHOLE = 0,
HEAD_HALF = 1,
HEAD_QUARTER = 2,
HEAD_BREVIS = 3,
HEAD_TYPES
};
NoteHead(Score* s = 0) : Symbol(s) {}
NoteHead &operator=(const NoteHead&) = delete;
virtual NoteHead* clone() const override { return new NoteHead(*this); }
virtual Element::Type type() const override { return Element::Type::NOTEHEAD; }
virtual void write(Xml& xml) const override;
Group headGroup() const;
static const char* groupToGroupName(Group group);
static const char* type2name(Type type);
static Type name2type(const QString&);
};
//---------------------------------------------------------
// NoteVal
// helper structure
//---------------------------------------------------------
struct NoteVal {
int pitch { -1 };
int tpc1 { Tpc::TPC_INVALID };
int tpc2 { Tpc::TPC_INVALID };
int fret { FRET_NONE };
int string { STRING_NONE };
NoteHead::Group headGroup { NoteHead::Group::HEAD_NORMAL };
NoteVal() {}
NoteVal(int p) : pitch(p) {}
};
//---------------------------------------------------------------------------------------
// @@ 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[Element] list of elements attached to notehead
// @P fret int fret number in tablature
// @P ghost bool ghost note (guitar: death note)
// @P headGroup enum (NoteHead.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 (NoteHead.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 small 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 : public Element {
Q_OBJECT
Q_PROPERTY(Ms::Accidental* accidental READ accidental)
Q_PROPERTY(int accidentalType READ qmlAccidentalType WRITE qmlSetAccidentalType)
Q_PROPERTY(QQmlListProperty<Ms::NoteDot> dots READ qmlDots)
Q_PROPERTY(int dotsCount READ qmlDotsCount)
Q_PROPERTY(QQmlListProperty<Ms::Element> elements READ qmlElements)
Q_PROPERTY(int fret READ fret WRITE undoSetFret)
Q_PROPERTY(bool ghost READ ghost WRITE undoSetGhost)
Q_PROPERTY(Ms::NoteHead::Group headGroup READ headGroup WRITE undoSetHeadGroup)
Q_PROPERTY(Ms::NoteHead::Type headType READ headType WRITE undoSetHeadType)
Q_PROPERTY(bool hidden READ hidden)
Q_PROPERTY(int line READ line)
Q_PROPERTY(bool mirror READ mirror)
Q_PROPERTY(int pitch READ pitch WRITE undoSetPitch)
Q_PROPERTY(bool play READ play WRITE undoSetPlay)
Q_PROPERTY(int ppitch READ ppitch)
Q_PROPERTY(bool small READ small WRITE undoSetSmall)
Q_PROPERTY(int string READ string WRITE undoSetString)
Q_PROPERTY(int subchannel READ subchannel)
Q_PROPERTY(Ms::Tie* tieBack READ tieBack)
Q_PROPERTY(Ms::Tie* tieFor READ tieFor)
Q_PROPERTY(int tpc READ tpc)
Q_PROPERTY(int tpc1 READ tpc1 WRITE undoSetTpc1)
Q_PROPERTY(int tpc2 READ tpc2 WRITE undoSetTpc2)
Q_PROPERTY(qreal tuning READ tuning WRITE undoSetTuning)
Q_PROPERTY(Ms::MScore::Direction userDotPosition READ userDotPosition WRITE undoSetUserDotPosition)
Q_PROPERTY(Ms::MScore::DirectionH userMirror READ userMirror WRITE undoSetUserMirror)
Q_PROPERTY(int veloOffset READ veloOffset WRITE undoSetVeloOffset)
Q_PROPERTY(Ms::Note::ValueType veloType READ veloType WRITE undoSetVeloType)
Q_ENUMS(ValueType)
Q_ENUMS(Ms::MScore::Direction)
Q_ENUMS(Ms::MScore::DirectionH)
public:
enum class ValueType : char { OFFSET_VAL, USER_VAL };
int qmlAccidentalType() const { return int(accidentalType()); }
void qmlSetAccidentalType(int t) { setAccidentalType(static_cast<AccidentalType>(t)); }
private:
bool _ghost { false }; ///< ghost note (guitar: death note)
bool _hidden { false }; ///< markes 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 mor enotes on the same string
bool dragMode { false };
bool _mirror { false }; ///< True if note is mirrored at stem.
bool _small { false };
bool _play { true }; // note is not played if false
mutable bool _mark { false }; // for use in sequencer
bool _fixed { false }; // for slash notation
MScore::DirectionH _userMirror { MScore::DirectionH::AUTO }; ///< user override of mirror
MScore::Direction _userDotPosition { MScore::Direction::AUTO }; ///< user override of dot position
NoteHead::Group _headGroup { NoteHead::Group::HEAD_NORMAL };
NoteHead::Type _headType { NoteHead::Type::HEAD_AUTO };
ValueType _veloType { ValueType::OFFSET_VAL };
char _offTimeType { 0 }; // compatibility only 1 - user(absolute), 2 - offset (%)
char _onTimeType { 0 }; // compatibility only 1 - user, 2 - offset
int _subchannel { 0 }; ///< articulation
int _line { 0 }; ///< 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
int _lineOffset { 0 }; ///< Used during mouse dragging.
qreal _tuning { 0.0 }; ///< pitch offset in cent, playable only by internal synthesizer
Accidental* _accidental { 0 };
ElementList _el; ///< fingering, other text, symbols or images
Tie* _tieFor { 0 };
Tie* _tieBack { 0 };
QList<NoteDot*> _dots { 0, 0, 0 };
NoteEventList _playEvents;
QVector<Spanner*> _spannerFor;
QVector<Spanner*> _spannerBack;
SymId _cachedNoteheadSym; // use in draw to avoid recomputing at every update
virtual QRectF drag(EditData*) override;
void endDrag();
void endEdit();
void addSpanner(Spanner*);
void removeSpanner(Spanner*);
int concertPitchIdx() const;
void updateRelLine(int relLine, bool undoable);
public:
Note(Score* s = 0);
Note(const Note&, bool link = false);
~Note();
Note& operator=(const Note&) = delete;
virtual Note* clone() const override { return new Note(*this, false); }
Element::Type type() const override { return Element::Type::NOTE; }
virtual qreal mag() const override;
QPointF pagePos() const; ///< position in page coordinates
QPointF canvasPos() const; ///< position in page coordinates
void layout();
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*, Element*), bool all=true);
void setTrack(int val);
int playTicks() const;
qreal headWidth() const;
qreal headHeight() const;
qreal tabHeadWidth(StaffType* tab = 0) const;
qreal tabHeadHeight(StaffType* tab = 0) const;
QPointF stemDownNW() const;
QPointF stemUpSE() const;
qreal bboxXShift() const;
qreal noteheadCenterX() const;
qreal bboxRightPos() const;
qreal headBodyWidth() const;
SymId noteHead() const;
NoteHead::Group headGroup() const { return _headGroup; }
NoteHead::Type headType() const { return _headType; }
void setHeadGroup(NoteHead::Group val);
void setHeadType(NoteHead::Type t);
virtual int subtype() const override { return (int) _headGroup; }
virtual QString subtypeName() const override;
void setPitch(int val);
void undoSetPitch(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
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;
void undoSetTpc1(int tpc) { undoChangeProperty(P_ID::TPC1, tpc); }
void undoSetTpc2(int tpc) { undoChangeProperty(P_ID::TPC2, tpc); }
int transposeTpc(int tpc);
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);
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 fretConflict() const { return _fretConflict; }
void setFretConflict(bool val) { _fretConflict = val; }
virtual void add(Element*) override;
virtual void remove(Element*) override;
bool mirror() const { return _mirror; }
void setMirror(bool val) { _mirror = val; }
bool small() const { return _small; }
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;
Note* lastTiedNote() const;
QList<Note*> tiedNotes() const;
void disconnectTiedNotes();
void connectTiedNotes();
Chord* chord() const { return (Chord*)parent(); }
void setChord(Chord* a) { setParent((Element*)a); }
void draw(QPainter*) const;
virtual void read(XmlReader&) override;
virtual void write(Xml& xml) const override;
bool acceptDrop(const DropData&) const override;
Element* drop(const DropData&);
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; }
QQmlListProperty<Ms::Element> qmlElements() { return QmlListAccess<Ms::Element>(this, _el); }
int subchannel() const { return _subchannel; }
void setSubchannel(int val) { _subchannel = val; }
MScore::DirectionH userMirror() const { return _userMirror; }
void setUserMirror(MScore::DirectionH d) { _userMirror = d; }
MScore::Direction userDotPosition() const { return _userDotPosition; }
void setUserDotPosition(MScore::Direction d) { _userDotPosition = d; }
bool dotIsUp() const; // actual dot position
void reset();
ValueType veloType() const { return _veloType; }
void setVeloType(ValueType 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]; }
QQmlListProperty<Ms::NoteDot> qmlDots() { return QmlListAccess<Ms::NoteDot>(this, _dots); }
int qmlDotsCount();
void updateAccidental(AccidentalState*);
void updateLine();
void setNval(const NoteVal&, int tick = -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; }
QVector<Spanner*> spannerFor() const { return _spannerFor; }
QVector<Spanner*> spannerBack() const { return _spannerBack; }
void addSpannerBack(Spanner* e) { if (!_spannerBack.contains(e)) _spannerBack.push_back(e); }
bool removeSpannerBack(Spanner* e) { return _spannerBack.removeOne(e); }
void addSpannerFor(Spanner* e) { if (!_spannerFor.contains(e)) _spannerFor.push_back(e); }
bool removeSpannerFor(Spanner* e) { return _spannerFor.removeOne(e); }
void transposeDiatonic(int interval, bool keepAlterations, bool useDoubleAccidentals);
void undoSetFret(int);
void undoSetString(int);
void undoSetGhost(bool);
void undoSetMirror(bool);
void undoSetSmall(bool);
void undoSetPlay(bool);
void undoSetTuning(qreal);
void undoSetVeloType(ValueType);
void undoSetVeloOffset(int);
void undoSetOnTimeUserOffset(int);
void undoSetOffTimeUserOffset(int);
void undoSetUserMirror(MScore::DirectionH);
void undoSetUserDotPosition(MScore::Direction);
void undoSetHeadGroup(NoteHead::Group);
void undoSetHeadType(NoteHead::Type);
virtual QVariant getProperty(P_ID propertyId) const override;
virtual bool setProperty(P_ID propertyId, const QVariant&) override;
virtual QVariant propertyDefault(P_ID) const override;
bool mark() const { return _mark; }
void setMark(bool v) const { _mark = v; }
virtual void setScore(Score* s) override;
void setDotY(MScore::Direction);
void addBracket();
bool isBefore(Note*);
static SymId noteHead(int direction, NoteHead::Group, NoteHead::Type);
NoteVal noteVal() const;
virtual Element* nextElement() override;
virtual Element* prevElement() override;
virtual QString accessibleInfo() override;
virtual QString screenReaderInfo() override;
virtual QString accessibleExtraInfo() override;
// for the synthesiser
QString accessibleInfoConst() const;
};
// extern const SymId noteHeads[2][int(NoteHead::Group::HEAD_GROUPS)][int(NoteHead::Type::HEAD_TYPES)];
} // namespace Ms
Q_DECLARE_METATYPE(Ms::NoteHead::Group);
Q_DECLARE_METATYPE(Ms::NoteHead::Type);
Q_DECLARE_METATYPE(Ms::Note::ValueType);
#endif
|