ScoreStruct¶
- class maelzel.scorestruct.ScoreStruct(score=None, timesig=None, tempo=None, endless=True, title='', composer='', readonly=False)[source]¶
Bases:
object
A ScoreStruct holds the structure of a score but no content
A ScoreStruct consists of some metadata and a list of
MeasureDefs
, where eachMeasureDef
defines the properties of the measure at the given index. If a ScoreStruct is marked as endless, it is possible to query it (convert beats to time, etc.) outside the defined measures.The ScoreStruct class is used extensively within
maelzel.core
(seescorestruct-and-maelzel-core
)- Parameters:
score (
Optional
[str
]) – if given, a score definition as a string (see below for the format)timesig (
Union
[Tuple
[int
,int
],str
,None
]) – time-signature. If no score is given, a timesig can be passed to define a basic scorestruct with a time signature and a default or given tempotempo (
Optional
[int
]) – the tempo of a quarter note, if given. Even if using a time-signature with a smaller denominator (like 3/8), the tempo is always given in reference to a quarter note.endless (
bool
) – mark this ScoreStruct as endless. Defaults to Truetitle – title metadata for the score, used when rendering
composer – composer metadata for this score, used when rendering
Example
# create an endless score with a given time signature s = ScoreStruct(endless=True) s.addMeasure((4, 4), quarterTempo=72) # this is the same as: s = ScoreStruct.fromTimesig((4, 4), 72) # Create the beginning of Sacre s = ScoreStruct() s.addMeasure((4, 4), 50) s.addMeasure((3, 4)) s.addMeasure((4, 4)) s.addMeasure((2, 4)) s.addMeasure((3, 4), numMeasures=2) # The same can be achieved via a score string: s = ScoreStruct(r''' 4/4, 50 3/4 4/4 2/4 3/4 . ''') # Or everything in one line: s = ScoreStruct('4/4, 50; 3/4; 4/4; 2/4; 3/4; 3/4 ')
Format
A definitions are divided by new line or by ;. Each line has the form:
measureIndex, timeSig, tempo
Tempo refers always to a quarter note
Any value can be left out: , 5/8,
measure numbers start at 0
comments start with
#
and last until the end of the lineA line with a single “.” repeats the last defined measure
A score ending with the line … is an endless score
The measure number and/or the tempo can both be left out. The following definitions are all the same:
1, 5/8, 63 5/8, 63 5/8
Example:
0, 4/4, 60, "mark A" ,3/4,80 # Assumes measureIndex=1 10, 5/8, 120 30,, . . # last measure (inclusive, the score will have 33 measures)
Methods Summary
addMeasure
([timesig, quarterTempo, ...])Add a measure definition to this score structure
addRehearsalMark
(idx, mark[, box])Add a rehearsal mark to this scorestruct
asBeat
(location)Given a beat or a location (measureidx, relativeoffset), returns an absolute beat
asText
()This ScoreStruct as parsable text format
b2t
(beat)Beat to time
beat
(a[, b])Convert a time in secs or a location (measure, beat) to a quarter-note beat
beatDelta
(start, end)Difference in beats between the two score locations or two times
beatToLocation
(beat)Return the location in score corresponding to the given beat
beatToTime
(beat)Convert beat-time to real-time
copy
()Create a copy of this ScoreStruct
dump
()Dump this ScoreStruct to stdout
The duration of this score, in quarternotes
The duration of this score, in seconds
ensureDurationInMeasures
(numMeasures)Extends this score to have at least the given number of measures
ensureDurationInSeconds
(duration)Ensure that this scorestruct is long enough to include the given time
exportMidiClickTrack
(midifile)Generate a MIDI click track from this ScoreStruct
getMeasureDef
(idx[, extend])Returns the MeasureDef at the given index.
Returns True if this ScoreStruct has no tempo changes
Returns True if this ScoreStruct does not have any time-signature change
Iterate over all measure definitions in this ScoreStruct.
locationToBeat
(measure[, beat])Returns the number of quarter notes up to the given location
locationToTime
(measure[, beat])Return the elapsed time at the given score location
ltob
(measure, beat)A shortcut to locationToBeat
makeClickTrack
([minMeasures, clickdur, ...])Create a click track from this ScoreStruct
measureOffsets
([startIndex, stopIndex])Returns a list with the time offsets of each measure
measuresBetween
(start, end)List of measures defined between the given times as beats
modified
()mark this ScoreStruct as modified
Returns the number of measures in this score structure
remapFrom
(sourcestruct, location)Remap a beat from sourcestruct to this this struct
remapSpan
(sourcestruct, offset, duration)Remap a time span from a source score structure to this score structure
remapTo
(deststruct, location)Remap a beat from this struct to another struct
setBarline
(measureIndex, linetype)Set the right barline type
setEnd
(numMeasures)Set an end measure to this ScoreStruct, in place
setTempo
(tempo[, reference, measureIndex])Set the tempo of the given measure, until the next tempo change
setTimeSignature
(measureIndex, timesig)- rtype:
None
show
([fmt, app, scalefactor, backend, ...])Render and show this ScoreStruct
t2b
(t)Time to beat
tempoAtTime
(time)Returns the tempo active at the given time (in seconds)
time
(a[, b])Convert a quarter-note beat or a location (measure, beat) to an absolute time in secs
timeDelta
(start, end)Returns the elapsed time between two beats or score locations.
timeToBeat
(t)Convert a time to a quarternote offset according to this ScoreStruct
timeToLocation
(time)Find the location in score corresponding to the given time in seconds
write
(path[, backend, renderoptions])Export this score structure
Methods Documentation
- addMeasure(timesig=None, quarterTempo=None, annotation='', numMeasures=1, rehearsalMark=None, keySignature=None, barline='', **kws)[source]¶
Add a measure definition to this score structure
- Parameters:
timesig (
Union
[tuple
[int
,int
],str
,TimeSignature
,None
]) – the time signature of the new measure. If not given, the last time signature will be used. The timesig can be given as str in the form “num/den”. For a compound time signature use “3/8+2/8”. To specify the internal subdivision use a TimeSignature object or a string in the form “5/8(3-2)”quarterTempo (
Union
[float
,Rational
,Fraction
,None
]) – the tempo of a quarter note. If not given, the last tempo will be usedannotation – each measure can have a text annotation
numMeasures – if this is > 1, multiple measures of the same kind can be added
rehearsalMark (
Union
[str
,RehearsalMark
,None
]) – if given, add a rehearsal mark to the new measure definition. A rehearsal mark can be a text or a RehearsalMark, which enables you to customize the rehearsal mark furtherkeySignature (
Union
[tuple
[int
,str
],KeySignature
,None
]) – either a KeySignature object or a tuple (fifths, mode); for example for A-Major,(3, 'major')
. Mode can also be left as an ampty stringbarline – if needed, the right barline of the measure can be set to one of ‘single’, ‘final’, ‘double’, ‘solid’, ‘dotted’, ‘dashed’, ‘tick’, ‘short’, ‘double-thin’ or ‘none’
**kws – any extra keyword argument will be saved as a property of the MeasureDef
- Return type:
None
Example:
# Create a 4/4 score, 32 measures long >>> s = ScoreStruct() >>> s.addMeasure((4, 4), 52, numMeasures=32)
- addRehearsalMark(idx, mark, box='square')[source]¶
Add a rehearsal mark to this scorestruct
The measure definition for the given index must already exist or the score must be set to autoextend
- Parameters:
idx (
int
) – the measure indexmark (
RehearsalMark
|str
) – the rehearsal mark, as text or as a RehearsalMarkbox (
str
) – one of ‘square’, ‘circle’ or ‘’ to avoid drawing a box around the rehearsal mark
- Return type:
None
- asBeat(location)[source]¶
Given a beat or a location (measureidx, relativeoffset), returns an absolute beat
- Parameters:
location (
Union
[float
,Rational
,Fraction
,tuple
[int
,Fraction
]]) – the location- Return type:
Fraction
- Returns:
the absolute beat in quarter notes
- asText()[source]¶
This ScoreStruct as parsable text format
- Return type:
str
- Returns:
this score as text
- beat(a, b=None)[source]¶
Convert a time in secs or a location (measure, beat) to a quarter-note beat
- Parameters:
a (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the time/location to convert. Either a timeb (
Union
[float
,Rational
,Fraction
,None
]) – when passign a location, the beat within the measure (a
contains the measure index)
- Return type:
Fraction
- Returns:
the corresponding quarter note beat according to this ScoreStruct
Example
>>> sco = ScoreStruct.fromTimesig('3/4', 120) # Convert time to beat >>> sco.beat(0.5) 1.0 # Convert score location (measure 1, beat 2) to beats >>> sco.beat((1, 2)) 5.0 # Also supported, similar to the previous operation: >>> sco.beat(1, 2) 5.0
See also
time()
- beatDelta(start, end)[source]¶
Difference in beats between the two score locations or two times
- Parameters:
start (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the start moment as a location (a tuple (measureIndex, beatOffset) or as a timeend (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the end location, a tuple (measureIndex, beatOffset)
- Return type:
Fraction
- Returns:
the distance between the two locations, in beats
Example
>>> from maelzel.scorestruct import ScoreStruct >>> s = ScoreStruct('4/4, 120; 3/4; 3/8; 5/8') # delta, in quarternotes, between time=2secs and location (2, 0) >>> s.beatDelta(2., (2, 0)) 5
See also
- beatToLocation(beat)[source]¶
Return the location in score corresponding to the given beat
The beat is the time-offset in quarter-notes. Given a beat (in quarter-notes), return the score location (measure, beat offset within the measure). Tempo does not play any role within this calculation.
- Return type:
tuple
[int
,Fraction
]- Returns:
a tuple (measure index, beat). Raises ValueError if beat is not defined within this score
Note
In the special case where a ScoreStruct is not endless and the beat is exactly at the end of the last measure, we return
(numMeasures, 0)
See also
locationToBeat()
, which performs the opposite operationExample
Given the following score: 4/4, 3/4, 4/4
input
output
4
(1, 0)
5.5
(1, 1.5)
8
(2, 1.0)
- beatToTime(beat)[source]¶
Convert beat-time to real-time
- Parameters:
beat (
Union
[float
,Rational
,Fraction
]) – the quarter-note beat- Return type:
Fraction
- Returns:
the corresponding time
Example
>>> from maelzel.scorestruct import ScoreStruct >>> sco = ScoreStruct.fromTimesig('4/4', quarterTempo=120) >>> sco.beatToTime(2) 1.0 >>> sco.timeToBeat(2) 4.0
See also
- durationQuarters()[source]¶
The duration of this score, in quarternotes
Raises ValueError if this score is endless
- Return type:
Fraction
- durationSecs()[source]¶
The duration of this score, in seconds
Raises ValueError if this score is endless
- Return type:
Fraction
- ensureDurationInMeasures(numMeasures)[source]¶
Extends this score to have at least the given number of measures
If the scorestruct already has reached the given length this operation does nothing
- Parameters:
numMeasures (
int
) – the minimum number of measures this score should have- Return type:
None
- ensureDurationInSeconds(duration)[source]¶
Ensure that this scorestruct is long enough to include the given time
This is of relevance in certain edge cases including endless scorestructs:
When creating a clicktrack from an endless score.
When exporting a scorestruct to midi
- Parameters:
duration (
Fraction
) – the duration in seconds to ensure- Return type:
None
- exportMidiClickTrack(midifile)[source]¶
Generate a MIDI click track from this ScoreStruct
- Parameters:
midifile (
str
) – the path of the MIDI file to generate- Return type:
None
See also
maelzel.core.clicktrack.makeClickTrack()
- getMeasureDef(idx, extend=None)[source]¶
Returns the MeasureDef at the given index.
- Parameters:
idx (
int
) – the measure index (measures start at 0)extend (
Optional
[bool
]) – if True and the index given is outside the defined measures, the score will be extended, repeating the last defined measure. For endless scores, the default is to extend the measure definitions.
- Return type:
If the scorestruct is endless and the index is outside the defined range, the returned MeasureDef will be a copy of the last defined MeasureDef.
The same result can be achieved via
__getitem__
Example
>>> from maelzel.scorestruct import ScoreStruct >>> s = ScoreStruct(r''' ... 4/4, 50 ... 3/4 ... 5/4, 72 ... 6/8 ... ''') >>> s.getMeasureDef(2) MeasureDef(timesig=(5, 4), quarterTempo=72, annotation='', timesigInherited=False, tempoInherited=True, barline='', subdivisionStructure=None) >>> s[2] MeasureDef(timesig=(5, 4), quarterTempo=72, annotation='', timesigInherited=False, tempoInherited=True, barline='', subdivisionStructure=None)
- hasUniqueTimesig()[source]¶
Returns True if this ScoreStruct does not have any time-signature change
- Return type:
bool
- iterMeasureDefs()[source]¶
Iterate over all measure definitions in this ScoreStruct.
If it is marked as
endless
, then the last defined measure will be returned indefinitely.- Return type:
Iterator
[MeasureDef
]
- locationToBeat(measure, beat=Fraction(0, 1))[source]¶
Returns the number of quarter notes up to the given location
This value is independent of any tempo given.
- Parameters:
measure (
int
) – the measure number (measures start at 0)beat (
Union
[float
,Rational
,Fraction
]) – the beat within the given measure (beat 0 = start of the measure), in quarter notes.
- Return type:
Fraction
- Returns:
the location translated to quarter notes.
Example
>>> s = ScoreStruct(r''' ... 3/4, 120 ... 3/8 ... 4/4 ... ''') >>> s.locationToBeat(1, 0.5) 3.5 >>> s.locationToTime(1, 0.5) 1.75
- locationToTime(measure, beat=Fraction(0, 1))[source]¶
Return the elapsed time at the given score location
- Parameters:
measure (
int
) – the measure number (starting with 0)beat (
Union
[float
,Rational
,Fraction
]) – the beat within the measure
- Return type:
Fraction
- Returns:
a time in seconds (as a Fraction to avoid rounding problems)
- ltob(measure, beat)[source]¶
A shortcut to locationToBeat
- Parameters:
measure (
int
) – the measure index (measures start at 0beat (
Union
[float
,Rational
,Fraction
]) – the beat within the given measure
- Return type:
Fraction
- Returns:
the corresponding beat in quarter notes
- makeClickTrack(minMeasures=0, clickdur=None, strongBeatPitch='5C', weakBeatPitch='5G', playTransposition=24)[source]¶
Create a click track from this ScoreStruct
The returned score can be displayed as notation via
maelzel.core.Score.show()
or exported as pdf or midi.This is a shortcut to
maelzel.core.tools.makeClickTrack()
. Use that for more customization optionsNote
The duration of the playback can be set individually from the duration of the displayed pitch
- Parameters:
clickdur (
Optional
[Fraction
]) – the length of each tick. Use None to use the duration of the beat.strongBeatPitch – the pitch used as a strong beat (at the beginning of each measure)
weakBeatPitch – the pitch used as a weak beat
playTransposition – the transposition interval between notated pitch and playback pitch
- Return type:
- Returns:
a maelzel.core.Score
Example
>>> from maelzel.core import * >>> scorestruct = ScoreStruct(r"4/4,72; .; 5/8; 3/8; 2/4,96; .; 5/4; 3/4") >>> clicktrack = scorestruct.makeClickTrack() >>> clicktrack.write('click.pdf') >>> clicktrack.play()
- measureOffsets(startIndex=0, stopIndex=0)[source]¶
Returns a list with the time offsets of each measure
- Parameters:
startIndex – the measure index to start with. 0=last measure definition
stopIndex – the measure index to end with (not included)
- Return type:
list
[Fraction
]- Returns:
a list of time offsets (start times), one for each measure in the interval selected
- measuresBetween(start, end)[source]¶
List of measures defined between the given times as beats
- Parameters:
start (
Fraction
) – start beat in quarter-tonesend (
Fraction
) – end beat in quarter-tones
- Return type:
list
[MeasureDef
]
Returns:
- modified()[source]¶
mark this ScoreStruct as modified
- Return type:
None
Example
>>> from maelzel.scorestruct import ScoreStruct >>> s = ScoreStruct(r''' ... 4/4, 60 ... 3/4 ... 4/4 ... . ... . ... 5/8 ... ''') >>> measure = s.getMeasureDef(3) >>> measure.timesig = 6/8 >>> s.modified()
- numMeasures()[source]¶
Returns the number of measures in this score structure
If self is endless, it returns the number of defined measures
- Return type:
int
Example
We create an endless structure (which is the default) where the last defined measure is at index 9. The number of measures is 10
>>> from maelzel.scorestruct import * >>> struct = ScoreStruct(r''' ... 4/4 ... . ... 3/4 ... 6, 4/4 ... 9, 3/4 ''') >>> struct.numMeasures() 10
- remapFrom(sourcestruct, location)[source]¶
Remap a beat from sourcestruct to this this struct
- Parameters:
location (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the beat offset in quarternotes or a location (measureindex, offset)sourcestruct (
ScoreStruct
) – the source score structure
- Return type:
Fraction
- Returns:
the beat within this struct which keeps the same absolute time as the given beat within sourcestruct
- remapSpan(sourcestruct, offset, duration)[source]¶
Remap a time span from a source score structure to this score structure
- Parameters:
sourcestruct (
ScoreStruct
) – the source score strcutureoffset (
Union
[float
,Rational
,Fraction
]) – the offsetduration (
Union
[float
,Rational
,Fraction
]) – the duration
- Return type:
tuple
[Fraction
,Fraction
]- Returns:
a tuple(offset, dur) where these represent the start and duration within this scorestruct which coincide in absolute time with the offset and duration given
- remapTo(deststruct, location)[source]¶
Remap a beat from this struct to another struct
- Parameters:
location (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the beat offset in quarternotes or a location (measureindex, offset)deststruct (
ScoreStruct
) – the destination scores structure
- Return type:
Fraction
- Returns:
the beat within deststruct which keeps the same absolute time
- setBarline(measureIndex, linetype)[source]¶
Set the right barline type
- Parameters:
measureIndex (
int
) – the measure index to modifylinetype (
str
) – one of ‘single’, ‘double’, ‘final’, ‘solid’, ‘dashed’
- Return type:
None
- setEnd(numMeasures)[source]¶
Set an end measure to this ScoreStruct, in place
If the scorestruct has less defined measures as requested, then it is extended by duplicating the last defined measure as needed. Otherwise, the scorestruct is cropped. The scorestruct ceases to be endless if that was the case previously
- Parameters:
numMeasures (
int
) – the requested number of measures after the operation- Return type:
None
- setTempo(tempo, reference=1, measureIndex=0)[source]¶
Set the tempo of the given measure, until the next tempo change
- Parameters:
tempo (
float
) – the new temporeference – the reference duration (1=quarternote, 2=halfnote, 0.5: 8th note, etc)
measureIndex (
int
) – the first measure to modify
- Return type:
None
- show(fmt='png', app='', scalefactor=1.0, backend=None, renderoptions=None)[source]¶
Render and show this ScoreStruct
- Parameters:
fmt – the format to render to, one of ‘png’ or ‘pdf’
app (
str
) – if given, the app used to open the produced documentscalefactor (
float
) – if given, a scale factor to enlarge or reduce the prduce imagebackend (
Optional
[str
]) – the backend used (None to use a sensible default). If given, one of ‘lilypond’ or ‘musicxml’renderoptions (
Optional
[RenderOptions
]) – if given, these options will be used for rendering this score structure as image.
- Return type:
None
Example
>>> from maelzel.scorestruct import ScoreStruct >>> sco = ScoreStruct(r''' ... ... ... ''') >>> from maelzel.scoring.render import RenderOptions
- tempoAtTime(time)[source]¶
Returns the tempo active at the given time (in seconds)
- Parameters:
time (
Union
[float
,Rational
,Fraction
]) – point in the timeline (in seconds)- Return type:
Fraction
- Returns:
the quarternote-tempo at the given time
- time(a, b=None)[source]¶
Convert a quarter-note beat or a location (measure, beat) to an absolute time in secs
- Parameters:
a (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the beat/location to convert. Either a beat, a tuple (measureindex, beat) or the measureindex itself, in which caseb
is also neededb (
Union
[float
,Rational
,Fraction
,None
]) – if given, thena
is the measureindex andb
is the beat
- Return type:
Fraction
- Returns:
the corresponding time according to this ScoreStruct
Example
>>> sco = ScoreStruct.fromTimesig('3/4', 120) # Convert time to beat >>> sco.time(1) 0.5 # Convert score location (measure 1, beat 2) to beats >>> sco.time((1, 2)) 2.5
See also
beat()
- timeDelta(start, end)[source]¶
Returns the elapsed time between two beats or score locations.
- Parameters:
start (beat_t) – the start location, as a beat or as a tuple (measureIndex, beatOffset)
end (beat_t) – the end location, as a beat or as a tuple (measureIndex, beatOffset)
- Return type:
F
- Returns:
the elapsed time, as a Fraction
Example
>>> from maelzel.scorestruct import ScoreStruct >>> s = ScoreStruct('4/4,60; 3/4; 3/8') >>> s.timeDelta((0, 0.5), (2, 0.5)) 7 >>> s.timeDelta(3, (1, 2)) 3
See also
- timeToBeat(t)[source]¶
Convert a time to a quarternote offset according to this ScoreStruct
- Parameters:
t (
Union
[float
,Rational
,Fraction
]) – the time (in absolute seconds)- Return type:
Fraction
- Returns:
A quarternote offset
will raise ValueError if the given time is outside this score structure
Example
>>> from maelzel.scorestruct import ScoreStruct >>> sco = ScoreStruct.fromTimesig('4/4', quarterTempo=120) >>> sco.beatToTime(2) 1.0 >>> sco.timeToBeat(2) 4.0
See also
- timeToLocation(time)[source]¶
Find the location in score corresponding to the given time in seconds
- Parameters:
time (
Union
[float
,Rational
,Fraction
]) – the time in seconds- Return type:
tuple
[int
|None
,Fraction
]- Returns:
a tuple (measureindex, measurebeat) where measureindex can be None if the score is not endless and time is outside the score
See also
- write(path, backend=None, renderoptions=None)[source]¶
Export this score structure
Write this as musicxml (.xml), lilypond (.ly), MIDI (.mid) or render as pdf or png. The format is determined by the extension of the file. It is also possible to write the score as text (in its own format) in order to load it later (.txt)
Note
when saving as MIDI, notes are used to fill each beat because an empty MIDI score is not supported by the MIDI standard
- Parameters:
path (
str
|Path
) – the path of the written filebackend (
Optional
[str
]) – for pdf or png only - the backend to use for rendering, one of ‘lilypond’ or ‘musicxml’renderoptions (
Optional
[RenderOptions
]) – if given, they will be used to customize the rendering process.
- Return type:
None