554 lines
21 KiB
C++
554 lines
21 KiB
C++
/*
|
|
* 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 MU_ENGRAVING_NOTE_H
|
|
#define MU_ENGRAVING_NOTE_H
|
|
|
|
/**
|
|
\file
|
|
Definition of classes Note and NoteHead.
|
|
*/
|
|
|
|
#include "containers.h"
|
|
|
|
#include "engravingitem.h"
|
|
|
|
#include "noteevent.h"
|
|
#include "pitchspelling.h"
|
|
#include "symbol.h"
|
|
#include "types.h"
|
|
|
|
namespace mu::engraving {
|
|
class Factory;
|
|
class Tie;
|
|
class Chord;
|
|
class Text;
|
|
class Score;
|
|
class AccidentalState;
|
|
class Accidental;
|
|
class NoteDot;
|
|
class Spanner;
|
|
class StaffType;
|
|
class StretchedBend;
|
|
class NoteEditData;
|
|
enum class AccidentalType;
|
|
|
|
static constexpr int MAX_DOTS = 4;
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// LINE ATTACHMENT POINT
|
|
// Represents the attachment point of any line (tie, slur, glissando...)
|
|
// with respect to the note. Each note can hold a vector of line attach points, which
|
|
// it may use to make spacing decision with the surrounding items.
|
|
//--------------------------------------------------------------------------------
|
|
class LineAttachPoint
|
|
{
|
|
public:
|
|
LineAttachPoint(EngravingItem* l, double x, double y)
|
|
: m_line(l), m_pos(PointF(x, y)) {}
|
|
|
|
const EngravingItem* line() const { return m_line; }
|
|
const PointF pos() const { return m_pos; }
|
|
|
|
private:
|
|
EngravingItem* m_line = nullptr;
|
|
PointF m_pos = PointF(0.0, 0.0);
|
|
};
|
|
|
|
//---------------------------------------------------------
|
|
// @@ NoteHead
|
|
//---------------------------------------------------------
|
|
|
|
class NoteHead final : public Symbol
|
|
{
|
|
OBJECT_ALLOCATOR(engraving, NoteHead)
|
|
DECLARE_CLASSOF(ElementType::NOTEHEAD)
|
|
|
|
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_LARGE_DIAMOND, .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
|
|
{
|
|
OBJECT_ALLOCATOR(engraving, Note)
|
|
DECLARE_CLASSOF(ElementType::NOTE)
|
|
|
|
public:
|
|
enum class SlideType {
|
|
Undefined = 0,
|
|
UpToNote,
|
|
DownToNote,
|
|
UpFromNote,
|
|
DownFromNote
|
|
};
|
|
|
|
enum DisplayFretOption {
|
|
Hide = -1,
|
|
NoHarmonic,
|
|
NaturalHarmonic,
|
|
ArtificialHarmonic
|
|
};
|
|
|
|
~Note();
|
|
|
|
std::vector<const Note*> compoundNotes() const;
|
|
|
|
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;
|
|
EngravingObjectList scanChildren() const override;
|
|
|
|
void undoUnlink() override;
|
|
|
|
double mag() const override;
|
|
EngravingItem* elementBase() const override;
|
|
|
|
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;
|
|
|
|
double headWidth() const;
|
|
double headHeight() const;
|
|
double tabHeadWidth(const StaffType* tab = 0) const;
|
|
double tabHeadHeight(const StaffType* tab = 0) const;
|
|
mu::PointF stemDownNW() const;
|
|
mu::PointF stemUpSE() const;
|
|
double bboxXShift() const;
|
|
double noteheadCenterX() const;
|
|
double bboxRightPos() const;
|
|
double headBodyWidth() const;
|
|
double outsideTieAttachX(bool up) const;
|
|
|
|
NoteHeadScheme headScheme() const { return m_headScheme; }
|
|
void updateHeadGroup(const NoteHeadGroup headGroup);
|
|
NoteHeadGroup headGroup() const { return m_headGroup; }
|
|
NoteHeadType headType() const { return m_headType; }
|
|
void setHeadScheme(NoteHeadScheme val);
|
|
void setHeadGroup(NoteHeadGroup val);
|
|
void setHeadType(NoteHeadType t);
|
|
|
|
int subtype() const override { return int(m_headGroup); }
|
|
TranslatableString subtypeUserName() const override;
|
|
|
|
void setPitch(int val, bool notifyAboutChanged = true);
|
|
void setPitch(int pitch, int tpc1, int tpc2);
|
|
int pitch() const { return m_pitch; }
|
|
int ottaveCapoFret() const;
|
|
int linkedOttavaPitchOffset() const;
|
|
int ppitch() const; // playback pitch
|
|
int epitch() const; // effective pitch
|
|
int octave() const;
|
|
int playingOctave() const;
|
|
double tuning() const { return m_tuning; }
|
|
void setTuning(double v) { m_tuning = v; }
|
|
double playingTuning() const;
|
|
void undoSetTpc(int v);
|
|
int transposition() const;
|
|
bool fixed() const { return m_fixed; }
|
|
void setFixed(bool v) { m_fixed = v; }
|
|
int fixedLine() const { return m_fixedLine; }
|
|
void setFixedLine(int v) { m_fixedLine = v; }
|
|
|
|
int tpc() const;
|
|
int tpc1() const { return m_tpc[0]; } // non transposed tpc
|
|
int tpc2() const { return m_tpc[1]; } // transposed tpc
|
|
String tpcUserName(bool explicitAccidental = false, bool full = false) const;
|
|
|
|
void setTpc(int v);
|
|
void setTpc1(int v) { m_tpc[0] = v; }
|
|
void setTpc2(int v) { m_tpc[1] = v; }
|
|
void setTpcFromPitch(Prefer prefer = Prefer::NEAREST);
|
|
int tpc1default(int pitch) const;
|
|
int tpc2default(int pitch) const;
|
|
int transposeTpc(int tpc) const;
|
|
|
|
int playingTpc() const;
|
|
|
|
Accidental* accidental() const { return m_accidental; }
|
|
void setAccidental(Accidental* a) { m_accidental = a; }
|
|
|
|
AccidentalType accidentalType() const;
|
|
void setAccidentalType(AccidentalType type);
|
|
|
|
int line() const;
|
|
void setLine(int n) { m_line = n; }
|
|
|
|
int fret() const { return m_fret; }
|
|
void setFret(int val) { m_fret = val; }
|
|
float harmonicFret() const { return m_harmonicFret; }
|
|
void setHarmonicFret(float val) { m_harmonicFret = val; }
|
|
DisplayFretOption displayFret() const { return m_displayFret; }
|
|
void setDisplayFret(DisplayFretOption val) { m_displayFret = val; }
|
|
String fretString() const { return m_fretString; }
|
|
void setFretString(const String& s) { m_fretString = s; }
|
|
bool negativeFretUsed() const;
|
|
int string() const { return m_string; }
|
|
void setString(int val) { m_string = val; }
|
|
|
|
bool ghost() const { return m_ghost; }
|
|
void setGhost(bool val) { m_ghost = val; }
|
|
bool deadNote() const { return m_deadNote; }
|
|
void setDeadNote(bool deadNote) { m_deadNote = deadNote; }
|
|
|
|
bool fretConflict() const { return m_fretConflict; }
|
|
void setFretConflict(bool val) { m_fretConflict = val; }
|
|
|
|
void add(EngravingItem*) override;
|
|
void remove(EngravingItem*) override;
|
|
|
|
bool isSmall() const { return m_isSmall; }
|
|
void setSmall(bool val);
|
|
|
|
bool play() const { return m_play; }
|
|
void setPlay(bool val) { m_play = val; }
|
|
|
|
GuitarBend* bendFor() const;
|
|
GuitarBend* bendBack() const;
|
|
Tie* tieFor() const { return m_tieFor; }
|
|
Tie* tieBack() const { return m_tieBack; }
|
|
void setTieFor(Tie* t) { m_tieFor = t; }
|
|
void setTieBack(Tie* t) { m_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 setupAfterRead(const Fraction& tick, bool pasteMode);
|
|
|
|
bool acceptDrop(EditData&) const override;
|
|
EngravingItem* drop(EditData&) override;
|
|
|
|
bool hidden() const { return m_hidden; }
|
|
void setHidden(bool val) { m_hidden = val; }
|
|
bool dotsHidden() const { return m_dotsHidden; }
|
|
void setDotsHidden(bool val) { m_dotsHidden = val; }
|
|
|
|
NoteType noteType() const;
|
|
String noteTypeUserName() const;
|
|
|
|
ElementList& el() { return m_el; }
|
|
const ElementList& el() const { return m_el; }
|
|
|
|
int subchannel() const { return m_subchannel; }
|
|
void setSubchannel(int val) { m_subchannel = val; }
|
|
|
|
DirectionH userMirror() const { return m_userMirror; }
|
|
void setUserMirror(DirectionH d) { m_userMirror = d; }
|
|
|
|
DirectionV userDotPosition() const { return m_userDotPosition; }
|
|
void setUserDotPosition(DirectionV d) { m_userDotPosition = d; }
|
|
DirectionV dotPosition() const { return m_dotPosition; }
|
|
void setDotPosition(DirectionV d) { m_dotPosition = d; }
|
|
bool dotIsUp() const; // actual dot position
|
|
|
|
void reset() override;
|
|
|
|
float userVelocityFraction() const;
|
|
int userVelocity() const { return m_userVelocity; }
|
|
void setUserVelocity(int v) { m_userVelocity = v; }
|
|
|
|
void setOnTimeOffset(int v);
|
|
void setOffTimeOffset(int v);
|
|
|
|
int customizeVelocity(int velo) const;
|
|
NoteDot* dot(int n) { return m_dots.at(n); }
|
|
const std::vector<NoteDot*>& dots() const { return m_dots; }
|
|
std::vector<NoteDot*>& dots() { return m_dots; }
|
|
|
|
int qmlDotsCount();
|
|
void updateAccidental(AccidentalState*);
|
|
void updateLine();
|
|
void setNval(const NoteVal&, Fraction = { -1, 1 });
|
|
NoteEventList& playEvents() { return m_playEvents; }
|
|
const NoteEventList& playEvents() const { return m_playEvents; }
|
|
NoteEvent* noteEvent(int idx) { return &m_playEvents[idx]; }
|
|
void setPlayEvents(const NoteEventList& l) { m_playEvents = l; }
|
|
|
|
const std::vector<Spanner*>& spannerFor() const { return m_spannerFor; }
|
|
const std::vector<Spanner*>& spannerBack() const { return m_spannerBack; }
|
|
|
|
void addSpannerBack(Spanner* e)
|
|
{
|
|
if (!mu::contains(m_spannerBack, e)) {
|
|
m_spannerBack.push_back(e);
|
|
}
|
|
}
|
|
|
|
bool removeSpannerBack(Spanner* e) { return mu::remove(m_spannerBack, e); }
|
|
void addSpannerFor(Spanner* e)
|
|
{
|
|
if (!mu::contains(m_spannerFor, e)) {
|
|
m_spannerFor.push_back(e);
|
|
}
|
|
}
|
|
|
|
bool removeSpannerFor(Spanner* e) { return mu::remove(m_spannerFor, e); }
|
|
|
|
void transposeDiatonic(int interval, bool keepAlterations, bool useDoubleAccidentals);
|
|
|
|
void localSpatiumChanged(double oldValue, double newValue) override;
|
|
PropertyValue getProperty(Pid propertyId) const override;
|
|
bool setProperty(Pid propertyId, const PropertyValue&) override;
|
|
PropertyValue propertyDefault(Pid) const override;
|
|
|
|
bool mark() const { return m_mark; }
|
|
void setMark(bool v) const { m_mark = v; }
|
|
void setScore(Score* s) override;
|
|
void setDotRelativeLine(int);
|
|
|
|
void setHeadHasParentheses(bool hasParentheses, bool addToLinked = true);
|
|
bool headHasParentheses() const { return m_hasHeadParentheses; }
|
|
|
|
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;
|
|
|
|
String accessibleInfo() const override;
|
|
String screenReaderInfo() const override;
|
|
String accessibleExtraInfo() const override;
|
|
|
|
std::vector<Note*> tiedNotes() const;
|
|
|
|
void setOffTimeType(int v) { m_offTimeType = v; }
|
|
void setOnTimeType(int v) { m_onTimeType = v; }
|
|
int offTimeType() const { return m_offTimeType; }
|
|
int onTimeType() const { return m_onTimeType; }
|
|
|
|
void attachSlide(SlideType slideType);
|
|
|
|
bool hasSlideToNote() const;
|
|
bool hasSlideFromNote() const;
|
|
SlideType slideToType() const { return m_slideToType; }
|
|
SlideType slideFromType() const { return m_slideFromType; }
|
|
|
|
void setStretchedBend(StretchedBend* s) { m_stretchedBend = s; }
|
|
StretchedBend* stretchedBend() const { return m_stretchedBend; }
|
|
bool isHammerOn() const { return m_isHammerOn; }
|
|
void setIsHammerOn(bool hammerOn) { m_isHammerOn = hammerOn; }
|
|
|
|
void setHarmonic(bool val) { m_harmonic = val; }
|
|
bool harmonic() const { return m_harmonic; }
|
|
|
|
bool isGrace() const { return noteType() != NoteType::NORMAL; }
|
|
|
|
bool isPreBendStart() const;
|
|
bool isGraceBendStart() const;
|
|
|
|
bool hasAnotherStraightAboveOrBelow(bool above) const;
|
|
|
|
void addLineAttachPoint(mu::PointF point, EngravingItem* line);
|
|
std::vector<LineAttachPoint>& lineAttachPoints() { return m_lineAttachPoints; }
|
|
const std::vector<LineAttachPoint>& lineAttachPoints() const { return m_lineAttachPoints; }
|
|
|
|
mu::PointF posInStaffCoordinates();
|
|
|
|
bool isTrillCueNote() const { return m_isTrillCueNote; }
|
|
void setIsTrillCueNote(bool v);
|
|
|
|
SymId noteHead() const;
|
|
bool isNoteName() const;
|
|
|
|
void updateFrettingForTiesAndBends();
|
|
|
|
struct LayoutData : public EngravingItem::LayoutData {
|
|
ld_field<bool> useTablature = { "[Note] useTablature", false };
|
|
ld_field<SymId> cachedNoteheadSym = { "[Note] cachedNoteheadSym", SymId::noSym }; // use in draw to avoid recomputing at every update
|
|
ld_field<SymId> cachedSymNull = { "[Note] cachedSymNull", SymId::noSym }; // additional symbol for some transparent notehead
|
|
ld_field<bool> mirror = { "[Note] mirror", false }; // True if note is mirrored at stem.
|
|
};
|
|
DECLARE_LAYOUTDATA_METHODS(Note)
|
|
|
|
private:
|
|
|
|
friend class 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);
|
|
|
|
void normalizeLeftDragDelta(Segment* seg, EditData& ed, NoteEditData* ned);
|
|
|
|
static String tpcUserName(int tpc, int pitch, bool explicitAccidental, bool full = false);
|
|
|
|
void getNoteListForDots(std::vector<Note*>& topDownNotes, std::vector<Note*>& bottomUpNotes, std::vector<int>& anchoredDots);
|
|
|
|
bool m_ghost = false; // ghost note
|
|
bool m_deadNote = false; // dead note
|
|
|
|
bool m_isTrillCueNote = false;
|
|
|
|
bool m_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 m_dotsHidden = false; // dots of hidden notes are hidden too
|
|
// except if only one note is dotted
|
|
bool m_fretConflict = false; // used by TAB staves to mark a fretting conflict:
|
|
// two or more notes on the same string
|
|
bool m_dragMode = false;
|
|
bool m_isSmall = false;
|
|
bool m_play = true; // note is not played if false
|
|
mutable bool m_mark = false; // for use in sequencer
|
|
bool m_fixed = false; // for slash notation
|
|
StretchedBend* m_stretchedBend = nullptr;
|
|
SlideType m_slideToType = SlideType::Undefined;
|
|
SlideType m_slideFromType = SlideType::Undefined;
|
|
|
|
DirectionH m_userMirror = DirectionH::AUTO; ///< user override of mirror
|
|
DirectionV m_userDotPosition = DirectionV::AUTO; ///< user override of dot position
|
|
DirectionV m_dotPosition = DirectionV::AUTO; // used as an intermediate step when resolving dot conflicts
|
|
|
|
NoteHeadScheme m_headScheme = NoteHeadScheme::HEAD_AUTO;
|
|
NoteHeadGroup m_headGroup = NoteHeadGroup::HEAD_NORMAL;
|
|
NoteHeadType m_headType = NoteHeadType::HEAD_AUTO;
|
|
|
|
VeloType m_veloType = VeloType::USER_VAL;
|
|
|
|
int m_offTimeType = 0; // compatibility only 1 - user(absolute), 2 - offset (%)
|
|
int m_onTimeType = 0; // compatibility only 1 - user, 2 - offset
|
|
|
|
int m_subchannel = 0; // articulation
|
|
int m_line = INVALID_LINE; // y-Position; 0 - top line.
|
|
int m_fret = -1; // for tablature view
|
|
float m_harmonicFret = -1.0;
|
|
DisplayFretOption m_displayFret = DisplayFretOption::NoHarmonic;
|
|
int m_string = -1;
|
|
mutable int m_tpc[2] = { Tpc::TPC_INVALID, Tpc::TPC_INVALID }; // tonal pitch class (concert/transposing)
|
|
mutable int m_pitch = 0; // Note pitch as midi value (0 - 127).
|
|
|
|
int m_userVelocity = 0; // velocity user offset in percent, or absolute velocity for this note
|
|
int m_fixedLine = 0; // fixed line number if _fixed == true
|
|
double m_tuning = 0.0; // pitch offset in cent, playable only by internal synthesizer
|
|
|
|
Accidental* m_accidental = nullptr;
|
|
|
|
Tie* m_tieFor = nullptr;
|
|
Tie* m_tieBack = nullptr;
|
|
|
|
Symbol* m_leftParenthesis = nullptr;
|
|
Symbol* m_rightParenthesis = nullptr;
|
|
bool m_hasHeadParentheses = false;
|
|
|
|
bool m_isHammerOn = false;
|
|
bool m_harmonic = false;
|
|
|
|
ElementList m_el; // fingering, other text, symbols or images
|
|
std::vector<NoteDot*> m_dots;
|
|
NoteEventList m_playEvents;
|
|
std::vector<Spanner*> m_spannerFor;
|
|
std::vector<Spanner*> m_spannerBack;
|
|
|
|
String m_fretString;
|
|
|
|
std::vector<LineAttachPoint> m_lineAttachPoints;
|
|
};
|
|
} // namespace mu::engraving
|
|
#endif
|