Making Records

Not of the vinyl variety, but the computer science data structure.

Csound comes with a few ways of generating, storing and retrieving data, with function tables being the primary data structure. Data can also be placed into global variables and chn busses. In terms of data abstractions, there isn’t a whole lot of choice. However, custom data abstractions and structures can be built from within a Csound orchestra.

In my blog Simple Keys — Modularized Key Mapping, I toyed with storing multiple key bindings, frequencies, amplitudes and function table numbers within a single ftable by treating the ftable as if it were an array of records, albeit a fairly clumsy one. Over the weekend, I continued along this line and distilled it even further.

Download: simple_record.csd

So far, I’m very happy with the results. Though the implementation maybe a bit hackish, the user-interface isn’t bad. This new system of making records is composed of five user-defined opcodes: RecordType, RecordField, Record, RecordSet and RecordGet. I additionally wrote wrapper GEN instruments, so they could be accessed from the score.

The first two, RecordType and RecordField, are used to create record abstractions. RecordType creates a new record type, while RecordField appends data fields to the record type. A record type is built from an ftable, thus shares the function table number space. The following score snippet creates a record type as ftable 100, and appends three fields: amp, freq and ftable.

i $RecordType  0 1 100           ; Record type stored at fn 100
i $RecordField 0 1 100 "amp"     ; Append field "amp"
i $RecordField 0 1 100 "freq"    ; Append field "freq"
i $RecordField 0 1 100 "ftable"  ; Append field "ftable"

For a record type to be useful, an instance of it must be created with Record. A record is also an ftable, and requires its own unique function table index. The following line creates a record from record type 100, and stores it in ftable 200:

i $Record 0 1 200 100  ; Instantiate record 200 from type 100

Once a record is created, the values of each field can be set with RecordSet:

i $RecordSet 0 1 200 "amp"    0.5  ; Set field "amp"
i $RecordSet 0 1 200 "freq"   440  ; Set field "freq"
i $RecordSet 0 1 200 "ftable" 1    ; Set field "ftable"

That’s just one record created from a single record type. In the csd, you’ll see I create two more records from the same record type.

Example

The Synth instrument is provided to show a simple example on how to use a record. Instead of passing amplitude, frequency and the function number of a stored single cycle wave as pfield data, a record number is passed to Synth with pfield 4. The user-defined opcode RecordGet is used to pull data from the record. The data is then passed to oscil.

instr $Synth
    irecord = p4  ; Record function number
    iamp RecordGet "amp", irecord        ; Get amplitude from record
    ifreq RecordGet "freq", irecord      ; Get frequency from record
    iftable RecordGet "ftable", irecord  ; Get ftable from record
    a1 oscil iamp, ifreq, iftable, -1
    out a1
endin
...
i $Synth 0 1 200  ; Feed synth record 200

More on all of this later.