Chord

class maelzel.core.event.Chord(notes, dur=None, amp=None, offset=None, gliss=False, label='', tied=False, dynamic='', properties=None, fixed=False, _init=True)[source]

Bases: MEvent

A Chord is a stack of Notes

a Chord can be instantiated as:

Chord(note1, note2, ...)
Chord([note1, note2, ...])
Chord("C4,E4,G4", ...)
Chord("C4 E4 G4", ...)

Where each note is either a Note, a notename (“C4”, “E4+”, etc) or a midinote

Parameters:
  • notes (Union[str, Sequence[Note | int | float | str]]) – the notes of this chord. Can be a list of pitches, where each pitch is either a fractional midinote or a notename (str); notes can be already created Note instances; or a string with multiple notes separated by a space

  • amp (Optional[float]) – the amplitude of this chord. To specify a different amplitude for each pitch within the chord, first create a Note for each pitch with its corresponding amplitude and use that list as the notes argument

  • dur (Union[float, Rational, Fraction, None]) – the duration of this chord (in quarternotes)

  • offset (Union[float, Rational, Fraction, None]) – the offset time (in quarternotes)

  • gliss (Union[str, bool, Sequence[Union[int, float, str]]]) – either a list of end pitches (with the same size as the chord), or True to leave the end pitches unspecified (a gliss to the next chord)

  • label (str) – if given, it will be used for printing purposes

  • tied – if True, this chord should be tied to a following chord, if possible

  • dynamic (str) – a dynamic for this chord (‘pp’, ‘mf’, ‘ff’, etc). Dynamics range from ‘pppp’ to ‘ffff’

  • fixed – if True, fix the spelling of the note to the notename given (this is only taken into account if the pitch was given as a notename). See also the configuration key fixStringNotenames. NB: it is possible to suffix the notename with a ‘!’ mark in order to lock its spelling, independently of the configuration settings

  • properties (Optional[dict[str, Any]]) – properties are a space given to the user to attach any information to this object

amp

the amplitude of the chord itself (each note can have an individual amp)

notes

the notes which build this chord

gliss

if True, this Chord makes a gliss to another chord. Also, a list of pitches can be given as gliss, these indicate the end pitch of the gliss as midinote

tied

is this Chord tied to another Chord?

Attributes Summary

amp

The playback amplitude 0-1 of this note

dur

The duration of this object, in quarternotes

dynamic

end

The end time of this object.

gliss

The end target of this event, if any

label

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

name

A string representing this event

notes

offset

Optional offset, in quarternotes.

parent

The parent of this object.

pitches

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)

tied

Is this event tied?

Methods Summary

absOffset()

Returns the absolute offset of this object in quarternotes

addSpanner(spanner[, endobj])

Adds a spanner symbol to this object

addSymbol(*args, **kws)

Add a notation symbol to this object

addText(text[, placement, italic, weight, ...])

Add a text annotation to this object

append(note)

append a note to this Chord

asGracenote([slash])

rtype:

Chord

automate(param, breakpoints[, ...])

Add an automation action to this event

clone(**kws)

Clone this object, changing parameters if needed

copy()

Returns a copy of this object

cropped(start, end)

A copy of Self, cropped to the given time range

dump([indents, forcetext])

Prints all relevant information about this object

durSecs()

Returns the duration in seconds according to the active score

equalize(curve)

Scale the amplitude of the notes according to their frequency, inplace

events([instr, delay, args, gain, chan, ...])

Returns the SynthEvents needed to play this object

extend(notes)

extend this Chord with the given notes

filter(predicate)

Return a new Chord with only the notes which satisfy the given predicate

findNote(pitch)

Find a note within this Chord

freqShift(freq)

Return a copy of this chord shifted in frequency

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

glissTarget()

The gliss targets as a list of notenames

insert(index, note)

rtype:

None

invertPitch(pivot)

Invert the pitch of this object

isGracenote()

Is this a grace note?

isRest()

Is this a rest?

linkedNext()

Is this event linked to the next?

linkedPrev()

Is this event linked to the previous?

loudest(n)

Return a new Chord with the loudest n notes from this chord

mappedAmplitudes(curve[, db])

Return new Chord with the amps of the notes modified according to curve

meanPitch()

The mean pitch of this object

