maelzel.core.offline Module

Functions

render([outfile, events, sr, wait, ksmps, ...])

Render to a soundfile / creates a context manager to render offline

Classes

OfflineRenderer([outfile, sr, ksmps, ...])

An OfflineRenderer is created to render musical objects to a soundfile

Class Inheritance Diagram

digraph inheritanceb0f1f33e55 { bgcolor=transparent; rankdir=LR; size="8.0, 12.0"; "ABC" [fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="setlinewidth(0.5),filled",tooltip="Helper class that provides a standard way to create an ABC using"]; "OfflineRenderer" [URL="#maelzel.core.offline.OfflineRenderer",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="setlinewidth(0.5),filled",target="_top",tooltip="An OfflineRenderer is created to render musical objects to a soundfile"]; "Renderer" -> "OfflineRenderer" [arrowsize=0.5,style="setlinewidth(0.5)"]; "Renderer" [URL="api/maelzel.core.renderer.Renderer.html#maelzel.core.renderer.Renderer",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=10,height=0.25,shape=box,style="setlinewidth(0.5),filled",target="_top",tooltip="Abstract class for realtime and offline rendering"]; "ABC" -> "Renderer" [arrowsize=0.5,style="setlinewidth(0.5)"]; }
maelzel.core.offline.render(outfile='', events=None, sr=None, wait=None, ksmps=None, verbose=None, nchnls=None, workspace=None, tail=None, run=True, endtime=0.0, show=False, tempfolder='', fmt='wav', **kws)[source]

Render to a soundfile / creates a context manager to render offline

When not used as a context manager the events / objects must be given. The soundfile will be generated immediately.

When used as a context manager the events argument should be left unset. Within this context any call to maelzel.core.MObj.play() will be redirected to the offline renderer and at the exit of the context all events will be rendered to a soundfile. Also, any pure csound events scheduled via playSession()._sched(...) will also be redirected to be renderer offline.

This enables to use the exact same code when doing realtime and offline rendering.

Parameters:
  • outfile – the generated file. If None, a file inside the recording path is created (see recordPath). Use “?” to save via a GUI dialog or

  • events (Optional[Sequence[Union[SynthEvent, MObj, Event, Sequence[MObj | SynthEvent]]]]) – the events/objects to play. This can only be left unset if using render as a context manager (see example).

  • sr (Optional[int]) – sample rate of the soundfile (config ‘rec.sr’)

  • ksmps (Optional[int]) – number of samples per cycle (config ‘rec.ksmps’)

  • nchnls (Optional[int]) – number of channels of the rendered soundfile

  • wait (Optional[bool]) – if True, wait until recording is finished. If None, use the config ‘rec.blocking’

  • verbose (Optional[bool]) – if True, show the output generated by the csound subprocess

  • tail (Optional[float]) – extra time added at the end of the render, usefull when rendering reverbs or long decaying sound. If None, uses use config ‘rec.extratime’

  • run – if True, perform the render itself

  • tail – extra time at the end, usefull when rendering reverbs or long deaying sounds

  • endtime – if given, sets the end time of the rendered segment. A value of 0. indicates to render everything. A value is needed if there are endless events

  • workspace (Optional[Workspace]) – if given, this workspace overrides the active workspace

Return type:

OfflineRenderer

Returns:

the OfflineRenderer used to render the events. If the outfile was not given, the path of the recording can be retrieved from renderer.outfile

Example

>>> a = Chord("A4 C5", start=1, dur=2)
>>> b = Note("G#4", dur=4)
>>> render("out.wav", events=[
...     a.events(chain=1),
...     b.events(chan=2, gain=0.2)
... ])

This function can be also used as a context manager, similar to maelzel.playback.play(). In that case events must be None:

>>> from maelzel.core import *
>>> scale = Chain([Note(n) for n in "4C 4D 4E 4F 4G".split()])
>>> playSession().defInstr('reverb', r'''
... |kfeedback=0.6|
... amon1, amon2 monitor
... a1, a2 reverbsc amon1, amon2, kfeedback, 12000, sr, 0.6
... outch 1, a1-amon1, 2, a2-amon2
... ''')
>>> with render() as r:
...     scale.play('.piano')   # .play here is redirected to the offline renderer
...     r.sched('reverb', priority=2)

See also

OfflineRenderer, maelzel.playback.play()


class maelzel.core.offline.OfflineRenderer(outfile='', sr=None, ksmps=None, numchannels=None, tail=0.0, verbose=None, endtime=0.0, session=None)[source]

