Search code examples
c++arrayspointersaudiovst

How to create pointer to pointer array same as VST audio buffer?


In the VST spec, a buffer of multichannel audio data is passed around.....

MyClass::ProcessDoubleReplacing(double **inputs, double **outputs, int frames)
{
    //and accessed like this...
    outputs[channel][sample] = inputs[channel][sample]
}

I want to create a similar "2d pointer array", but am not having much success. I can create a simple pointer and iterate through it reading/writing values....

double* samples;
samples[0] = aValue;

.... but am having a crash festival trying to implement something that will allow me to...

samples[0][0] = aValue;

What would be the correct way to implement this?


Solution

  • If you want to write something in C++ to provide a similar interface like the one you showed, I would use std::vector for managing the memory like this:

    vector<vector<double>> buffers (2,vector<double>(500));
    

    This only stores the data. For an array of pointers you need an array of pointers. :)

    vector<double*> pointers;
    pointers.push_back(buffers[0].data());
    pointers.push_back(buffers[1].data());
    

    This works since std::vector makes the guarantee that all elements are stored adjacent and linearly in memory. So, you're also allowed to do this:

    double** p = pointers.data();
    p[0][123] = 17;
    p[1][222] = 29;
    

    It's important to note that if you resize some of these vectors, the pointers might get invalid in which case you should go ahead and get the new pointer(s).

    Keep in mind that the data member function is a C++11 feature. If you don't want to use it, you can write

    &some_vector[0] // instead of some_vector.data()
    

    (unless the vector is empty)

    Instead of passing a double** to some function, you might be interested in passing the buffers vector directly by reference, though, this obviously won't work if you want your interface to be C compatible. Just saying.

    Edit: A note on why I chose std::vector over new[] and malloc: Because it's the right thing to do in modern C++! The chance of messing up in this case is lower. You won't have any memory leaks since the vector takes care of managing the memory. This is especially important in C++ since you might have exceptions flying around so that functions might be exited early before the use of a delete[] at the end of the function.