I'm try to put together a nim wrapper for the Clap AudioPlugin API/ABI/interface.
In the c world a clap audio plugin has a process method that will be called by the host. One of the arguments is a clap_process struct that stores info about, and pointers to audio buffers. In the process method the plugin can read from and write into the audio buffers.
typedef struct clap_audio_buffer {
float **data;
uint32_t channel_count;
uint32_t latency;
uint64_t constant_mask;
} clap_audio_buffer_t;
typedef struct clap_process {
uint32_t frames_count;
const clap_audio_buffer_t *audio_inputs;
clap_audio_buffer_t *audio_outputs;
uint32_t audio_inputs_count;
uint32_t audio_outputs_count;
} clap_process_t;
c2nim converts this to the following:
type
clap_audio_buffer* {.bycopy.} = object
data*: ptr ptr cfloat
channel_count*: uint32
latency*: uint32
constant_mask*: uint64
clap_process* {.bycopy.} = object
frames_count*: uint32
audio_inputs*: ptr clap_audio_buffer
audio_outputs*: ptr clap_audio_buffer
audio_inputs_count*: uint32
audio_outputs_count*: uint32
inputs can be multiple "groups" of multi channel audio buffers. In c, you can easily access the samples in the audio buffers using array-style indexing.
for (; i < process->frames_count; ++i) {
// fetch input samples
const float in_l = process->audio_inputs[0].data32[0][i];
const float in_r = process->audio_inputs[0].data32[1][i];
/* TODO: process samples, here we simply swap left and right channels */
const float out_l = in_r;
const float out_r = in_l;
// store output samples
process->audio_outputs[0].data32[0][i] = out_l;
process->audio_outputs[0].data32[1][i] = out_r;
}
c2nim converts the pointers to refs but that does not allow indexing AFAIK.
I thought I might use openArray, but that did not seem to work.
This compiles:
type
clap_audio_buffer* {.bycopy.} = object
data*: array[0..0, array[0..0, cfloat]]
channel_count*: uint32
proc testProcess*(buffer: ptr clap_audio_buffer): bool =
var sample: cfloat = buffer.data[5][0]
return true
but I am not sure this is the right way to do it.
Thanks, that worked!
I should have figured that myself, I was so busy trying to get rid of UncheckedArray in other bits of code that c2nim had created that I didnt realize it might be usefull here.
For future nim forum users needing a solution:
c2nim was converting
float **data;
to
data*: ptr ptr cfloat
After the c2nim conversion I run a postprocessing script that replaces that line with:
data*: ptr UncheckedArray[UncheckedArray[cfloat]]