Engine

Contents

Engine#

Engine class#

An Engine implements a simple interface to run and control a csound process.

from csoundengine import Engine
# create an engine with default options for the platform
engine = Engine()
engine.compile(r'''
  instr synth
    kmidinote = p4
    kamp = p5
    kcutoff = p6
    kfreq = mtof:k(kmidinote)
    asig = vco2:a(kamp, kfreq)
    asig = moogladder2(asig, kcutoff, 0.9)
    asig *= linsegr:a(0, 0.1, 1, 0.1, 0)
    outs asig, asig
  endin
''')

# start a synth with indefinite duration. This returns a unique (fractional)
# instance number
p1 = engine.sched("synth", args=[67, 0.1, 3000])

# any parameter with k-rate can be modified while running:
# change midinote
engine.setp(p1, 4, 67)

# modify cutoff
engine.setp(p1, 6, 1000, delay=4)

# stop the synth:
engine.unsched(p1)

See also Session for a higher level interface:

from csoundengine import *
session = Engine().session()
session.defInstr('mysynth', r'''
    |kmidinote=60, kamp=0.1, kcutoff=3000|
    kfreq = mtof:k(kmidinote)
    asig = vco2:a(kamp, kfreq)
    asig = moogladder2(asig, kcutoff, 0.9)
    aenv = linsegr:a(0, 0.1, 1, 0.1, 0)
    asig *= aenv
    outs asig, asig
''')
# Session sched returns a Synth object
synth = session.sched('mysynth', kmidinote=67, kcutoff=2000)

# Change the midinote after 2 seconds
synth.setp(kmidinote=60, delay=2)

Configuration#

Defaults for Engine / Session can be customized via:

from csoundengine import *
config.edit()

Hint

For more information, see Configuration

Interactive Use#

csoundengine is optimized to be used interactively and particularly within Jupyter. See Csoundengine inside Jupyter

IPython Magic#

csoundengine also defines a set of ipython/jupyter magics

_images/eventui.png

Classes:

Engine([name, sr, ksmps, backend, outdev, ...])

Implements a simple interface to run and control a csound process.

Functions:

getEngine(name)

Get an already created engine by name

activeEngines()

Returns the names of the active engines

class csoundengine.engine.Engine(name='', sr=0, ksmps=None, backend='default', outdev=None, indev=None, a4=0, nchnls=None, nchnls_i=None, realtime=False, buffersize=None, numbuffers=None, globalcode='', numAudioBuses=None, numControlBuses=None, quiet=None, udpserver=None, udpport=0, commandlineOptions=None, includes=None, midibackend='default', midiin=None, autosync=False, latency=None, numthreads=0)[source]#

Implements a simple interface to run and control a csound process.

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

  • sr – sample rate. If not given, the sr of the backend will be used, if possible

  • ksmps (int | None) – samples per k-cycle

  • backend (str) – passed to -+rtaudio (“?” to select interactively). If not given, the most appropriate backend will be used.

  • outdev (str | None) – the audio output device, passed to -o (“?” to select interactively). Leave unset to use the default

  • indev (str | None) – the audio input device, passed to -i (“?” to select interactively). Leave unset to use the default

  • a4 (int) – freq of a4

  • nchnls (int | None) – number of output channels (passed to nchnls). Leave unset to use the number of channels defined by the backend (if known)

  • nchnls_i (int | None) – number of input channels. Similar to nchnls. If not given it will either fallback to the number of input channels provided by the backend, or to nchnls

  • buffersize (int | None) – samples per buffer, corresponds to csound’s -b option

  • numbuffers (int | None) – the number of buffers to fill. Together with the buffersize determines the latency of csound and any communication between csound and the python host

  • globalcode (str) – code to evaluate as instr0 (global variables, etc.)

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

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

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

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

  • udpserver (bool | None) – if True, start a udp server for communication (see udpport)

  • udpport (int) – the udpport to use for real-time messages. 0=autoassign port

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

  • midiin (str | None) – if given, use this device as midi input. Can be ‘?’ to select from a list, or ‘all’ to use all devices. None indicates no midi input

  • latency (float | None) – an extra latency added when scheduling events to ensure synchronicity. See also Engine.lockClock() and Engine.pushClock()

Note

Any option with a default value of None has a corresponding slot in the config. Default values can be configured via config.edit(), see Configuration

Instrument Numbers#

An Engine defines internal instruments to perform some of its tasks (reading tables, sample playback, etc). To avoid clashes between these internal instruments and user instruments, there are some reserved instrument numbers: all instrument numbers from 1 to 99 are reserved for internal use, so the first available instrument number is 100.

Example

from csoundengine import *
# create an engine with default options for the platform
engine = Engine()
engine.compile(r'''
  instr synth
    kmidinote = p4
    kamp = p5
    kcutoff = p6
    asig = vco2:a(kamp, mtof:k(kmidinote))
    asig = moogladder2(asig, kcutoff, 0.9)
    asig *= linsegr:a(0, 0.1, 1, 0.1, 0)
    outs asig, asig
  endin
''')

# start a synth with indefinite duration. This returns a unique (fractional)
# instance number
p1 = engine.sched("synth", args=[67, 0.1, 3000])

# any parameter with k-rate can be modified while running
engine.setp(p1, 4, 60)

# modify cutoff
engine.setp(p1, 6, 1000, delay=4)

# stop the synth:
engine.unsched(p1)

Attributes:

activeEngines

Active engines mapped by name (class variable)

name

Name of this Engine

sr

Sample rate

backend

Name of the backend used (jack, portaudio, etc)

a4

Reference frequency for A4

ksmps

Number of samples per cycle

onecycle

Duration of one performance cycle (ksmps/sr)

outdev