mergeWith(other)

Merge this with other, return None if not possible

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

rtype:

Axes

quantizePitch([step])

Returns a copy of this chord, with the pitches quantized.

quantizedScore([scorestruct, config, ...])

Returns a QuantizedScore representing this object

rec([outfile, sr, verbose, wait, nchnls, ...])

Record the output of .play as a soundfile

relOffset()

Resolve the offset of this object, relative to its parent

remap(deststruct[, sourcestruct])

Remap times (offset, dur) from source scorestruct to destination scorestruct

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

Renders this object as notation

resolveAmps(config, dyncurve)

rtype:

list[float]

resolveEnd()

Returns the resolved end of this object, relative to its parent

resolveGliss()

Resolve the target pitch for this chord's glissando

scaleAmplitudes(factor[, offset])

Scale the amplitudes of the notes within this chord inplace

scorestruct([resolve])

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

scoringEvents([groupid, config, parentOffset])

Returns its notated form as scoring.Notations

scoringParts([config])

Returns this object as a list of scoring UnquantizedParts.

setAmplitudes(amp)

Set the amplitudes of the notes in this chord to amp (inplace)

setNotatedPitch(notenames)

rtype:

None

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.

sort([key, reverse])

Sort INPLACE.

splitAt(offset[, tie, nomerge])

Split this event at the given absolute offset

splitAtOffsets(offsets[, tie, nomerge])

Split this event at the given offsets

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 transformation to the time axes of this

transpose(interval)

Transpose this object by the given interval

transposeByRatio(ratio)

Transpose this by a given frequency ratio, if applicable

transposeTo(fundamental)

Return a copy of self, transposed to the new fundamental

unquantizedScore([title])

Create a maelzel.scoring.UnquantizedScore from this object

withExplicitOffset([forcecopy])

Copy of self with explicit times

write(outfile[, backend, resolution])

Export to multiple formats

Attributes Documentation

amp: float | None

The playback amplitude 0-1 of this note

dur

The duration of this object, in quarternotes

dynamic: str
end

The end time of this object.

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

gliss
label: str

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

name
notes: list[Note]
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

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

tied: bool

Is this event tied?

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

addSpanner(spanner, endobj=None)

Adds a spanner symbol to 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

  • endobj (Optional[MEvent]) – the object where this spanner ends, if known

Return type:

Self

Returns:

self (allows to chain calls)

Example

>>> from maelzel.core import *
>>> a = Note("4C")
>>> b = Note("4E")
>>> c = Note("4G")
>>> a.addSpanner('slur', c)
>>> chain = Chain([a, b, c])

See also

Spanner.bind()

In some cases the end target can be inferred:

>>> chain = Chain([
... Note("4C", 1, dynamic='p').addSpanner("<"),
... Note("4D", 0.5),
... Note("4E", dynamic='f')   # This ends the hairpin spanner
... ])

Or it can be set later

>>> chain = Chain([
... Note("4C", 1).addSpanner("slur"),
... Note("4D", 0.5),
... Note("4E").addSpanner("~slur")   # This ends the last slur spanner
... ])
addSymbol(*args, **kws)

Add a notation symbol to this object

Notation symbols are attributes attached to one event and are intended for notation only. Such symbols include articulations, ornaments, fermatas but also properties, like color, size, etc. Also customizations like notehead shape, bend signs, all are considered symbols. Notation symbols spanning across multiple events (like slurs, crescendo hairpins, lines, etc.) are considered spanners and are added via addSpanner()

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

Note

Dynamics are not treated as symbols since they can also be used for playback

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)

Symbol

Possible Values

text

any text

notehead

cross, harmonic, triangleup, xcircle, triangle, rhombus, square, rectangle

articulation

accent, staccato, tenuto, marcato, staccatissimo, etc.

size

A relative size (0=default, 1, 2, …=bigger, -1, -2, … = smaller)

color

a css color

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 (Optional[int]) – 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

append(note)[source]

append a note to this Chord

Return type:

None

asGracenote(slash=True)[source]
Return type:

Chord

automate(param, breakpoints, interpolation='linear', relative=True)

Add an automation action to this event

