Recently I made a post where due to resistor tolerance (~10%), the maximum values I could receive at my inputs where about a 0.1 low.

Today I extracted these values and tried to include them in a vector that I would later use within a map function to make their respective highest value equal to one, hence calibrating the inputs to 0-1. However, this has been giving me problems: when I do, I get no results on the scope.

I am attaching the code here:

#include <Bela.h>
#include <cmath>
#include <libraries/Scope/Scope.h>
#include <iostream>
#include <libraries/Oscillator/Oscillator.h>
#include <vector>

Scope scope;

int gAudioFramesPerAnalogFrame = 0;
float gInverseSampleRate;

const size_t kNumOscs = 8;
std::vector<Oscillator> gOscs;
std::vector<float> gIns(kNumOscs);
std::vector<float> gInsMax(kNumOscs);


bool setup(BelaContext *context, void *userData)
{
	
	for(unsigned int n = 0; n < 8; ++n)
		gOscs.push_back({context->audioSampleRate});

	// setup the scope with 8 channels at the audio sample rate
	scope.setup(8, context->audioSampleRate);


	if(context->analogFrames)
		gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
	gInverseSampleRate = 1.0 / context->audioSampleRate;
	return true;
	
	//Set values to map
	gInsMax.push_back(0.899);
	gInsMax.push_back(0.895);
	gInsMax.push_back(0.874);
	gInsMax.push_back(0.899);
	gInsMax.push_back(0.925);
	gInsMax.push_back(0.929);
	gInsMax.push_back(0.919);
	gInsMax.push_back(0.933);
	
	
}

void render(BelaContext *context, void *userData)
{
	for(unsigned int n = 0; n < context->audioFrames; n++) 
	{
		
		
		for(unsigned int c = 0; c < gOscs.size() && c < context->analogInChannels; ++c)
		{
			// Read values from inputs and map them to their maximum values.
			gIns[c] = analogRead(context, n / gAudioFramesPerAnalogFrame, c);
			gIns[c] = map(gIns[c], 0.f, gInsMax[c], 0.f, 1.f);
		}
		
		
		// log mapped values into scope.
		scope.log(gIns[0], gIns[1], gIns[2], gIns[3], gIns[4], gIns[5], gIns[6], gIns[7]);
		
	}
}

void cleanup(BelaContext *context, void *userData)
{
}

I believe this is correct C++ syntax, which in turn should be printing to the scope the correct mapped values. Clearly I must have made some sort of mistake somewhere... But I am pretty clueless at the moment.

Also, there is probably a way to push.back the results into the vector at initialisation with reiteration but I could not quite figure out how.

return true;

//Set values to map
gInsMax.push_back(0.899);

the return statement there means that the function returns and what's below that won't get executed. So your values are never pushed into the vector.

Now, if you move the return true; statement to the end of the function, the values will be pushed back. Your gInMax vector has an initial size of kNumOsc, as per its definition:

std::vector<float> gInsMax(kNumOscs);

The initial elements will be initialised to 0. Calling push_back() on a vector will append values to it, so once you are done pushing back values, gInMax will contain 16 elements:

{0, 0, 0, 0, 0, 0, 0, 0, 0.899, 0.895, 0.874, 0.899, 0.925, 0.929, 0.919, 0.933}

which is not what you want, because this line:

			gIns[c] = map(gIns[c], 0.f, gInsMax[c], 0.f, 1.f);

will only use the first 8 elements which are all 0.
So instead of calling push_back(), you should just set the existing values:

	//Set values to map
	gInsMax[0] = 0.899;
	gInsMax[1] = 0.895;
	gInsMax[2] = 0.874;
	gInsMax[3] = 0.899;
	gInsMax[4] = 0.925;
	gInsMax[5] = 0.929;
	gInsMax[6] = 0.919;
	gInsMax[7] = 0.933;

A more concise way of doing this is to change the definition to:

std::vector<float> gInsMax = { 0.899, 0.895, 0.874, 0.899, 0.925, 0.929, 0.919, 0.933 };

You can also be more concise in your scope.log() call.

		scope.log(gIns[0], gIns[1], gIns[2], gIns[3], gIns[4], gIns[5], gIns[6], gIns[7]);

There is an overloaded log() method that takes a pointer to a C array of floats instead of enumerating all values:


void Scope::log	(	const float * 	values	)	
Logs a frame of data to the scope.

Accepts a pointer to an array of floats representing each channel's value in ascending order.

Parameters
values	a pointer to an array containing numChannels values.

So you can get the pointer to the first element of the vector with gIn.data() and pass that to scope.log():

scope.log(gIn.data());

In short, here's a working and less verbose example. Other improvements I included:

  • removed gInverseSampleRate as it's unused
  • replace the constant 8 with kNumOscs, which should save you headaches in the future when you change that.
  • check the number of channels is consistent
#include <Bela.h>
#include <cmath>
#include <libraries/Scope/Scope.h>
#include <iostream>
#include <libraries/Oscillator/Oscillator.h>
#include <vector>

Scope scope;
int gAudioFramesPerAnalogFrame = 0;
const size_t kNumOscs = 8;
std::vector<Oscillator> gOscs;
std::vector<float> gIns(kNumOscs);
std::vector<float> gInsMax = { 0.899, 0.895, 0.874, 0.899, 0.925, 0.929, 0.919, 0.933 };

bool setup(BelaContext *context, void *userData)
{
	if(gIns.size() != gInsMax.size() || gIns.size() != context->analogInChannels)
	{
		fprintf(stderr, "Wrong number of analog ins\n");
		return false;
	}
	for(unsigned int n = 0; n < kNumOscs; ++n)
		gOscs.push_back({context->audioSampleRate});

	// setup the scope with kNumOscs  channels at the audio sample rate
	scope.setup(kNumOscs, context->audioSampleRate);

	if(context->analogFrames)
		gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
	return true;
}

void render(BelaContext *context, void *userData)
{
	for(unsigned int n = 0; n < context->audioFrames; n++) 
	{
		for(unsigned int c = 0; c < gOscs.size() && c < context->analogInChannels; ++c)
		{
			// Read values from inputs and map them to their maximum values.
			gIns[c] = analogRead(context, n / gAudioFramesPerAnalogFrame, c);
			gIns[c] = map(gIns[c], 0.f, gInsMax[c], 0.f, 1.f);
		}
		// log mapped values into scope.
		scope.log(gIns.data());
	}
}

void cleanup(BelaContext *context, void *userData)
{
}