Output device used

outdevName

Long name of the output device

indev

Input device

indevName

Long name of the input device

nchnls

Number of output channels

nchnls_i

Number of input channels

globalCode

Global (init) code to execute at the start of the Engine

extraOptions

Extra options passed to csound

commandlineOptions

All command line options used to start the engine

includes

List of include files

extraLatency

Added latency for better synch

numAudioBuses

Number of audio buses

numControlBuses

Number of control buses

csound

The csound object

autosync

If True, call .sync whenever is needed

bufferSize

Buffer size

numBuffers

Number of buffers to fill

midiBackend

Midi backend used

started

Has this engine already started?

numthreads

Number of threads to use in performance (corresponds to csound -j N)

midiin

Midi input device

udpPort

UDP port used (0 if no udp port is active)

blockSize

The size of the processing block in samples.

Methods:

reservedInstrRanges()

A dict containing reserved instr number ranges

userInstrumentsRange()

Returns the range of available instrument numbers

stop()

Stop this Engine

start()

Start this engine.

restart([wait])

Restart this engine.

registerOutvalueCallback(chan, func)

Set a callback to be fired when "outvalue" is used in csound

bufferLatency()

The latency of the communication to the csound process.

controlLatency()

Time latency between a scheduled action and its response.

sync([timeout, force, threshold])

Block until csound has processed its immediate events

needsSync()

True if ths engine has been modified

compile(code[, block])

Send orchestra code to the running csound instance.

evalCode(code)

Evaluate code, return the result of the evaluation

tableWrite(tabnum, idx, value[, delay])

Write to a specific index of a table

getTableData(idx[, flat])

Returns a numpy array pointing to the data of the table.

realElapsedTime([threshold])

Reports the elapsed time of the engine, independent of any locking

elapsedTime()

Returns the elapsed time since start of the engine

lockClock([lock])

Lock the elapsed time clock

isClockLocked()

Returns True if the clock is locked

pushLock([latency])

Lock the clock of this engine

popLock()

Reverts the action of pushLock, unlocking the clock

lockedClock([latency])

Context manager, locks and unlocks the reference time

sched(instr[, delay, dur, args, relative, ...])

Schedule an instrument

queryNamedInstr(instrname[, cached, callback])

Find the instrument number corresponding to instrument name

unsched(p1[, delay])

Stop a playing event

unschedFuture(p1)

Stop a future event

unschedAll()

Remove all playing and future events :rtype: None

session([priorities, maxControlsPerInstr, ...])

Return the Session corresponding to this Engine

reserveInstrRange(name, mininstrnum, maxinstrnum)

Declares the instrument numbers in the given range as reserved

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

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

makeTable(data[, tabnum, sr, block, callback])

Create a new table and fill it with data.

tableExists(tabnum)

Returns True if a table with the given number exists

setTableMetadata(tabnum, sr[, numchannels, ...])

Set metadata for a table holding sound samples.

callLater(delay, callback)

Call callback after delay, triggered by csound scheduler

plotTableSpectrogram(tabnum[, fftsize, ...])

Plot a spectrogram of the audio data in the given table

plotTable(tabnum[, sr])

Plot the content of the table via matplotlib.pyplot

schedSync(instr[, delay, dur, args, timeout])

Schedule an instr, wait for a sync message

channelPointer(channel[, kind, mode])

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

setChannel(channel, value[, method, delay])

Set the value of a software channel

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

Create a channel and set its initial value

getControlChannel(channel)

Get the value of a channel

fillTable(tabnum, data[, method, block])

Fill an existing table with data

tableInfo(tabnum[, cache])

Retrieve information about the given table

includeFile(include)

Add an #include file to this Engine

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

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

soundfontPlay(index, pitch[, amp, delay, ...])

Play a note of a previously loaded soundfont

soundfontPreparePreset(sf2path[, preset])

Prepare a soundfont's preset to be used

getUniqueInstrInstance(instr)

Returns a unique instance number (a float p1) for instr

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

Play a sample already loaded into a table.

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

Play a soundfile from disk via diskin2

setp(p1, *pairs[, delay])

Modify a pfield of an active note

getp(eventid, idx)

Get the current pfield value of an active note.

automateTable(tabnum, idx, pairs[, mode, ...])

Automate a table slot

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

Automate a pfield of a running event

strSet(s[, sync])

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

definedStrings()

Returns a dict mapping defined strings to their integer id

strGet(index)

Get a string previously set via strSet.

freeTable(tableindex[, delay])

Free the table with the given index

testAudio([dur, delay, period, mode, gaindb])

Test this engine's output

udpSendOrc(code)

Send orchestra code via UDP.

udpSendScoreline(scoreline)

Send a score line to csound via udp

udpSetChannel(channel, value)

Set a channel via UDP.

writeBus(bus, value[, delay])

Set the value of a control bus

automateBus(bus, pairs[, mode, delay, overtake])

Automate a control bus

readBus(bus[, default])

Read the current value of a control bus

releaseBus(bus)

Release a persistent bus :rtype: None

assignBus([kind, value, persist])

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

busSystemStatus()

Get debugging nformation about the status of the bus system

hasBusSupport()

Returns True if this Engine was started with bus support :rtype: bool

eventUI(eventid, **pargs)

Modify pfields through an interactive user-interface

activeEngines: dict[str, Engine] = {}#

Active engines mapped by name (class variable)

name#

Name of this Engine

sr: int#

Sample rate

backend#

Name of the backend used (jack, portaudio, etc)

a4: int | float#

Reference frequency for A4

ksmps: int#

Number of samples per cycle

onecycle: float#

Duration of one performance cycle (ksmps/sr)

outdev#

Output device used

outdevName#

Long name of the output device