Parameters:
  • param (str) – the playback parameter to modify, either a builtin parameter like position, or an instrument defined parameter (for example, an instrument based on substractive synthesis could define a ‘filterattack’ parameter, or a vocal synthesis instrument could define a ‘vibratoamount’ parameter)

  • breakpoints (list[tuple[Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]], float]] | list[tuple[Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]], float, str]] | list[Union[float, Rational, Fraction]]) – the data, a list of pairs in the form (time, value), or (time, value, interpolation). time is given in quarternotes or as a location (measure, beatoffset); value is any valid valud for the given parameter; interpolation is one of ‘linear’, ‘cos’. As a shortcut it is possible to also pass a flat list of the form [time0, value0, time1, value1, …]. A single point is also possible. This sets the value for the given param at the specified time

  • interpolation – default interpolation used for breakpoints without interpolation

  • relative – if True, the time positions are relative to the absolute offset of this event. If False, these times are absolute times

Return type:

None

Example

note = Note("4c", 10)

# Automate position starting at beat 5 after this event has started
note.automate('position', [(5, 0.), (6, 1.)], relative=True)

# The same data can be given as a flat list
note.automate('position', [5, 0., 6, 1.])

# Time position can be also given as a tuple (measure num, beat offset),
# and the time mode can be set to absolute
# In this case, this automation indicates a modification of the
# pan position, from 0 to 1 starting at the 4th measure (index 3) and
# ending at the 5th measure (index 4)
note.automate('position', [(3, 0), 0., (4, 0), 1.], relative=False)

Any dynamic parameter can be automated:

# Define a preset with some dynamic parameter

defPreset('detuned', '''
|kdetune=2|
    aout1 = oscili:a(kamp, kfreq) + oscili:a(kamp, kfreq+kdetune)
''')

# Automate the kdetune param. When automating a Note/Chord, the times
# are given in quarterbeats, which means that the real time in seconds
# depend on the tempo structure. In this case the kdetune param will
# be shifted from 0 to 20 starting at the moment the note is played
# and ending 4 **quarterbeats** after.
note.automate('kdetune', (0, 0, 4, 20))

# When the note is actually played the automation takes effect
synth = note.play(instr='detuned')

# The synth itself can be automated. In this case, we are already
# in the real-time realm and any times are given in seconds. If
# needed the active scorestruct can be used to convert between
# quarterbeats and seconds
synth.automate('position', (2, 0.5, 4, 1))
clone(**kws)

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

Returns a copy of this object

cropped(start, end)

A copy of Self, cropped to the given time range

The returned event will have an explicit offset set to its absolute offset. It is parentless

Parameters:
  • start (beat_t) – the start location to crop this event

  • end (beat_t) – the end location to crop this event

Return type:

Self

Returns:

the cropped event

dump(indents=0, forcetext=False)[source]

Prints all relevant information about this object

Parameters:
  • indents – number of indents

  • forcetext – if True, force text output via print instead of html even when running inside jupyter

durSecs()

Returns the duration in seconds according to the active score

Return type:

Fraction

Returns:

the duration of self in seconds

equalize(curve)[source]

Scale the amplitude of the notes according to their frequency, inplace

Parameters:

curve (Callable[[float], float]) – a func mapping freq to gain

Return type:

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

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

  • pitchinterpol (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. 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.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))
extend(notes)[source]

extend this Chord with the given notes

Return type:

None

filter(predicate)[source]

Return a new Chord with only the notes which satisfy the given predicate

Example:

# filter out notes which do not belong to the C-major triad
>>> ch = Chord("C3 D3 E4 G4")
>>> ch2 = ch.filter(lambda note: (note.pitch % 12) in {0, 4, 7})
Return type:

Chord

findNote(pitch)[source]

Find a note within this Chord

Parameters:

pitch (Union[int, float, str, None]) – the pitch to match (a midinote or a notename)

Return type:

Note | None

Returns:

the matched note or None

freqShift(freq)[source]

Return a copy of this chord shifted in frequency

Return type:

Chord

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

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

glissTarget()[source]

The gliss targets as a list of notenames

Raised ValueError if this chord does not have a gliss

Return type:

list[str]

Returns:

The gliss target as notename

insert(index, note)[source]
Return type:

None

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])
../_images/dodecaphonic-series-1-inverted.png
isGracenote()

Is this a grace note?

A grace note has a pitch but no duration

