OfflineRenderer¶
- class maelzel.core.offline.OfflineRenderer(outfile='', sr=None, ksmps=None, numchannels=None, tail=0.0, verbose=None, endtime=0.0, session=None)[source]¶
Bases:
Renderer
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 returnedsr (
Optional
[int
]) – the sr of the render (config key: ‘rec.sr’)ksmps (
Optional
[int
]) – the ksmps used for the recordingnumchannels (
Optional
[int
]) – number of channels of this renderer. If not set, this will depend on the scheduled events and the final call to .renderverbose (
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
torender()
Attributes Summary
The scheduled events
Methods Summary
assignBus
([kind, value, persist])Assign a bus of the given kind
Get all instruments available within this OfflineRenderer
getCsd
()Return the .csd as string
getInstr
(instrname)Get the csoundengine's Instr corresponding to instrname
Return the Session associated with this OfflineRenderer, if any
getSynth
(token)Get a synth by token/synthid
includeFile
(path)Add an include clause to this renderer.
isInstrDefined
(instrname)Is an Instr with the given name defined?
Is this a realtime renderer?
True if still rendering
Last rendered outfile, None if no soundfiles were rendered
Last process (subprocess.Popen) used for rendering
makeTable
([data, size, sr, tabnum])Create a table in this renderer
openLastOutfile
([timeout])Open last rendered soundfile in an external app
play
(obj, **kws)Schedule the events generated by this obj to be renderer offline
playSample
(source[, delay, dur, chan, gain, ...])Play a sample through this renderer
popLock
()Pop the lock of the audio engine (must be preceded by a pushLock)"
prepareEvent
(event)Prepare an event to be scheduled
prepareEvents
(events[, sessionevents])Prepare a series of events for scheduling
prepareInstr
(instr, priority)Reify an instance of instr at the given priority
preparePreset
(presetdef, priority)Prepare a preset to be used
prepareSessionEvent
(sessionevent)Prepare a session event
pushLock
()Lock the audio engine
readSoundfile
(soundfile[, chan, skiptime])Read a soundfile into the renderer
registerInstr
(name, instrdef)Register a csoundengine.Instr to be used with this OfflineRenderer
registerPreset
(presetdef)Register the given PresetDef with this renderer
releaseBus
(busnum)Signal that we no longer use the given bus
render
([outfile, wait, verbose, ...])Render the events scheduled until now.
Returns the last rendered soundfile as a
maelzel.snd.audiosample.Sample
sched
(instrname[, delay, dur, priority, ...])Schedule a csound event
schedDummyEvent
([dur])Schedule a dummy synth
schedEvent
(event)Schedule a SynthEvent or a csound event
schedEvents
(coreevents[, sessionevents, ...])Schedule multiple events as returned by
MObj.events()
show
()If inside jupyter, force a display of this OfflineRenderer
sync
()Block until the audio engine has processed its immediate events
The time range of the scheduled events
wait
([timeout])Wait until finished rendering
writeCsd
([outfile])Write the .csd which would render all events scheduled until now
Attributes Documentation
- scheduledEvents¶
The scheduled events
Methods Documentation
- 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)
- 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
- 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
- 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
- isInstrDefined(instrname)¶
Is an Instr with the given name defined?
- Return type:
bool
- isRendering()[source]¶
True if still rendering
- Return type:
bool
- Returns:
True if rendering is still in course
- 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 datasize (
int
) – if data is not given, an empty table of the given size is created. Otherwise, this parameter is ignoredsr (
int
) – the sample rate of the data, if applicabletabnum (
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 offlinekws – 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
- popLock()¶
Pop the lock of the audio engine (must be preceded by a pushLock)”
This only makes sense for realtime rendering and is a no-op when rendering offline
- Return type:
None
- prepareEvent(event)¶
Prepare an event to be scheduled
- Parameters:
event (
SynthEvent
) – the event to schedule- Return type:
bool
- Returns:
True if the operation performed some action on the audio engine
- prepareEvents(events, sessionevents=None)¶
Prepare a series of events for scheduling
All init codes which need to be compiled are compiled and synched, then all presets are prepared for the given priority. This method minimizes the number of syncs needed.
- Parameters:
events (
list
[SynthEvent
]) – the core events to preparesessionevents (
Optional
[list
[Event
]]) – any session events
- Return type:
bool
- Returns:
True if the renderer needs to be synched. The called is resposible for calling the
Renderer.sync()
method
- 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 Instrpriority (
int
) – the priority to instantiate this instr with. Priorities start with 1
- Return type:
bool
- Returns:
False
- preparePreset(presetdef, priority)¶
Prepare a preset to be used
- Parameters:
presetdef (
PresetDef
) – the preset definitionpriority (
int
) – the priority to use
- Return type:
bool
- Returns:
True if this operation performed some action on the audio engine. This can be used to sync the audio engine if needed.
- prepareSessionEvent(sessionevent)[source]¶
Prepare a session event
- Parameters:
sessionevent (
Event
) – the session event to prepare. This is mostly used internally- Return type:
None
- pushLock()¶
Lock the audio engine
This only makes sense for realtime rendering and is a no-op when rendering offline
- Return type:
None
- readSoundfile(soundfile, chan=0, skiptime=0.0)[source]¶
Read a soundfile into the renderer
- Parameters:
soundfile (
str
) – the soundfile to readchan – 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 presetinstrdef (
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
- releaseBus(busnum)[source]¶
Signal that we no longer use the given bus
- Parameters:
busnum (
int
) – the bus token as returned byOfflineRenderer.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) vialastRenderProc()
- 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 doneverbose (
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 inconfig['.rec.compressionBitrate']
openWhenDone – if True, open the rendered soundfile in the default application
ksmps (
Optional
[int
]) – the samples per cycle used when renderingtail (
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:
- 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. namedelay – 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 p5whenfinished – 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')
- schedDummyEvent(dur=0.001)¶
Schedule a dummy synth
- schedEvent(event)[source]¶
Schedule a SynthEvent or a csound event
- Parameters:
event (
SynthEvent
|Event
) – aSynthEvent
- 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 schedulesessionevents (
Optional
[list
[Event
]]) – csound events as packed within a csoundengine.session.SessionEventwhenfinished (
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 viaset()
,automate()
orstop
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')
- show()¶
If inside jupyter, force a display of this OfflineRenderer
- Return type:
None
- sync()¶
Block until the audio engine has processed its immediate events
- Return type:
None
- timeRange()[source]¶
The time range of the scheduled events
- Return type:
tuple
[float
,float
]- Returns:
a tuple (start, end)