indev#

Input device

indevName#

Long name of the input device

nchnls: int#

Number of output channels

nchnls_i: int#

Number of input channels

globalCode: str#

Global (init) code to execute at the start of the Engine

extraOptions: list[str]#

Extra options passed to csound

commandlineOptions: list[str]#

All command line options used to start the engine

includes: list[str]#

List of include files

extraLatency: float#

Added latency for better synch

numAudioBuses: int#

Number of audio buses

numControlBuses: int#

Number of control buses

csound: None | ctcsound.Csound#

The csound object

autosync: bool#

If True, call .sync whenever is needed

bufferSize: int#

Buffer size

numBuffers: int#

Number of buffers to fill

midiBackend: None | str#

Midi backend used

started#

Has this engine already started?

numthreads: int#

Number of threads to use in performance (corresponds to csound -j N)

midiin: csoundlib.MidiDevice | None#

Midi input device

udpPort#

UDP port used (0 if no udp port is active)

reservedInstrRanges()[source]#

A dict containing reserved instr number ranges

An Engine has some internal instruments for performing tasks like automation, bus support, etc. Moreover, if an Engine has an attached Session, the session will declare a range of instrument numbers as reserved.

This method returns all those reserved ranges in the form of a list of tuples, where each tuple represents a reserved range. Each tuple has the form (rangename: str, minInstrNumber: int, maxInstrNumber: int), where rangename is the name of the range, minInstrNumber and maxInstrNumber represent the instr numbers reserved

Any instr number outside of this range can be used. Bear in mind that when an Engine has an attached Session, compiling an instrument using a name instead of a number might

Return type:

list[tuple[str, int, int]]

userInstrumentsRange()[source]#

Returns the range of available instrument numbers

Notice that the first instrument numbers are reserved for internal instruments. If this Engine has an attached Session, the session itself will reserve a range of numbers for its events

Returns:

int, maxinstr: int) defining a range of available instrument numbers for user instruments.

Return type:

