Chain¶
- class maelzel.core.chain.Chain(items=None, offset=None, label='', properties=None, parent=None, _init=True)[source]¶
Bases:
MContainer
A Chain is a sequence of Notes, Chords or other Chains
- Parameters:
items (
Union
[Sequence
[MEvent
|Chain
|str
],str
,None
]) – the items of this Chain. The start time of any object, if given, is interpreted as relative to the start of the chain.offset (
Union
[float
,Rational
,Fraction
,None
]) – offset of the chain itself relative to its parentlabel (
str
) – a label for this chainproperties (
Optional
[dict
[str
,Any
]]) – any properties for this chain. Properties can be anything, they are a way for the user to attach data to an object
Attributes Summary
The duration of this sequence
The end time of this object.
The items in this chain, a list of events of other chains
a label can be used to identify an object within a group of objects
Optional offset, in quarternotes.
The parent of this object.
playargs are set via
setPlay()
and are used to customize playback (instr, gain, …).User-defined properties as a dict (None by default).
A list of all symbols added via
addSymbol()
(None by default)Methods Summary
Returns the absolute offset of this object in quarternotes
absorbInitialOffset
([removeRedundantOffsets])Moves the offset of the first event to the offset of the chain itself
addSpanner
(spanner[, endobj])Adds a spanner symbol across this object
addSymbol
(*args, **kws)- rtype:
Self
addSymbolAt
(location, symbol)Adds a symbol at the given location
addText
(text[, placement, italic, weight, ...])Add a text annotation to this object
append
(item)Append an item to this chain
asVoice
([removeOffsets])Create a Voice as a copy of this Chain
automate
(param, breakpoints[, relative, ...])- rtype:
None
beamBreak
(location)Add a 'soft' beam break at the given location
childOffset
(child)Returns the offset of child within this chain
clone
([items, offset, label, properties])Clone this object, changing parameters if needed
copy
()Returns a copy of this object
cropped
(start, end)Returns a copy of this chain, cropped to the given beat range
cycle
(totaldur[, crop])Cycle over the items of self for the given total duration
dump
([indents, forcetext])Dump this chain, recursively
durSecs
()Returns the duration in seconds according to the active score
eventAt
(location[, margin, split])The event present at the given location
events
([instr, delay, args, gain, chan, ...])Returns the SynthEvents needed to play this object
eventsBetween
(start, end[, partial])Events between the given time range
eventsWithOffset
([start, end, partial])Recurse the events in self and resolves each event's offset
extend
(items)Extend this chain with items
fillGaps
([recurse])Fill any gaps with rests, inplace
The first event in this chain, recursively
Returns the offset (relative to the start of this chain) of the first event in this chain
flat
([forcecopy])A flat version of this Chain
A list of flat events, with explicit absolute offsets set
getPlay
(key[, default, recursive])Get a playback attribute previously set via
MObj.setPlay()
getProperty
(key[, default])Get a property of this objects
getSymbol
(classname)Get a symbol of a given class, if present
True if self has an explicit offset and all items as well (recursively)
invertPitch
(pivot)Invert the pitch of this object
isFlat
()Is self flat?
isRest
()Is this object a Rest?
itemsBetween
(start, end[, partial])Items between the given time range
Iterate over the items of this chain with their absolute offset
Iterate over the items of this chain with their relative offset
The last event in this chain, recursively
matchOrfanSpanners
([removeUnmatched])Match unmatched spanners
The mean pitch of this object
Merge tied events inplace
nextEvent
(event)Returns the next event after event
nextItem
(item)Returns the next item after item
The absolute offset of the parent
The pitch range of this object, if applicable
pitchTransform
(pitchmap)Apply a pitch-transform to this object, returns a copy
play
([instr, delay, args, gain, chan, ...])Plays this object.
plot
(**kws)- rtype:
Axes
previousEvent
(event)Returns the event before the given event
previousItem
(item)Returns the item (an event or a chain) previous to the given one
quantizePitch
([step])Returns a new object, with pitch rounded to step
quantizedScore
([scorestruct, config, ...])Returns a QuantizedScore representing this object
rec
([outfile, sr, verbose, wait, nchnls, ...])Record the output of .play as a soundfile
recurse
([reverse])Yields all events (Notes/Chords) in this chain, recursively
Resolve the offset of this object, relative to its parent
remap
(deststruct[, sourcestruct])Remap times (offset, dur) from source scorestruct to destination scorestruct
Remove over-specified start times in this Chain (in place)
render
([backend, renderoptions, ...])Renders this object as notation
Returns the resolved end of this object, relative to its parent
scorestruct
([resolve])Returns the ScoreStruct active for this obj or its parent (recursively)
scoringEvents
([groupid, config, parentOffset])Returns the scoring events corresponding to this object.
scoringParts
([config])Returns this object as a list of scoring UnquantizedParts.
setPlay
(**kws)Set any playback attributes, returns self
setProperty
(key, value)Set a property, returns self
show
([fmt, external, backend, scorestruct, ...])Show this as notation.
splitAt
(location[, tie, beambreak, nomerge])Split any event present at the given absolute offset (in place)
splitEventsAtMeasures
([scorestruct, ...])Splits items in self at measure offsets, inplace (recursively)
splitEventsAtOffsets
(offsets[, tie, nomerge])Splits items in self at the given offsets, inplace (recursively)
stack
()Stack events to the left INPLACE, making offsets explicit
timeRangeSecs
([parentOffset, scorestruct])The absolute time range, in seconds
timeScale
(factor[, offset])Create a copy with modified timing by applying a linear transformation
timeShift
(timeoffset)Return a copy of this object with an added offset
timeShiftInPlace
(timeoffset)Shift the time of this by the given offset (inplace)
timeTransform
(timemap[, inplace])Apply a time-transform to this object
transpose
(interval)Transpose this object by the given interval
transposeByRatio
(ratio)Transpose this by a given frequency ratio, if applicable
unquantizedScore
([title])Create a maelzel.scoring.UnquantizedScore from this object
withExplicitOffset
([forcecopy])Copy of self with explicit offset
write
(outfile[, backend, resolution])Export to multiple formats
Attributes Documentation
- dur¶
The duration of this sequence
- items: list[MEvent | Chain]¶
The items in this chain, a list of events of other chains
- label: str¶
a label can be used to identify an object within a group of objects
- offset: F | None¶
Optional offset, in quarternotes. Specifies the start time relative to its parent
It can be None, which indicates that within a container this object would start after the previous object. For an object without a parent, the offset is an absolute offset.
- parent¶
The parent of this object.
This attribute is set by the parent when an object is added to it. For example, when adding a Note to a Chain, the Chain is set as the parent of the Note. This enables the Note to query information about the parent, like its absolute position or if a score structure has been set upstream
- playargs: PlayArgs | None¶
playargs are set via
setPlay()
and are used to customize playback (instr, gain, …). None by default
- properties: dict[str, Any] | None¶
User-defined properties as a dict (None by default). Set them via
setProperty()
- symbols: list[_symbols.Symbol] | None¶
A list of all symbols added via
addSymbol()
(None by default)
Methods Documentation
- absOffset()¶
Returns the absolute offset of this object in quarternotes
If this object is embedded (has a parent) in a container, its absolute offset depends on the offset of its parent, recursively. If the object has no parent then the absolute offset is just the resolved offset
- Return type:
Fraction
- Returns:
the absolute start position of this object
- absorbInitialOffset(removeRedundantOffsets=True)[source]¶
Moves the offset of the first event to the offset of the chain itself
- Parameters:
removeRedundantOffsets – remove redundant offsets.
Example
Notice how the offset of the first note is now None and the chain itself has an offset of 0.5
>>> ch = Chain([ ... "4C:1:offset=0.5", ... "4E:1", ... "4G:1" ... ]) >>> ch.dump() Chain - beat: 0, offset: None, dur: 3.5 location beat offset dur name 0:0.5 0.5 0.5 1 4C 0:1.5 1.5 (1.5) 1 4E 0:2.5 2.5 (2.5) 1 4G >>> ch._absorbInternalOffset() >>> ch.dump() Chain - beat: 1/2, offset: 0.5, dur: 3 location beat offset dur name 0:0.5 0.5 (0) 1 4C 0:1.5 1.5 (1) 1 4E 0:2.5 2.5 (2) 1 4G
- addSpanner(spanner, endobj=None)[source]¶
Adds a spanner symbol across this object
A spanner is a slur, line or any other symbol attached to two or more objects. A spanner always has a start and an end.
- Parameters:
spanner (
str
|Spanner
) – a Spanner object or a spanner description (one of ‘slur’, ‘<’, ‘>’, ‘trill’, ‘bracket’, etc. - seemaelzel.core.symbols.makeSpanner()
When passing a string description, prepend it with ‘~’ to create an end spannerendobj (
Optional
[MEvent
]) – the object where this spanner ends. If not given, the last event of this chain
- Return type:
Self
- Returns:
self (allows to chain calls)
Example
>>> chain = Chain([ ... Note("4C", 1), ... Note("4D", 0.5), ... Note("4E") # This ends the hairpin spanner ... ]) >>> chain.addSpanner('slur')
This is the same as:
>>> chain[0].addSpanner('slur', chain[-1])
- addSymbol(*args, **kws)¶
- Return type:
Self
- addSymbolAt(location, symbol)[source]¶
Adds a symbol at the given location
If there is no event starting at the given location, the quantized part is split at the location when rendering and the symbol is added to the event. This allows to add ‘soft’ symbols at any location without the need to modify the events themselves. If there actually is an event starting at the given offset, the symbol is added to the event directly.
- Parameters:
location (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the location to add the symbol atsymbol (
Symbol
) – the symbol to add
- Return type:
Self
- Returns:
self
Example
>>> chain = Chain([ ... Note("4C", 2), ... Note("4E", 1) ]) >>> chain.addSymbolAt(1, symbols.Fermata())
See also
- addText(text, placement='above', italic=False, weight='normal', fontsize=None, fontfamily='', box='')¶
Add a text annotation to this object
This is a shortcut to
self.addSymbol(symbols.Text(...))
. Use that for in-depth customization.- Parameters:
text (
str
) – the text annotationplacement – where to place the annotation (‘above’, ‘below’)
italic – if True, use italic as font style
weight – ‘normal’ or ‘bold’
fontsize (
Optional
[int
]) – the size of the annotationfontfamily – the font family to use. It is probably best to leave this unset
box – the enclosure shape, or ‘’ for no box around the text. Possible shapes are ‘square’, ‘circle’, ‘rounded’
- Return type:
Self
- Returns:
self
- append(item)[source]¶
Append an item to this chain
- Parameters:
item (
MEvent
) – the item to add- Return type:
None
- asVoice(removeOffsets=True)[source]¶
Create a Voice as a copy of this Chain
- Parameters:
removeOffsets – if True, remove any redundant offsets in the returned voice
- Return type:
- beamBreak(location)[source]¶
Add a ‘soft’ beam break at the given location
A soft beam break does not modify the actual events in this Chain/Voice. It adds a beam break to the quantized score when rendering. Any syncopation at the given location will be broken for rendering but stays unmodified as an event. This is similar to performing:
>>> chain.splitAt(location).addSymbol(symbols.BeamBreak())
But the Chain/Voice itself remains unmodified: the operation is only performed at the quantized score
- Parameters:
location (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the location to add a beam break to- Return type:
Self
- Returns:
self
See also
- childOffset(child)[source]¶
Returns the offset of child within this chain
raises ValueError if self is not a parent of child
- Parameters:
child (
MObj
) – the object whose offset is to be determined- Return type:
Fraction
- Returns:
The offset of this child within this chain
- clone(items=None, offset=UNSET, label=None, properties=None)[source]¶
Clone this object, changing parameters if needed
- Parameters:
**kws – any keywords passed to the constructor
- Return type:
- Returns:
a clone of this object, with the given arguments changed
Example:
>>> from maelzel.core import * >>> a = Note("C4+", dur=1) >>> b = a.clone(dur=0.5)
- cropped(start, end)[source]¶
Returns a copy of this chain, cropped to the given beat range
Returns None if there are no events in this chain within the given time range
- Parameters:
start (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – start of the beat rangeend (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – end of the beat range
- Return type:
Optional
[Self
]- Returns:
a Chain cropped at the given beat range
- cycle(totaldur, crop=False)[source]¶
Cycle over the items of self for the given total duration
- Parameters:
totaldur (
Fraction
) – the total duration of the resulting sequencecrop – if True, crop last item if it exceeds the given total duration
- Return type:
Self
- Returns:
a copy of self representing cycles of its items
- dump(indents=0, forcetext=False)[source]¶
Dump this chain, recursively
Values inside parenthesis are implicit. For example if an object inside this chain does not have an explicit .offset, its withExplicitTimes offset will be shown within parenthesis
- Parameters:
indents – the number of indents to use
forcetext – if True, force print output instea of html, even when running inside jupyter
- Return type:
None
- durSecs()¶
Returns the duration in seconds according to the active score
- Return type:
Fraction
- Returns:
the duration of self in seconds
- eventAt(location, margin=Fraction(1, 8), split=False)[source]¶
The event present at the given location
- Parameters:
location (
Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the beat or a tuple (measureindex, beatoffset). If a beat is given, it is interpreted as an absoute offsetmargin – a time margin (in quarternotes) from the given location. This can help in corner cases
split – if True split the event at the given offset. This will modify the event itself, which will remain split after this call.
- Return type:
MEvent
|None
- Returns:
the event present at the given location, or None if no event was found. An explicit rest will be returned if found but empty space will return None
- events(instr=None, delay=None, args=None, gain=None, chan=None, pitchinterpol=None, fade=None, fadeshape=None, position=None, skip=None, end=None, sustain=None, workspace=None, transpose=0.0, **kwargs)¶
Returns the SynthEvents needed to play this object
All these attributes here can be set previously via
playargs
(or usingsetPlay()
)- Parameters:
gain (
Optional
[float
]) – modifies the own amplitude for playback/recording (0-1)delay (
Optional
[float
]) – delay in seconds, added to the start of the object As opposed to the .offset attribute of each object, which is defined in quarternotes, the delay is always in secondsinstr (
Optional
[str
]) – which instrument to use (see defPreset, definedPresets). Use “?” to select from a list of defined presets.chan (
Optional
[int
]) – the channel to output to. Channels start at 1pitchinterpol (
Optional
[str
]) – ‘linear’, ‘cos’, ‘freqlinear’, ‘freqcos’fade (
Union
[float
,tuple
[float
,float
],None
]) – fade duration in seconds, can be a tuple (fadein, fadeout)fadeshape (
Optional
[str
]) – ‘linear’ | ‘cos’args (
Optional
[dict
[str
,float
]]) – named arguments passed to the note. A dict{paramName: value}
position (
Optional
[float
]) – the panning position (0=left, 1=right)skip (
Optional
[float
]) – start playback at the given offset (in quarternotes), relative to the start of the object. Allows to play a fragment of the object (NB: this trims the playback of the object. Usedelay
to offset the playback in time while keeping the playback time unmodified)end (
Optional
[float
]) – end time of playback, in quarternotes. Allows to play a fragment of the object by trimming the end of the playbacksustain (
Optional
[float
]) – a time added to the playback events to facilitate overlapping/legato between notes, or to allow one-shot samples to play completely without being cropped.workspace (
Optional
[Workspace
]) – a Workspace. If given, overrides the current workspace. It’s scorestruct is used to determine the mapping between beat-time and real-time.transpose (
float
) – an interval to transpose any pitch
- Return type:
list
[SynthEvent
]- Returns:
A list of SynthEvents (see
SynthEvent
)
Example
>>> from maelzel.core import * >>> n = Note(60, dur=1).setPlay(instr='piano') >>> n.events(gain=0.5) [SynthEvent(delay=0.000, gain=0.5, chan=1, fade=(0.02, 0.02), instr=piano) bps 0.000s: 60, 1.000000 1.000s: 60, 1.000000] >>> play(n.events(chan=2))
- eventsBetween(start, end, partial=True)[source]¶
Events between the given time range
If
partial
is false, only events which lie completey within the given range are included. Gracenotes at the edges are always included. The returned events are the actual events in this Chain or subchains: they are NOT copies.- Parameters:
start (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – absolute start location (a beat or a score location)end (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – absolute end location (a beat or score location)partial – include also events wich are partially included within the given time range
- Return type:
list
[MEvent
]- Returns:
a list of the events within the given time range
See also
- eventsWithOffset(start=None, end=None, partial=True)[source]¶
Recurse the events in self and resolves each event’s offset
- Parameters:
start (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]],None
]) – absolute start beat/location. Filters the returned event pairs to events within this time rangeend (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]],None
]) – absolute end beat/location. Filters the returned event pairs to events within the given rangepartial – only used if either start or end are given, this controls how events are matched. If True, events only need to be defined within the time range. Otherwise, events need to be fully included within the time range
- Return type:
list
[tuple
[MEvent
,Fraction
]]- Returns:
- a list of pairs, where each pair has the form (event, offset), the offset being
the absolute offset of the event. Event themselves are not modified
Example
>>> from maelzel.core import * >>> chain = Chain([ ... "4C:0.5", ... "4D", ... Chain(["4E:0.5"], offset=2) ... ], offset=1)
- extend(items)[source]¶
Extend this chain with items
- Parameters:
items (
list
[MEvent
]) – a list of items to append to this chain- Return type:
None
Note
Items passed are marked as children of this chain (their .parent attribute is modified)
- fillGaps(recurse=True)[source]¶
Fill any gaps with rests, inplace
A gap is produced when an event within a chain has an explicit offset later than the offset calculated by stacking the previous objects in terms of their duration
- Parameters:
recurse – if True, fill gaps within subchains
- Return type:
None
- firstOffset()[source]¶
Returns the offset (relative to the start of this chain) of the first event in this chain
- Return type:
Fraction
|None
- flat(forcecopy=False)[source]¶
A flat version of this Chain
A Chain can contain other Chains. This method flattens all objects inside this Chain and any sub-chains to a flat chain of events (notes/chords/clips).
If this Chain is already flat (it does not contain any Chains), self is returned unmodified (unless forcecopy=True).
Note
All items in the returned Chain will have an explicit
.offset
attribute. To remove any redundant .offset callChain.removeRedundantOffsets()
- Parameters:
forcecopy – all items in the returned Chain are a copy of self, even if self is already flat
- Return type:
Self
- Returns:
a flat chain
See also
- flatEvents()[source]¶
A list of flat events, with explicit absolute offsets set
The returned events are a clone of the events in this chain, not the actual events themselves
- Return type:
list
[MEvent
]- Returns:
a list of events (Notes, Chords, Clips, …) with explicit offset
- getPlay(key, default=None, recursive=True)¶
Get a playback attribute previously set via
MObj.setPlay()
- Parameters:
key (
str
) – the key (see setPlay for possible keys)default – the value to return if the given key has not been set
recursive – if True, search the given attribute up the parent chain
- Returns:
either the value previously set, or default otherwise.
- getProperty(key, default=None)¶
Get a property of this objects
Any MObj can have multiple properties. A property is a key:value pair, where the key is a string and the value can be anything. Properties can be used to attach information to an object, to tag it in any way needed.
Properties are set via
MObj.setProperty()
. TheMObj.properties
attribute can be queries directly, but bear in mind that if no properties have been set, this attribute is ``None`` by default.- Parameters:
key (
str
) – the property to querydefault – returned value if the property has not been set
- Returns:
the value of the property, or the default value
See also
setProperty()
,properties
- getSymbol(classname)¶
Get a symbol of a given class, if present
This is only supported for symbol classes which are exclusive (notehead, color, ornament, etc.). For symbols like ‘articulation’, which can be present multiple times, query the symbols attribute directly (NB: symbols might be
None
if no symbols have been set):if note.symbols: articulations = [s for s in note.symbols if s.name == 'articulation']
- Parameters:
classname (
str
) – the class of the symbol. Possible values are ‘articulation’, ‘text’, ‘notehead’, ‘color’, ‘ornament’, ‘fermata’, ‘notatedpitch’. See XXX (TODO) for a complete list- Return type:
Symbol
|None
- Returns:
a symbol of the given class, or None
- hasOffsets()[source]¶
True if self has an explicit offset and all items as well (recursively)
- Return type:
bool
- Returns:
True if all items in self have explicit offsets
- invertPitch(pivot)¶
Invert the pitch of this object
- Parameters:
pivot (
Union
[int
,float
,str
]) – the point around which to invert pitches- Return type:
Self
- Returns:
the inverted object
>>> from maelzel.core import * >>> series = Chain("4Bb 4E 4F# 4Eb 4F 4A 5D 5C# 4G 4G# 4B 5C".split()) >>> inverted = series.invertPitch("4F#") >>> print(" ".join(_.name.ljust(4) for _ in series)) ... print(" ".join(_.name.ljust(4) for _ in inverted)) 4A# 4E 4F# 4D# 4F 4A 5D 5C# 4G 4G# 4B 5C 4D 4G# 4F# 4A 4G 4D# 3A# 3B 4F 4E 4C# 4C >>> Score([series, inverted])
- isFlat()[source]¶
Is self flat?
A flat chain/voice contains only events, not other containers
- Return type:
bool
- isRest()¶
Is this object a Rest?
Rests are used as separators between objects inside an Chain or a Track
- Return type:
bool
- itemsBetween(start, end, partial=True)[source]¶
Items between the given time range
An item is either an event (Note, Chord, Clip, etc.) or another Chain.
If
partial
is false, only items which lie completey within the given range are included. Gracenotes at the edges are always included- Parameters:
start (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – absolute start location (a beat or a score location)end (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – absolute end location (a beat or score location)partial – include also events wich are partially included within the given time range
- Return type:
- Returns:
a list of the items within the given time range
See also
- itemsWithOffset()[source]¶
Iterate over the items of this chain with their absolute offset
- Returns:
an iterator over tuple[item, offset], where an item can be an event or a Chain, and offset is the absolute offset
See also
- itemsWithRelativeOffset()[source]¶
Iterate over the items of this chain with their relative offset
- Return type:
- Returns:
an iterator over tuple[item, offset], where an item can be an event or a Chain, and offset is the offset relative to this chain
See also
- matchOrfanSpanners(removeUnmatched=False)[source]¶
Match unmatched spanners
When adding spanners to objects, it is possible to create a spanner without a partner spanner. As long as there are as many start spanners as end spanners for a specific spanner class, these “orfan” spanners are matched. This method makes the matches explicit, as if they had been created with a partner spanner.
- Parameters:
removeUnmatched – if True, any spanners which cannot be matched will be removed
- Return type:
None
- mergeTiedEvents()[source]¶
Merge tied events inplace
Two events can be merged if they are tied and the second event does not provide any extra information (does not have an individual amplitude, dynamic, does not start a gliss, etc.)
- Return type:
None
- Returns:
True if self was modified
- nextEvent(event)[source]¶
Returns the next event after event
- Return type:
MEvent
|None
Example
>>> from maelzel.core import * >>> chain = Chain(['4C', '4D', Chain(['4E', '4F'])]) >>> chain.eventAfter(chain[1]) 4E >>> chain.itemAfter(chain[1]) Chain([4E, 4F])
- nextItem(item)[source]¶
Returns the next item after item
An item can be an event (note, chord) or another chain
- Parameters:
- Return type:
- Returns:
the item following item or None if the given item is not in this container, or it has no item after it
Example
>>> from maelzel.core import * >>> chain = Chain(['4C', '4D', Chain(['4E', '4F'])]) >>> chain.eventAfter(chain[1]) 4E >>> chain.itemAfter(chain[1]) Chain([4E, 4F])
- parentAbsOffset()¶
The absolute offset of the parent
- Return type:
Fraction
- Returns:
the absolute offset of the parent if this object has a parent, else 0
- pitchRange()[source]¶
The pitch range of this object, if applicable
This is useful in order to assign this object to a proper Voice when distributing objects among voices
- Return type:
tuple
[float
,float
] |None
- Returns:
either None or a tuple (lowest pitch, highest pitch)
- pitchTransform(pitchmap)[source]¶
Apply a pitch-transform to this object, returns a copy
- Parameters:
pitchmap (
Callable
[[float
],float
]) – a function mapping pitch to pitch- Return type:
Self
- Returns:
the object after the transform
- play(instr=None, delay=None, args=None, gain=None, chan=None, pitchinterpol=None, fade=None, fadeshape=None, position=None, skip=None, end=None, whenfinished=None, sustain=None, workspace=None, transpose=0, config=None, display=False, **kwargs)¶
Plays this object.
Play is always asynchronous (to block, use some sleep funcion). By default,
play()
schedules this event to be renderer in realtime.Note
To record events offline, see the example below
- Parameters:
gain (
Optional
[float
]) – modifies the own amplitude for playback/recording (0-1)delay (
Optional
[float
]) – delay in seconds, added to the start of the object As opposed to the .offset attribute of each object, which is defined in symbolic (beat) time, the delay is always in real (seconds) timeinstr (
Optional
[str
]) – which instrument to use (see defPreset, definedPresets). Use “?” to select from a list of defined presets.chan (
Optional
[int
]) – the channel to output to. Channels start at 1pitchinterpol (
Optional
[str
]) – ‘linear’, ‘cos’, ‘freqlinear’, ‘freqcos’fade (
Union
[float
,tuple
[float
,float
],None
]) – fade duration in seconds, can be a tuple (fadein, fadeout)fadeshape (
Optional
[str
]) – ‘linear’ | ‘cos’args (
Optional
[dict
[str
,float
]]) – arguments passed to the note. A dict{paramName: value}
position (
Optional
[float
]) – the panning position (0=left, 1=right)skip (
Optional
[float
]) – amount of time (in quarternotes) to skip. Allows to play a fragment of the object (NB: this trims the playback of the object. Usedelay
to offset the playback in time while keeping the playback time unmodified)end (
Optional
[float
]) – end time of playback. Allows to play a fragment of the object by trimming the end of the playbacksustain (
Optional
[float
]) – a time added to the playback events to facilitate overlapping/legato between notes, or to allow one-shot samples to play completely without being cropped.workspace (
Optional
[Workspace
]) – a Workspace. If given, overrides the current workspace. It’s scorestruct is used to to determine the mapping between beat-time and real-time.transpose (
float
) – add a transposition interval to the pitch of this objectconfig (
Optional
[CoreConfig
]) – if given, overrides the current configwhenfinished (
Optional
[Callable
]) – function to be called when the playback is finished. Only applies to realtime renderingdisplay – if True and running inside Jupyter, display the resulting synth’s html
- Return type:
SynthGroup
- Returns:
A
SynthGroup
See also
render()
,
Example
Play a note
>>> from maelzel.core import * >>> note = Note(60).play(gain=0.1, chan=2)
Play multiple objects synchronised
>>> play( ... Note(60, 1.5).events(gain=0.1, position=0.5) ... Chord("4E 4G", 2, start=1.2).events(instr='piano') ... )
Or using play as a context managger:
>>> with play(): ... Note(60, 1.5).play(gain=0.1, position=0.5) ... Chord("4E 4G", 2, start=1.2).play(instr='piano') ... ...
Render offline
>>> with render("out.wav", sr=44100) as r: ... Note(60, 5).play(gain=0.1, chan=2) ... Chord("4E 4G", 3).play(instr='piano')
- plot(**kws)¶
- Return type:
Axes
- previousItem(item)[source]¶
Returns the item (an event or a chain) previous to the given one
- Parameters:
- Return type:
- Returns:
the item previous to item
See also
- quantizedScore(scorestruct=None, config=None, quantizationProfile=None, enharmonicOptions=None, nestedTuplets=None)¶
Returns a QuantizedScore representing this object
- Parameters:
scorestruct (
Optional
[ScoreStruct
]) – if given it will override the scorestructure active for this objectconfig (
Optional
[CoreConfig
]) – if given will override the active configquantizationProfile (
Union
[str
,QuantizationProfile
,None
]) – if given it is used to customize the quantization process. Otherwise, a profile is constructed based on the config. It is also possible to pass the name of a quantization preset (possible values: ‘lowest’, ‘low’, ‘medium’, ‘high’, ‘highest’, seemaelzel.scoring.quant.QuantizationProfile.fromPreset()
)enharmonicOptions (
Optional
[EnharmonicOptions
]) – if given it is used to customize enharmonic respelling. Otherwise, the enharmonic options used for respelling are constructed based on the confignestedTuplets (
Optional
[bool
]) – if given, overloads the config value ‘quant.nestedTuplets’. This is used to disallow nested tuplets, mainly for rendering musicxml since there are some music editors (MuseScore, for example) which fail to import nested tuplets. This can be set at the config level asgetConfig()['quant.nestedTuplets'] = False
- Return type:
- Returns:
a quantized score. To render such a quantized score as notation call its
render()
method
A QuantizedScore contains a list of QuantizedParts, which each consists of list of QuantizedMeasures. To access the recursive notation structure of each measure call its
asTree()
method
- rec(outfile='', sr=None, verbose=None, wait=None, nchnls=None, instr=None, delay=None, args=None, gain=None, position=None, extratime=None, workspace=None, **kws)¶
Record the output of .play as a soundfile
- Parameters:
outfile – the outfile where sound will be recorded. Can be None, in which case a filename will be generated. Use ‘?’ to open a save dialog
sr (
Optional
[int
]) – the sampling rate (config key: ‘rec.sr’)wait (
Optional
[bool
]) – if True, the operation blocks until recording is finishes (config ‘rec.block’)nchnls (
Optional
[int
]) – if given, use this as the number of channels to record.gain (
Optional
[float
]) – modifies the own amplitude for playback/recording (0-1)delay (
Optional
[float
]) – delay in seconds, added to the start of the object As opposed to the .start attribute of each object, which is defined in symbolic (beat) time, the delay is always in real (seconds) timeinstr (
Optional
[str
]) – which instrument to use (see defPreset, definedPresets). Use “?” to select from a list of defined presets.args (
Optional
[dict
[str
,float
]]) – named arguments passed to the note. A dict{paramName: value}
position (
Optional
[float
]) – the panning position (0=left, 1=right)workspace (
Optional
[Workspace
]) – if given it overrides the active workspaceextratime (
Optional
[float
]) – extratime added to the recording (config key: ‘rec.extratime’)verbose (
Optional
[bool
]) – if True, display synthesis output**kws – any keyword passed to .play
- Return type:
- Returns:
the offline renderer used. If no outfile was given it is possible to access the renderer soundfile via
OfflineRenderer.lastOutfile()
Example
>>> from maelzel.core import * >>> # a simple note >>> chord = Chord("4C 4E 4G", dur=8).setPlay(gain=0.1, instr='piano') >>> renderer = chord.rec(wait=True) >>> renderer.lastOutfile() '/home/testuser/.local/share/maelzel/recordings/tmpashdas.wav'
See also
OfflineRenderer
- recurse(reverse=False)[source]¶
Yields all events (Notes/Chords) in this chain, recursively
This method guarantees that the yielded events are the actual objects included in this chain or its sub-chains. This is usefull when used in combination with methods like addSpanner, which modify the objects themselves.
- Parameters:
reverse – if True, recurse the chain in reverse
- Return type:
Iterator
[MEvent
]- Returns:
an iterator over all notes/chords within this chain and its sub-chains, where for each event a tuple (event: MEvent, offset: F) is returned. The offset is relative to the offset of this chain, so in order to determine the absolute offset for each returned event one needs to add the absolute offset of this chain
- relOffset()¶
Resolve the offset of this object, relative to its parent
If this object has no parent the offset is an absolute offset.
The
.offset
attribute holds the explicit offset. If this attribute is unset (None
) this object might ask its parent to determine the offset based on the durations of any previous objects- Return type:
Fraction
- Returns:
the offset, in quarter notes. If no explicit or implicit offset and the object has no parent it returns 0.
See also
MObj.absOffset()
- remap(deststruct, sourcestruct=None)[source]¶
Remap times (offset, dur) from source scorestruct to destination scorestruct
The absolute time remains the same
- Parameters:
deststruct (ScoreStruct) – the destination scorestruct
sourcestruct (ScoreStruct) – the source scorestructure, or None to use the resolved scoresturct
- Return type:
_MObjT
- Returns:
a clone of self remapped to the destination scorestruct
- removeRedundantOffsets()[source]¶
Remove over-specified start times in this Chain (in place)
- Return type:
None
- render(backend='', renderoptions=None, scorestruct=None, config=None, quantizationProfile=None)¶
Renders this object as notation
First the object is quantized to abstract notation, then it is passed to the backend to render it for the specific format (lilypond, musicxml, …), which is then used to generate a document (pdf, png, …)
- Parameters:
backend – the backend to use, one of ‘lilypond’, ‘musicxml’. If not given, defaults to the config key ‘show.backend’
renderoptions (
Optional
[RenderOptions
]) – the render options to use. If not given, these are generated from the active configscorestruct (
Optional
[ScoreStruct
]) – if given, overrides the scorestruct set within the active Workspace and any scorestruct attached to this objectconfig (
Optional
[CoreConfig
]) – if given, overrides the active configquantizationProfile (
Union
[str
,QuantizationProfile
,None
]) – if given, it is used to customize the quantization process and will override any config option related to quantization. A QuantizationProfile can be created from a config viamaelzel.core.config.CoreConfig.makeQuantizationProfileFromPreset()
.
- Return type:
- Returns:
a scoring.render.Renderer. This can be used to write the rendered structure to an image (png, pdf) or as a musicxml or lilypond file.
Example
>>> from maelzel.core import * >>> voice = Voice(...) # Render with the settings defined in the config >>> voice.render() # Customize the rendering process >>> from maelzel.scoring.renderer import RenderOptions >>> from maelzel.scoring.quant import QuantizationProfile >>> quantprofile = QuantizationProfile.simple( ... possibleDivisionsByTempo={80: [] ... })
- resolveEnd()¶
Returns the resolved end of this object, relative to its parent
An object’s offset can be explicit (set in the
.offset
attributes) or implicit, as calculated from the context of the parent. For example, inside a Chain, the offset of an event depends on the offsets and durations of the objects preceding it.Note
To calculate the absolute end of an object, use
obj.absOffset() + obj.resolveEnd
- Return type:
Fraction
- Returns:
the resolved end of this object, relative to its parent. If this object has no parent, the relative end and the absolute end are the same
See also
MObj.relOffset()
,MObj.absOffset()
- scorestruct(resolve=False)¶
Returns the ScoreStruct active for this obj or its parent (recursively)
If this object has no parent
None
is returned. If resolve is True and this object has no associated scorestruct, the active scorestruct is returned- Parameters:
resolve – if True and this obj (or its parent, recursively) has no associated scorestruct, the active scorestruct is returned
- Return type:
ScoreStruct
|None
- Returns:
the associated scorestruct or the active struct if resolve is True and this object has no associated struct (either directly or through its parent)
Example
>>> from maelzel.core import * >>> n = Note("4C", 1) >>> voice = Voice([n]) >>> score = Score([voice]) >>> score.setScoreStruct(ScoreStruct(timesig=(3, 4), tempo=72)) >>> n.scorestruct() ScoreStruct(timesig=(3, 4), tempo=72)
- scoringEvents(groupid='', config=None, parentOffset=None)[source]¶
Returns the scoring events corresponding to this object.
The scoring events returned always have an absolute offset
- Parameters:
groupid – if given, all events are given this groupid
config (
Optional
[CoreConfig
]) – the configuration used (None to use the active config)parentOffset (
Optional
[Fraction
]) – if given will override the parent’s offset
- Return type:
list
[Notation
]- Returns:
the scoring notations representing this object
- scoringParts(config=None)[source]¶
Returns this object as a list of scoring UnquantizedParts.
- Parameters:
config (
Optional
[CoreConfig
]) – if given, this config instead of the active config will be used- Return type:
list
[UnquantizedPart
]- Returns:
a list of unquantized parts
This method is used internally to generate the parts which constitute a given MObj prior to rendering, but might be of use itself so it is exposed here.
An
maelzel.scoring.UnquantizedPart
is an intermediate format used by the scoring package to represent notated events. It represents a list of non-simultaneous Notations, unquantized and independent of any score structure
- setPlay(**kws)¶
Set any playback attributes, returns self
- Parameters:
**kws – any argument passed to
play()
(delay, dur, chan, gain, fade, instr, pitchinterpol, fadeshape, params, priority, position).- Return type:
Self
- Returns:
self. This allows to chain this to any constructor (see example)
Attribute
Type
Descr
instr
str
The instrument preset to use
delay
float
Delay in seconds, added to the start of the object
chan
int
The channel to output to, channels start at 1
fade
float
The fade time; can also be a tuple (fadein, fadeout)
fadeshape
str
One of ‘linear’, ‘cos’, ‘scurve’
pitchinterpol
str
One of ‘linear’, ‘cos’, ‘freqlinear’, ‘freqcos’
gain
float
A gain factor applied to the amplitud of this object. Dynamic argument (kgain)
position
float
Dynamic argument. Panning position (0=left, 1=right). Dynamic argument (kpos)
skip
float
Skip time of playback; allows to play a fragment of the object. NB: set the delay to the -skip to start playback at the original time but from the timepoint specified by the skip param
end
float
End time of playback; counterpart of
skip
, allow to trim playback of the objectsustain
float
An extra sustain time. This is useful for sample based instruments
transpose
float
Transpose the pitch of this object only for playback
glisstime
float
The duration (in beats) of the glissando for events with glissando. A short glisstime can be used for legato playback in non-percusive instruments
priority
int
The order of evaluation. Events scheduled with a higher priority are evaluated later in the chain
args
dict
Named arguments passed to the playback instrument
gliss
float/ bool
An object can be set to have a playback only gliss. It is equivalent to having a gliss., but the gliss is not displayed as notation.
Example:
# a piano note >>> from maelzel.core import * # Create a note with predetermined instr and panning position >>> note = Note("C4+25", dur=0.5).setPlay(instr="piano", position=1) # When .play is called, the note will play with the preset instr and position >>> note.play()
See also
addSymbol()
,playargs
- setProperty(key, value)¶
Set a property, returns self
Any MObj can have user-defined properties. These properties are optional: before any property is created the
.properties
attribute isNone
. This method creates the dict if it is still None and sets the property.- Parameters:
key (
str
) – the key to setvalue – the value of the property
- Return type:
Self
- Returns:
self (similar to setPlay or setSymbol, to allow for chaining calls)
Example
>>> from maelzel.core import * >>> n = Note("4C", 1) >>> n.setProperty('foo', 'bar') 4C:1♩ >>> # To query a property do: >>> n.getProperty('foo') bar >>> # Second Method: query the properties attribute directly. >>> # WARNING: if no properties were set, this attribute would be None >>> if n.properties: ... foo = n.properties.get('foo') ... print(foo) bar
See also
getProperty()
,properties
- show(fmt=None, external=None, backend='', scorestruct=None, config=None, resolution=None)¶
Show this as notation.
- Parameters:
external (
Optional
[bool
]) – True to force opening the image in an external image viewer, even when inside a jupyter notebook. If False, show will display the image inline if inside a notebook environment. To change the default, modify config[‘openImagesInExternalApp’]backend – backend used when rendering to png/pdf. One of ‘lilypond’, ‘musicxml’. If not given, use default (see config[‘show.backend’])
fmt (
Optional
[str
]) – one of ‘png’, ‘pdf’, ‘ly’. None to use default.scorestruct (
Optional
[ScoreStruct
]) – if given overrides the current/default score structureconfig (
Optional
[CoreConfig
]) – if given overrides the current/default configresolution (
Optional
[int
]) – dpi resolution when rendering to an image, overrides the config key ‘show.pngResolution’
- Return type:
None
- splitAt(location, tie=True, beambreak=False, nomerge=False)[source]¶
Split any event present at the given absolute offset (in place)
The parts resulting from the split operation will be part of this chain/voice.
To split at a relative offset, substract the absolute offset of this Chain from the given offset
- Parameters:
location (
Union
[Fraction
,Rational
,float
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]) – the absolute offset to split at, or a score location (measureindex, measureoffset)tie – tie the parts of an event together if the split intersects an event
beambreak – if True, add a BeamBreak symbol to the given event
nomerge – if True, enforce that the items splitted cannot be merged at a later stage (they are marked with a NoMerge symbol)
- Return type:
MEvent
|None
- Returns:
if an event was split, returns the part of the event starting at the given offset. Otherwise returns None.
- splitEventsAtMeasures(scorestruct=None, startindex=0, stopindex=0)[source]¶
Splits items in self at measure offsets, inplace (recursively)
After this method is called, no event extends for longer than a measure, as defined in the given scorestruct or this object’s scorestruct.
Note
To avoid modifying self, create a copy first:
newchain = self.copy().splitEventsAtMeasure(...)
- Parameters:
scorestruct (
Optional
[ScoreStruct
]) – if given, overrides any active scorestruct for this objectstartindex – the first measure index to use
stopindex – the last measure index to use. 0=len(measures). The stopindex is not included (similar to how python’s builtin
range
behaves`
- Return type:
None
- splitEventsAtOffsets(offsets, tie=True, nomerge=False)[source]¶
Splits items in self at the given offsets, inplace (recursively)
The offsets are absolute. Split items are by default tied together. This method is useful for the case where a part of an event needs to be adressed in some way. For example, a symbol needs to be added to a part of a note (a crescendo hairpin which starts in the middle of an event).
- Parameters:
offsets (
list
[Union
[float
,Rational
,Fraction
,tuple
[int
,Union
[float
,Rational
,Fraction
]]]]) – the offsets to split items at (either absolute offsets or score locations as tuple (measureindex, measureoffset)tie – if True, parts of an item are tied together
nomerge – if True, add event breaks to prevent events from being merged
- Return type:
None
- stack()[source]¶
Stack events to the left INPLACE, making offsets explicit
- Return type:
Fraction
- Returns:
the total duration of self
- timeRangeSecs(parentOffset=None, scorestruct=None)¶
The absolute time range, in seconds
- Parameters:
parentOffset (
Optional
[Fraction
]) – if given, use this offset as parent offset. This is useful if the parent’s offset has already been calculatedscorestruct (
Optional
[ScoreStruct
]) – use this scorestruct to calculate absolute time. This is useful if the scorestruct is already known.
- Return type:
tuple
[Fraction
,Fraction
]- Returns:
a tuple (absolute start time in seconds, absolute end time in seconds)
- timeScale(factor, offset=0)¶
Create a copy with modified timing by applying a linear transformation
- Parameters:
factor (
Union
[float
,Rational
,Fraction
]) – a factor which multiplies all durations and start timesoffset (
Union
[float
,Rational
,Fraction
]) – an offset added to all start times
- Return type:
Self
- Returns:
the modified object
- timeShift(timeoffset)[source]¶
Return a copy of this object with an added offset
- Parameters:
timeoffset (
Union
[float
,Rational
,Fraction
]) – a delta time added- Return type:
Self
- Returns:
a copy of this object shifted in time by the given amount
- timeShiftInPlace(timeoffset)[source]¶
Shift the time of this by the given offset (inplace)
- Parameters:
timeoffset (
Union
[float
,Rational
,Fraction
]) – the time delta (in quarterNotes)- Return type:
None
- timeTransform(timemap, inplace=False)[source]¶
Apply a time-transform to this object
- Parameters:
timemap (
Callable
[[Fraction
],Fraction
]) – a function mapping old time to new timeinplace – if True changes are applied inplace
- Return type:
Self
- Returns:
the resulting object (self if inplace)
Note
time is conceived as abstract ‘beat’ time, measured in quarter-notes. The actual time will be also determined by any tempo changes in the active score structure.
- transpose(interval)¶
Transpose this object by the given interval
- Parameters:
interval (
int
|float
) – the interval in semitones- Return type:
Self
- Returns:
the transposed object
- transposeByRatio(ratio)¶
Transpose this by a given frequency ratio, if applicable
A ratio of 2 equals to transposing an octave higher.
- Parameters:
ratio (float) – the ratio to transpose by
- Return type:
_MObjT
- Returns:
a copy of this object, transposed by the given ratio
Example
>>> from maelzel.core import * >>> n = Note("4C") # A transposition by a ratio of 2 results in a pitch an octave higher >>> n.transposeByRatio(2) 5C
- unquantizedScore(title='')¶
Create a maelzel.scoring.UnquantizedScore from this object
- Parameters:
title – the title of the resulting score (if given)
- Return type:
- Returns:
the Arrangement representation of this object
An
UnquantizedScore
is a list ofUnquantizedPart
, which is itself a list ofNotation
. AnArrangement
represents an unquantized score, meaning that the Notations within each part are not split into measures, nor organized in beats. To generate a quantized score seequantizedScore()
This method is mostly used internally when an object is asked to be represented as a score. In this case, an Arrangement is created first, which is then quantized, generating a
QuantizedScore
See also
quantizedScore()
,QuantizedScore
- withExplicitOffset(forcecopy=False)[source]¶
Copy of self with explicit offset
If self already has explicit offset, self itself is returned.
- Parameters:
forcecopy – if forcecopy, a copy of self will be returned even if self already has explicit times
- Return type:
Self
- Returns:
a clone of self with explicit times
Example
The offset and dur shown as the first two columns are the resolved times. When an event has an explicit offset, these are shown as part of the event repr. See for example the second note, 4C, which in the first version does not have any explicit times and is shown as “4C” and in the second version it appears as “4C:2.5♩:offset=0.5”
>>> from maelzel.core import * >>> chain = Chain([Rest(0.5), Note("4C"), Chord("4D 4E", offset=3)]) >>> chain.dump() Chain offset: 0 dur: 0.5 | Rest:0.5♩ offset: 0.5 dur: 2.5 | 4C offset: 3 dur: 1 | ‹4D 4E offset=3› >>> chain.withExplicitTimes().dump() Chain offset: 0 dur: 0.5 | Rest:0.5♩:offset=0 offset: 0.5 dur: 2.5 | 4C:2.5♩:offset=0.5 offset: 3 dur: 1 | ‹4D 4E 1♩ offset=3›
- write(outfile, backend='', resolution=None)¶
Export to multiple formats
Formats supported: pdf, png, musicxml (extension: .xml or .musicxml), lilypond (.ly), midi (.mid or .midi) and pickle
- Parameters:
outfile (
str
) – the path of the output file. The extension determines the format. Formats available are pdf, png, lilypond, musicxml, midi, csd and pickle.backend – the backend used when writing as pdf or png. If not given, the default defined in the active config is used (key: ‘show.backend’). Possible backends:
lilypond
;musicxml
(uses MuseScore to render musicxml as image so MuseScore needs to be installed)resolution (
Optional
[int
]) – image DPI (only valid if rendering to an image) - overrides the config key ‘show.pngResolution’
- Return type:
None
Formats¶
pdf, png: will render the object as notation and save that to the given format
lilypond:
.ly
extension. Will render the object as notation and save it as lilypond text- midi:
.mid
or.midi
extension. At the moment this is done via lilypond, so the midi produced follows the quantization process used for rendering to notation. Notice that midi cannot reproduce many features of a maelzel object, like microtones, and many complex rhythms will not be translated correctly
- midi:
- pickle: the object is serialized using the pickle module. This allows to load it
via
pickle.load
:myobj = pickle.load(open('myobj.pickle'))