OfflineEngine Class#

The OfflineEngine class represents an offline csound process rendering to a soundfile instead of to the dac. An OfflineEngine is, for the most part, a drop-in replacement of the Engine class. The main difference is that for an OfflineEngine time needs to be advanced explicitely via its perform() method.

At any moment it is possible to interact with the offline csound process. While an OfflineEngine is running it is possible to query variables, load resources, read and write to channels, etc.

Example 1#

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()
_images/offlineengine-example1.png

Example 2: sound analysis#

TODO


class csoundengine.offlineengine.OfflineEngine(sr=44100, ksmps=64, outfile='', nchnls=2, a4=0, globalcode='', numAudioBuses=None, numControlBuses=None, quiet=True, includes=None, sampleAccurate=False, encoding='', commandlineOptions=None)[source]#

Non-real-time engine using the csound API

This is similar to an csoundengine.engine.Engine but it renders offline to a soundfile

Parameters:
  • sr – sample rate

  • ksmps (int) – samples per cycle

  • outfile (str) – soundfile to render to. If not given a tempfile is used

  • nchnls – number of output channels

  • a4 (int) – reference frequency

  • numAudioBuses (int | None) – number of audio buses (see Bus Opcodes)

  • numControlBuses (int | None) – number of control buses (see Bus Opcodes)

  • quiet – if True, suppress output of csound (-m 0)

  • includes (list[str] | None) – a list of files to include. Can be added later via Engine.includeFile()

  • sampleAccurate – use sample-accurate scheduling

  • commandlineOptions (list[str] | None) – command line options passed verbatim to the csound process when started

  • encoding – the sample encoding of the rendered file, given as ‘pcm<bits>’ or ‘float<bits>’, where bits presents the bit-depth (for example, ‘pcm16’, ‘pcm24’, ‘float32’, etc). If no encoding is given a suitable default for the sample format is chosen.

Methods:

compile(code)

Send orchestra code to csound

assignEventId(instr)

Assign a unique p1 value for the given instrument number

sched(instr[, delay, dur, args, unique, comment])

Schedule an instrument

unsched(p1[, delay])

Stop a playing event

nohistory()

A context manager to suppress tracking history

setEndMarker(time)

Set the end marker

perform([endtime, extratime])

Advance the time, performing any scheduled events within the current time and the end time

cancel([remove])

Cancel performance of this engine

stop([render, extratime])

Stop this csound process, optionally rendering any pending events

strSet(s)

Assign a numeric index to a string to be used inside csound

inputMessage(msg)

Schedule a score line

readSoundfile(path[, tabnum, chan, ...])

Read a soundfile into a table (via GEN1), returns the table number

queryVariable(variable)

Query the value of a csound variable via the return opcode

call(func)

Call an init-time csound function, returns the result

makeEmptyTable(size[, numchannels, sr, delay])

Create an empty table, returns the index of the created table

channelPointer(channel[, kind, mode])

Returns a numpy array aliasing the memory of a control or audio channel

initChannel(channel[, value, kind, mode])

Create a channel and set its initial value

getControlChannel(channel)

Get the value of a control channel

fillTable(tabnum, data)

Fill an existing table with data

makeTable(data[, sr, tabnum, delay])

Create a new table and fill it with data.

elapsedTime()

Reports the logical elapsed time of this engine

playSample(tabnum[, delay, chan, speed, ...])

Play a sample already loaded into a table.

automatep(p1, pfield, pairs[, mode, delay, ...])

Automate a pfield of a scheduled event

rewind([offset])

Unschedule future events and set the time pointer to the given offset

generateCsd()

Generate a Csd from this OfflineEngine

write(outfile)

Dump this OfflineEngine as a .csd

includeFile(include)

Add an #include file to this Engine

playSoundFromDisk(path[, delay, dur, chan, ...])

Play a soundfile from disk via diskin2

setp(p1, *pairs[, delay])

Modify a pfield of an active note

assignBus([kind, value, persist])

Assign one audio/control bus, returns the bus number.

releaseBus(bus[, delay])

Release a persistent bus

writeBus(bus, value[, delay])

Set the value of a control bus

openOutfile([app])

Open the generated soundfile in an external app

Attributes:

now

The current elapsed time

compile(code)[source]#

Send orchestra code to csound

The code sent can be any orchestra code

Parameters:

code (str) – the code to compile

