Chain

class maelzel.core.chain.Chain(items=(), 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]) – 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[int, float, Fraction, None]) – offset of the chain itself relative to its parent

  • label (str) – a label for this chain

  • properties (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

dur

The duration of this sequence

end

The end time of this object.

items

The items in this chain, a list of events of other chains

label

a label can be used to identify an object within a group of objects

offset

Optional offset, in quarternotes.

parent

The parent of this object.

playargs

playargs are set via setPlay() and are used to customize playback (instr, gain, …).

properties

User-defined properties as a dict (None by default).

symbols

A list of all symbols added via addSymbol() (None by default)

Methods Summary

absEnd()

Returns the absolute end of this offset, as quarternotes

absOffset()

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

activeScorestruct()

Returns the ScoreStruct active for this obj or its parent.

addBreak(location)

Adds a symbolic break at the given location.

addSpanner(spanner[, start, end, post])

Adds a spanner symbol across this object

addSymbol(*args, **kws)

Add a notation symbol to this object

addSymbolAt(symbol, offset[, post, skipGrace])

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, ...])

clone([items, offset, label, properties])

Clone this object, changing parameters if needed

convertGlissTargetsToGracenotes()

Convert gliss.

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

dynamicAt(absoffset[, fallback])

eventAfter(offset)

First event starting at or after offset

eventAt(location[, split, margin, start])

The event present at the given location

eventBefore(offset)

Last event ending before or at the offset

eventsAt(location[, start])

Returns all events present at the given location

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 self with items

fillGaps([recurse])

Fill any gaps with rests, inplace

firstEvent([acceptRest])

The first event in this chain, recursively :rtype: MEvent | None

firstOffset()

The offset (relative to the start of this chain) of the first event

flat([forcecopy])

A flat version of this Chain

flatEvents([forcecopy])

A list of flat events, with explicit absolute offsets set

getConfig([prototype])

Returns a CoreConfig overloaded with options set for this object

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

hasOffsets()

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

itemsWithOffset()

Iterate over the items of this chain with their absolute offset

lastEvent([acceptRest])

The last event in this chain, recursively :rtype: MEvent | None

location()

Returns the location of this object within the active score struct

matchOrfanSpanners([removeUnmatched])

Match unmatched spanners

meanPitch()

The mean pitch of this object

mergeTiedEvents()

Merge tied events inplace

nextEvent(event)

Returns the next event after event

nextItem(item)

Returns the next item after item

parentAbsOffset()

The absolute offset of the parent

pitchRange()

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([axes, figsize, timeSignatures, grid])

Plot this object

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

relEnd()

Resolved end of this object, relative to its parent

relOffset()

Resolve the offset of this object, relative to its parent

remap(deststruct[, sourcestruct, setStruct])

Creates a clone, remapping times from source scorestruct to destination scorestruct

removeRedundantOffsets()

Remove over-specified start times in this Chain (in place)

render([backend, renderoptions, ...])

Renders this object as notation

root()

The root of this object

scorestruct()

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.

setConfig(*args)

Configure this object

setItems(items)

Set the items of this chain/voice, inplace

setPlay(**kws)

Set any playback attributes, returns self

setProperty(key, value)

Set a property, returns self

setScoreStruct(scorestruct)

Set the ScoreStruct for this object and its children

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 events in self at the given offsets, inplace (recursively)

stack()

Stack events to the left INPLACE, making offsets explicit

synthEvents([instr, delay, args, gain, ...])

Returns the SynthEvents needed to play this object

timeRange()

Returns a tuple (starttime, endtime), in seconds

timeScale(factor[, offset])

Create a copy with modified timing by applying a linear transformation

timeShift(offset)

Return a copy of this object with an added offset

timeShiftInPlace(offset)

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

updateChildrenOffsets()

withExplicitOffset([forcecopy])

Copy of self with explicit offset

write(outfile[, backend, resolution, format])

Export to multiple formats

Attributes Documentation

dur

The duration of this sequence

end

The end time of this object.