a tuple (mininstr

property blockSize: int#

The size of the processing block in samples.

csound defines two variables to control its communication with the audio backend, a hardware buffer (-B option) and a software buffer (-b option). With each audio backend these values are interpreted somewhat differently. In general it can be said that ksmps must divide the software buffer (-b) and the software buffer itself must divide the hardware buffer (-B). Common values for these are: ksmps=64, software buffer=256, hardware buffer=512

stop()[source]#

Stop this Engine

start()[source]#

Start this engine.

The call to .start() is performed as part of the init process and only needs to be called explicitely if the engine was previously stopped. If the engine has already been started this method does nothing

restart(wait=1)[source]#

Restart this engine. All defined instrs / tables are removed

Return type:

None

registerOutvalueCallback(chan, func)[source]#

Set a callback to be fired when “outvalue” is used in csound

Register a function func(channelname:str, newvalue: float) -> None, which will be called whenever the given channel is modified via the “outvalue” opcode. Multiple functions per channel can be registered

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

  • func (Callable[[str, float], None]) – a function of the form func(chan:str, newvalue: float) -> None

Return type:

None

bufferLatency()[source]#

The latency of the communication to the csound process.

bufferLatencySeconds = buffersize * numbuffers / sr

This latency depends on the buffersize and number of buffers.

Return type:

float

controlLatency()[source]#

Time latency between a scheduled action and its response.

This is normally ksmps/sr * 2 but the actual latency varies if the engine is being run in realtime (in that case init-pass is done async, which might result in longer latency).

Return type:

float

sync(timeout=None, force=False, threshold=2.0)[source]#

Block until csound has processed its immediate events

Parameters:
  • timeout (float | None) – a timeout in seconds; None = use default timeout as defined in the configuration (TODO: add link to configuration docs)

  • force – if True, sync even if not needed

  • threshold – if time since last modification is longuer than this threshold assume that sync is not needed

Return type:

bool

Returns:

True if it synced, False if no sync was performed

Raises TimeoutError if the sync operation takes too long

Example

>>> from csoundengine import *
>>> e = Engine(...)
>>> tables = [e.makeEmptyTable(size=1000) for _ in range(10)]
>>> e.sync()
>>> # do something with the tables
needsSync()[source]#

True if ths engine has been modified

Actions that modify an engine: code compilation, table allocation, …

Return type:

bool

compile(code, block=False)[source]#

Send orchestra code to the running csound instance.

The code sent can be any orchestra code

Parameters:
  • code (str) – the code to compile

  • block (bool) – if True, this method will block until the code has been compiled

Return type:

None

Raises CsoundError if the compilation failed

Note

If this instance has been started with a UDP port and the config option ‘prefer_udp’ is true, the code will be sent via udp. Otherwise the API is used. This might have an impact in the resulting latency of the operation, since using the API when running a performance thread can cause delays under certain circumstances

Example

>>> e = Engine()
>>> e.compile("giMelody[] fillarray 60, 62, 64, 65, 67, 69, 71")
>>> code = open("myopcodes.udo").read()
>>> e.compile(code)
evalCode(code)[source]#

Evaluate code, return the result of the evaluation

Parameters:

code (str) – the code to evaluate. Usually an expression returning a float value (see example)

Return type:

float

Returns:

the result of the evaluation

NB: this operation is synchronous and has a latency of at least self.bufferLatency()

Example

>>> e = Engine()
>>> e.compile(r'''
... instr myinstr
...   prints "myinstr!"
...   turnoff
... ''')
>>> e.compile(r'''
... opcode getinstrnum, i, S
...   Sinstr xin
...   inum nstrnum
...   xout inum
... endop''')
>>> e.evalCode('getinstrnum("myinstr")')
tableWrite(tabnum, idx, value, delay=0.0)[source]#

Write to a specific index of a table

Parameters:
  • tabnum (int) – the table number

  • idx (int) – the index to modify

  • value (float) – the new value

  • delay (float) – delay time in seconds. Use 0 to write synchronously

Return type:

None

getTableData(idx, flat=False)[source]#

Returns a numpy array pointing to the data of the table.

Any modifications to this array will modify the table itself.

Note

Multichannel audio is loaded into a csound table as a flat array with samples interleaved.

Parameters:
  • idx (int) – the table index

  • flat – if True, the data will be returned as a flat (1D) array even if the table holds a multi-channel sample.

Return type:

ndarray

Returns:

a numpy array pointing to the data array of the table. Raises IndexError if the table was not found

realElapsedTime(threshold=0.1)[source]#

Reports the elapsed time of the engine, independent of any locking

Parameters:

threshold – the reporting threshold. If this method is called multiple times during this time interval the engine time is extrapolated from the time reported by python and no call to csound is made

Return type:

float

Returns:

the time elapsed since start of the engine.

elapsedTime()[source]#

Returns the elapsed time since start of the engine

This time is used as a reference when scheduling events. Since scheduling itself takes a small but not negligible amount of time, when scheduling a great number of events, these will fall out of sync. For this reason the elapsed time can be used as a reference to schedule events in absolute time. Moreover, the elapsed time stays unmodified as long as the engine’s clock is locked for scheduling (see example)

Return type:

float

Example

>>> from csoundengine import Engine
>>> import numpy as np
>>> e = Engine()
>>> e.compile(r'''
... instr 100
...   ifreq = p4
...   outch 1, oscili:a(0.1, ifreq) * linseg:a(0, 0.01, 1, 0.1, 0)
... endin
... ''')
>>> now = e.elapsedTime()
>>> for t in np.arange(0, 60, 0.2):
...     e.sched(100, t+now, 0.15, args=[1000], relative=False)
...     e.sched(100, t+now, 0.15, args=[800], relative=False)
>>> # The same result can be achieved by locking the elapsed-time clock:
>>> with e.lockedClock():
...     for t in np.arange(0, 10, 0.2):
...         e.sched(100, t, 0.15, args=[1000])
...         e.sched(100, t, 0.15, args=[800])
lockClock(lock=True)[source]#

Lock the elapsed time clock

This ensures that events scheduled while the clock is locked will run in sync. For this to work all events scheduled must have some latency (they must run in the future)

Example

>>> from csoundengine import Engine
>>> import numpy as np
>>> e = Engine()
>>> e.compile(r'''
... instr 100
...   ifreq = p4
...   outch 1, oscili:a(0.1, ifreq) * linseg:a(0, 0.01, 1, 0.1, 0)
... endin
... ''')
>>> e.lockClock()
>>> for t in np.arange(0, 10, 0.2):
...     e.sched(100, t, 0.15, args=[1000])
...     e.sched(100, t, 0.15, args=[800])
>>> e.lockClock(False)
isClockLocked()[source]#

Returns True if the clock is locked

Return type:

bool

pushLock(latency=None)[source]#

Lock the clock of this engine

Allows for recursive locking, so users do not need to see if what the current state of the lock is

See also

Engine.popLock()

popLock()[source]#

Reverts the action of pushLock, unlocking the clock

lockedClock(latency=None)[source]#

Context manager, locks and unlocks the reference time

By locking the reference time it is possible to ensure that events which are supposed to be in sync are scheduled correctly into the future. :rtype: Engine

Note

A shortcut for this is to just use the engine as context manager:

with engine:
    engine.sched(...)
    engine.sched(...)
    engine.session().sched(...)
    ...

Example

>>> from csoundengine import Engine
>>> import numpy as np
>>> e = Engine()
>>> e.compile(r'''
... instr 100
...   ifreq = p4
...   outch 1, oscili:a(0.1, ifreq) * linseg:a(0, 0.01, 1, 0.1, 0)
... endin
... ''')
>>> with e.lockedClock():
...     for t in np.arange(0, 10, 0.2):
...         e.sched(100, t, 0.15, args=[1000])
...         e.sched(100, t, 0.15, args=[800])
sched(instr, delay=0.0, dur=-1.0, args=None, relative=True, unique=True)[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 – time to wait before instrument is started. If relative is False, this represents the time since start of the engine (see examples)

  • dur – duration of the event

  • args (Union[ndarray, Sequence[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

  • relative – if True, delay is relative to the scheduling time, otherwise it is relative to the start time of the engine. To get an absolute time since start of the engine, call engine.elapsedTime()

  • unique – if True, assign a unique p1

Return type:

float

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
    kfreq = p4
    kcutoff = p5
    Smode strget p6
    asig vco2 0.1, kfreq
    if strcmp(Smode, "lowpass") == 0 then
      asig moogladder2 asig, kcutoff, 0.95
    else
      asig K35_hpf asig, kcutoff, 9.0
    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)

See also

unschedAll()

queryNamedInstr(instrname, cached=True, callback=None)[source]#

Find the instrument number corresponding to instrument name

Parameters:
  • instrname (str) – the name of the instrument

  • cached – if True, results are cached

  • callback – if given, the operation is async and the callback will be called when the result is available. Callback is of the form func(instrname: str, instrnum: int) -> None. If no callback is given this method blocks until the instrument number is returned

Return type:

int

Returns:

the instr number if called without callback, 0 otherwise. If the instrument was not found (either because it was never compiled or the compilation is not ready yet) -1 will be returned

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) – if 0, remove the instance as soon as possible

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

unschedFuture(p1)[source]#

Stop a future event

Parameters:

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

Return type:

None

unschedAll()[source]#

Remove all playing and future events :rtype: None

session(priorities=None, maxControlsPerInstr=None, numControlSlots=None)[source]#

Return the Session corresponding to this Engine

Since each Engine can have only one associated Session, the parameters passed are only valid for the creation of the Session. Any subsequent call to this method returns the already created Session, and the arguments passed are not taken into consideration.

Parameters:
  • priorities (int | None) – the max. number of priorities for scheduled instrs

  • numControlSlots (int | None) – the total number of slots allocated for dynamic args. The default is determined by the config ‘dynamic_args_num_slots’

  • maxControlsPerInstr (int | None) – the max. number of dynamic args per instr (the default is set in the config ‘max_dynamic_args_per_instr’)

Return type:

Session

Returns:

the corresponding Session

Example

>>> from csoundengine import *
>>> session = Engine().session()
>>> session.defInstr("synth", r'''
... kamp  = p5    ; notice that p4 is reserved
... kmidi = p6
... asig vco2 kamp, mtof:k(kmidi)
... chnmix asig, "mix1"
... ''')
>>> session.defInstr("post", r'''
... a1 chnget "mix1"
... a2 chnget "mix2"
... aL, aR reverbsc a1, a2, 0.85, 12000, sr, 0.5, 1
... outch 1, aL, 2, aR
... chnclear "mix1", "mix2"
... ''')
>>> session.sched("post", priority=2)
>>> for i, midi in enumerate([60, 64, 67]):
...     session.sched("synth", delay=i, dur=4, kamp=0.1, kmidi=midi)
reserveInstrRange(name, mininstrnum, maxinstrnum)[source]#

Declares the instrument numbers in the given range as reserved

Instrument numbers within this range will not be allocated when using named instruments.

Parameters:
  • name (str) – the name of the reserved block

  • mininstrnum (int) – lowest instrument number to reserve

  • maxinstrnum (int) – highest instrument number to reserve (not included in the range)

Return type:

None

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

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

Parameters:
  • size – 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

Example

Use a table as an array of buses

>>> from csoundengine import *
>>> engine = Engine()
>>> source = engine.makeEmptyTable(128)
>>> engine.compile(r'''
... instr 100
...   imidi = p4
...   iamptab = p5
...   islot = p6
...   kamp table islot, iamptab
...   asig = oscili:a(interp(kamp), mtof(imidi))
...   outch 1, asig
... endin
... ''')
>>> tabarray = engine.getTableData(source)
>>> tabarray[0] = 0.5
>>> eventid = engine.sched(100, args=[67, source, 0])
makeTable(data, tabnum=-1, sr=0, block=True, callback=None)[source]#

Create a new table and fill it with data.

Parameters:
  • data (Union[Sequence[float], ndarray]) – 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)

  • block – wait until the table is actually created

  • callback – call this function when ready - f(token, tablenumber) -> None

  • 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

Return type:

int

Returns:

the index of the new table, if wait is True

Example

from csoundengine import *
e = Engine()
import sndfileio
sample, sr = sndfileio.sndread("stereo.wav")
# modify the sample in python
sample *= 0.5
source = e.makeTable(sample, sr=sr, block=True)
e.playSample(source)
tableExists(tabnum)[source]#

Returns True if a table with the given number exists

Return type:

bool

setTableMetadata(tabnum, sr, numchannels=1, delay=0.0, check=True)[source]#

Set metadata for a table holding sound samples.

When csound reads a soundfile into a table, it stores some additional data, like samplerate and number of channels. A table created by other means and then filled with samples normally does not have this information. In most of the times this is ok, but there are some opcodes which need this information (loscil, for example). This method allows to set this information for such tables.

Parameters:
  • tabnum (int) – the table number

  • sr (int) – the sample rate

  • numchannels (int) – number of channels of data

  • check – if True, it will check if the table exists in the case where the table wass not created via the engine

  • delay – when to perform the operation.

Return type:

None

callLater(delay, callback)[source]#

Call callback after delay, triggered by csound scheduler

Parameters:
  • delay (float) – the delay time, in seconds

  • callback (callable) – the callback, a function of the sort () -> None

Return type:

None

The callback will be called after the given delay, plus some jitter (~ 2/3 k-cycles after, never before)

Example

>>> from csoundengine import *
>>> import time
>>> e = Engine()
>>> startTime = time.time()
>>> e.callLater(2, lambda:print(f"Elapsed time: {time.time() - startTime}"))
plotTableSpectrogram(tabnum, fftsize=2048, mindb=-90, maxfreq=None, overlap=4, minfreq=0, sr=44100, chan=0)[source]#

Plot a spectrogram of the audio data in the given table

Requires that the samplerate is set, either because it was read via gen01 (or using .readSoundfile), or it was manually set via setTableMetadata

Parameters:
  • source – the table to plot

  • fftsize (int) – the size of the fft

  • mindb (int) – the min. dB to plot

  • maxfreq (int) – the max. frequency to plot

  • overlap (int) – the number of overlaps per window

  • minfreq (int) – the min. frequency to plot

  • sr (int) – the fallback samplerate, used when the table has no samplerate information of its own

  • chan – which channel to plot if the table is multichannel

Return type:

None

Example

>>> from csoundengine import *
>>> e = Engine()
>>> source = e.readSoundfile("mono.wav", block=True)
>>> e.plotTableSpectrogram(source)
_images/tableproxy-plotspectrogram.png
plotTable(tabnum, sr=0)[source]#

Plot the content of the table via matplotlib.pyplot

If the sr is known the table is plotted as a waveform, with time as the x-coord. Otherwise the table’s raw data is plotted, with the index as x the x-coord. The samplerate will be known if the table was created via Engine.readSoundfile() or read via GEN1. The sr can also be passed explicitely as a parameter.

Parameters:
  • tabnum (int) – the table to plot

  • sr (int) – the samplerate of the data. Needed to plot as a waveform if the table was not loaded via GEN1 (or via Engine.readSoundfile()).

Return type:

None

from csoundengine import *
e = Engine()
source = e.readSoundfile("mono.wav", block=True)
# no sr needed here since the output was rea via readSoundfile
e.plotTable(source)
_images/tableproxy-plot.png
import sndfileio
data, sr = sndfileio.sndread("stereo.wav")
tabnum2 = e.makeTable(data, sr=sr)
e.plotTable(tabnum2)
_images/tableplot-stereo.png
e = Engine()
xs = np.linspace(0, 6.28, 1000)
ys = np.sin(xs)
source = e.makeEmptyTable(len(ys))
e.fillTable(source, data=ys)
e.plotTable(source)
_images/tableplot-sine.png
schedSync(instr, delay=0, dur=-1, args=None, timeout=-1)[source]#

Schedule an instr, wait for a sync message

Similar to sched() but waits until the instrument sends a sync message. The instrument should expect a sync token at p4 (see example)

Note

args should start with p5 since the sync token is sent as p4

Parameters:
  • instr (int | float | str) – the instrument number/name. If it is a fractional number, that value will be used as the instance number.

  • delay (float) – time to wait before instrument is started

  • dur (float) – duration of the event

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

  • timeout – if a non-negative number is given, this function will block at most this time and then raise a TimeoutError

Return type:

tuple[float, float]

Returns:

the fractional p1 of the scheduled note, the sync return value (see example)

Example

>>> from csoundengine import *
>>> e = Engine()
>>> e.compile(r'''
... instr readsound
...   itoken = p4
...   Spath strget p5
...   itab ftgen ftgen 0, 0, 0, -1, Spath, 0, 0, 0
...   tabw_i itab, itoken, gi__responses
...   outvalue "__sync__", itoken
...   turnoff
... endin
... ''')
>>> eventid, tabnum = e.schedSync('readsound', args=['/path/to/sound.wav'])
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

setChannel(channel, value, method='', delay=0.0)[source]#

Set the value of a software channel

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

  • value (float | str | ndarray) – the new value, should match the type of the channel (a float for a control channel, a string for a string channel or a numpy array for an audio channel)

  • method – one of 'api', 'score', 'udp'. An empty str will choose the most appropriate method for the current engine/args

  • delay – a delay to set the channel

Return type:

None

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

Example

>>> from csoundengine import *
>>> e = Engine()
>>> e.initChannel("freq", mode="w")
>>> e.compile('''
... instr pitchtrack
...   asig inch 1
...   afreq, alock plltrack asig, 0.25, 20, 0.33, 50, 800
...   kfreq = k(afreq)
...   chnset kfreq, "freq"
... endin
... ''')
>>> eventid = e.sched("pitchtrack")
>>> while True:
...     freq = e.getControlChannel("freq")
...     print(f"freq: {freq:.1f}")
...     time.sleep(0.1)
fillTable(tabnum, data, method='pointer', block=False)[source]#

Fill an existing table with data

Parameters:
  • tabnum (int) – the table number

  • data – the data to put into the table

  • method – the method used, one of ‘pointer’ or ‘api’.

  • block – this is only used for the api method

Return type:

None

Example

>>> from csoundengine import *
>>> import numpy as np
>>> e = Engine()
>>> xs = np.linspace(0, 6.28, 1000)
>>> ys = np.sin(xs)
>>> source = e.makeEmptyTable(len(ys))
>>> e.fillTable(source, data=ys)
>>> e.plotTable(source)
_images/tableplot-sine.png
tableInfo(tabnum, cache=True)[source]#

Retrieve information about the given table

Parameters:
  • tabnum (int) – the table number

  • cache – if True, query the cache to see if info for this table has already been requested

Return type:

TableInfo

Returns:

a TableInfo with fields tableNumber, sr (ftsr), numChannels (ftchnls), numFrames (nsamps), size (ftlen).

Note

Some information, like sr, is only available for tables allocated via GEN01 (for example, using readSoundfile()). This data can also be set explicitely via setTableMetadata()

Example

>>> from csoundengine import *
>>> e = Engine()
>>> source = e.readSoundfile("stereo.wav", block=True)
>>> e.tableInfo(source)
TableInfo(tableNumber=200, sr=44100.0, numChannels=2, numFrames=88200, size=176401)
includeFile(include)[source]#

Add an #include file to this Engine

Parameters:

include (str) – the path to the include file

Return type:

None

readSoundfile(path='?', tabnum=None, chan=0, callback=None, block=False, skiptime=0.0)[source]#

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

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

  • tabnum (int | None) – if given, a table index. If None, an index is autoassigned

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

  • block – if True, wait until output is read, then return

  • callback – if given, this function () -> None, will be called when output has been read.

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

Return type:

int

Returns:

the index of the created table

>>> from csoundengine import *
>>> engine = Engine()
>>> source = engine.readSoundfile("stereo.wav", block=True)
>>> eventid = engine.playSample(source)
>>> # Reduce the gain to 0.8 after 2 seconds
>>> engine.setp(eventid, 4, 0.8, delay=2)
soundfontPlay(index, pitch, amp=0.7, delay=0.0, dur=-1.0, vel=None, chan=1)[source]#

Play a note of a previously loaded soundfont

The soundfont’s program (bank, preset) must have been read before via Engine.soundfontPreparePreset()

Parameters:
  • index (int) – as returned via soundfontPrearePreset()

  • pitch (float) – the pitch of the played note, as a midinote (can be fractional)

  • amp (float) – the amplitude. If vel (velocity) is left as None, this is used to determine the velocity. Otherwise, set the velocity (this might be used by the soundfont to play the correct sample) and the amplitude is used to scale the output

  • vel (int) – the velocity of the played note, used internally to determine which sample/layer to play

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

  • delay (float) – when to start playback

  • dur (float) – the duration of playback. Use -1 to play until the end (the note will be stopped when the soundfont playback detects the end of the sample)

Return type:

float

Returns:

the instance number of the playing instrument.

Important

Dynamic Fields

  • p4: kpitch

  • p5: kamp

Example

from csoundengine import *
e = Engine()

# Since the preset is not specified, this will launch a gui dialog
# to select a preset from a list of available presets
idx = e.soundfontPreparePreset('Orgue-de-salon.sf2')
event = e.soundfontPlay(idx, 60)

# Automate kpitch (p4) a major 3rd glissando from the current pitch,
offset, glissdur = 2, 8
e.automatep(event, 4, [offset, 60, offset+glissdur, 64])
_images/select-preset.png
soundfontPreparePreset(sf2path, preset=None)[source]#

Prepare a soundfont’s preset to be used

Assigns an index to a soundfont bank:preset to be used with sfplay or via soundfontPlay()

The soundfont is loaded if it was not loaded before

_images/select-preset.png
Parameters:
  • sf2path (str) – the path to a sf2 file – Use “?” to select a file interactively

  • preset (tuple[int, int] | None) – a tuple (bank, presetnum), where both bank and presetnum are ints in the range (0-127). None to select a preset interactively

Return type:

int

Returns:

an index assigned to this preset, which can be used with sfplay/sfplay3 or with :meth:~Engine.soundfontPlay

getUniqueInstrInstance(instr)[source]#

Returns a unique instance number (a float p1) for instr

Parameters:

instr (int|str) – an already defined csound instrument

Return type:

float

Returns:

a unique p1.

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
playSoundFromDisk(path, delay=0.0, 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

  • 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 (float) – the p1 of the instrument to automate

  • *pairs – each pair consists of a pfield index and a value

  • delay – when to start the automation

Return type:

None

Example

>>> engine = Engine(...)
>>> engine.compile(r'''
... instr 100
...   kamp = p5
...   kfreq = p6
...   a0 oscili kamp, kfreq
...   outch 1, a0
... endin
... ''')
>>> p1 = engine.sched(100, args=[0.1, 440])
>>> engine.setp(p1, 5, 0.2, delay=0.5)

See also

getp(eventid, idx)[source]#

Get the current pfield value of an active note.

Note

This action has always a certain latency, since it implies scheduling an internal event to read the value and send it back to python. The action is blocking

Parameters:
  • eventid (float) – the (fractional) id (a.k.a p1) of the event

  • idx (int) – the index of the p-field, starting with 1 (4=p4)

Return type:

float | None

Returns:

the current value of the given pfield

Example

TODO

See also

setp()

automateTable(tabnum, idx, pairs, mode='linear', delay=0.0, overtake=False)[source]#

Automate a table slot

Parameters:
  • tabnum (int) – the number of the table to modify

  • idx (int) – the slot index

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

  • mode – one of ‘linear’, ‘cos’, ‘expon(xx)’, ‘smooth’. See the opcode interp1d for more information

  • delay – the time delay to start the automation.

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

Return type:

float

Returns:

the eventid of the instance performing the automation

Example

>>> engine = Engine(...)
>>> engine.compile(r'''
... instr 100
...   itab = p4
...   kamp  table 0, itab
...   kfreq table 1, itab
...   outch 1, oscili:a(0.1, kfreq)
...   ftfree itab, 1  ; free the table when finished
... endin
... ''')
>>> source = engine.makeTable([0.1, 1000])
>>> eventid = engine.sched(100, 0, 10, args=(source,))
>>> # automate the frequency (slot 1)
>>> engine.automateTable(source, 1, [0, 1000, 3, 200, 5, 200])
>>> # Automate from the current value, will produce a fade-out
>>> engine.automateTable(source, 0, [0, -1, 2, 0], overtake=True, delay=5)

See also

setp(), automatep()

automatep(p1, pidx, pairs, mode='linear', delay=0.0, overtake=False)[source]#

Automate a pfield of a running event

The automation is done by another csound event, so it happens within the “csound” realm and thus is assured to stay in sync

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

  • pidx (int) – 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.

  • 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 = Engine()
>>> 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])
strSet(s, sync=False)[source]#

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

Parameters:
  • s (str) – the string to set

  • sync – if True, block if needed until the csound process receives the message

Return type:

int

Returns:

the index associated with s. When passed to a csound instrument it can be used to retrieve the original string via Sstr = strget(idx)

See also

strGet()

definedStrings()[source]#

Returns a dict mapping defined strings to their integer id

These are strings defined via strSet() by the Engine, not internally using csound itself

Warning

Using strset within an instrument or as global code will probably result in conflicts with the strings defined via the Engine using Engine.setStr()

Return type:

dict[str, int]

Returns:

a dict mapping defined strings to their corresponding index

strGet(index)[source]#

Get a string previously set via strSet.

This method will not retrieve any string set internally via the strset opcode, only strings set via strSet()

Return type:

str | None

Example

>>> e = Engine(...)
>>> idx = e.strSet("foo")
>>> e.strGet(idx)
foo

See also

strSet()

freeTable(tableindex, delay=0.0)[source]#

Free the table with the given index

Parameters:
  • tableindex (int) – the index of the table to free

  • delay – when to free it (0=right now)

Return type:

None

See also

makeTable()

testAudio(dur=4.0, delay=0.0, period=1.0, mode='pink', gaindb=-6.0)[source]#

Test this engine’s output

Parameters:
  • dur – the duration of the test

  • delay – when to start the test

  • period – the duration of sound output on each channel

  • mode – the test mode, one of ‘pink’, ‘sine’

  • gaindb – the gain of the output, in dB

Return type:

float

Returns:

the p1 of the scheduled event

udpSendOrc(code)[source]#

Send orchestra code via UDP.

The code string can be of any size (if the code is too long for a UDP package, it is split into multiple packages)

Parameters:

code (str) – the code to send

Return type:

None

udpSendScoreline(scoreline)[source]#

Send a score line to csound via udp

Return type:

None

Example

>>> e = Engine(udpserver=True)
>>> e.compile(r'''
... instr 100
...   ifreq = p4
...   outch 1, oscili:a(0.1, ifreq)
... endin
... ''')
>>> e.udpSendScoreline("i 100 0 4 440")
udpSetChannel(channel, value)[source]#

Set a channel via UDP. The value will determine the kind of channel

Parameters:
  • channel (str) – the channel name

  • value (float | str) – the new value

Return type:

None

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

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)
automateBus(bus, pairs, mode='linear', delay=0.0, overtake=False)[source]#

