The pitch module¶
Classes and functions to deal with LilyPond pitches.
A pitch consists of a step (note, the index in the global default scale) and an alteration, which is a rational value (fraction or floating point) in whole tones. The notes 0..6 correspond with the usual “white keys” C, D, E, F, G, A, B; a sharp is represented by a +0.5 alteration value, and a flat by a -0.5 value.
The octave of a pitch is 0 for the octave starting at middle C, just like LilyPond handles the octave.
All functions and classes in this module, and also in the key module,
allow specifying a different global default scale (set in the
MAJOR_SCALE module constant), to theoretically support other tone
systems, but that will probably almost never be necessary.
-
MAJOR_SCALE= (0, 1, 2, 2.5, 3.5, 4.5, 5.5)¶ Major scale: C D E F G A B, with the default pitch offset from the starting C in whole tones.
-
MAJOR_FLATS= (1.5, 5)¶ Which pitch values get a flat by default instead of a sharp when converting a MIDI key number to a pitch.
-
class
Pitch(octave, note, alter)[source]¶ Bases:
objectA pitch with
octave,note, andalterattributes.The attributes may be manipulated directly, and have the same contents and meaning as the three values in LilyPond’s
(ly:make-pitch octave note alter)construct.The
octaveis an integer where 0 stands for the octave containing “middle C” (with one apostrophe in LilyPond’s format). Thenoteis an integer in the 0..6 range, where 0 stands for C; thealteris an integer, float or fraction denoting the alteration in whole tones, where all pitch languages support the values -1, -0.5, 0, 0.5, 1, and some languages also support semi, three-quarter alterations like 0.25 (i.e.Fraction(1, 4)), or even other alterations.Pitches compare equal when their attributes are the same, and also support the
>,<,>=and<=operators. These operators compare on octave first, then note, then alter.format(pitch)returns always the dutch notation (or a question mark if there’s no known name for the note, alter combination), but you can usePitchProcessorto read/write pitch names in all LilyPond languages.-
classmethod
from_midi(key, scale=None, flats=None)[source]¶ Return a
Pitchfrom the MIDI key value.All altered notes get a sharp, unless a pitch value is listed in the
flatsparameter. By default, the pitch values 1.5 and 5 get a flat, resulting in an e-flat instead of d-sharp and a b-flat instead of an a-sharp.An example:
>>> from quickly.pitch import Pitch >>> Pitch.from_midi(60) <Pitch note=0, alter=0, octave=1 (c')> >>> Pitch.from_midi(61) <Pitch note=0, alter=0.5, octave=1 (cis')> >>> Pitch.from_midi(70) <Pitch note=6, alter=-0.5, octave=1 (bes')> >>> Pitch.from_midi(70, flats=()) <Pitch note=5, alter=0.5, octave=1 (ais')>
A more powerful way to convert MIDI key numbers to pitches is in the
KeySignatureclass.
-
classmethod
-
class
PitchProcessor(language=None)[source]¶ Bases:
objectRead and write pitch names in all LilyPond languages.
The language to use by default can be given on instantiation or set in the
languageattribute. Some languages have multiple pitch names for the same note; using theprefer_attributes you can control which style is chosen when writing the pitch name.-
prefer_long= False¶ Prefer long names in english, e.g.
c-sharpsharpabovecss
-
prefer_accented= False¶ Prefer
réabovere(in francais)
-
prefer_x= False¶ Prefer
doxabovedoss,cxabovecss, etc in enspanol, english, francais
-
prefer_double_s= False¶ Prefer
ssabovesinside note names in norsk
-
prefer_classic= True¶ Prefer
esaboveeesandasaboveaes(in nederlands, norsk)
-
prefer_deprecated= False¶ Prefer names marked as deprecated
-
language¶ The language to use (default:
"nederlands").Deleting this attribute sets it back to
"nederlands".Raises a
KeyErrorif the language you try to set does not exist. Valid languages are:"arabic","bagpipe","catalan","català","deutsch","english","espanol","español","français","italiano","nederlands","norsk","portugues","português","suomi","svenska","vlaams".Do not modify the language between a
read_node()andwrite_node()operation on the same node. For translation of pitch names, use two PitchProcessors.
-
pitch(name)[source]¶ Return a
Pitchfor the specified note name.Raises a
KeyErrorif the language does not know the pitch name, or when the language name is unknown.For example:
>>> from quickly.pitch import PitchProcessor >>> p = PitchProcessor() >>> p.read('cis') <Pitch octave=-1, note=0, alter=0.5 (cis)>
-
name_octave(pitch)[source]¶ Return a two-tuple (name, octave) for the
Pitch.The name is the note name, the octave is the number of
,(if negative) or'that still need to be added.Raises a
KeyErrorif the language does not contain a pitch name.
-
to_string(pitch)[source]¶ Return a string representing the pitch.
Raises a
KeyErrorif the language does not contain a pitch name.For example:
>>> from quickly.pitch import PitchProcessor >>> p = PitchProcessor() >>> p.write(Pitch(-1, 0, 0)) 'c' >>> p.write(Pitch(0, 4, 1)) "gisis'" >>> p.language = 'english' >>> p.write(Pitch(0, 4, 1)) "gss'" >>> p.prefer_long = True >>> p.write(Pitch(0, 4, 1)) "g-sharpsharp'"
-
read_node(node)[source]¶ Return a Pitch, initialized from the node.
The
nodeis aNote, positionedPitchedRestor any otherPitchableFor example:>>> from quickly.pitch import PitchProcessor >>> from quickly.dom import lily >>> n = lily.Note('re') >>> p = PitchProcessor('français') >>> p.read_node(n) <Pitch octave=-1, note=1, alter=0 (d)>
The octave handling might be a little confusing at first sight: A Note node without octave characters has octave 0, while the pitch has octave -1. This is because, just like in LilyPond, the pitch name itself carries the octave -1, and the octave count of the node is added to it to get the resulting octave of the actual pitch:
>>> n.octave # number of ' or , 0 >>> p.read_node(n).octave # actual octave -1
-
write_node(node, pitch)[source]¶ Write the Pitch’s note, alter and octave to the node.
The
nodeis aNoteorPitchedRest. Example:>>> from quickly.pitch import Pitch, PitchProcessor >>> from quickly.dom import lily >>> n = lily.Note('c') >>> p = PitchProcessor() >>> p.write_node(n, Pitch(2, 1, 0.5)) >>> n.dump() <lily.Note 'dis' (1 child)> ╰╴<lily.Octave 3>
-
process(node, write=True)[source]¶ Return a context manager that yields a
Pitchwhen entered.The
nodeis aNoteorPitchedRest. You can manipulate the Pitch, and when done, the node will be updated if the pitch was changed. An example:>>> from quickly.pitch import PitchProcessor >>> from quickly.dom import lily >>> n = lily.Note('c') >>> p = PitchProcessor() >>> with p.process(n) as pitch: ... pitch.note += 2 ... pitch.alter = 0.5 ... pitch.octave += 1 ... >>> n.write() "eis'" >>> n.dump() <lily.Note 'eis' (1 child)> ╰╴<lily.Octave 1>
If you set the
writeparameter to False on invocation, the pitch changes will not be written back to the DOM node, this enables you to e.g. apply changes only within a certain range.
-
pitchable(pitch, cls=None)[source]¶ Return a new Pitchable element for the pitch.
By default, a Note is returned, but you may specify any Pitchable subclass.
>>> from quickly.pitch import * >>> p = PitchProcessor('nederlands') >>> n = p.pitchable(Pitch(2, 3, -.25)) >>> n.dump() <lily.Note 'feh' (1 child)> ╰╴<lily.Octave 3> >>> n.write() "feh'''"
-
find_language(node)[source]¶ Search backwards from node to find the last set language.
If an
\includecommand is found that names a language file, or a\languagecommand with a valid language, that language is set.
-
follow_language(nodes)[source]¶ Iterate over the DOM nodes and follow language changes.
Yield every node, except for
lily.Languageorlily.Includeif a language name is included. Sets the language attribute according to the\languageor\includecommand.
-
distill_preferences(names)[source]¶ Iterate over the
namesand try to distill the preferred style.Adjust the preferences based on the encountered pitch names.
This can be used to analyze existing music and use the same pitch name preferences for newly entered music.
The
namesiterable may be a set but also an ordered sequence or generator. If a name is encountered that is a language name, that language is followed to test following pitch names. (Thelanguageattribute is not changed.)
-
-
octave_to_string(n)[source]¶ Convert a numeric value to an octave notation.
The octave notation consists of zero or more
'or,. The octave0returns the empty string.
-
octave_from_string(octave)[source]¶ Convert an octave string to a numeric value.
''is converted to 2,,to -1. The empty string gives 0.
-
determine_language(names)[source]¶ Yield the language names that have all the specified pitch names.
This can be used to auto-determine the language of music if the language name somehow is not set in a file. Just harvest all the pitch names and call this function. The pitch names
"r","R","s"and"q"are ignored. For example:>>> from quickly.pitch import determine_language >>> list(determine_language(['c', 'd', 'es', 'fis', 'bis'])) ['nederlands'] >>> list(determine_language(['c', 'do'])) [] # ambiguous