Will be None if this object has no explicit offset. Use :meth:`

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, _t.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

absEnd()

Returns the absolute end of this offset, as quarternotes

If this object is embedded (has a parent) in a container, its absolute end 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 end position of this object

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
activeScorestruct()

Returns the ScoreStruct active for this obj or its parent.

Otherwise returns the scorestruct for the active workspace

Return type:

ScoreStruct

Returns:

the active scorestruct for this object

See also

MObj.scorestruct()

addBreak(location)[source]

Adds a symbolic break at the given location.

This only modifies the representation as notation, it does not split any note/chord within this Chain. To actually split any item at the given location, use Chain.splitAt()

Parameters:

location (Fraction | tuple[int, Fraction]) – the absolute location to break the beam (a beat or a tuple (measureidx, beat))

Return type:

None

addSpanner(spanner, start=None, end=None, post=False)[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. - see maelzel.core.symbols.makeSpanner() When passing a string description, prepend it with ‘~’ to create an end spanner

  • start (Union[tuple[int, Union[int, float, Fraction]], MEvent, None]) – start location or event

  • end (Union[tuple[int, Union[int, float, Fraction]], MEvent, None]) – end location or event

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)[source]

Add a notation symbol to this object

Some symbols are exclusive, meaning that adding a symbol of this kind will replace a previously set symbol. Exclusive symbols include any properties (color, size, etc) and other customizations like notehead shape

Example

>>> from maelzel.core import *
>>> n = Note(60)
>>> n.addSymbol(symbols.Articulation('accent'))
# The same can be achieved via keyword arguments:
>>> n.addSymbol(articulation='accent')
# Multiple symbols can be added at once:
>>> n = Note(60).addSymbol(text='dolce', articulation='tenuto')
>>> n2 = Note("4G").addSymbol(symbols.Articulation('accent'), symbols.Ornament('mordent'))
# Known symbols - most common symbols don't actually need keyword arguments:
>>> n = Note("4Db").addSymbol('accent').addSymbol('fermata')
# Some symbols can take customizations:
>>> n3 = Note("4C+:1/3").addSymbol(symbols.Harmonic(interval='4th'))
Return type:

Self

Returns:

self (similar to setPlay, allows to chain calls)

addSymbolAt(symbol, offset, post=False, skipGrace=False)[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:
  • symbol (EventSymbol | str) – the symbol to add

  • offset (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – the location to add the symbol as an absolute beat or a location (measureindex, measureoffset)

  • post – if True, add this symbol at quantization, not to the event itself. If there is no event starting at the given offset, post is enforced even if false

  • skipGrace – If there are multiple notes found at the location (this happens only if a note starts at the location, preceded by one or many gracenotes), a True value would apply the symbol to the “real” event, skipping the gracenotes

Return type:

Self

Returns:

self

Example

>>> chain = Chain([
... Note("4C", 2),
... Note("4E", 1)
])
>>> chain.addSymbolAt(symbols.Fermata(), 1)

See also

Chain.addBreak()

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 annotation

  • placement – where to place the annotation (‘above’, ‘below’)

  • italic – if True, use italic as font style

  • weight – ‘normal’ or ‘bold’

  • fontsize (int | None) – the size of the annotation

  • fontfamily – 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. This can be used to create an object and add text in one call

Example

>>> chain = Chain([
...     Note("4C", 1).addText('do'),
...     Note("4D", 1).addText('re')
... ])
>>> chain
api/assets/event-addText.png
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:

Voice

Returns:

this chain as a Voice

automate(param, breakpoints, relative=True, interpolation='linear')[source]
Return type:

None

clone(items=None, offset=-1, label=None, properties=None)[source]

Clone this object, changing parameters if needed

Parameters:

**kws – any keywords passed to the constructor

Return type:

Self

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)
convertGlissTargetsToGracenotes()[source]

Convert gliss. end pitches within events as gracenotes, in place

Return type:

list[MEvent]

Returns:

the list of newly created gracenotes (an empty list if no changes where performed). The returned gracenotes are part of self or any corresponding subchain

copy()[source]

Returns a copy of this object

Return type:

Self

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[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – absolute start of the beat range

  • end (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – absolute 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 sequence

  • crop – 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

dynamicAt(absoffset, fallback='')[source]
Return type:

str

eventAfter(offset)[source]

First event starting at or after offset

If you want events strictly after offset, add an epsilon to offset

Parameters:

offset (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – absolute start location (a beat or score location)

Return type:

MEvent | None

Returns:

the first event starting at or after offset, if exists, None otherwise

eventAt(location, split=False, margin=Fraction(0, 1), start=False)[source]

The event present at the given location

Note

If there are multiple events at the given location (gracenotes have a duration if 0 and thus can share a location with other gracenotes and with an event starting at that location) only the first event will be returned. Use Chain.eventsAt() to return all events at a given location

Parameters:
  • location (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – the beat or a tuple (measureindex, beatoffset). If a beat is given, it is interpreted as an absoute offset

  • split – if the offset lies within an event, splits the event at the given offset, returns the right part of the event (the part starting at the offset), as a tied event. If the returned event is not modified (no symbol is added or any other property is changed) it might be remerged when shown as notation. To prevent merging without any other visible side-effects you can add a NoMerge symbol to the returned event

  • margin (Fraction) – if given, the first event within location and location+margin will be returned

  • start – if True, an event will be returned only if it starts at the given offset

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. If there are multiple events at the given location (due to gracenotes having 0 duration), the first event will be returned.

eventBefore(offset)[source]

Last event ending before or at the offset

If you want an event ending strictly before the given offset, substract an epsilon to the offset

Parameters:

offset (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – absolute end location (a beat or score location)

Return type:

MEvent | None

Returns:

the last event ending before or at the offset, if exists, None otherwise

eventsAt(location, start=False)[source]

Returns all events present at the given location

Parameters:
  • location (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – the beat or a tuple (measureindex, beatoffset). If a beat is given, it is interpreted as an absoute offset

  • start – if True, only events starting at the given location are returned

Return type:

list[MEvent]

Returns:

the events present or starting at the given location

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.

Note

The returned events are the actual events in this Chain or subchains: they are NOT copies. If these events do not have an .offset set or they are nested, their resulting offset when used parentless will differ. To force every event having an explicit offset use .stack()

Parameters:
  • start (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – absolute start location (a beat or a score location)

  • end (Union[int, float, Fraction, tuple[int, Union[int, float, 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. The actual events are returned, so modifying the returned events will modify self

eventsWithOffset(start=None, end=None, partial=True)[source]

Recurse the events in self and resolves each event’s offset

Parameters:
  • start (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]], None]) – absolute start beat/location. Filters the returned event pairs to events within this time range

  • end (Union[int, float, Fraction, tuple[int, Union[int, float, Fraction]], None]) – absolute end beat/location. Filters the returned event pairs to events within the given range

  • partial – only used if either start or end are given, this controls how events are matched. If True, events only need to be partially defined within the time range. Otherwise, they 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)
>>> chain.eventsWithOffset()
[(4C:0.5♩, Fraction(1, 1)), (4D:1♩, Fraction(3, 2)), (4E:0.5♩, Fraction(3, 1))]
extend(items)[source]

Extend self with items

Parameters:

items (Sequence[MEvent | Chain]) – 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

firstEvent(acceptRest=True)[source]

The first event in this chain, recursively :rtype: MEvent | None

See also

:meth:`Chain.recurse