Automate a control bus

The automation is performed within csound and is thus assured to stay in sync

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

  • pairs (Union[Sequence[float], tuple[Sequence[float], Sequence[float]]]) – the automation data as a flat sequence (t0, value0, t1, value1, …) Times are relative to the start of the automation event

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

  • delay – when to start the automation

  • overtake – if True, the first value of pairs is replaced with the current value of the bus. The same effect can be achieved if the first value of the automation line is a nan

Return type:

None

Example

>>> e = Engine()
>>> e.compile(r'''
... instr 100
...   ifreqbus = p4
...   kfreq = busin:k(ifreqbus)
...   outch 1, oscili:a(0.1, kfreq)
... endin
... ''')
>>> freqbus = e.assignBus(value=440)
>>> eventid = e.sched(100, args=(freqbus,))
>>> e.automateBus(freqbus, [0, float('nan'), 3, 200, 5, 200])
readBus(bus, default=None)[source]#

Read the current value of a control bus

Buses can be used to allow communication between instruments, or between a running csound instrument and python. Buses are useful for continuous streams; when using buses to communicate discrete values with python an opcode like trighold might be necessary. In general for discrete events it might be better to use other communication means, like OSC, which provide buffering.

Parameters:
  • bus (int) – the bus number, as returned by assignBus

  • default (float | None) – the value returned if the bus does not exist

