Offline Rendering#
Offline rendering follows real-time processing very closely. The OfflineEngine
class represents a csound process running in offline mode and is an almost drop-in replacement to the
Engine class.
High-level rendering is implemented via the OfflineSession class,
which has the same interface as a Session
Example low-level API#
from csoundengine import OfflineEngine
import random
engine = OfflineEngine()
engine.compile(r'''
instr vco
pset 0, 0, 0, 263, 0.1, 1, 1000, 0.1, 0.5
ifreq = p4
iamp = p5
ktransp = p6
kcutoff = p7
ifade = p8
ifilterq = p9
kfreq = ifreq * ktransp
aout = vco2:a(iamp, kfreq)
iresonance = 0.6
idistortion = 0.
aout = lpf18(aout, kcutoff, iresonance, idistortion)
aout *= linsegr:a(0, ifade, 1, ifade, 0)
outch 1, aout
endin
''')
f0 = 130
for factor in [1, 2.76, 5.3, 5.4, 8.93]:
freq = f0 * factor
# with unique=True a fractional p1 is generated, this makes it
# possible to automate the event later
# NB: csoundengine parses instr code and is aware of names given to pfields
event = engine.sched('vco', engine.now, 8, unique=True,
ifreq=freq, iamp=0.1, kcutoff=freq*3, ifade=freq/f0* 0.5, ifilterq=0.8)
transp = random.uniform(0.92, 1.08)
# start automation of p6 at time=2. This case, modify the transposition factor,
# from 1 to a random value between 0.92 and 1.08
engine.automatep(event, 6, (0, 1, 5, transp), delay=2)
# The pfield can also be given by name. With overtake=True the value given
# to the pfield at init is used as the starting point
engine.automatep(event, 'kcutoff', (0, 0, 3, freq*1.1), overtake=True, delay=2 + factor*0.3)
# Advance time to actually perform the events. We give some extra time
# to account for fade outs.
engine.perform(extratime=5)
engine.stop()
Example (high-level API)#
from csoundengine import *
from pitchtools import *
session = OfflineSession(sr=44100, nchnls=2)
session.defInstr('saw', r'''
kmidi = p5
outch 1, oscili:a(0.1, mtof:k(kfreq))
''')
events = [
session.sched('saw', 0, 2, kmidi=ntom('C4')),
session.sched('saw', 1.5, 4, kmidi=ntom('4G')),
session.sched('saw', 1.5, 4, kmidi=ntom('4G+10'))
]
# offline events can be automated just like real-time events
events[0].automate('kmidi', (0, 0, 2, ntom('B3')), overtake=True)
events[1].set(delay=3, kmidi=67.2)
events[2].set(kmidi=80, delay=4)
session.render("out.wav")
It is possible to create an OfflineSession out of an existing
Session, by calling session.makeRenderer.
This creates an OfflineSession with all Instr and resources
(tables, include files, global code, etc.) in the Session already defined.
from csoundengine import *
session = Session()
session.defInstr('test', ...)
table = session.readSoundfile('path/to/soundfile')
session.sched('test', ...)
session.playSample(table)
# Render offline
renderer = session.makeRenderer()
renderer.sched('test', ...)
renderer.playSample('path/to/soundfile')
renderer.render('out.wav')
An alternative way to render offline given a live Session is to use the
rendering() method:
from csoundengine import *
session = Session()
session.defInstr('test', ...)
table = session.readSoundfile('path/to/soundfile')
with session.rendering('out.wav') as r:
r.sched('test', ...)
r.playSample(table)