Return type:

None

assignEventId(instr)[source]#

Assign a unique p1 value for the given instrument number

This is used internally to assign a fractional p1 when called sched with unique=True, but it can also be used to generate unique p1 for OfflineEngine.inputMessage() or when using csound’s schedule with OfflineEngine.compile()

Parameters:

instr (int | str) – the instrument number

Return type:

float

Returns:

a unique fractional p1

sched(instr, delay=0.0, dur=-1.0, *pfields, args=None, unique=False, comment='', **namedpfields)[source]#

Schedule an instrument

Parameters:
  • instr (int | float | str) – the instrument number/name. If it is a fractional number, that value will be used as the instance number. An integer or a string will result in a unique instance assigned by csound if unique is True. Named instruments with a fractional number can also be scheduled (for example, for an instrument named “myinstr” you canuse “myinstr.001”)

  • delay – start time, relative to the elapsed time. (see OfflineEngine.now)

  • dur – duration of the event

  • args (ndarray | list[float | str] | None) – any other args expected by the instrument, starting with p4 (as a list of floats/strings, or a numpy array). Any string arguments will be converted to a string index via strSet. These can be retrieved in csound via strget

  • unique – if True, assign a unique p1

  • namedpfields – pfields can be given as keyword arguments of the form p4=…, p6=… Defaults are filled with values defined via pset

Return type:

float | str

Returns:

a fractional p1 of the instr started, which identifies this event. If instr is a fractional named instr, like “synth.01”, then this same instr is returned as eventid (as a string).

Example

from csoundengine import *
e = Engine()
e.compile(r'''
  instr 100
    pset 0, 0, 0, 1000, 2000, 0, 9.0
    kfreq = p4
    kcutoff = p5
    Smode strget p6
    iq = p7
    asig vco2 0.1, kfreq
    if strcmp(Smode, "lowpass") == 0 then
      asig moogladder2 asig, kcutoff, 0.95
    else
      asig K35_hpf asig, kcutoff, iq
    endif
    outch 1, asig
  endin
''')
eventid = e.sched(100, 2, args=[200, 400, "lowpass"])
# simple automation in python
for cutoff in range(400, 3000, 10):
    e.setp(eventid, 5, cutoff)
    time.sleep(0.01)
e.unsched(eventid)
#
# To ensure simultaneity between events:
now = e.elapsedTime()
for t in np.arange(2, 4, 0.2):
    e.sched(100, t+now, 0.2, relative=False, p7=9.8)

See also

unschedAll()

unsched(p1, delay=0)[source]#

Stop a playing event

If p1 is a round number, all events with the given number are unscheduled. Otherwise only an exact matching event is unscheduled, if it exists

Parameters:
  • p1 (float | str) – the instrument number/name to stop

  • delay (float) – absolute time to turnoff the given event. A value of 0 means to unschedule it at the current time

Return type:

None

Example

>>> from csoundengine import *
>>> e = Engine(...)
>>> e.compile(r'''
... instr sine
...   a0 oscili 0.1, 1000
...   outch 1, a0
... endin
... ''')
>>> # sched an event with indefinite duration
>>> eventid = e.sched(10, 0, -1)
>>> e.unsched(eventid, 10)

See also

unschedAll()

nohistory()[source]#

A context manager to suppress tracking history

setEndMarker(time)[source]#

Set the end marker

When calling OfflineEngine.perform(), performance will be advanced up to this absolute time

The current end time can be queried via the OfflineEngine.endtime attribute

Return type:

None

perform(endtime=0.0, extratime=0.0)[source]#

Advance the time, performing any scheduled events within the current time and the end time

By default, perform until the end marker. The end marker is set by the last end time of an event. NB: Events with infinite duration do not modify the end marker. Use extratime to assign rendering time for such events.

This method is called implicitely at object destruction. To prevent implicit rendering, call OfflineEngine.stop() with renderPending=False

The rendering process is finished when OfflineEngine.stop() is called, which happens implicitely at object destrution. If the rendered audiofile needs to be accessed immediately, then OfflineEngine.stop() needs to be called explicitely

Note

stop() will call perform() if there are any pending events, so in order to render a process to completion, only stop() needs to be called

Parameters:
  • endtime – if given, overrides the endtime of the engine

  • extratime – time added to the current end marker, it is not taken into account if endtime is given

Return type:

None

Example