Return type:

float | None

Returns:

the current value of the bus, or default if the bus does not exist

Example

>>> e = Engine()
>>> e.compile(r'''
... instr 100
...   irmsbus = p4
...   asig inch 1
...   krms = rms:k(asig)
...   busout irmsbus, krms
... endin
... ''')
>>> rmsbus = e.assignBus(kind='control')
>>> event = e.sched(100, 0, args=[rmsbus])
>>> while True:
...     rmsvalue = e.readBus(rmsbus)
...     print(f"Rms value: {rmsvalue}")
...     time.sleep(0.1)
releaseBus(bus)[source]#

Release a persistent bus :rtype: None

See also

assignBus()

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 garanteed

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 bus is reference counted and is collected when there are no more clients using it. 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. Multiple clients can use a bus and the bus is kept alive as long as there are clients using it or if the bus was created as persistent. When each client starts using the bus via any of the bus opcodes, like busin, the reference count of the bus is increased. After a client has finished using it the reference count is automatically decreased and if it reaches 0 the bus is collected.

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 = Engine(...)
>>> 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,))

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 = Engine(...)
>>> 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()
busSystemStatus()[source]#

Get debugging nformation about the status of the bus system

This is only provided for debugging

Return type:

dict

Returns:

a dict containing information about the status of the bus system (used buses, free buses, etc)