Example

>>> chain = Chain([
...     Chain("4E:0.5", offset=2),
...     "4C:0.5",
...     "4D"])
>>> chain.firstEvent()
4E:0.5♩

The returned event is the actual event enclosed in this chain/voice. As seen in the example, it can be an event enclosed in a subchain

firstOffset()[source]

The offset (relative to the start of this chain) of the first event

The offset returned might refer to an item of this chain or any subchain, recursively.

Return type:

Fraction | None

Returns:

the offset of the first event, relative to self, None if empty.

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 call Chain.removeRedundantOffsets()

Parameters:

forcecopy – return a new chain, even if self is already flat

Return type:

Self

Returns:

a flat chain

flatEvents(forcecopy=False)[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

Parameters:

forcecopy – if True, all returned events are copy of events within self, even if they have an explicit absolute offset

Return type:

list[MEvent]

Returns:

a list of events (Notes, Chords, Clips, …) with explicit absolute offset offset

getConfig(prototype=None)

Returns a CoreConfig overloaded with options set for this object

Parameters:

prototype (Optional[CoreConfig]) – the config to use as prototype, falls back to the active config

Return type:

CoreConfig | None

Returns:

A clone of the active config with any customizations made via Voice.setConfig() or Voice.configQuantization() If no customizations have been made, None is returned

getPlay(key, default=None, recursive=True)

Get a playback attribute previously set via MObj.setPlay()

All locally set playback attributes are accessible via the MEvent.playargs attribute. This method checks not only the locally set attributes, but any attribute set by the parent

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

An 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(). The MObj.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 query

  • default – returned value if the property has not been set

Returns:

the value of the property, or the default value

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:

_symbols.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 (str | float | int) – 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])
../_images/dodecaphonic-series-1-inverted.png
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[int, float, Fraction, tuple[int, Union[int, float, Fraction]]]) – absolute start location (a beat or a score location)

  • end (Union[int, float, Fraction, tuple[int, Union[int, float, 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 | Chain]

Returns:

a list of the items within the given time range. The actual items are returned

itemsWithOffset()[source]

Iterate over the items of this chain with their absolute offset

Return type:

Iterator[tuple[MEvent | Chain, Fraction]]

Returns:

an iterator over tuple[item, offset], where an item can be an event or a Chain, and offset is the absolute offset

lastEvent(acceptRest=True)[source]

The last event in this chain, recursively :rtype: MEvent | None

See also

:meth:`Chain.recurse

Example

>>> chain = Chain([
...     "4C:0.5",
...     "4D",
...     Chain(["4E:0.5", "4F:0.5"])
...     ])
>>> chain.lastEvent()
4F:0.5♩

The returned event is the actual event enclosed in this chain/voice. As seen in the example, it can be an event enclosed in a subchain

location()

Returns the location of this object within the active score struct

Return type:

tuple[location_t, location_t]

Returns:

a tuple (startlocation, endlocation) where both startlocation are tuples (measureindex, beatoffset) representing the position of this object within the score

Example

>>> setScoreStruct(timesig='3/4')
>>> note = Note("4C", 1, offset=5)
>>> note.location()
((1, Fraction(2, 1)), (2, Fraction(0, 1)))

The note starts at measure 1, beat 2 and ends at measure 2, beat 0 (both measures and beats start at 0)

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

meanPitch()[source]

The mean pitch of this object

Return type:

float

Returns:

The mean pitch of this object

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

nextEvent(event)[source]

Returns the next event after event

Parameters:

event (MEvent) – the start event

Return type:

MEvent | None

Returns:

The event following the given event, even if this is part of a chain, or None if no event exists after the given event

Example

>>> from maelzel.core import *
>>> chain = Chain(['4C', '4D', Chain(['4E', '4F'])])
# Notice how this method returns the event within the sub-chain
>>> chain.nextEvent(chain[1])
4E
# In this case the next item is the entire chain
>>> chain.nextItem(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:

item (MEvent | Chain) – the item to find its next item

Return type:

MEvent | Chain | None

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='', delay=None, args=None, gain=None, chan=None, pitchinterpol='', fade=None, fadeshape='', 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 (float | None) – modifies the own amplitude for playback/recording (0-1)

  • delay (float | None) – 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) time. Delay can be negative, in which case synth events start the given amount of seconds earlier.

  • instr – which instrument to use (see defPreset, definedPresets). Use “?” to select from a list of defined presets.

  • chan (int | None) – the channel to output to. Channels start at 1

  • pitchinterpol – ‘linear’, ‘cos’, ‘freqlinear’, ‘freqcos’

  • fade (float | tuple[float, float] | None) – fade duration in seconds, can be a tuple (fadein, fadeout)

  • fadeshape – ‘linear’ | ‘cos’

  • args (dict[str, float] | None) – arguments passed to the note. A dict {paramName: value}

  • position (float | None) – the panning position (0=left, 1=right)

  • skip (float | None) – amount of time (in quarternotes) to skip. Allows to play a fragment of the object (NB: this trims the playback of the object. Use delay to offset the playback in time while keeping the playback time unmodified)

  • end (float | None) – end time of playback. Allows to play a fragment of the object by trimming the end of the playback

  • sustain (float | None) – 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 (Workspace | None) – 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 object

  • config (CoreConfig | None) – if given, overrides the current config

  • whenfinished (_t.Callable | None) – function to be called when the playback is finished. Only applies to realtime rendering

  • display – if True and running inside Jupyter, display the resulting synth’s html

Return type:

csoundengine.synth.SynthGroup

Returns:

A SynthGroup

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).synthEvents(gain=0.1, position=0.5)
... Chord("4E 4G", 2, start=1.2).synthEvents(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(axes=None, figsize=(15, 5), timeSignatures=True, grid=True, **kws)

Plot this object

To see all supported options, see maelzel.core.plotting.plotVoices()

Parameters:
  • axes (Axes | None) – use this Axes, if given

  • figsize (tuple[int, int]) – figure size of the plot, if not axes is given (otherwise uses the figure corresponding to the given axes)

  • timeSignatures – draw time signatures

  • grid – draw a grid

  • kws – passed to maelzel.core.plotting.plotVoices

Return type:

Axes

Returns:

the axes used

previousEvent(event)[source]

Returns the event before the given event

Parameters:

event (MEvent) – the event to query

Return type:

MEvent | None

Returns:

the event before the given event, or None if no event is found. Raises ValueError if event is not part of this container

previousItem(item)[source]

Returns the item (an event or a chain) previous to the given one

Parameters:

item (MEvent | Chain) – the item to query.

Return type:

MEvent | Chain | None

Returns:

the item previous to item

quantizePitch(step=0.0)[source]

Returns a new object, with pitch rounded to step

Parameters:

step – quantization step, in semitones. A value of 0 used the default semitone division in the active config (can be configured via getConfig()['semitoneDivisions']

Returns:

a copy of self with the pitch quantized

quantizedScore(scorestruct=None, config=None, quantizationProfile=None, enharmonicOptions=None, nestedTuplets=None)

Returns a QuantizedScore representing this object

Parameters:
  • scorestruct (ScoreStruct | None) – if given it will override the scorestructure active for this object

  • config (CoreConfig | None) – if given will override the active config

  • quantizationProfile (str | quant.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’, see maelzel.scoring.quant.QuantizationProfile.fromPreset())

  • enharmonicOptions (enharmonics.EnharmonicOptions | None) – if given it is used to customize enharmonic respelling. Otherwise, the enharmonic options used for respelling are constructed based on the config

  • nestedTuplets (bool | None) – 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 as getConfig()['quant.nestedTuplets'] = False

Return type:

quant.QuantizedScore

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=0, verbose=None, wait=None, nchnls=None, instr='', 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 (int) – the sampling rate (config key: ‘rec.sr’)

  • wait (bool | None) – if True, the operation blocks until recording is finishes (config ‘rec.block’)

  • nchnls (int | None) – if given, use this as the number of channels to record.

  • gain (float | None) – modifies the own amplitude for playback/recording (0-1)

  • delay (float | None) – 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) time

  • instr – which instrument to use (see defPreset, definedPresets). Use “?” to select from a list of defined presets.

  • args (dict[str, float] | None) – named arguments passed to the note. A dict {paramName: value}

  • position (float | None) – the panning position (0=left, 1=right)

  • workspace (Workspace | None) – if given it overrides the active workspace

  • extratime (float | None) – extratime added to the recording (config key: ‘rec.extratime’)

  • verbose (bool | None) – if True, display synthesis output

  • **kws – any keyword passed to .play

Return type:

offline.OfflineRenderer

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

relEnd()

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.dur

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()

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

absOffset()

remap(deststruct, sourcestruct=None, setStruct=True)[source]

Creates a clone, remapping times from source scorestruct to destination scorestruct

The absolute time remains the same

Parameters:
  • deststruct (ScoreStruct) – the destination scorestruct

  • sourcestruct (Optional[ScoreStruct]) – the source scorestructure, or None to use the resolved scoresturct

  • setStruct – if True, explicitely sets deststruct as the score structure for this chain/voice

Return type:

Self

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='')

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 (RenderOptions | None) – the render options to use. If not given, these are generated from the active config

  • scorestruct (ScoreStruct | None) – if given, overrides the scorestruct set within the active Workspace and any scorestruct attached to this object

  • config (CoreConfig | None) – if given, overrides the active config

  • quantizationProfile (str | quant.QuantizationProfile) – 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 via maelzel.core.config.CoreConfig.makeQuantizationProfileFromPreset().

Return type:

Renderer

Returns:

a scoring.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: []
...     })
root()

The root of this object

Objects are organized in a tree structure. For example, a note can be embedded in a Chain, which is part of a Voice, which is part of a Score. In this case, the root of all this objects is the score. A container without no parent is its own root.

Return type:

MContainer

Returns:

the root of this object

Example

>>> voice = Voice([
... "4C:1",
... Chain("4D 4E 4F")
... ])
>>> score = Score([voice])
>>> voice[0].root() is score
True
>>> score.root() is score
True
>>> Note(60).root() is None
True
>>> voice2 = voice.copy()
>>> voice2.parent is None
True
>>> voice2.root() is voice2
True
scorestruct()

Returns the ScoreStruct active for this obj or its parent (recursively)

If this object has no parent None is returned. Use activeScorestruct() to always resolve the active struct for this object

Return type:

ScoreStruct | None

Returns:

the associated scorestruct, if set (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

setConfig(*args)

Configure this object

Possible keys are any CoreConfig keys with the prefixes ‘quant.’ and ‘show.’ and also secondary keys starting with ‘.quant’ and ‘.show’

Internal note: any subclass can set the keys accepted by its instances by overloading MContainer._configKeys()

Parameters:

args – an even number of args of the form key1, value1, key2, value2, …

Return type:

None

Example

Configure the voice to break syncopations at every beat when rendered or quantized as a QuantizedScore

>>> voice = Voice(...)
>>> voice.setConfig('quant.brakeSyncopationsLevel', 'all')

Now, whenever the voice is shown all syncopations across beat boundaries will be split into tied notes.

This is the same as:

>>> voice = Voice(...)
>>> score = Score([voice])
>>> quantizedscore = score.quantizedScore()
>>> quantizedscore.parts[0].brakeSyncopations(level='all')
>>> quantizedscore.render()
setItems(items)[source]

Set the items of this chain/voice, inplace

Parameters:

items (list[MEvent | Chain]) – the new items

Return type:

None

Setting the .items attribute directly will result in errors, since the given items need to be modified in order to have their .parent attribute set and the cache for this container and its parents, if any, need to be invalidated

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. Time in beats relative to the start 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, in beats, relative to the start of the object; counterpart of skip, allow to trim playback of the object

sustain

float

An extra sustain time, in seconds. 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. Implies gliss. to the next event.

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()
setProperty(key, value)

Set a property, returns self

An MObj can have user-defined properties. These properties are optional: before any property is created the .properties attribute is None. This method creates the dict if it is still None and sets the property.

Parameters:
  • key (str) – the key to set

  • value – 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

setScoreStruct(scorestruct)

Set the ScoreStruct for this object and its children

This ScoreStruct will be used for any object embedded downstream.

Parameters:

scorestruct (ScoreStruct | None) – the ScoreStruct, or None to remove any scorestruct previously set

Return type:

None

show(fmt='', external=None, backend='', scorestruct=None, resolution=0, pageSize='', staffSize=None, cents=None, voiceMaxStaves=None, **kws)

Show this as notation.

Parameters:
  • external (bool | None) – 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 – one of ‘png’, ‘pdf’, ‘ly’. None to use default.

  • scorestruct (ScoreStruct | None) – if given overrides the current/default score structure

  • resolution (int) – dpi resolution when rendering to an image, overrides the config key ‘show.pngResolution’

  • pageSize – if given, overrides config ‘show.pageSize’. One of ‘a3’, ‘a4’, …

  • staffSize (float | None) – if given, overrides config ‘show.staffSize’. A value in points (default = 10.)

  • cents (bool | None) – overrides config ‘show.cents’. False to hide cents deviations as text annotation

  • voiceMaxStaves (int | None) – overrides config ‘show.voiceMaxStaves’. Max. number of staves used when expanding a voice to multiple staves

  • kws – any keyword is used to override the config. All options starting with the ‘show.’ prefix can be used directly (see below)

Return type:

None

Useful keywords

kws

Config Option

Description

staffSize

show.staffSize

Size of a staff, in points

spacing

show.spacing

One of normal (traditional spacing), strict (proportional), uniform (proportional)

voiceMaxStaves

show.voiceMaxStaves

Expands any voice to at most this number of staves

autoClefChanges

show.autoClefChanges

Adds automatic clef changes when rendering

clefSimplify

show.clefSimplify

Simplifies automatic clef changes

cents

show.cents

set to False to avoid showing cents deviations as text annotation

glissStemless

show.glissStemless

remove stems from the end note of a gliss

horizontalSpace

show.horizontalSpace

configure proportional spacing (one of “default”, “small”, “medium”, “large”)

pageOrientation

show.pageOrientation

one of “landscape”, “portrait”

pageSize

show.pageSize

one of “a4”, “a3”, …

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[int, float, Fraction, tuple[int, Union[int, float, 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:

Returns the event starting at the given offset, or None if no event found at the given offset. The returned event can be a part of a previous event spanning across the given offset, or an event starting exactly at the given offset.

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 the active scorestruct.

Note

To avoid modifying self, create a copy first: newchain = self.copy(); newchain.splitEventsAtMeasure(...)

Parameters:
  • scorestruct (Optional[ScoreStruct]) – if given, overrides any active scorestruct for this object

  • startindex – 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

See also

Chain.splitAt()

splitEventsAtOffsets(offsets, tie=True, nomerge=False)[source]

Splits events in self at the given offsets, inplace (recursively)

The offsets are absolute. Split events 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 (Sequence[Union[int, float, Fraction, tuple[int, Union[int, float, 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 – add a break to prevent events from being merged

Return type:

None

stack()[source]

Stack events to the left INPLACE, making offsets explicit

This method modifies the items within this object.

Return type:

None

Example

>>> chain = Chain([Note("4C", dur=0.5),
...                Note("4D", dur=1, offset=4),
...                Note("4E", dur=0.5)])
>>> chain.dump()
Chain -- beat: 0, offset: None, dur: 11/2
  beat   offset  dur    item
  0      None    0.5    4C:0.5♩
  4      4       1      4D:1♩:offset=4
  5      None    0.5    4E:0.5♩
>>> chain.stack()
>>> chain.dump()  # Notice how all offsets are now explicit (they are no longer None)
Chain -- beat: 0, offset: None, dur: 11/2
  beat   offset  dur    item
  0      0       0.5    4C:0.5♩:offset=0
  4      4       1      4D:1♩:offset=4
  5      5       0.5    4E:0.5♩:offset=5
synthEvents(instr='', delay=None, args=None, gain=None, chan=None, pitchinterpol='', fade=None, fadeshape='', 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 using setPlay())

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 seconds. It can be negative, in which case synth events start the given amount of seconds earlier.

  • instr – 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 1

  • pitchinterpol – ‘linear’, ‘cos’, ‘freqlinear’, ‘freqcos’

  • fade (Union[float, tuple[float, float], None]) – fade duration in seconds, can be a tuple (fadein, fadeout)

  • fadeshape – ‘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 beat (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. Use delay 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 playback

  • sustain (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.synthEvnets(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.synthEvents(chan=2))
timeRange()

Returns a tuple (starttime, endtime), in seconds

Return type:

tuple[Fraction, Fraction]

Returns:

a tuple (starttime: F, endtime: F), where starttime and endtime are both absolute times in seconds

timeScale(factor, offset=Fraction(0, 1))

Create a copy with modified timing by applying a linear transformation

Parameters:
  • factor (num_t) – a factor which multiplies all durations and start times

  • offset (num_t) – an offset added to all start times

Return type:

Self

Returns:

the modified object

timeShift(offset)[source]

Return a copy of this object with an added offset

Parameters:

offset (Union[int, float, Fraction]) – a delta time added

Return type:

Self

Returns:

a copy of this object shifted in time by the given amount

timeShiftInPlace(offset)[source]

Shift the time of this by the given offset (inplace)

Parameters:

offset (Union[int, float, 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 time

  • inplace – 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 in seconds 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:

Self

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:

UnquantizedScore

Returns:

the Arrangement representation of this object

An UnquantizedScore is a list of UnquantizedPart, which is itself a list of Notation. It represents a score in which the Notations within each part are not split into measures, nor organized in beats. To generate a quantized score see quantizedScore()

This method is mostly used internally when an object is asked to be represented as a score. In this case, an UnquantizedScore is created first, which is then quantized, generating a QuantizedScore

updateChildrenOffsets()[source]
Return type:

None

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=0, format='')

Export to multiple formats

Formats supported: pdf, png, musicxml (extension: .xml or .musicxml), lilypond (.ly), midi (.mid or .midi) and pickle

To configure any options either modify the active config or use setConfig() for self. You can also use a config as context manager to temporary change the active config

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 (int) – image DPI (only valid if rendering to an image) - overrides the config key ‘show.pngResolution’

  • format – the format to write to. If not given, the format is inferred from the extension of the output file. If the extension is not recognized, an error is raised. One of ‘pdf’, ‘png’, ‘lilypond’, ‘musicxml’, ‘midi’, ‘csd’, ‘pickle’.

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

  • pickle: the object is serialized using the pickle module. This allows to load it

    via pickle.load: myobj = pickle.load(open('myobj.pickle'))

Example

chain = Chain(...)
with CoreConfig({'show.voiceMaxStaves': 2, 'show.staffSize': 12}):
    chain.write('chain.pdf')