from csoundengine import OfflineEngine
import sndfileio
e = OfflineEngine()
e.compile(r'''
instr pitchtrack
  itabnum = p4   ; the sound source
  itabfreq = p5  ; the table where to put tracked pitch. The table must be big enough
  itabsize = ftlen(itabfreq)
  ifftsize = 2048
  ifftsize2 = ifftsize * 4  ; this second anaylsis helps smooth the result
  iwtype = 0        ; hamming
  kcount init 1     ; the first element is the element count
  aouts[] loscilx 1, 1, itabnum, 4, 1
  a0 = aouts[0]     ; only analyze first channel
  a0d = delay(a0, ifftsize2 * 0.5 / sr)  ; shift the original signal
  fsig  pvsanal a0d, ifftsize, 512, ifftsize, iwtype
  fsig2 pvsanal a0, ifftsize2, 512, ifftsize2, iwtype
  kfreq, kamp pvspitch fsig, 0.1
  kfreq2, kamp2 pvspitch fsig2, 0.08
  if kcount >= itabsize || detectsilence(a0, db(-90), 0.1) == 1 then
    turnoff
  endif
  if (kfreq2 == 0 ? 1 : kfreq / kfreq2) < 0.5 then
    kfreq = kfreq2
  endif
  tabw kfreq, kcount, itabfreq
  kcount += 1
  tabw kcount, 0, itabfreq
  ; To validate the analysis, we output the original sound and the resynthesized audio
  outs delay(a0, ifftsize + ifftsize2*0.5), vco2(kamp, kfreq)
endin
''')

