## 2 The Framework
### Registering Opcodes with Csound
struct Oscillator : csnd::Plugin<1,3> { static constexpr char const *otypes = \"a\"; static constexpr char const *itypes = \"kki\"; csnd::Table tab; double scl; double x;

int init() { tab.init(csound,inargs(2));  scl = tab.len()/csound->sr();  x = 0;  return OK; }

int aperf() { csnd::AudioSig out(this, outargs(0));  MYFLT amp = inargs[0];  MYFLT si = inargs[1] * scl; double ph = x;

for(auto &s : out) {  s = amp * tab[(uint32_t) ph];ph += si;  while (ph < 0) ph += tab.len();  while (ph >= tab.len()) ph -= tab.len();  }  x = ph;  return OK;  } };

A table is initialised by passing the relevant argument pointer to it (using its data() method). This will hold the function table number that is passed to opcode. In this example, as we need a precise index value, it is more convenient to use array index access instead of iterators, although these are also available in the class. This opcode is registered by

csnd::plugin<Oscillator>(csound, \"oscillator\", csnd::thread::ia);

### String Types

String variables in Csound are held in a STRINGDAT data structure, containing two members, a pointer to the address holding the zero-terminated string, and a size:

typedef struct {  char *data;  int size; } STRINGDAT;

The size parameter contains the total space currently allocated for the string, which might be larger than the actual string. While CPOF does not wrap strings, it provides a translated access to string arguments through the argument objects str_data() function. This takes an argument index (similarly to data()) and returns a reference to the string variable, as demonstrated in this example:

struct Tprint : csnd::Plugin<0,1> {  static constexpr char const *otypes = \"\";  static constexpr char const *itypes = \"S\";  int init() {  char *s = inargs.str_data(0).data;  csound->message(s);  return OK;  } };

This opcode will print the string to the console. Note that we have no output arguments, so we set the first template parameter to 0. We register it using

csnd::plugin<Tprint>(csound, \"tprint\", csnd::thread::i);

### Array Variables

Opcodes with array inputs or outputs use the data structure ARRAYDAT for parameters. Again, in order to facilitate access to these argument types, CPOF provides a template class, Vector<typename T>. This currently supports only one-dimensional arrays directly, but can be used with all basic Csound variable types. This container class is derived from ARRAYDAT and wraps an array argument of a type defined by its template parameter. Input variables of these types are already properly initialised, but outputs need to be initialised with a given array size. The class has the following members:init(): initialises an output variable. * operator[]: array-subscript access to the vector data. * data(): returns a pointer to the vector data. * len(): returns the length of the vector. * begin(),cbegin(): iterators to the beginning and end of the vector. * end(),cend(): end iterators. * iterator and const_iterator: iterator types for this class. * data_array(): returns a pointer to the vector data address. In addition to this, the inargs and outargs objects in the Plugin class have a template method that can be used to get a Vector class reference. A trivial example is shown in Listing 8, implementing both i-time and k-rate array operations. ```
structSimpleArray:csnd::Plugin<1,1>{ intinit(){ csnd::Vector<MYFLT>&out=outargs.vector_data<MYFLT>(0); csnd::Vector<MYFLT>&in=inargs.vector_data<MYFLT>(0); out.init(csound,in.len()); std::copy(in.begin(),in.end(),out.begin()); returnOK; } }
```
```
intkperf(){ csnd::Vector<MYFLT>&out=outargs.vector_data<MYFLT>(0); csnd::Vector<MYFLT>&in=inargs.vector_data<MYFLT>(0); std::copy(in.begin(),in.end(),out.begin()); returnOK; } };
```

This opcode is registered using

```
csnd::plugin<SimpleArray>(csound,\"simple\",\"i[]\",\"i[]\",csnd::thread::i); fori-time operation and csnd::plugin<SimpleArray>(csound,\"simple\",\"k[]\",\"k[]\",csnd::thread::ik); forperf-time processing. This is an example of an _overloaded_ opcode, that can operate on i and k-type variables.