hasBusSupport()[source]#

Returns True if this Engine was started with bus support :rtype: bool

eventUI(eventid, **pargs)[source]#

Modify pfields through an interactive user-interface

If run inside a jupyter notebook, this method will create embedded widgets to control the values of the dynamic pfields of an event

Parameters:
  • eventid (float) – p1 of the event to modify

  • **pfields – a dict mapping pfield to a tuple (minvalue, maxvalue)

Return type:

None

Example

from csoundengine import *
e = Engine()
e.compile(r'''
instr synth
  kmidinote = p4
  kampdb = p5
  kcutoff = p6
  kres = p7
  kfreq = mtof:k(kmidinote)
  asig = vco2:a(ampdb(kampdb), kfreq)
  asig = moogladder2(asig, kcutoff, kres)
  asig *= linsegr:a(0, 0.1, 1, 0.1, 0)
  outs asig, asig
endin
''')
ev = e.sched('synth', args=[67, -12, 3000, 0.9])
e.eventUI(ev, p4=(0, 127), p5=(-48, 0), kcutoff=(200, 5000), kres=(0.1, 1))
_images/eventui.png
csoundengine.engine.getEngine(name)[source]#

Get an already created engine by name

Return type:

Engine | None

Example

>>> import csoundengine as ce
>>> ce.Engine(name='old', a4=435)
>>> getEngine('old')
Engine(name=old, sr=44100, backend=jack, outdev=dac, nchnls=2, indev=adc, nchnls_i=2,
       bufferSize=256)
>>> getEngine('foo') is None
True
csoundengine.engine.activeEngines()[source]#

Returns the names of the active engines

Return type:

list[str]

Example

>>> import csoundengine as ce
>>> ce.Engine(nchnls=2)   # Will receive a generic name
>>> ce.Engine(name='multichannel', nchnls=8)
>>> ce.activeEngines()
['engine0', 'multichannel']