An OfflineRenderer is created to render musical objects to a soundfile

OfflineRenderer as context manager

The simplest way to render offline is to use an OfflineRenderer as a context manager (see also render()). Within this context any .play call will be collected and everything will be rendered when exiting the context (see example below)

Parameters:
  • outfile (str) – the path to the rendered soundfile. If not given, a path within the record path [1] is returned

  • sr (Optional[int]) – the sr of the render (config key: ‘rec.sr’)

  • ksmps (Optional[int]) – the ksmps used for the recording

  • numchannels (Optional[int]) – number of channels of this renderer. If not set, this will depend on the scheduled events and the final call to .render

  • verbose (Optional[bool]) – if True, debugging output is show. If None, defaults to config (key: ‘rec.verbose’)

  • endtime – used when the OfflineRenderer is called as a context manager

If rendering offline in tandem with audio samples and other csoundengine’s functionality, it is possible to access the underlying csoundengine’s Renderer via the .renderer attribute

(see recordPath())

Example

Render a chromatic scale in sync with a soundfile

>>> from maelzel.core import *
>>> import sndfileio
>>> notes = [Note(n, dur=0.5) for n in range(48, 72)]
>>> chain = Chain(notes)
>>> defPresetSoundfont('piano', sf2path='/path/to/piano.sf2')
>>> samples, sr = sndfileio.sndread('/path/to/soundfile')
>>> with render('scale.wav') as r:
...     chain.play(instr='piano')
...     # This allows access to the underlying csound renderer
...     r.renderer.playSample((samples, sr))

When exiting the context manager the file ‘scale.wav’ is rendered. During the context manager, all calls to .play are intersected and scheduled via the OfflineRenderer. This makes it easy to switch between realtime and offline rendering by simply changing from play to render()

a4

A value for the reference frequency

assignBus(kind='', value=None, persist=False)[source]

Assign a bus of the given kind

Return type:

int

Returns:

the bus token. Can be used with any bus opcode (busin, busout, busmix, etc)

csoundRenderer: csoundengine.offline.Renderer

The actual csoundengine.Renderer

definedInstrs()[source]

Get all instruments available within this OfflineRenderer

All presets and all extra intruments registered at the active Session (as returned via getPlaySession) are available

Returns:

csoundengine.Instr} with all instruments available

Return type:

