Just wanted to say thanks to all developers for making Bela. Really smooth experience getting up and going with the platform. I really like the USB Ethernet thing. All I had to do was ifconfig eth2 192.168.7.1, type in Bela ip address in web browser and I was making a sine tone. This web based IDE is really slick and I'm lovin' it 🙂

In my first 1/2 hour for fun I re-implemented the sine tone with a sine-wave oscillator. It might be useful for some of those pushing the envelope on CPU usage needing a more efficient way to approximate a sine function:

void setup_oscillator(float Phase, float* s, float* c)
{
     //LFO
     *s = sin(Phase);
     *c = cos(Phase);
}

float run_oscillator(float* s, float* c, float o, float d, float frq)
{
	float k =  2.0*M_PI*frq* gInverseSampleRate; 

	//run oscillator
       *s += *c*k;
       *c -= *s*k;
	return *s*d + o;
}

Define some float* type state variables and pass by reference
s ==> SinPart
c ==> CosPart

These are handy if using it as a modulator (like tremolo)
o ==> Oscillator offset ( zero for a tone )
d ==> Oscillator "depth", or amplitude
frq ==> Oscillator frequency

For a constant tone (or LFO rate) you wouldn't normally want to compute k on every run of the oscillator.

My first 1/2 hour experiment was to make a police siren sound where the frequency was being modulated by the LFO just as a proof-of concept. The next obvious evolution is a tremolo effect using the sine oscillator just so I can get familiar with using the analog inputs (reading a pot for depth and rate).

Here's the full sketch of the Police Siren for anybody who wants a more irritating "hello world" to try:

*************************
#include <Bela.h>
#include <cmath>

float gFrequency = 82.0*12;
float cosPartT = 0.0;
float sinPartT = 0.0;
float Tconst = 0.0;
float modulated_frequency = gFrequency;
float fmod_depth = 0.5;
float gPhase;
float gInverseSampleRate;
float modulator = 1.0;

float sinPart = 0.0;
float cosPart = 0.0;
float lfoConst = 0.0;
float lfoRate = 3;
float lfodepth = 0.5;

void setup_oscillator(float Phase, float* s, float* c)
{
     //LFO
     *s = sin(Phase);
     *c = cos(Phase);
}

float run_oscillator(float* s, float* c, float o, float d, float frq)
{
	float k =  2.0*M_PI*frq* gInverseSampleRate; 
	//run oscillator

    *s += *c*k;
    *c -= *s*k;
	return *s*d + o;
}

bool setup(BelaContext *context, void *userData)
{
	gInverseSampleRate = 1.0 / context->audioSampleRate;
	gPhase = 0.0;
	
	setup_oscillator(1.0, &sinPart, &cosPart);
	setup_oscillator(1.0,  &sinPartT, &cosPartT);

	return true;
}

void render(BelaContext *context, void *userData)
{
	for(unsigned int n = 0; n < context->audioFrames; n++) {
		float out = run_oscillator(&sinPartT, &cosPartT, 0.0, 0.8,modulated_frequency)*run_oscillator(&sinPart, &cosPart, 1.0, 0.5,lfoRate);
		modulated_frequency = gFrequency*(1.0 + sinPart*fmod_depth);

		for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
			// Two equivalent ways to write this code

			// The long way, using the buffers directly:
			// context->audioOut[n * context->audioOutChannels + channel] = out;

			// Or using the macros:
			audioWrite(context, n, channel, out);
		}
	}
}

    Welcome to Bela and thanks for your feedback.
    I edited your post so to enclose code blocks within triple back ticks:

    ```    
    Like this
    ```   

    to provide nice formatting and improve readability.

    LiamDonovan Interesting. I hadn't explored the examples enough to notice the neon example. Actually this is really nice to have been made aware of the neon optimized libraries -- a lot of useful stuff in there.

    If I were to make a guess I would think the NEON-optimized oscillator bank would win for performance, especially with a large number of constant-frequency oscillators.

    The application in which my oscillator example might show an advantage is in the case of continuous frequency modulation. How much overhead is incurred to implement continuous FM with the neon oscillator bank? Does it require cross-fading? I don't know the guts of this algorithm but it would appear if there was a benchmark experiment performed, FM performance would be one of the test cases to cover.

    With 11-Extras/oscillator-bank you can change frequency as often as once per block without performance penalty (except - of course - the CPU time needed to actually recompute the frequencies and store them in memory).
    I guess you will still see good performance by changing frequency every frame, if you have a large number of oscillators: you will still be processing a batch of gNumOscillators samples at a time, with the extra overhead of having context->audioFramesfunction calls (instead of 1), but you are right, this is surely something interesting to benchmark.

    You can find more details on the optimized math functions here.