C++ Instruments:

The new Csound Opcode Plugin Framework

Introduction

Csound has a fairly straightforward plugin mechanism that can be used extend its language, adding new native functionality to the system.

The main interface for this mechanism was originally provided via the C language, which is also the language used in the core part of the software.

For many programmers, C++ is more accessible language, even though it is much bigger and with a lot more conceptual complexities.

CPOF aims to provide an easy-to-use, heavily re-usable, API for plugin opcode development, with scalable qualities as far complexity is concerned.

It is also important to point out that an alternative API by Michael Gogins provides some of this functionality in Csound, trying to add a C++ face to the underlying C-language functions.

However, CPOF has been designed from the ground up with heavy use of templating to provide a more complete C++ solution to the problem.

The C Opcode API

Adding an opcode to Csound in C involves three things

  1. A data structure containing the opcode base, pointers to its out/in arguments (if any) and any state variables (if needed).
  2. Up to three functions to compute the output at initialisation and/or performance times.
  3. Boilerplate code to register the opcode with the system.

On startup, Csound finds all plugins, and registers them with the system (using 3)

If an opcode is used in the code, when this is instantiated, Csound allocates memory for its data space (1), and calls its processing functions (2) as appropriate.

Generally, it is very simple to write straightforward C opcodes.

The complexity picks up quickly when we need resources from the system (memory allocation, function table access, advanced variable types, FFTs, etc.) to do more involved stuff.

CPOF API Basics

The CPOF API is built on top of this tripartite model. However, being C++, it employs significant code re-use through templates. So the three elements get reduced to two:

  1. A class that defines the opcode.
  2. A call to a registering (template) function

The opcode class is derived from the Plugin template base class:

The above is actually a minimum (but non-op) opcode with one output and one input (the template parametes). To do something, we will need to add processsing methods to this class.

In Csound, an opcode can be active at init and/or perf times. Init-time code is run once (e.g. on instantiation or re-initialisation in the case of instruments). Perf-time code runs repeatedly when Csound is processing audio or control signals. For each one of these actions (init, control, or audio), an opcode can provide a computing method: init(), kperf(), or aperf().

To register an opcode, we call a template function that takes the class as its template parameter, plus the name, argument types and action thread (init, perf, and/or audio). This template function is called inside onload(), the entry point for the opcode plugin library.

Base Classes

Support Classes