Return type:

bool

Returns:

True if this can be considered a grace note

isRest()

Is this a rest?

Return type:

bool

linkedNext()

Is this event linked to the next?

An event is linked to a next event if it is tied or has glissando set to True where this applies. This is not the case if the event has a gliss value set to other than True

Return type:

bool

linkedPrev()

Is this event linked to the previous?

Return type:

bool

loudest(n)[source]

Return a new Chord with the loudest n notes from this chord

Return type:

Chord

mappedAmplitudes(curve, db=False)[source]

Return new Chord with the amps of the notes modified according to curve

Example:

# compress all amplitudes to 30 dB
>>> import bpf4 as bpf
>>> chord = Chord([Note(60, amp=0.5), Note(65, amp=0.1)])
>>> curve = bpf.linear(-90, -30, -30, -12, 0, 0)
>>> chord2 = chord.mappedAmplitudes(curve, db=True)
Parameters:
  • curve – a func mapping amp -> amp

  • db – if True, the value returned by func is interpreted as dB if False, it is interpreted as amplitude (0-1)

Return type:

Chord

Returns:

the resulting chord

meanPitch()[source]

The mean pitch of this object

Return type:

float | None

Returns:

The mean pitch of this object

mergeWith(other)[source]

Merge this with other, return None if not possible

Parameters:

other (Chord) – the event to concatenato to this. Only events of the same type can be merged (a Note with a Note, a Chord with a Chord)

Return type:

Chord | None

Returns:

the merged event, or None

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:

