accessing (data) buffers (C++)

thetechnobear's icon

any examples or documentation in this area from C++?


I cannot find any docs, so have been digging thru the source code....

as far as I can tell, I need to get access to the ExternalDataRef

its seems, if the buffer has been created with the RNBO patch, it looks like Id have to use a an ExternalDataHandler - correct?

do we then wrap this with one of the data view classes?

the alternative, seems to be, to let the C++ 'host' allocate the buffers, and then use SetExternalDataRef on core object... which might be what Id do,

but Id like to also gain access to the buffers created/pre-allocated within RNBO.

Isabel Kaspriskie's icon

The documentation on loading file dependencies might be helpful, if you haven't checked it out already.

thetechnobear's icon

unfortunately, that covers the bit I already know... which is letting the host allocate the buffer, using SetExternalData.

what I was interested in was the API that covers gaining access to the existing buffers.
Ive got a pretty good idea how to do this via ExternalDataHandler, but I was interested to see if my ideas match the 'official' way - as potentially, I could be using an unintended approach the api allows, which might suddenly stop working in a future version of RNBO


frankly, now im digging into RNBO deeper, the documentation is woeful... the C++ API reference documentation is nothing more than auto generation from code comments. currently, appears the only way forward is to read the source code...
now I dont have an issue with that... Im used to it, as this is the same as Pure Data, but I kind of expected a bit more for a commercial product... thats cost nearly $400 (+ max license)




David Alexander's icon

@technobear did you figure out how to do this? I’d like to be able to access RNBO buffers with the C++ API for a visualiser. Has anyone tried this?

thetechnobear's icon

yeah, as I pointed out above... the approach you have to use is to have the 'host' allocate the buffer, and supply it to the rnbo api.
I did this for various rnbo 'plugins' that I created that wanted to visualise various waveforms e.g. loopers/granular etc... works pretty well.

the tricky bit when I started out using the RNBO api, was realising which bits of rnbo functionality are the host's responsibility vs what could be in done within the api.

unfortunately, the description/feature set of rnbo, kind of blur this due to the plugin/web code implementations, which include both host and rnbo patch functionality.
though in fairness, doesn't take long to work out whats being done where, and its pretty 'obvious'..


that said, c74 really should shift some of the stuff thats in the json files into the rnbo api, as some of its would be very useful when you create your own host, but don't want to start parsing the json, or running your own 'generator' over the json files to pick up these 'extras'

TobyAM's icon

Hey 'Bear, I'm in the same situation now, I've got a GUI for my plugin but I want to visualize the audio from some of my RNBO buffers to complete the interface.

Can you share some explicit tips or examples?
Do you use coreObject.getExternalDataInfo? The struct returned for the buffer I want only contains the file, tag, and type, which doesn't seem to apply to an internally generated buffer.

RNBO buffers aside, what other ways are there to pull audio streams from RNBO for visualizations?

thetechnobear's icon

as I pointed out above, you have to 'reverse' the problem....

what you do is have the host allocate the data buffers, and you setExternalData,
so that the rnbo patch can use the buffers supplied by the host.


this has worked perfectly for me... i.e. I created a looper module for my host, which displayed the waveforms in the UI. but all the dsp processing was handed in rnbo.

as for getExternalDataInfo, its just information supplied to the host. so that it can create the external data buffers as necessary.

I think the confusion here (at least for me) is the role of host vs rnbo.
its important to realise that the VST 'host' can be considered an example implementation of a host, rather than part of RNBO... so if you are creating your own host, you can look at it, as an example of how to implement a host, and what the role of the host is, compared to the generated rnbo c++ code.
... or at least, this is what helped me to get to grips with creating my own hosts :)

manysounds's icon

AH! So, I have created a rather personalized VST/AU FX plugin through RNBO which works just as I want in various hosts BUT I haven't figured out where/how to get data for visualizing my LFOs and such when it comes time to make a custom UI in JUCE because, as you point out, there really isn't any documentation at all and seems to be none at all for this specific issue.
So am I forced to read through alllllllll of the source to find these output variables OR I suppose there must be some easier search way like using "varname" on the info-tab. ORRR maybe could it be even more clever-ish to simply add more [out~] objects tied to these data streams and then use that in JUCE? Seems processor intensive that way, IDK.
/I'm a blundering hack, but I know what I like

TobyAM's icon

I figured it out!

declare a private member variable like:
float *sampleBuffer = (float *) malloc(sizeof(float) * 2048);

then in your:
void MyUIClass::setAudioProcessor(RNBO::JuceAudioProcessor* p)
{
processor = p;
RNBO::ParameterInfo parameterInfo;
RNBO::CoreObject& coreObject = processor->getRnboObject();

// allocate data buffer
RNBO::Float32AudioBuffer bufferType(1, 48000);
// Make space to store the file

const uint32_t sampleBufferSize = sizeof(float) * 2048;
float *sampleBuffer = (float *) malloc(sampleBufferSize);
coreObject.setExternalData(
"myRNBObuffer",
reinterpret_cast<char *>(sampleBuffer),
2048 * sizeof(float) / sizeof(char),
bufferType,
&freeBuffer
);


Then finally you can loop through sampleBuffer[i] for the buffer values!

At least that's the basics of it and I just got this much going.

TobyAM's icon

I just realized, this buffer allocation will erase your buffer every time you open the plugin window, which is very bad if you use that buffer in RNBO for DSP. In that case, copy your DSP buffer to a buffer only used by Juce for visualization.

Maybe there's a better place to initialize these, but for now this works well.

xinisnot's icon

If you want to use RNBO buffers for DSP, I think it is effective to call setExternalData() in the constructor of CustomAudioProcessor. Then you can pass pointers of buffer to CustomAudioEditor via CustomAudioProcessor::createEditor(). In this case, you should reimplement the construcor of CustomAudioEditor so that it can get pointers.

In this way, I have could prevented my oscilloscope from erasing drawing of waveform. If you're interested, please take a look at the source code of my plugin.