You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1340 lines
42 KiB
1340 lines
42 KiB
/*
|
|
Rosegarden
|
|
A sequencer and musical notation editor.
|
|
|
|
This program is Copyright 2000-2008
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <bownie@bownie.com>
|
|
|
|
The moral right of the authors to claim authorship of this work
|
|
has been asserted.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version. See the file
|
|
COPYING included with this distribution for more information.
|
|
*/
|
|
|
|
#ifndef _NOTATION_TYPES_H_
|
|
#define _NOTATION_TYPES_H_
|
|
|
|
#include <list>
|
|
#include <map>
|
|
|
|
#include "Event.h"
|
|
#include "Instrument.h"
|
|
|
|
/*
|
|
* NotationTypes.h
|
|
*
|
|
* This file contains definitions of several classes to assist in
|
|
* creating and manipulating certain event types. The classes are:
|
|
*
|
|
* Accidental
|
|
* Clef
|
|
* Key
|
|
* Indication
|
|
* Pitch
|
|
* Note
|
|
* TimeSignature
|
|
* AccidentalTable
|
|
*
|
|
* The classes in this file are _not_ actually used for storing
|
|
* events. Events are always stored in Event objects (see Event.h).
|
|
*
|
|
* These classes are usually constructed on-the-fly when a particular
|
|
* operation specific to a single sort of event is required, and
|
|
* usually destroyed as soon as they go out of scope. The most common
|
|
* usages are for creating events (create an instance of one of these
|
|
* classes with the data you require, then call getAsEvent on it), for
|
|
* doing notation-related calculations from existing events (such as
|
|
* the bar duration of a time signature), and for doing calculations
|
|
* that are independent of any particular instance of an event (such
|
|
* as the Note methods that calculate duration-related values without
|
|
* reference to any specific pitch or other note-event properties; or
|
|
* everything in Pitch).
|
|
*
|
|
* This file also defines the event types and standard property names
|
|
* for the basic events.
|
|
*/
|
|
|
|
namespace Rosegarden
|
|
{
|
|
|
|
extern const int MIN_SUBORDERING;
|
|
|
|
typedef std::list<int> DurationList;
|
|
|
|
|
|
/**
|
|
* Accidentals are stored in the event as string properties, purely
|
|
* for clarity. (They aren't manipulated _all_ that often, so this
|
|
* probably isn't a great inefficiency.) Originally we used an enum
|
|
* for the Accidental type with conversion functions to and from
|
|
* strings, but making Accidental a string seems simpler.
|
|
*/
|
|
|
|
typedef std::string Accidental;
|
|
|
|
namespace Accidentals
|
|
{
|
|
extern const Accidental NoAccidental;
|
|
extern const Accidental Sharp;
|
|
extern const Accidental Flat;
|
|
extern const Accidental Natural;
|
|
extern const Accidental DoubleSharp;
|
|
extern const Accidental DoubleFlat;
|
|
|
|
typedef std::vector<Accidental> AccidentalList;
|
|
|
|
/**
|
|
* When no accidental is specified for a pitch, there are several
|
|
* strategies to determine what accidental to display for an
|
|
* out-of-key pitch
|
|
*/
|
|
enum NoAccidentalStrategy {
|
|
/** always use sharps */
|
|
UseSharps,
|
|
/** always use flats */
|
|
UseFlats,
|
|
/** always use sharps or always use flats depending on of what
|
|
* type of accidentals the current key is made up */
|
|
UseKeySharpness,
|
|
/** use the most likely accidental for this key */
|
|
UseKey
|
|
};
|
|
|
|
/**
|
|
* Get the predefined accidentals (i.e. the ones listed above)
|
|
* in their defined order.
|
|
*/
|
|
extern AccidentalList getStandardAccidentals();
|
|
|
|
/**
|
|
* Get the change in pitch resulting from an accidental: -1 for
|
|
* flat, 2 for double-sharp, 0 for natural or NoAccidental etc.
|
|
* This is not as useful as it may seem, as in reality the
|
|
* effect of an accidental depends on the key as well -- see
|
|
* the Key and Pitch classes.
|
|
*/
|
|
extern int getPitchOffset(const Accidental &accidental);
|
|
|
|
|
|
/**
|
|
* Get the Accidental corresponding to a change in pitch: flat
|
|
* for -1, double-sharp for 2, natural for 0 etc.
|
|
*
|
|
* Useful for tying to code that represents accidentals by
|
|
* their pitch change.
|
|
*/
|
|
extern Accidental getAccidental(int pitchChange);
|
|
}
|
|
|
|
|
|
/**
|
|
* Marks, like Accidentals, are stored in the event as string properties.
|
|
*/
|
|
|
|
typedef std::string Mark;
|
|
|
|
namespace Marks //!!! This would be better as a class, these days
|
|
{
|
|
extern const Mark NoMark; // " "
|
|
|
|
extern const Mark Accent; // ">"
|
|
extern const Mark Tenuto; // "-" ("legato" in RG2.1)
|
|
extern const Mark Staccato; // "."
|
|
extern const Mark Staccatissimo; // "'"
|
|
extern const Mark Marcato; // "^"
|
|
extern const Mark Sforzando; // "sf"
|
|
extern const Mark Rinforzando; // "rf"
|
|
|
|
extern const Mark Trill; // "tr"
|
|
extern const Mark LongTrill; // with wiggly line
|
|
extern const Mark TrillLine; // line on its own
|
|
extern const Mark Turn; // "~"
|
|
|
|
extern const Mark Pause; // aka "fermata"
|
|
|
|
extern const Mark UpBow; // "v"
|
|
extern const Mark DownBow; // a square with the bottom side missing
|
|
|
|
extern const Mark Mordent;
|
|
extern const Mark MordentInverted;
|
|
extern const Mark MordentLong;
|
|
extern const Mark MordentLongInverted;
|
|
|
|
/**
|
|
* Given a string, return a mark that will be recognised as a
|
|
* text mark containing that string. For example, the Sforzando
|
|
* mark is actually defined as getTextMark("sf").
|
|
*/
|
|
extern Mark getTextMark(std::string text);
|
|
|
|
/**
|
|
* Return true if the given mark is a text mark.
|
|
*/
|
|
extern bool isTextMark(Mark mark);
|
|
|
|
/**
|
|
* Extract the string from a text mark.
|
|
*/
|
|
extern std::string getTextFromMark(Mark mark);
|
|
|
|
/**
|
|
* Given a string, return a mark that will be recognised as a
|
|
* fingering mark containing that string. (We use a string
|
|
* instead of a number to permit "fingering" marks containing
|
|
* labels like "+".)
|
|
*/
|
|
extern Mark getFingeringMark(std::string fingering);
|
|
|
|
/**
|
|
* Return true if the given mark is a fingering mark.
|
|
*/
|
|
extern bool isFingeringMark(Mark mark);
|
|
|
|
/**
|
|
* Extract the string from a fingering mark.
|
|
*/
|
|
extern std::string getFingeringFromMark(Mark mark);
|
|
|
|
/**
|
|
* Extract the number of marks from an event.
|
|
*/
|
|
extern int getMarkCount(const Event &e);
|
|
|
|
/**
|
|
* Extract the marks from an event.
|
|
*/
|
|
extern std::vector<Mark> getMarks(const Event &e);
|
|
|
|
/**
|
|
* Return the first fingering mark on an event (or NoMark, if none).
|
|
*/
|
|
extern Mark getFingeringMark(const Event &e);
|
|
|
|
/**
|
|
* Add a mark to an event. If unique is true, add the mark only
|
|
* if the event does not already have it (otherwise permit
|
|
* multiple identical marks).
|
|
*/
|
|
extern void addMark(Event &e, const Mark &mark, bool unique);
|
|
|
|
/**
|
|
* Remove a mark from an event. Returns true if the mark was
|
|
* there to remove. If the mark was not unique, removes only
|
|
* the first instance of it.
|
|
*/
|
|
extern bool removeMark(Event &e, const Mark &mark);
|
|
|
|
/**
|
|
* Returns true if the event has the given mark.
|
|
*/
|
|
extern bool hasMark(const Event &e, const Mark &mark);
|
|
|
|
/**
|
|
* Get the predefined marks (i.e. the ones listed above) in their
|
|
* defined order.
|
|
*/
|
|
extern std::vector<Mark> getStandardMarks();
|
|
}
|
|
|
|
|
|
/**
|
|
* Clefs are represented as one of a set of standard strings, stored
|
|
* within a clef Event. The Clef class defines those standards and
|
|
* provides a few bits of information about the clefs.
|
|
*/
|
|
|
|
class Clef
|
|
{
|
|
public:
|
|
static const std::string EventType;
|
|
static const int EventSubOrdering;
|
|
static const PropertyName ClefPropertyName;
|
|
static const PropertyName OctaveOffsetPropertyName;
|
|
static const Clef DefaultClef;
|
|
typedef Exception BadClefName;
|
|
|
|
static const std::string Treble;
|
|
static const std::string French;
|
|
static const std::string Soprano;
|
|
static const std::string Mezzosoprano;
|
|
static const std::string Alto;
|
|
static const std::string Tenor;
|
|
static const std::string Baritone;
|
|
static const std::string Varbaritone;
|
|
static const std::string Bass;
|
|
static const std::string Subbass;
|
|
|
|
/**
|
|
* Construct the default clef (treble).
|
|
*/
|
|
Clef() : m_clef(DefaultClef.m_clef), m_octaveOffset(0) { }
|
|
|
|
/**
|
|
* Construct a Clef from the clef data in the given event. If the
|
|
* event is not of clef type or contains insufficient data, this
|
|
* returns the default clef (with a warning). You should normally
|
|
* test Clef::isValid() to catch that before construction.
|
|
*/
|
|
Clef(const Event &e);
|
|
|
|
/**
|
|
* Construct a Clef from the given data. Throws a BadClefName
|
|
* exception if the given string does not match one of the above
|
|
* clef name constants.
|
|
*/
|
|
Clef(const std::string &s, int octaveOffset = 0);
|
|
|
|
Clef(const Clef &c) : m_clef(c.m_clef), m_octaveOffset(c.m_octaveOffset) {
|
|
}
|
|
|
|
Clef &operator=(const Clef &c);
|
|
|
|
bool operator==(const Clef &c) const {
|
|
return c.m_clef == m_clef && c.m_octaveOffset == m_octaveOffset;
|
|
}
|
|
|
|
bool operator!=(const Clef &c) const {
|
|
return !(c == *this);
|
|
}
|
|
|
|
~Clef() { }
|
|
|
|
/**
|
|
* Test whether the given event is a valid Clef event.
|
|
*/
|
|
static bool isValid(const Event &e);
|
|
|
|
/**
|
|
* Return the basic clef type (Treble, French, Soprano, Mezzosoprano, Alto, Tenor, Baritone, Varbaritone, Bass, Subbass)
|
|
*/
|
|
std::string getClefType() const { return m_clef; }
|
|
|
|
/**
|
|
* Return any additional octave offset, that is, return 1 for
|
|
* a clef shifted an 8ve up, etc
|
|
*/
|
|
int getOctaveOffset() const { return m_octaveOffset; }
|
|
|
|
/**
|
|
* Return the number of semitones a pitch in the treble clef would
|
|
* have to be lowered by in order to be drawn with the same height
|
|
* and accidental in this clef
|
|
*/
|
|
int getTranspose() const;
|
|
|
|
/**
|
|
* Return the octave component of getTranspose(), i.e. the number
|
|
* of octaves difference in pitch between this clef and the treble
|
|
*/
|
|
int getOctave() const;
|
|
|
|
/**
|
|
* Return the intra-octave component of getTranspose(), i.e. the
|
|
* number of semitones this clef is distinct in pitch from the treble
|
|
* besides the difference in octaves
|
|
*/
|
|
int getPitchOffset() const;
|
|
|
|
/**
|
|
* Return the height-on-staff (in Pitch terminology)
|
|
* of the clef's axis -- the line around which the clef is drawn.
|
|
*/
|
|
int getAxisHeight() const;
|
|
|
|
typedef std::vector<Clef> ClefList;
|
|
|
|
/**
|
|
* Return all the clefs, in ascending order of pitch
|
|
*/
|
|
static ClefList getClefs();
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsEvent(timeT absoluteTime) const;
|
|
|
|
private:
|
|
std::string m_clef;
|
|
int m_octaveOffset;
|
|
};
|
|
|
|
/**
|
|
* All we store in a key Event is the name of the key. A Key object
|
|
* can be constructed from such an Event or just from its name, and
|
|
* will return all the properties of the key. The Key class also
|
|
* provides some useful mechanisms for getting information about and
|
|
* transposing between keys.
|
|
*/
|
|
|
|
class Key
|
|
{
|
|
public:
|
|
static const std::string EventType;
|
|
static const int EventSubOrdering;
|
|
static const PropertyName KeyPropertyName;
|
|
static const Key DefaultKey;
|
|
typedef Exception BadKeyName;
|
|
typedef Exception BadKeySpec;
|
|
|
|
/**
|
|
* Construct the default key (C major).
|
|
*/
|
|
Key();
|
|
|
|
/**
|
|
* Construct a Key from the key data in the given event. If the
|
|
* event is not of key type or contains insufficient data, this
|
|
* returns the default key (with a warning). You should normally
|
|
* test Key::isValid() to catch that before construction.
|
|
*/
|
|
Key(const Event &e);
|
|
|
|
/**
|
|
* Construct the named key. Throws a BadKeyName exception if the
|
|
* given string does not match one of the known key names.
|
|
*/
|
|
Key(const std::string &name);
|
|
|
|
/**
|
|
* Construct a key from signature and mode. May throw a
|
|
* BadKeySpec exception.
|
|
*/
|
|
Key(int accidentalCount, bool isSharp, bool isMinor);
|
|
|
|
/**
|
|
* Construct the key with the given tonic and mode. (Ambiguous.)
|
|
* May throw a BadKeySpec exception.
|
|
*/
|
|
Key(int tonicPitch, bool isMinor);
|
|
|
|
Key(const Key &kc);
|
|
|
|
~Key() {
|
|
delete m_accidentalHeights;
|
|
}
|
|
|
|
Key &operator=(const Key &kc);
|
|
|
|
bool operator==(const Key &k) const {
|
|
return k.m_name == m_name;
|
|
}
|
|
|
|
bool operator!=(const Key &k) const {
|
|
return !(k == *this);
|
|
}
|
|
|
|
/**
|
|
* Test whether the given event is a valid Key event.
|
|
*/
|
|
static bool isValid(const Event &e);
|
|
|
|
/**
|
|
* Return true if this is a minor key. Unlike in RG2.1,
|
|
* we distinguish between major and minor keys with the
|
|
* same signature.
|
|
*/
|
|
bool isMinor() const {
|
|
return m_keyDetailMap[m_name].m_minor;
|
|
}
|
|
|
|
/**
|
|
* Return true if this key's signature is made up of
|
|
* sharps, false if flats.
|
|
*/
|
|
bool isSharp() const {
|
|
return m_keyDetailMap[m_name].m_sharps;
|
|
}
|
|
|
|
/**
|
|
* Return the pitch of the tonic note in this key, as a
|
|
* MIDI (or RG4) pitch modulo 12 (i.e. in the range 0-11).
|
|
* This is the pitch of the note named in the key's name,
|
|
* e.g. 0 for the C in C major.
|
|
*/
|
|
int getTonicPitch() const {
|
|
return m_keyDetailMap[m_name].m_tonicPitch;
|
|
}
|
|
|
|
/**
|
|
* Return the number of sharps or flats in the key's signature.
|
|
*/
|
|
int getAccidentalCount() const {
|
|
return m_keyDetailMap[m_name].m_sharpCount;
|
|
}
|
|
|
|
/**
|
|
* Return the key with the same signature but different
|
|
* major/minor mode. For example if called on C major,
|
|
* returns A minor.
|
|
*/
|
|
Key getEquivalent() const {
|
|
return Key(m_keyDetailMap[m_name].m_equivalence);
|
|
}
|
|
|
|
/**
|
|
* Return the name of the key, in a human-readable form
|
|
* also suitable for passing to the Key constructor.
|
|
*/
|
|
std::string getName() const {
|
|
return m_name;
|
|
}
|
|
|
|
/**
|
|
* Return the name of the key, in the form used by RG2.1.
|
|
*/
|
|
std::string getRosegarden2Name() const {
|
|
return m_keyDetailMap[m_name].m_rg2name;
|
|
}
|
|
|
|
/**
|
|
* Return the accidental at the given height-on-staff
|
|
* (in Pitch terminology) in the given clef.
|
|
*/
|
|
Accidental getAccidentalAtHeight(int height, const Clef &clef) const;
|
|
|
|
/**
|
|
* Return the accidental for the the given number of steps
|
|
* from the tonic. For example: for F major, step '3' is the
|
|
* Bb, so getAccidentalForStep(3) will yield a Flat.
|
|
*/
|
|
Accidental getAccidentalForStep(int steps) const;
|
|
|
|
/**
|
|
* Return the heights-on-staff (in Pitch
|
|
* terminology) of all accidentals in the key's signature,
|
|
* in the given clef.
|
|
*/
|
|
std::vector<int> getAccidentalHeights(const Clef &clef) const;
|
|
|
|
/**
|
|
* Return the result of applying this key to the given
|
|
* pitch, that is, modifying the pitch so that it has the
|
|
* same status in terms of accidentals as it had when
|
|
* found in the given previous key.
|
|
*/
|
|
int convertFrom(int pitch, const Key &previousKey,
|
|
const Accidental &explicitAccidental =
|
|
Accidentals::NoAccidental) const;
|
|
|
|
/**
|
|
* Return the result of transposing the given pitch into
|
|
* this key, that is, modifying the pitch by the difference
|
|
* between the tonic pitches of this and the given previous
|
|
* key.
|
|
*/
|
|
int transposeFrom(int pitch, const Key &previousKey) const;
|
|
|
|
/**
|
|
* Reduce a height-on-staff to a single octave, so that it
|
|
* can be compared against the accidental heights returned
|
|
* by the preceding method.
|
|
*/
|
|
static inline unsigned int canonicalHeight(int height) {
|
|
return (height > 0) ? (height % 7) : ((7 - (-height % 7)) % 7);
|
|
}
|
|
|
|
typedef std::vector<Key> KeyList;
|
|
|
|
/**
|
|
* Return all the keys in the given major/minor mode, in
|
|
* no particular order.
|
|
*/
|
|
static KeyList getKeys(bool minor = false);
|
|
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsEvent(timeT absoluteTime) const;
|
|
|
|
/**
|
|
* Transpose this key by the specified interval given in pitch and steps
|
|
*
|
|
* For example: transposing F major by a major triad (4,2) yields
|
|
* A major.
|
|
*/
|
|
Key transpose(int pitchDelta, int heightDelta);
|
|
|
|
private:
|
|
std::string m_name;
|
|
mutable std::vector<int> *m_accidentalHeights;
|
|
|
|
struct KeyDetails {
|
|
bool m_sharps;
|
|
bool m_minor;
|
|
int m_sharpCount;
|
|
std::string m_equivalence;
|
|
std::string m_rg2name;
|
|
int m_tonicPitch;
|
|
|
|
KeyDetails(); // ctor needed in order to live in a map
|
|
|
|
KeyDetails(bool sharps, bool minor, int sharpCount,
|
|
std::string equivalence, std::string rg2name,
|
|
int m_tonicPitch);
|
|
|
|
KeyDetails(const KeyDetails &d);
|
|
|
|
KeyDetails &operator=(const KeyDetails &d);
|
|
};
|
|
|
|
|
|
typedef std::map<std::string, KeyDetails> KeyDetailMap;
|
|
static KeyDetailMap m_keyDetailMap;
|
|
static void checkMap();
|
|
void checkAccidentalHeights() const;
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Indication is a collective name for graphical marks that span a
|
|
* series of events, such as slurs, dynamic marks etc. These are
|
|
* stored in indication Events with a type and duration. The
|
|
* Indication class gives a basic set of indication types.
|
|
*/
|
|
|
|
class Indication
|
|
{
|
|
public:
|
|
static const std::string EventType;
|
|
static const int EventSubOrdering;
|
|
static const PropertyName IndicationTypePropertyName;
|
|
typedef Exception BadIndicationName;
|
|
|
|
static const std::string Slur;
|
|
static const std::string PhrasingSlur;
|
|
static const std::string Crescendo;
|
|
static const std::string Decrescendo;
|
|
static const std::string Glissando;
|
|
|
|
static const std::string QuindicesimaUp;
|
|
static const std::string OttavaUp;
|
|
static const std::string OttavaDown;
|
|
static const std::string QuindicesimaDown;
|
|
|
|
Indication(const Event &e)
|
|
/* throw (Event::NoData, Event::BadType) */;
|
|
Indication(const std::string &s, timeT indicationDuration)
|
|
/* throw (BadIndicationName) */;
|
|
|
|
Indication(const Indication &m) : m_indicationType(m.m_indicationType),
|
|
m_duration(m.m_duration) { }
|
|
|
|
Indication &operator=(const Indication &m);
|
|
|
|
~Indication() { }
|
|
|
|
std::string getIndicationType() const { return m_indicationType; }
|
|
timeT getIndicationDuration() const { return m_duration; }
|
|
|
|
bool isOttavaType() const {
|
|
return
|
|
m_indicationType == QuindicesimaUp ||
|
|
m_indicationType == OttavaUp ||
|
|
m_indicationType == OttavaDown ||
|
|
m_indicationType == QuindicesimaDown;
|
|
}
|
|
|
|
int getOttavaShift() const {
|
|
return (m_indicationType == QuindicesimaUp ? 2 :
|
|
m_indicationType == OttavaUp ? 1 :
|
|
m_indicationType == OttavaDown ? -1 :
|
|
m_indicationType == QuindicesimaDown ? -2 : 0);
|
|
}
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsEvent(timeT absoluteTime) const;
|
|
|
|
private:
|
|
bool isValid(const std::string &s) const;
|
|
|
|
std::string m_indicationType;
|
|
timeT m_duration;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* Definitions for use in the text Event type.
|
|
*/
|
|
|
|
class Text
|
|
{
|
|
public:
|
|
static const std::string EventType;
|
|
static const int EventSubOrdering;
|
|
static const PropertyName TextPropertyName;
|
|
static const PropertyName TextTypePropertyName;
|
|
static const PropertyName LyricVersePropertyName;
|
|
|
|
/**
|
|
* Text styles
|
|
*/
|
|
static const std::string UnspecifiedType;
|
|
static const std::string StaffName;
|
|
static const std::string ChordName;
|
|
static const std::string KeyName;
|
|
static const std::string Lyric;
|
|
static const std::string Chord;
|
|
static const std::string Dynamic;
|
|
static const std::string Direction;
|
|
static const std::string LocalDirection;
|
|
static const std::string Tempo;
|
|
static const std::string LocalTempo;
|
|
static const std::string Annotation;
|
|
static const std::string LilyPondDirective;
|
|
|
|
/**
|
|
* Special LilyPond directives
|
|
*/
|
|
static const std::string Segno; // print segno here
|
|
static const std::string Coda; // print coda sign here
|
|
static const std::string Alternate1; // first alternative ending
|
|
static const std::string Alternate2; // second alternative ending
|
|
static const std::string BarDouble; // next barline is double
|
|
static const std::string BarEnd; // next barline is final double
|
|
static const std::string BarDot; // next barline is dotted
|
|
static const std::string Gliss; // \glissando on this note (to next note)
|
|
static const std::string Arpeggio; // \arpeggio on this chord
|
|
// static const std::string ArpeggioUp; // \ArpeggioUp on this chord
|
|
// static const std::string ArpeggioDn; // \ArpeggioDown on this chord
|
|
static const std::string Tiny; // begin \tiny font section
|
|
static const std::string Small; // begin \small font section
|
|
static const std::string NormalSize; // begin \normalsize font section
|
|
|
|
Text(const Event &e)
|
|
/* throw (Event::NoData, Event::BadType) */;
|
|
Text(const std::string &text,
|
|
const std::string &textType = UnspecifiedType);
|
|
Text(const Text &);
|
|
Text &operator=(const Text &);
|
|
~Text();
|
|
|
|
std::string getText() const { return m_text; }
|
|
std::string getTextType() const { return m_type; }
|
|
|
|
int getVerse() const { return m_verse; } // only relevant for lyrics
|
|
void setVerse(int verse) { m_verse = verse; }
|
|
|
|
static bool isTextOfType(Event *, std::string type);
|
|
|
|
/**
|
|
* Return those text types that the user should be allowed to
|
|
* specify directly and visually
|
|
*/
|
|
static std::vector<std::string> getUserStyles();
|
|
|
|
/**
|
|
* Return a list of available special LilyPond directives
|
|
*/
|
|
static std::vector<std::string> getLilyPondDirectives();
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsEvent(timeT absoluteTime) const;
|
|
|
|
private:
|
|
std::string m_text;
|
|
std::string m_type;
|
|
long m_verse;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* Pitch stores a note's pitch and provides information about it in
|
|
* various different ways, notably in terms of the position of the
|
|
* note on the staff and its associated accidental.
|
|
*
|
|
* (See docs/discussion/units.txt for explanation of pitch units.)
|
|
*
|
|
* This completely replaces the older NotationDisplayPitch class.
|
|
*/
|
|
|
|
class Pitch
|
|
{
|
|
public:
|
|
/**
|
|
* Construct a Pitch object based on the given Event, which must
|
|
* have a BaseProperties::PITCH property. If the property is
|
|
* absent, NoData is thrown. The BaseProperties::ACCIDENTAL
|
|
* property will also be used if present.
|
|
*/
|
|
Pitch(const Event &e)
|
|
/* throw Event::NoData */;
|
|
|
|
/**
|
|
* Construct a Pitch object based on the given performance (MIDI) pitch.
|
|
*/
|
|
Pitch(int performancePitch,
|
|
const Accidental &explicitAccidental = Accidentals::NoAccidental);
|
|
|
|
/**
|
|
* Construct a Pitch based on octave and pitch in octave. The
|
|
* lowest permissible octave number is octaveBase, and middle C is
|
|
* in octave octaveBase + 5. pitchInOctave must be in the range
|
|
* 0-11 where 0 is C, 1 is C sharp, etc.
|
|
*/
|
|
Pitch(int pitchInOctave, int octave,
|
|
const Accidental &explicitAccidental = Accidentals::NoAccidental,
|
|
int octaveBase = -2);
|
|
|
|
/**
|
|
* Construct a Pitch based on octave and note in scale. The
|
|
* lowest permissible octave number is octaveBase, and middle C is
|
|
* in octave octaveBase + 5. The octave supplied should be that
|
|
* of the root note in the given key, which may be in a different
|
|
* MIDI octave from the resulting pitch (as MIDI octaves always
|
|
* begin at C). noteInScale must be in the range 0-6 where 0 is
|
|
* the root of the key and so on. The accidental is relative to
|
|
* noteInScale: if there is an accidental in the key for this note
|
|
* already, explicitAccidental will be "added" to it.
|
|
*
|
|
* For minor keys, the harmonic scale is used.
|
|
*/
|
|
Pitch(int noteInScale, int octave, const Key &key,
|
|
const Accidental &explicitAccidental = Accidentals::NoAccidental,
|
|
int octaveBase = -2);
|
|
|
|
/**
|
|
* Construct a Pitch based on (MIDI) octave, note in the C major scale and
|
|
* performance pitch. The accidental is calculated based on these
|
|
* properties.
|
|
*/
|
|
Pitch(int noteInCMajor, int octave, int pitch,
|
|
int octaveBase = -2);
|
|
|
|
/**
|
|
* Construct a Pitch based on octave and note name. The lowest
|
|
* permissible octave number is octaveBase, and middle C is in
|
|
* octave octaveBase + 5. noteName must be a character in the
|
|
* range [CDEFGAB] or lower-case equivalents. The key is supplied
|
|
* so that we know how to interpret the NoAccidental case.
|
|
*/
|
|
Pitch(char noteName, int octave, const Key &key,
|
|
const Accidental &explicitAccidental = Accidentals::NoAccidental,
|
|
int octaveBase = -2);
|
|
|
|
/**
|
|
* Construct a Pitch corresponding a staff line or space on a
|
|
* classical 5-line staff. The bottom staff line has height 0,
|
|
* the top has height 8, and both positive and negative values are
|
|
* permissible.
|
|
*/
|
|
Pitch(int heightOnStaff, const Clef &clef, const Key &key,
|
|
const Accidental &explicitAccidental = Accidentals::NoAccidental);
|
|
|
|
Pitch(const Pitch &);
|
|
Pitch &operator=(const Pitch &);
|
|
|
|
/**
|
|
* Return the MIDI pitch for this Pitch object.
|
|
*/
|
|
int getPerformancePitch() const;
|
|
|
|
/**
|
|
* Return the accidental for this pitch using a bool to prefer sharps over
|
|
* flats if there is any doubt. This is the accidental
|
|
* that would be used to display this pitch outside of the context
|
|
* of any key; that is, it may duplicate an accidental actually in
|
|
* the current key. This should not be used if you need to get an
|
|
* explicit accidental returned for E#, Fb, B# or Cb.
|
|
*
|
|
* This version of the function exists to avoid breaking old code.
|
|
*/
|
|
Accidental getAccidental(bool useSharps) const;
|
|
|
|
/**
|
|
* Return the accidental for this pitch, using a key. This should be used
|
|
* if you need an explicit accidental returned for E#, Fb, B# or Cb, which
|
|
* can't be resolved correctly without knowing that their key requires
|
|
* them to take an accidental. The provided key will also be used to
|
|
* determine whether to prefer sharps over flats.
|
|
*/
|
|
Accidental getAccidental(const Key &key) const;
|
|
|
|
/**
|
|
* Return the accidental that should be used to display this pitch
|
|
* in a given key. For example, if the pitch is F-sharp in a key
|
|
* in which F has a sharp, NoAccidental will be returned. (This
|
|
* is in contrast to getAccidental, which would return Sharp.)
|
|
* This obviously can't take into account things like which
|
|
* accidentals have already been displayed in the bar, etc.
|
|
*/
|
|
Accidental getDisplayAccidental(const Key &key) const;
|
|
|
|
/**
|
|
* Return the accidental that should be used to display this pitch
|
|
* in a given key, using the given strategy to resolve pitches where
|
|
* an accidental is needed but not specified.
|
|
*/
|
|
Accidental getDisplayAccidental(const Key &key, Accidentals::NoAccidentalStrategy) const;
|
|
|
|
/**
|
|
* Return the position in the scale for this pitch, as a number in
|
|
* the range 0 to 6 where 0 is the root of the key.
|
|
*/
|
|
int getNoteInScale(const Key &key) const;
|
|
|
|
/**
|
|
* Return the note name for this pitch, as a single character in
|
|
* the range A to G. (This is a reference value that should not
|
|
* normally be shown directly to the user, for i18n reasons.)
|
|
*/
|
|
char getNoteName(const Key &key) const;
|
|
|
|
/**
|
|
* Return the height at which this pitch should display on a
|
|
* conventional 5-line staff. 0 is the bottom line, 1 the first
|
|
* space, etc., so for example middle-C in the treble clef would
|
|
* return -2.
|
|
*
|
|
* Chooses the most likely accidental for this pitch in this key.
|
|
*/
|
|
int getHeightOnStaff(const Clef &clef, const Key &key) const;
|
|
|
|
/**
|
|
* Return the height at which this pitch should display on a
|
|
* conventional 5-line staff. 0 is the bottom line, 1 the first
|
|
* space, etc., so for example middle-C in the treble clef would
|
|
* return -2.
|
|
*
|
|
* Chooses the accidental specified by the 'useSharps' parameter
|
|
*/
|
|
int getHeightOnStaff(const Clef &clef, bool useSharps) const;
|
|
|
|
/**
|
|
* Return the octave containing this pitch. The octaveBase argument
|
|
* specifies the octave containing MIDI pitch 0; middle-C is in octave
|
|
* octaveBase + 5.
|
|
*/
|
|
int getOctave(int octaveBase = -2) const;
|
|
|
|
/**
|
|
* Return the pitch within the octave, in the range 0 to 11.
|
|
*/
|
|
int getPitchInOctave() const;
|
|
|
|
/**
|
|
* Return whether this pitch is diatonic in the given key.
|
|
*/
|
|
bool isDiatonicInKey(const Key &key) const;
|
|
|
|
/**
|
|
* Return a reference name for this pitch. (C4, Bb2, etc...)
|
|
* according to http://www.harmony-central.com/MIDI/Doc/table2.html
|
|
*
|
|
* Note that this does not take into account the stored accidental
|
|
* -- this string is purely an encoding of the MIDI pitch, with
|
|
* the accidental in the string selected according to the
|
|
* useSharps flag (which may be expected to have come from a call
|
|
* to Key::isSharp).
|
|
*
|
|
* If inclOctave is false, this will return C, Bb, etc.
|
|
*/
|
|
std::string getAsString(bool useSharps,
|
|
bool inclOctave = true,
|
|
int octaveBase = -2) const;
|
|
|
|
/**
|
|
* Return a number 0-6 corresponding to the given note name, which
|
|
* must be in the range [CDEFGAB] or lower-case equivalents. The
|
|
* return value is in the range 0-6 with 0 for C, 1 for D etc.
|
|
*/
|
|
static int getIndexForNote(char noteName);
|
|
|
|
/**
|
|
* Return a note name corresponding to the given note index, which
|
|
* must be in the range 0-6 with 0 for C, 1 for D etc.
|
|
*/
|
|
static char getNoteForIndex(int index);
|
|
|
|
/**
|
|
* Calculate and return the performance (MIDI) pitch corresponding
|
|
* to the stored height and accidental, interpreting them as
|
|
* Rosegarden-2.1-style values (for backward compatibility use),
|
|
* in the given clef and key
|
|
*/
|
|
static int getPerformancePitchFromRG21Pitch(int heightOnStaff,
|
|
const Accidental &accidental,
|
|
const Clef &clef,
|
|
const Key &key);
|
|
|
|
/**
|
|
* return the result of transposing the given pitch by the
|
|
* specified interval in the given key. The key is left unchanged,
|
|
* only the pitch is transposed.
|
|
*/
|
|
Pitch transpose(const Key &key, int pitchDelta, int heightDelta);
|
|
|
|
/**
|
|
* checks whether the accidental specified for this pitch (if any)
|
|
* is valid - for example, a Sharp for pitch 11 is invalid, as
|
|
* it's between A# and B#.
|
|
*/
|
|
bool validAccidental() const;
|
|
|
|
/**
|
|
* Returned event is on heap; caller takes responsibility for ownership
|
|
*/
|
|
Event *getAsNoteEvent(timeT absoluteTime, timeT duration) const;
|
|
|
|
private:
|
|
int m_pitch;
|
|
Accidental m_accidental;
|
|
|
|
static void rawPitchToDisplayPitch
|
|
(int, const Clef &, const Key &, int &, Accidental &,
|
|
Accidentals::NoAccidentalStrategy);
|
|
|
|
static void displayPitchToRawPitch
|
|
(int, Accidental, const Clef &, const Key &,
|
|
int &, bool ignoreOffset = false);
|
|
};
|
|
|
|
|
|
|
|
class TimeSignature;
|
|
|
|
|
|
/**
|
|
* The Note class represents note durations only, not pitch or
|
|
* accidental; it's therefore just as relevant to rest events as to
|
|
* note events. You can construct one of these from either.
|
|
*/
|
|
|
|
class Note
|
|
{
|
|
public:
|
|
static const std::string EventType;
|
|
static const std::string EventRestType;
|
|
static const int EventRestSubOrdering;
|
|
|
|
typedef int Type; // not an enum, too much arithmetic at stake
|
|
|
|
// define both sorts of names; some people prefer the American
|
|
// names, but I just can't remember which of them is which
|
|
|
|
static const Type
|
|
|
|
SixtyFourthNote = 0,
|
|
ThirtySecondNote = 1,
|
|
SixteenthNote = 2,
|
|
EighthNote = 3,
|
|
QuarterNote = 4,
|
|
HalfNote = 5,
|
|
WholeNote = 6,
|
|
DoubleWholeNote = 7,
|
|
|
|
Hemidemisemiquaver = 0,
|
|
Demisemiquaver = 1,
|
|
Semiquaver = 2,
|
|
Quaver = 3,
|
|
Crotchet = 4,
|
|
Minim = 5,
|
|
Semibreve = 6,
|
|
Breve = 7,
|
|
|
|
Shortest = 0,
|
|
Longest = 7;
|
|
|
|
|
|
/**
|
|
* Create a Note object of the given type, representing a
|
|
* particular sort of duration. Note objects are strictly
|
|
* durational; they don't represent pitch, and may be as
|
|
* relevant to rests as actual notes.
|
|
*/
|
|
Note(Type type, int dots = 0) :
|
|
m_type(type < Shortest ? Shortest :
|
|
type > Longest ? Longest :
|
|
type),
|
|
m_dots(dots) { }
|
|
|
|
Note(const Note &n) : m_type(n.m_type), m_dots(n.m_dots) { }
|
|
~Note() { }
|
|
|
|
Note &operator=(const Note &n);
|
|
|
|
Type getNoteType() const { return m_type; }
|
|
int getDots() const { return m_dots; }
|
|
|
|
/**
|
|
* Return the duration of this note type.
|
|
*/
|
|
timeT getDuration() const {
|
|
return m_dots ? getDurationAux() : (m_shortestTime * (1 << m_type));
|
|
}
|
|
|
|
/**
|
|
* Return the Note whose duration is closest to (but shorter than or
|
|
* equal to) the given duration, permitting at most maxDots dots.
|
|
*/
|
|
static Note getNearestNote(timeT duration, int maxDots = 2);
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsNoteEvent(timeT absoluteTime, int pitch) const;
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsRestEvent(timeT absoluteTime) const;
|
|
|
|
|
|
private:
|
|
Type m_type;
|
|
int m_dots;
|
|
|
|
timeT getDurationAux() const;
|
|
|
|
// a time & effort saving device; if changing this, change
|
|
// TimeSignature::m_crotchetTime etc too
|
|
static const timeT m_shortestTime;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* TimeSignature contains arithmetic methods relevant to time
|
|
* signatures and bar durations, including code for splitting long
|
|
* rest intervals into bite-sized chunks. Although there is a time
|
|
* signature Event type, these Events don't appear in regular Segments
|
|
* but only in the Composition's reference segment.
|
|
*/
|
|
|
|
class TimeSignature
|
|
{
|
|
public:
|
|
static const TimeSignature DefaultTimeSignature;
|
|
typedef Exception BadTimeSignature;
|
|
|
|
TimeSignature() :
|
|
m_numerator(DefaultTimeSignature.m_numerator),
|
|
m_denominator(DefaultTimeSignature.m_denominator),
|
|
m_common(false), m_hidden(false), m_hiddenBars(false) { }
|
|
|
|
/**
|
|
* Construct a TimeSignature object describing a time signature
|
|
* with the given numerator and denominator. If preferCommon is
|
|
* true and the time signature is a common or cut-common time, the
|
|
* constructed object will return true for isCommon; if hidden is
|
|
* true, the time signature is intended not to be displayed and
|
|
* isHidden will return true; if hiddenBars is true, the bar lines
|
|
* between this time signature and the next will not be shown.
|
|
*/
|
|
TimeSignature(int numerator, int denominator,
|
|
bool preferCommon = false,
|
|
bool hidden = false,
|
|
bool hiddenBars = false)
|
|
/* throw (BadTimeSignature) */;
|
|
|
|
TimeSignature(const TimeSignature &ts) :
|
|
m_numerator(ts.m_numerator),
|
|
m_denominator(ts.m_denominator),
|
|
m_common(ts.m_common),
|
|
m_hidden(ts.m_hidden),
|
|
m_hiddenBars(ts.m_hiddenBars) { }
|
|
|
|
~TimeSignature() { }
|
|
|
|
TimeSignature &operator=(const TimeSignature &ts);
|
|
|
|
bool operator==(const TimeSignature &ts) const {
|
|
return ts.m_numerator == m_numerator && ts.m_denominator == m_denominator;
|
|
}
|
|
bool operator!=(const TimeSignature &ts) const {
|
|
return !operator==(ts);
|
|
}
|
|
|
|
int getNumerator() const { return m_numerator; }
|
|
int getDenominator() const { return m_denominator; }
|
|
|
|
bool isCommon() const { return m_common; }
|
|
bool isHidden() const { return m_hidden; }
|
|
bool hasHiddenBars() const { return m_hiddenBars; }
|
|
|
|
timeT getBarDuration() const;
|
|
|
|
/**
|
|
* Return the unit of the time signature. This is the note
|
|
* implied by the denominator. For example, the unit of 4/4 time
|
|
* is the crotchet, and that of 6/8 is the quaver. (The numerator
|
|
* of the time signature gives the number of units per bar.)
|
|
*/
|
|
Note::Type getUnit() const;
|
|
|
|
/**
|
|
* Return the duration of the unit of the time signature.
|
|
* See also getUnit(). In most cases getBeatDuration() gives
|
|
* a more meaningful value.
|
|
*/
|
|
timeT getUnitDuration() const;
|
|
|
|
/**
|
|
* Return true if this time signature indicates dotted time.
|
|
*/
|
|
bool isDotted() const;
|
|
|
|
/**
|
|
* Return the duration of the beat of the time signature. For
|
|
* example, the beat of 4/4 time is the crotchet, the same as its
|
|
* unit, but that of 6/8 is the dotted crotchet (there are only
|
|
* two beats in a 6/8 bar). The beat therefore depends on whether
|
|
* the signature indicates dotted or undotted time.
|
|
*/
|
|
timeT getBeatDuration() const;
|
|
|
|
/**
|
|
* Return the number of beats in a complete bar.
|
|
*/
|
|
int getBeatsPerBar() const {
|
|
return getBarDuration() / getBeatDuration();
|
|
}
|
|
|
|
/**
|
|
* Get the "optimal" list of rest durations to make up a bar in
|
|
* this time signature.
|
|
*/
|
|
void getDurationListForBar(DurationList &dlist) const;
|
|
|
|
/**
|
|
* Get the "optimal" list of rest durations to make up a time
|
|
* interval of the given total duration, starting at the given
|
|
* offset after the start of a bar, assuming that the interval
|
|
* is entirely in this time signature.
|
|
*/
|
|
void getDurationListForInterval(DurationList &dlist,
|
|
timeT intervalDuration,
|
|
timeT startOffset = 0) const;
|
|
|
|
/**
|
|
* Get the level of emphasis for a position in a bar. 4 is lots
|
|
* of emphasis, 0 is none.
|
|
*/
|
|
int getEmphasisForTime(timeT offset);
|
|
|
|
/**
|
|
* Return a list of divisions, subdivisions, subsubdivisions
|
|
* etc of a bar in this time, up to the given depth. For example,
|
|
* if the time signature is 6/8 and the depth is 3, return a list
|
|
* containing 2, 3, and 2 (there are 2 beats to the bar, each of
|
|
* which is best subdivided into 3 subdivisions, each of which
|
|
* divides most neatly into 2).
|
|
*/
|
|
void getDivisions(int depth, std::vector<int> &divisions) const;
|
|
|
|
private:
|
|
friend class Composition;
|
|
friend class TimeTempoSelection;
|
|
|
|
TimeSignature(const Event &e)
|
|
/* throw (Event::NoData, Event::BadType, BadTimeSignature) */;
|
|
|
|
static const std::string EventType;
|
|
static const int EventSubOrdering;
|
|
static const PropertyName NumeratorPropertyName;
|
|
static const PropertyName DenominatorPropertyName;
|
|
static const PropertyName ShowAsCommonTimePropertyName;
|
|
static const PropertyName IsHiddenPropertyName;
|
|
static const PropertyName HasHiddenBarsPropertyName;
|
|
|
|
/// Returned event is on heap; caller takes responsibility for ownership
|
|
Event *getAsEvent(timeT absoluteTime) const;
|
|
|
|
private:
|
|
int m_numerator;
|
|
int m_denominator;
|
|
|
|
bool m_common;
|
|
bool m_hidden;
|
|
bool m_hiddenBars;
|
|
|
|
mutable int m_barDuration;
|
|
mutable int m_beatDuration;
|
|
mutable int m_beatDivisionDuration;
|
|
mutable bool m_dotted;
|
|
void setInternalDurations() const;
|
|
|
|
// a time & effort saving device
|
|
static const timeT m_crotchetTime;
|
|
static const timeT m_dottedCrotchetTime;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* AccidentalTable represents a set of accidentals in force at a
|
|
* given time.
|
|
*
|
|
* Keep an AccidentalTable variable on-hand as you track through a
|
|
* staff; then when reading a chord, call processDisplayAccidental
|
|
* on the accidentals found in the chord to obtain the actual
|
|
* displayed accidentals and to tell the AccidentalTable to
|
|
* remember the accidentals that have been found in the chord.
|
|
* Then when the chord ends, call update() on the AccidentalTable
|
|
* so that that chord's accidentals are taken into account for the
|
|
* next one.
|
|
*
|
|
* Create a new AccidentalTable whenever a new key is encountered,
|
|
* and call newBar() or newClef() when a new bar happens or a new
|
|
* clef is encountered.
|
|
*/
|
|
class AccidentalTable
|
|
{
|
|
public:
|
|
enum OctaveType {
|
|
OctavesIndependent, // if c' and c'' sharp, mark them both sharp
|
|
OctavesCautionary, // if c' and c'' sharp, put the second one in brackets
|
|
OctavesEquivalent // if c' and c'' sharp, only mark the first one
|
|
};
|
|
|
|
enum BarResetType {
|
|
BarResetNone, // c# | c -> omit natural
|
|
BarResetCautionary, // c# | c -> add natural to c in brackets
|
|
BarResetExplicit // c# | c -> add natural to c
|
|
};
|
|
|
|
AccidentalTable(const Key &, const Clef &,
|
|
OctaveType = OctavesCautionary,
|
|
BarResetType = BarResetCautionary);
|
|
|
|
AccidentalTable(const AccidentalTable &);
|
|
AccidentalTable &operator=(const AccidentalTable &);
|
|
|
|
Accidental processDisplayAccidental(const Accidental &displayAcc,
|
|
int heightOnStaff,
|
|
bool &cautionary);
|
|
|
|
void update();
|
|
|
|
void newBar();
|
|
void newClef(const Clef &);
|
|
|
|
private:
|
|
Key m_key;
|
|
Clef m_clef;
|
|
OctaveType m_octaves;
|
|
BarResetType m_barReset;
|
|
|
|
struct AccidentalRec {
|
|
AccidentalRec() : accidental(Accidentals::NoAccidental), previousBar(false) { }
|
|
AccidentalRec(Accidental a, bool p) : accidental(a), previousBar(p) { }
|
|
Accidental accidental;
|
|
bool previousBar;
|
|
};
|
|
|
|
typedef std::map<int, AccidentalRec> AccidentalMap;
|
|
|
|
AccidentalMap m_accidentals;
|
|
AccidentalMap m_canonicalAccidentals;
|
|
|
|
AccidentalMap m_newAccidentals;
|
|
AccidentalMap m_newCanonicalAccidentals;
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|