Hello,

/*
 ____  _____ _        _    
| __ )| ____| |      / \   
|  _ \|  _| | |     / _ \  
| |_) | |___| |___ / ___ \ 
|____/|_____|_____/_/   \_\

http://bela.io

C++ Real-Time Audio Programming with Bela - Lecture 4: Parameter control
wavetable-slider: oscillator example using a browser-based GUI for control
*/

#include <Bela.h>
#include <libraries/Gui/Gui.h>
#include <libraries/GuiController/GuiController.h>
#include <cmath>

const int gWavetableLength = 512;	// The length of the buffer in frames
float gWavetable[gWavetableLength];	// Buffer that holds the wavetable
float gReadPointers[2] = {0, 0};    // Position of the last frame we played

// Browser-based GUI to adjust parameters
Gui gui;
GuiController controller;

bool setup(BelaContext *context, void *userData)
{
	    // Generate a sawtooth waveform (a ramp from -1 to 1) and
    // store it in the buffer. Notice: generating the wavetable does 
    // not depend on the audio sample rate (why not?)
    for(unsigned int n = 0; n < gWavetableLength; n++) {
	    gWavetable[n] = -1.0 + 2.0 * (float)n / (float)(gWavetableLength - 1);
    }

    // Set up the GUI
    gui.setup(context->projectName);
    controller.setup(&gui, "Wavetable Controller");	

    // Arguments: name, default value, minimum, maximum, increment
    controller.addSlider("Frequency", 220, 55, 440, 0);
    controller.addSlider("Amplitude", -20, -40, 0, 0);
        controller.addSlider("Detune", 0, 0, 0.05, 0);

    return true;
}

void render(BelaContext *context, void *userData)
{
    float frequency = controller.getSliderValue(0);	// Frequency is first slider
    float amplitude = controller.getSliderValue(1);	// Amplitude is second slider	
    float detune = controller.getSliderValue(2);    // Detune is our third slider

    float amplitude = powf(10.0, amplitudeDB / 20); // I RECEIVE AN ERROR HERE

    float frequencies[2];
    frequencies[0] = centreFrequency * (1.0 + detune); // I RECEIVE AN ERROR HERE
    frequencies[1] = centreFrequency * (1.0 - detune); // I RECEIVE AN ERROR HERE, TOO

    for(unsigned int n = 0; n < context->audioFrames; n++) {
	    float out = 0;
	
	    for(unsigned int i = 0; i < 2; i++) {
	        // The pointer will take a fractional index. Look for the sample on
	        // either side which are indices we can actually read into the buffer.
	        // If we get to the end of the buffer, wrap around to 0.
	        int indexBelow = floorf(gReadPointers[i]);
	        int indexAbove = indexBelow + 1;
	        if(indexAbove >= gWavetableLength)
		    indexAbove = 0;
	 
	        // For linear interpolation, we need to decide how much to weigh each
	        // sample. The closer the fractional part of the index is to 0, the
	        // more weight we give to the "below" sample. The closer the fractional
	        // part is to 1, the more weight we give to the "above" sample.
	        float fractionAbove = gReadPointers[i] - indexBelow;
	        float fractionBelow = 1.0 - fractionAbove;
	
	        // Calculate the weighted average of the "below" and "above" samples
                out += amplitude * (fractionBelow * gWavetable[indexBelow] +
    				    fractionAbove * gWavetable[indexAbove]);
    				
    	        gReadPointers[i] += gWavetableLength * frequencies[i] / context->audioSampleRate;
    	        while(gReadPointers[i] >= gWavetableLength)
    	            gReadPointers[i] -= gWavetableLength;
	    }
        
	        for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
		    // Write the sample to every audio output channel
		    audioWrite(context, n, channel, out);
	        }
    }
}

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

}

I think I am missing something from Course 4 online on Youtube.com.

Seth

P.S. If you see where I am making errors, please let me know. Oh...

Bela stopped
redefinition of 'amplitude' column: 8, line: 54
use of undeclared identifier 'amplitudeDB'; did you mean 'amplitude'? column: 31, line: 54
use of undeclared identifier 'centreFrequency' column: 19, line: 57
use of undeclared identifier 'centreFrequency' column: 19, line: 58

    let's look at the errors:

    silver2row redefinition of 'amplitude' column: 8, line: 54

    this means that a variable got defined twice in the same scope. In this case you see you have two lines that start with:

    float amplitude

    this is illegal.

    use of undeclared identifier 'amplitudeDB'; did you mean 'amplitude'? column: 31, line: 54

    this means that you are using an identifier amplitudeDB which is undeclared. In this case, you have not defined any variable called amplitudeDB before the point where you are trying to use it, and this is what is causing this error.
    Given these two errors, I would guess that this line:

        float amplitude = controller.getSliderValue(1);	// Amplitude is second slider	

    should instead be

        float amplitudeDB = controller.getSliderValue(1);	// Amplitude is second slider	

    . This way, the slider's value is in dB, and gets converted to linear at this line:

        float amplitude = powf(10.0, amplitudeDB / 20); // I RECEIVE AN ERROR HERE

    These:

    use of undeclared identifier 'centreFrequency' column: 19, line: 57
    use of undeclared identifier 'centreFrequency' column: 19, line: 58

    mean that you are trying to use the centreFrequency variable without declaring it. You probably intended to declare it in the first line of the function, which should become:

        float centreFrequency = controller.getSliderValue(0);	// Frequency is first slider

    Hello,

    Yes sir. I see now. I have undeclared variables and mistakenly put:

    float amplitude 

    instead of...

    float amplitudeDB

    I am starting to realize the errors now. Okay. I will attempt this idea later and get back to you. Thank you, again.

    Seth

    P.S. I made some corrections like you stated. I could not really figure out how to use frequency just yet but it was in my slider GUI configuration still. So, anyway, this is my source for that particular issue:

    void render(BelaContext *context, void *userData)
    {
        // float frequency = controller.getSliderValue(0);	// Frequency is first slider
        float amplitudeDB = controller.getSliderValue(1);	// Amplitude is second slider	
        float detune = controller.getSliderValue(2);    // Detune is our third slider
        float centreFrequency = controller.getSliderValue(0);
    
        float amplitude = powf(10.0, amplitudeDB / 20);
    
        float frequencies[2];  // Frequencies of each individual oscillator
        frequencies[0] = centreFrequency * (1.0 + detune);
        frequencies[1] = centreFrequency * (1.0 - detune);

    What do you think of this idea?