sndtab = e.readSoundfile(sndfile)
duration = sndfileio.info(sndfile).duration
numcycles = int((duration * e.sr / e.ksmps)
freqtab = e.makeEmptyTable(numcycles + 100)
e.sched('pitchtrack', 0, duration + 0.1, sndtab, freqtab)
# Advance time until analysis has been done
e.perform()
# Now retrieve information
outarr = e.getTableData(freqtab)
datalen = outarr[0]
freqs = outarr[1:1+datalen]
# At any moment the user can access the generated soundfile via the
# renderjob variable, even if the engine is still active.
e.renderjob.openOutfile()
# Stop the engine to clean up
e.stop()
cancel(remove=True)[source]#

Cancel performance of this engine

Parameters:

remove – if True, remove the generated outfile

Return type:

None

stop(render=True, extratime=0.0)[source]#

Stop this csound process, optionally rendering any pending events

Parameters:
  • render – if True, advance the clock to render any pending scheduled event.

  • extratime – if render is True, add extra render time to allow for decays

Return type:

RenderJob | None

Returns:

a RenderJob containing information about the rendered file, or None if no render took place.

strSet(s)[source]#

Assign a numeric index to a string to be used inside csound

Parameters:

s (str) – the string to set

Return type:

int

Returns:

the index associated with s. When passed to a csound instrument it can be retrieved via strget.

inputMessage(msg)[source]#

Schedule a score line

At the moment, due to a limitation in the csound scheduler input messages are only scheduled at the beginning of the performance. Any meesage scheduled after OfflineEngine.perform() has been called will be ignored

Parameters:

msg (str) – the message in score format ('i1 0.5 3 ...')

Return type:

None

Returns:

the p1, will be 0 if a named instrument is used

readSoundfile(path, tabnum=0, chan=0, skiptime=0.0, delay=0.0, unique=True)[source]#

Read a soundfile into a table (via GEN1), returns the table number

Parameters:
  • path (str) – the path to the output – “?” to open file interactively

  • tabnum – if given, a table index. If None, an index is autoassigned

  • chan – the channel to read. 0=read all channels

  • skiptime – time to skip at the beginning of the soundfile.

  • delay – performance time at which to read the soundfile

  • unique – if False and the same file with the same params is already loaded, the existing table is returned

Return type:

int

Returns:

the table number. Information about the read soundfile can be obtained via OfflineEngine.tableInfo()

queryVariable(variable)[source]#

Query the value of a csound variable via the return opcode

Return type:

float

Example

>>> engine.compile(r'''
... gkfoo init 0
... instr 100
...   gkfoo = p4
... endin
... ''')
>>> engine.sched(100, 0, 0, 314)
>>> engine.perform()
>>> engine.queryVariable('gkfoo')
314.0
call(func)[source]#

Call an init-time csound function, returns the result

Parameters:

func (str) – the function to call, like ‘ftgen(200, 0, 100, 2, 0)’. It must be an init-time function returning one init value

Return type:

float

Returns:

the value returned by the function

Example

# Create an empty table manually with size 100 >>> engine.compile(r’i0 = ftgen(200, 0, 100, 2, 0)’) # Check that the size is correct >>> engine.call(‘ftlen(200)’) 100

makeEmptyTable(size, numchannels=1, sr=0, delay=0.0)[source]#

Create an empty table, returns the index of the created table

Parameters:
  • size (int) – the size of the table

  • numchannels – if the table will be used to hold audio, the number of channels of the audio

  • sr – the samplerate of the audio, if the table is used to hold audio

  • delay – when to create the table

Return type:

int

Returns:

the table number

channelPointer(channel, kind='control', mode='rw')[source]#

Returns a numpy array aliasing the memory of a control or audio channel

If the channel does not exist, it will be created with the given kind and set to the given mode. The returned numpy arrays are internally cached and are valid as long as this Engine is active. Accessing the channel through the pointer is not thread-safe.

Parameters:
  • channel (str) – the name of the channel

  • kind – one of ‘control’ or ‘audio’ (string channels are not supported yet)

  • mode – the kind of channel, ‘r’, ‘w’ or ‘rw’

Return type:

ndarray

Returns:

a numpy array of either 1 or ksmps size

See also

Engine.setChannel()

initChannel(channel, value=0, kind='', mode='r')[source]#

Create a channel and set its initial value

Parameters:
  • channel (str) – the name of the channel

  • value (float | str | ndarray) – the initial value of the channel, will also determine the type (k, a, S)

  • kind – One of ‘k’, ‘S’, ‘a’. Use None to auto determine the channel type.

  • mode – r for read, w for write, rw for both.

Return type:

None

Note

the mode is set from the perspective of csound. A read (input) channel is a channel which can be written to by the api and read from csound. An write channel (output) can be written by csound and read from the api

Example

>>> from csoundengine import *
>>> e = Engine()
>>> e.initChannel("mastergain", 1.0)
>>> e.compile(r'''
... instr 100
...   asig oscili 0.1, 1000
...   kmastergain = chnget:k("mastergain")
...   asig *= intrp(kmastergain)
... endin
... ''')
>>> eventid = e.sched(100)
>>> e.setChannel("mastergain", 0.5)
getControlChannel(channel)[source]#

Get the value of a control channel

Parameters:

channel (str) – the name of the channel

Return type:

float

Returns:

the value of the channel. Raises KeyError if the channel does not exist.

fillTable(tabnum, data)[source]#

Fill an existing table with data

If data is bigger than the table itself, then only the data which fits in the table is copied. If, on the contrary, the data is smaller than the table, then the rest of the table is left unmodified. For more control considere using getTableData()

Parameters:
  • tabnum (int) – the table number of an already existing table

  • data (Union[ndarray, Sequence[float]]) – the data to put into the table

Return type:

None

makeTable(data, sr=0, tabnum=-1, delay=0.0)[source]#

Create a new table and fill it with data.

Parameters:
  • data (Union[ndarray, Sequence[float]]) – the data used to fill the table

  • tabnum (int) – the table number. If -1, a number is assigned by the engine. If 0, a number is assigned by csound (this operation will be blocking if no callback was given)

  • sr (int) – only needed if filling sample data. If given, it is used to fill the table metadata in csound, as if this table had been read via gen01

  • delay – when to allocate the table

Return type:

int

Returns:

the index of the new table

property now: float#

The current elapsed time

This is the same as OfflineEngine.elapsedTime()

elapsedTime()[source]#

Reports the logical elapsed time of this engine

Return type:

float

playSample(tabnum, delay=0.0, chan=1, speed=1.0, gain=1.0, fade=0.0, starttime=0.0, lagtime=0.01, dur=-1.0)[source]#

Play a sample already loaded into a table.

Speed and gain can be modified via setp while playing

Parameters:
  • tabnum (int) – the table where the sample data was loaded

  • delay – when to start playback

  • chan – the first channel to send output to (channels start with 1)

  • speed – the playback speed

  • gain – a gain applied to this sample

  • fade – fadein/fadeout time in seconds

  • starttime – playback can be started from anywhere within the table

  • lagtime – a lag value for dynamic pfields (see below)

  • dur – the duration of playback. Use -1 to play until the end

Return type:

float

Returns:

the instance number of the playing instrument.

Dynamic Fields

  • p4: gain

  • p5: speed

Example

>>> from csoundengine import *
>>> e = Engine()
>>> import sndfileio
>>> sample, sr = sndfileio.sndread("stereo.wav")
>>> # modify the samples in python
>>> sample *= 0.5
>>> table = e.makeTable(sample, sr=sr, block=True)
>>> eventid = e.playSample(table)
... # gain (p4) and speed (p5) can be modified while playing
>>> e.setp(eventid, 5, 0.5)   # Play at half speed
automatep(p1, pfield, pairs, mode='linear', delay=0.0, overtake=False)[source]#

Automate a pfield of a scheduled event

Parameters:
  • p1 (float | str) – the fractional instr number of a running event, or an int number to modify all running instances of that instr

  • pfield (int | str) – the pfield index. For example, if the pfield to modify if p4, pidx should be 4. Values of 1, 2, and 3 are not allowed.

  • pairs (Union[Sequence[float], ndarray]) – the automation data is given as a flat data. of pairs (time, value). Times are relative to the start of the automation event

  • mode – one of ‘linear’, ‘cos’, ‘expon(xx)’, ‘smooth’. See the csound opcode interp1d for more information (https://csound-plugins.github.io/csound-plugins/opcodes/interp1d.html)

  • delay – the time delay to start the automation, relative to the elapsed time

  • overtake – if True, the first value of pairs is replaced with the current value in the running instance

Return type:

float

Returns:

the p1 associated with the automation synth

Example

>>> e = OfflineEngine()
>>> e.compile(r'''
... instr 100
...   kfreq = p4
...   outch 1, oscili:a(0.1, kfreq)
... endin
... ''')
>>> eventid = e.sched(100, 0, 10, args=(1000,))
>>> e.automatep(eventid, 4, [0, 1000, 3, 200, 5, 200])

See also

setp(), automateTable()

rewind(offset=0.0)[source]#

Unschedule future events and set the time pointer to the given offset

Return type:

None

generateCsd()[source]#

Generate a Csd from this OfflineEngine

This can be used to export a project file and use the csound binary to render it. It might also be useful for debugging

Return type:

Csd

Returns:

the generated Csd

write(outfile)[source]#

Dump this OfflineEngine as a .csd

This will include all code, instruments and opcodes compiled until now as well as any events scheduled, etc.

Any data files added are written to a folder '<csdfile>.assets' besides the generated .csd file.

Parameters:

outfile (str) – the path of the generated .csd file

Return type:

None

includeFile(include)[source]#

Add an #include file to this Engine

Parameters:

include (str) – the path to the include file

playSoundFromDisk(path, delay=0.0, dur=-1, chan=0, speed=1.0, fade=0.01)[source]#

Play a soundfile from disk via diskin2

Parameters:
  • path (str) – the path to the output

  • delay – time offset to start playing

  • dur – duration of playback, use -1 to play until the end of the file

  • chan – first channel to output to

  • speed – playback speed (2.0 will sound an octave higher)

  • fade – fadein/out in seconds

Return type:

float

Returns:

the instance number of the scheduled event

setp(p1, *pairs, delay=0.0)[source]#

Modify a pfield of an active note

Multiple pfields can be modified simultaneously. It only makes sense to modify a pfield if a control-rate (k) variable was assigned to this pfield (see example)

Parameters:
  • p1 (int | float | str) – the p1 of the instrument to automate. A float or a “<name>.<instanceid>” will set the value for a specific instance, an int or a unqualified name will set the value of the given parameter for all instances

  • *pairs – each pair consists of a pfield index and a value. The index is an int, matching the pfield number (4=p4, 5=p5, etc), the value can be a number (string values are not supported)

  • delay – when to start the automation

Return type:

None

Example

>>> engine = OfflineEngine(...)
>>> engine.compile(r'''
... instr foo
...   kamp = p5
...   kfreq = p6
...   a0 oscili kamp, kfreq
...   outch 1, a0
... endin
... ''')
>>> p1 = engine.sched('foo', args=[0.1, 440], unique=True)
>>> p1
'foo.0001'
>>> engine.setp(p1, 5, 0.2, delay=0.5)
assignBus(kind='', value=None, persist=False)[source]#

Assign one audio/control bus, returns the bus number.

Audio buses are always mono.

Parameters:
  • kind – the kind of bus, “audio” or “control”. If left unset and value is not given it defaults to an audio bus. Otherwise, if value is given a control bus is created. Explicitely asking for an audio bus and setting an initial value will raise an expection

  • value (float | None) – for control buses it is possible to set an initial value for the bus. If a value is given the bus is created as a control bus. For audio buses this should be left as None

  • persist – if True the bus created is kept alive until the user calls releaseBus(). Otherwise, the bus is reference counted and is released after the last user releases it.

Return type:

int

Returns:

the bus token, can be passed to any instrument expecting a bus to be used with the built-in opcodes busin, busout, etc.

A bus created here can be used together with the built-in opcodes busout, busin and busmix. A bus can also be created directly in csound by calling busassign

A non-persistent bus is reference counted: it is kept alive as long as there are clients using it and it is released when it is not used anymore. At creation the bus is “parked”, waiting to be used by any client. As long as no clients use it, the bus stays in this state and is ready to be used. A persistent bus stays alive until it is freed via OfflineEngine.releaseBus()

Order of evaluation is important: audio buses are cleared at the end of each performance cycle and can only be used to communicate from a low priority to a high priority instrument.

For more information, see Bus Opcodes

Example

Pass audio from one instrument to another. The bus will be released after the events are finished.

>>> e = OfflineEngine(...)
>>> e.compile(r'''
... instr 100
...   ibus = p4
...   kfreq = 1000
...   asig vco2 0.1, kfreq
...   busout(ibus, asig)
... endin
... ''')
>>> e.compile(r'''
... instr 110
...   ibus = p4
...   asig = busin(ibus)
...   ; do something with asig
...   asig *= 0.5
...   outch 1, asig
... endin
... ''')
>>> bus = e.assignBus("audio")
>>> s1 = e.sched(100, 0, 4, (bus,))
>>> s2 = e.sched(110, 0, 4, (bus,))
>>> e.perform()

Modulate one instr with another, at k-rate. NB: control buses act like global variables, the are not cleared at the end of each cycle.

>>> e = OfflineEngine(...)
>>> e.compile(r'''
... instr 130
...   ibus = p4
...   ; lfo between -0.5 and 0 at 6 Hz
...   kvibr = linlin(lfo:k(1, 6), -0.5, 0, -1, 1)
...   busout(ibus, kvibr)
... endin
...
... instr 140
...   itranspbus = p4
...   kpitch = p5
...   ktransp = busin:k(itranspbus, 0)
...   kpitch += ktransp
...   asig vco2 0.1, mtof(kpitch)
...   outch 1, asig
... endin
... ''')
>>> bus = e.assignBus()
>>> s1 = e.sched(140, 0, -1, (bus, 67))
>>> s2 = e.sched(130, 0, -1, (bus,))  # start moulation
>>> e.unsched(s2)        # remove modulation
>>> e.writeBus(bus, 0)   # reset value
>>> e.unschedAll()

See also

writeBus(), readBus(), releaseBus()

releaseBus(bus, delay=None)[source]#

Release a persistent bus

Parameters:
  • bus (int) – the bus to release, as returned by OfflineEngine.assignBus()

  • delay (float | None) – when to release the bus. None means now

Return type:

None

See also

assignBus()

writeBus(bus, value, delay=0.0)[source]#

Set the value of a control bus

Normally a control bus is set via another running instrument, but it is possible to set it directly from python. The first time a bus is set or queried there is short delay, all subsequent operations on the bus are very fast.

Parameters:
  • bus (int) – the bus token, as returned via Engine.assignBus()

  • value (float) – the new value

  • delay – if given, the modification is scheduled in the future

Return type:

None

See also

readBus() assignBus() automateBus()

Example

>>> e = Engine(...)
>>> e.compile(r'''
... instr 100
...   ifreqbus = p4
...   kfreq = busin:k(ifreqbus)
...   outch 1, vco2:a(0.1, kfreq)
... endin
... ''')
>>> freqbus = e.assignBus(value=1000)
>>> e.sched(100, 0, 4, args=[freqbus])
>>> e.writeBus(freqbus, 500, delay=0.5)
openOutfile(app='')[source]#

Open the generated soundfile in an external app

Return type:

None