dict {instrname

endtime

Default endtime

getCsd()[source]

Return the .csd as string

Return type:

str

getInstr(instrname)[source]

Get the csoundengine’s Instr corresponding to instrname

Parameters:

instrname (str) – the name of the csoundengine’s Instr

Return type:

Instr | None

Returns:

If found, the csoundengine’s Instr

getSession()[source]

Return the Session associated with this OfflineRenderer, if any

Return type:

Session | None

getSynth(token)[source]

Get a synth by token/synthid

Return type:

SchedEvent | None

includeFile(path)[source]

Add an include clause to this renderer.

OfflineRenderer keeps track of includes so trying to include the same file multiple times will generate only one #include clause

Parameters:

path (str) – the path of the file to include

Return type:

None

instrs: dict[str, csoundengine.instr.Instr]

An index of registered Instrs, mapping name to the Instr instance

isRealtime()[source]

Is this a realtime renderer?

Return type:

bool

isRendering()[source]

True if still rendering

Return type:

bool

Returns:

True if rendering is still in course

ksmps

ksmps value (samples per block)

lastOutfile()[source]

Last rendered outfile, None if no soundfiles were rendered

Return type:

str | None

Example

>>> r = OfflineRenderer(...)
>>> r._sched(...)
>>> r.render(wait=True)
>>> r.lastOutfile()
'~/.local/share/maelzel/recordings/tmpsasjdas.wav'
lastRenderProc()[source]

Last process (subprocess.Popen) used for rendering

Return type:

Popen | None

Example

>>> r = OfflineRenderer(...)
>>> r._sched(...)
>>> r.render("outfile.wav", wait=False)
>>> if (proc := r.lastRenderProc()) is not None:
...     proc.wait()
...     print(proc.stdout.read())
makeTable(data=None, size=0, sr=0, tabnum=0)[source]

Create a table in this renderer

Parameters:
  • data (Union[ndarray, list[float], None]) – if given, the table will be created with the given data

  • size (int) – if data is not given, an empty table of the given size is created. Otherwise, this parameter is ignored

  • sr (int) – the sample rate of the data, if applicable

  • tabnum (int) – leave it as 0 to let the renderer assign a table number

Return type:

int

Returns:

the assigned table number

openLastOutfile(timeout=None)[source]

Open last rendered soundfile in an external app

Will do nothing if there is no outfile. If the render is in progress this operation will block.

Parameters:

timeout – if the render is not finished this operation will block with the given timeout

Return type:

str

Returns:

the path of the soundfile or an empty string if no soundfile was rendered

play(obj, **kws)[source]

Schedule the events generated by this obj to be renderer offline

Parameters:
  • obj (MObj) – the object to be played offline

  • kws – any keyword passed to the .events method of the obj

Return type:

SchedEventGroup

Returns:

the offline score events

playSample(source, delay=0.0, dur=0, chan=1, gain=1.0, speed=1.0, loop=False, pos=0.5, skip=0.0, fade=None, crossfade=0.02)[source]

Play a sample through this renderer

Parameters:
  • source (int | str | TableProxy | tuple[np.ndarray, int] | audiosample.Sample) – a soundfile, a TableProxy, a tuple (samples, sr) or a maelzel.snd.audiosample.Sample

  • delay – when to play

  • dur – the duration. -1 to play until the end (will detect the end of the sample)

  • chan – the channel to output to

  • gain – a gain applied

  • speed – playback speed

  • loop – should the sample be looped?

  • pos – the panning position

  • skip – time to skip from the audio sample

  • fade (float | tuple[float, float] | None) – a fade applied to the playback

  • crossfade – a crossfade time when looping

Return type:

csoundengine.offline.SchedEvent

Returns:

a csoundengine.offline.SchedEvent

prepareInstr(instr, priority)[source]

Reify an instance of instr at the given priority

This method also prepares any resources and initialization that the given Instr might have

Parameters:
  • instr (Instr) – a csoundengine’s Instr

  • priority (int) – the priority to instantiate this instr with. Priorities start with 1

Return type:

bool

Returns:

False

prepareSessionEvent(sessionevent)[source]

Prepare a session event

Parameters:

sessionevent (Event) – the session event to prepare. This is mostly used internally

Return type:

None

readSoundfile(soundfile, chan=0, skiptime=0.0)[source]

Read a soundfile into the renderer

Parameters:
  • soundfile (str) – the soundfile to read

  • chan – the channel to read, 0 to read all channels

  • skiptime – start reading from this time

Return type:

int

registerInstr(name, instrdef)[source]

Register a csoundengine.Instr to be used with this OfflineRenderer

Note

All csoundengine.Instr defined in the play Session are available to be rendered offline without the need to be registered

Parameters:
  • name (str) – the name of this preset

  • instrdef (Instr) – the csoundengine.Instr instance

Return type:

None

registerPreset(presetdef)[source]

Register the given PresetDef with this renderer

Parameters:

presetdef (PresetDef) – the preset to register. Any global/init code declared by the preset will be made available to this renderer

Return type:

bool

Returns:

to adjust to the Renderer parent class we always return False since offline rendering does not need to sync

registeredPresets: dict[str, presetdef.PresetDef]

Maps preset name to preset definition

releaseBus(busnum)[source]

Signal that we no longer use the given bus

Parameters:

busnum (int) – the bus token as returned by OfflineRenderer.assignBus()

Return type:

None

render(outfile='', wait=None, verbose=None, openWhenDone=False, compressionBitrate=None, endtime=None, ksmps=None, tail=None)[source]

Render the events scheduled until now.

You can access the rendering subprocess (a subprocess.Popen object) via lastRenderProc()

Parameters:
  • outfile – the soundfile to generate. Use “?” to save via a GUI dialog, None will render to a temporary file

  • wait (Optional[bool]) – if True, wait until rendering is done

  • verbose (Optional[bool]) – if True, show output generated by csound itself (print statements and similar opcodes still produce output)

  • endtime (Optional[float]) – if given, crop rendering to this absolute time (in seconds)

  • compressionBitrate (Optional[int]) – the compression bit rate when rendering to .ogg (in kb/s, the default can be configured in config['.rec.compressionBitrate']

  • openWhenDone – if True, open the rendered soundfile in the default application

  • ksmps (Optional[int]) – the samples per cycle used when rendering

  • tail (Optional[float]) – an extra time at the end of the render to make room for long decaying sounds / reverbs. If given, overrides the tail parameter given at init.

Return type:

str

Returns:

the path of the rendered file

Example

>>> from maelzel.core import *
>>> scale = Chain([Note(n) for n in "4C 4D 4E 4F 4G".split()])
>>> playback.playSession().defInstr('reverb', r'''
... |kfeedback=0.6|
... amon1, amon2 monitor
... a1, a2 reverbsc amon1, amon2, kfeedback, 12000, sr, 0.6
... outch 1, a1-amon1, 2, a2-amon2
... ''')
>>> presetManager.defPresetSoundfont('piano', '/path/to/piano.sf2')
>>> renderer = playback.OfflineRenderer()
>>> renderer.schedEvents(scale.events(instr='piano'))
>>> renderer._sched('reverb', priority=2)
>>> renderer.render('outfile.wav')
renderedSample()[source]

Returns the last rendered soundfile as a maelzel.snd.audiosample.Sample

Return type:

Sample

renderedSoundfiles: list[str]

A list of soundfiles rendered with this renderer

sched(instrname, delay=0.0, dur=-1.0, priority=1, args=None, whenfinished=None, relative=True, **kws)[source]

Schedule a csound event

This method can be used to schedule non-preset based instruments when rendering offline (things like global effects, for example), similarly to how a user might schedule a non-preset based instrument in real-time.

If an OfflineRenderer is used as a context manager it is also possible to call the session’s ._sched method directly since its _sched callback is rerouted to call this OfflineRenderer instead

Parameters:
  • instrname (str) – the instr. name

  • delay – start time

  • dur – duration

  • priority – priority of the event

  • args (Union[list[float], dict[str, float], None]) – any pfields passed to the instr., starting at p5

  • whenfinished – this argument does nothing under this context. It is only present to make the signature compatible with the interface

  • relative – dummy argument, here to conform to the signature of csoundengine’s Session.sched, which is redirected to this method when an OfflineRenderer is used as a context manager

  • **kws – named pfields

Return type:

SchedEvent

Returns:

the offline.ScoreEvent, which can be used as a reference by other offline events

Example

Schedule a reverb at a higher priority to affect all notes played. Notice that the reverb instrument is declared at the play Session (see play.getPlaySession()). All instruments registered at this Session are immediately available for offline rendering.

>>> from maelzel.core import *
>>> scale = Chain([Note(n) for n in "4C 4D 4E 4F 4G".split()])
>>> playback.playSession().defInstr('reverb', r'''
... |kfeedback=0.6|
... amon1, amon2 monitor
... a1, a2 reverbsc amon1, amon2, kfeedback, 12000, sr, 0.6
... outch 1, a1-amon1, 2, a2-amon2
... ''')
>>> presetManager.defPresetSoundfont('piano', '/path/to/piano.sf2')
>>> with playback.OfflineRenderer() as r:
...     r._sched('reverb', priority=2)
...     scale.play('piano')
schedEvent(event)[source]

Schedule a SynthEvent or a csound event

Parameters:

event (SynthEvent | Event) – a SynthEvent

Return type:

SchedEvent

Returns:

a SchedEvent

schedEvents(coreevents, sessionevents=None, whenfinished=None)[source]

Schedule multiple events as returned by MObj.events()

Parameters:
  • coreevents (list[SynthEvent]) – the events to schedule

  • sessionevents (Optional[list[Event]]) – csound events as packed within a csoundengine.session.SessionEvent

  • whenfinished (Optional[Callable]) – dummy arg, here to conform to the signature of the parent. Only makes sense in realtime

Return type:

SchedEventGroup

Returns:

a csoundengine.offline.SchedEventGroup. This can be used to modify scheduled events via set(), automate() or stop

Example

>>> from maelzel.core import *
>>> scale = Chain([Note(m, 0.5) for m in range(60, 72)])
>>> renderer = OfflineRenderer()
>>> renderer.schedEvents(scale.events(instr='piano'))
>>> renderer.render('outfile.wav')
property scheduledEvents: dict[int, SchedEvent]

The scheduled events

showAtExit

Display the results at exit if running in jupyter

sr

The sr. If not given, [‘rec.sr’] is used

tail

Extra time at the end of rendering to make space for reverbs or long-decaying sounds

timeRange()[source]

The time range of the scheduled events

Return type:

tuple[float, float]

Returns:

a tuple (start, end)

wait(timeout=0)[source]

Wait until finished rendering

Parameters:

timeout – a timeout (0 to wait indefinitely)

Return type:

None

writeCsd(outfile='?')[source]

Write the .csd which would render all events scheduled until now

Parameters:

outfile (str) – the path of the saved .csd

Return type:

str

Returns:

the outfile