Hey, there is a WIP branch that got recently updated with a new, more efficient scope backend. This is not polished yet, and re-instantiation doesn't work yet (because of some weirdness in how to cleanup Xenomai RT-ipc). I will fix this soon as I get a response from Xenomai.
However, as long as you keep the Scope
object alive and do not try to re-instantiate it after deleting it, this will work. This is the branch I am talking about: https://github.com/BelaPlatform/Bela/tree/dev-websocket-rebased .
Example: e.g.:
#include <Bela.h>
#include <cmath>
#include <Scope.h>
Scope* scope;
int gAudioFramesPerAnalogFrame = 0;
float gInverseSampleRate;
float gPhase;
float gAmplitude;
float gFrequency;
float gIn1;
float gIn2;
// For this example you need to set the Analog Sample Rate to
// 44.1 KHz which you can do in the settings tab.
bool setup(BelaContext *context, void *userData)
{
// setup the scope with 3 channels at the audio sample rate
static bool loaded = false;
if(!loaded)
{
scope = new Scope();
scope->setup(3, context->audioSampleRate);
loaded = true;
}
if(context->analogSampleRate > context->audioSampleRate)
{
fprintf(stderr, "Error: for this project the sampling rate of the analog inputs has to be <= the audio sample rate\n");
return false;
}
if(context->analogInChannels < 2)
{
fprintf(stderr, "Error: for this project you need at least two analog inputs\n");
return false;
}
if(context->analogFrames)
gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
gInverseSampleRate = 1.0 / context->audioSampleRate;
gPhase = 0.0;
return true;
}
void render(BelaContext *context, void *userData)
{
for(unsigned int n = 0; n < context->audioFrames; n++) {
if(gAudioFramesPerAnalogFrame && !(n % gAudioFramesPerAnalogFrame)) {
// read analog inputs and update frequency and amplitude
gIn1 = analogRead(context, n/gAudioFramesPerAnalogFrame, 0);
gIn2 = analogRead(context, n/gAudioFramesPerAnalogFrame, 1);
gAmplitude = gIn1 * 0.8f;
gFrequency = map(gIn2, 0, 1, 100, 1000);
}
// generate a sine wave with the amplitude and frequency
float out = gAmplitude * sinf(gPhase);
gPhase += 2.0f * (float)M_PI * gFrequency * gInverseSampleRate;
if(gPhase > M_PI)
gPhase -= 2.0f * (float)M_PI;
// log the sine wave and sensor values on the scope
scope->log(out, gIn1, gIn2);
// pass the sine wave to the audio outputs
for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
audioWrite(context, n, channel, out);
}
}
}
void cleanup(BelaContext *context, void *userData)
{
// delete scope; // we are not deleting, alas. You can delete from your wrapper if you want, but only when the program exits.
}