Chord

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

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

  • pitchinterpol (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. Use delay 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 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 to determine the mapping between beat-time and real-time.

  • transpose (float) – add a transposition interval to the pitch of this object

  • config (Optional[CoreConfig]) – if given, overrides the current config

  • whenfinished (Optional[Callable]) – 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:

SynthGroup

Returns:

A SynthGroup

See also

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

quantizePitch(step=0.0)[source]

Returns a copy of this chord, with the pitches quantized.

Two notes with the same pitch are considered equal if they quantize to the same pitch, independently of their amplitude. In the case of two equal notes, only the first one is kept.

Return type:

Chord

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 object

  • config (Optional[CoreConfig]) – if given will override the active config

  • quantizationProfile (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’, see maelzel.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 config

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

Return type:

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

  • instr (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 workspace

  • extratime (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:

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

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)

Remap times (offset, dur) 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

Return type:

Self

Returns:

a clone of self remapped to the destination scorestruct

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 config

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

  • config (Optional[CoreConfig]) – if given, overrides the active config

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

Return type:

Renderer

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: []
...     })
resolveAmps(config, dyncurve)[source]
Return type:

list[float]

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

resolveGliss()[source]

Resolve the target pitch for this chord’s glissando

Return type:

list[float]

Returns:

the target pitch or this note’s own pitch if its target pitch cannot be determined

scaleAmplitudes(factor, offset=0.0)[source]

Scale the amplitudes of the notes within this chord inplace

Note

Each note (instance of Note) within a Chord can have its own ampltidue. The Chord itself can also have an amplitude, which is used as fallback for any note with unset amplitude. These two amplitudes do not multiply

Parameters:
  • factor (float) – a factor to multiply the amp of each note

  • offset – a value to add to the amp of each note

Return type:

None

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 its notated form as scoring.Notations

These can then be converted into notation via some of the available backends: musicxml or lilypond

Parameters:
  • groupid – passed by an object higher in the hierarchy to mark this objects as belonging to a group

  • config (Optional[CoreConfig]) – a configuration to customize rendering

  • parentOffset (Optional[Fraction]) – if given this should be the absolute offset of this object’s parent

Return type:

list[Notation]

Returns:

A list of scoring.Notation which best represent this object as notation

scoringParts(config=None)

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

setAmplitudes(amp)[source]

Set the amplitudes of the notes in this chord to amp (inplace)

This modifies the Note objects within this chord, without modifying the amplitude of the chord itself

Note

Each note (instance of Note) within a Chord can have its own ampltidue. The Chord itself can also have an amplitude, which is used as fallback for any note with unset amplitude. These two amplitudes do not multiply

Parameters:

amp (float) – the new amplitude for the notes of this chord

Return type:

None

Example

>>> chord = Chord("3f 3b 4d# 4g#", dur=4)
>>> chord.amp = 0.5                 # Fallback amplitude
>>> chord[0:-1].setAmplitude(0.01)  # Sets the amp of all notes but the last
>>> chord.events()
[SynthEvent(delay=0, dur=4, gain=0.5, chan=1, fade=(0.02, 0.02), instr=_piano)
 bps 0.000s: 53       0.01
     4.000s: 53       0.01    ,
 SynthEvent(delay=0, dur=4, gain=0.5, chan=1, fade=(0.02, 0.02), instr=_piano)
 bps 0.000s: 59       0.01
     4.000s: 59       0.01    ,
 SynthEvent(delay=0, dur=4, gain=0.5, chan=1, fade=(0.02, 0.02), instr=_piano)
 bps 0.000s: 63       0.01
     4.000s: 63       0.01    ,
 SynthEvent(delay=0, dur=4, gain=0.5, chan=1, fade=(0.02, 0.02), instr=_piano)
 bps 0.000s: 68       0.5
     4.000s: 68       0.5     ]

Notice that the last event, corresponding to the highest note, has taken the ampltidue of the chord (0.5) as default, since it was unset. The other notes have an amplitude of 0.01, as set via setAmplitudes()

setNotatedPitch(notenames)[source]
Return type:

None

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 object

sustain

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

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 structure

  • config (Optional[CoreConfig]) – if given overrides the current/default config

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

Return type:

None

sort(key='pitch', reverse=False)[source]

Sort INPLACE.

If inplace sorting is undesired, use x = chord.copy(); x.sort()

Parameters:
  • key – either ‘pitch’ or ‘amp’

  • reverse – similar as sort

Return type:

None

splitAt(offset, tie=True, nomerge=False)

Split this event at the given absolute offset

Parameters:
  • offset (beat_t) – the absolute offset at which to split this event. Can be a beat or a location

  • tie – tie the parts

  • nomerge – if True, adds a break symbol to the events resulted in the split operation to prevent them from being merged when converted to notation

Return type:

tuple[Self, …]

Returns:

a tuple with the parts. If the offset lies perfectly at the start or end of this event, only one part will be returned. If the offset does not intersect the event, ValueError is raised

Example

>>> n = Note(60, 4)
>>> n.splitAt(2)
TODO
splitAtOffsets(offsets, tie=True, nomerge=False)

Split this event at the given offsets

Parameters:
  • offsets (list[Union[float, Rational, Fraction]]) – absolute offsets. To use score locations, convert those to absolute offsets via scorestruct.locationToBeat

  • tie – if True, tie the parts

  • nomerge – if True, adds a break symbol to the events resulted in the split operation to prevent them from being merged when converted to notation

Return type:

list[Self]

Returns:

the parts. The total duration of the parts should sum up to the 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 calculated

  • scorestruct (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 times

  • offset (Union[float, Rational, Fraction]) – an offset added to all start times

Return type:

Self

Returns:

the modified object

timeShift(timeoffset)

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)

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)

Apply a transformation to the time axes of this

Parameters:
  • timemap (Callable[[Fraction], Fraction]) – a callable mapping time (in quarterbeats) to time (in quarterbeats)

  • inplace

Return type:

Self

Returns:

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

Return a copy of self, transposed to the new fundamental

Note

the fundamental is the lowest note in the chord

Parameters:

fundamental (Union[int, float, str]) – the new lowest note in the chord

Return type:

Chord

Returns:

A Chord transposed to the new fundamental

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. An Arrangement 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 see quantizedScore()

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)

Copy of self with explicit times

If self already has explicit offset and duration, self itself is returned. If you relie on the fact that this method returns a copy, use forcecopy=True

Parameters:

forcecopy – if forcecopy, a copy of self will be returned even if self already has explicit times

Returns:

a clone of self with explicit times

Example

>>> n = None("4C", dur=0.5)
>>> n
4C:0.5♩
>>> n.offset is None
True
# An unset offset resolves to 0
>>> n.withExplicitTimes()
4C:0.5♩:offset=0
# An unset duration resolves to 1 quarternote beat
>>> Note("4C", offset=2.5).withExplicitTimes()
4C:1♩:offset=2.5
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

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

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