- Edited
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);
}
}
}