This program checks that audio and analog I/O work properly. You should physically connect each audio and analog output back to its respective input.
 
#include <cmath>
#include <Gpio.h>
 
float ANALOG_OUT_LOW;
float ANALOG_OUT_HIGH;
float ANALOG_IN_LOW;
float ANALOG_IN_HIGH;
 
enum {
        kStateTestingAudioLeft = 0,
        kStateTestingAudioRight,
        kStateTestingAudioDone,
        kStateTestingAnalog,
        kStateTestingAnalogDone,
        kStateTestingNone
};
 
uint64_t gLastErrorFrame = 0;
uint32_t gEnvelopeSampleCount = 0;
float gEnvelopeValueL = 0.5, gEnvelopeValueR = 0.5;
float gEnvelopeDecayRate = 0.9995;
int gEnvelopeLastChannel = 0;
 
float gPositivePeakLevels[2] = {0, 0};
float gNegativePeakLevels[2] = {0, 0};
float gPeakLevelDecayRate = 0.999;
int gAnalogTestSuccessCounter = 0;
const float gPeakLevelLowThreshold = 0.02;
const float gPeakLevelHighThreshold = 0.2;
const float gDCOffsetThreshold = 0.1;
int gAudioTestState = kStateTestingNone;
int gAudioTestStateSampleCount = 0;
int gAudioTestSuccessCounter = 0;
const int gAudioTestSuccessCounterThreshold = 64;
const int gAudioTestStateSampleThreshold = 16384;
 
 
{
        printf("To prepare for this test you should physically connect each audio and analog output back to its respective input\n");
        {
                printf("On Bela Mini, feed back the line out L to audio in L and analogs 0, 2, 4, 6, and a feed the line out R to audio in L and analogs 1, 3, 5 ,7\n");
                
                
                ANALOG_OUT_LOW = -1; 
                ANALOG_OUT_HIGH = 1; 
                ANALOG_IN_LOW = 0.15;
                ANALOG_IN_HIGH = 0.5;
                
                led1->
open(87, Gpio::OUTPUT);
                led2->
open(89, Gpio::OUTPUT);
        } else {
                ANALOG_OUT_LOW = 0;
                ANALOG_OUT_HIGH = 50000.0 / 65536.0;
                ANALOG_IN_LOW = 2048.0 / 65536.0;
                ANALOG_IN_HIGH = 50000.0 / 65536.0;
        }
        return true;
}
 
{
 
        
        
        static float phase = 0.0;
        static int sampleCounter = 0;
        static int invertChannel = 0;
        float frequency = 0;
 
        if(gAudioTestState == kStateTestingNone){
                gAudioTestState = kStateTestingAudioLeft;
                rt_printf("Testing audio left\n");
        }
 
        if(gAudioTestState == kStateTestingAudioDone)
        {
                gAudioTestState = kStateTestingAnalog;
                rt_printf("Testing analog\n");
        }
 
        
        for(
unsigned int n = 0; n < context->
audioFrames; n++) {
 
 
                
                
                        if(value > gPositivePeakLevels[ch])
                                gPositivePeakLevels[ch] = value;
                        gPositivePeakLevels[ch] += 0.1f;
                        gPositivePeakLevels[ch] *= gPeakLevelDecayRate;
                        gPositivePeakLevels[ch] -= 0.1f;
                        if(value < gNegativePeakLevels[ch])
                                gNegativePeakLevels[ch] = value;
                        gNegativePeakLevels[ch] -= 0.1f;
                        gNegativePeakLevels[ch] *= gPeakLevelDecayRate;
                        gNegativePeakLevels[ch] += 0.1f;
                }
 
                int enabledChannel;
                int disabledChannel;
                const char* enabledChannelLabel;
                const char* disabledChannelLabel;
                if(gAudioTestState == kStateTestingAudioLeft) {
                        enabledChannel = 0;
                        disabledChannel = 1;
                        enabledChannelLabel = "Left";
                        disabledChannelLabel = "Right";
                } else if (gAudioTestState == kStateTestingAudioRight) {
                        enabledChannel = 1;
                        disabledChannel = 0;
                        enabledChannelLabel = "Right";
                        disabledChannelLabel = "Left";
                }
                if(gAudioTestState == kStateTestingAudioLeft || gAudioTestState  == kStateTestingAudioRight)
                {
                        audioWrite(context, n, enabledChannel, 0.2f * sinf(phase));
 
 
                        frequency = 3000.0;
                        if(phase >= M_PI)
                                phase -= 2.0f * (float)M_PI;
 
                        gAudioTestStateSampleCount++;
                        if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) {
                                
                                
                                
                                if((gPositivePeakLevels[enabledChannel] - gNegativePeakLevels[enabledChannel]) >= gPeakLevelHighThreshold
                                        && (gPositivePeakLevels[disabledChannel] -  gNegativePeakLevels[disabledChannel]) <= gPeakLevelLowThreshold &&
                                        fabsf(gPositivePeakLevels[disabledChannel]) < gDCOffsetThreshold &&
                                        fabsf(gNegativePeakLevels[disabledChannel]) < gDCOffsetThreshold) {
                                        
                                        gAudioTestSuccessCounter++;
                                        if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) {
                                                rt_printf("Audio %s test successful\n", enabledChannelLabel);
                                                if(gAudioTestState == kStateTestingAudioLeft)
                                                {
                                                        gAudioTestState = kStateTestingAudioRight;
                                                        rt_printf("Testing audio Right\n");
                                                } else if(gAudioTestState == kStateTestingAudioRight)
                                                {
                                                        gAudioTestState = kStateTestingAudioDone;
                                                }
 
                                                gAudioTestStateSampleCount = 0;
                                                gAudioTestSuccessCounter = 0;
                                        }
 
                                }
                                else {
                                                
                                                if((gPositivePeakLevels[enabledChannel] - gNegativePeakLevels[enabledChannel]) < gPeakLevelHighThreshold)
                                                        rt_printf("%s Audio In FAIL: insufficient signal: %f\n", enabledChannelLabel,
                                                                                gPositivePeakLevels[enabledChannel] - gNegativePeakLevels[enabledChannel]);
                                                else if(gPositivePeakLevels[disabledChannel] -  gNegativePeakLevels[disabledChannel] > gPeakLevelLowThreshold)
                                                        rt_printf("%s Audio In FAIL: signal present when it should not be: %f\n", disabledChannelLabel,
                                                                                gPositivePeakLevels[disabledChannel] -  gNegativePeakLevels[disabledChannel]);
                                                else if(fabsf(gPositivePeakLevels[disabledChannel]) >= gDCOffsetThreshold ||
                                                                fabsf(gNegativePeakLevels[disabledChannel]) >= gDCOffsetThreshold)
                                                        rt_printf("%s Audio In FAIL: DC offset: (%f, %f)\n", disabledChannelLabel,
                                                                                gPositivePeakLevels[disabledChannel], gNegativePeakLevels[disabledChannel]);
                                        }
                                        gAudioTestSuccessCounter--;
                                        if(gAudioTestSuccessCounter <= 0)
                                                gAudioTestSuccessCounter = 0;
                                }
                        }
                }
                if(
                        gAudioTestState == kStateTestingAnalogDone || 
                )
                {
                        
                        
                        audioWrite(context, n, 0, gEnvelopeValueL * sinf(phase));
 
                        audioWrite(context, n, 1, gEnvelopeValueR * sinf(phase));
 
 
                        
                        
                        {
                                gEnvelopeValueL *= gEnvelopeDecayRate;
                                gEnvelopeValueR *= gEnvelopeDecayRate;
                                gEnvelopeSampleCount++;
                                if(gEnvelopeSampleCount > 22050) {
                                        if(gEnvelopeLastChannel == 0)
                                                gEnvelopeValueR = 0.5;
                                        else
                                                gEnvelopeValueL = 0.5;
                                        gEnvelopeLastChannel = !gEnvelopeLastChannel;
                                        gEnvelopeSampleCount = 0;
                                }
                                frequency = 880.0;
                                if(led1)
                                {
                                        led1->write(gEnvelopeValueL > 0.2);
                                }
                                if(led2)
                                {
                                        led2->write(gEnvelopeValueR > 0.2);
                                }
                        } else {
                                gEnvelopeValueL = gEnvelopeValueR = 0.5;
                                gEnvelopeLastChannel = 0;
                                frequency = 220.0;
                        }
 
                        if(phase >= M_PI)
                                phase -= 2.0f * (float)M_PI;
                }
        }
 
        if(gAudioTestState == kStateTestingAnalog)
        {
                for(unsigned int n = 0; n < outFrames; n++) {
                        
                        for(unsigned int k = 0; k < outChannels; k++) {
                                float outValue;
                                if((k % outChannels) == (invertChannel % outChannels))
                                        outValue = sampleCounter < 512 ? ANALOG_OUT_HIGH : ANALOG_OUT_LOW;
                                else
                                        outValue = sampleCounter < 512 ? ANALOG_OUT_LOW : ANALOG_OUT_HIGH;
                                else
                        }
                }
 
                        
                        
                        if(sampleCounter == 256 || sampleCounter == 768) {
                                        bool inverted = ((k % outChannels) == (invertChannel % outChannels));
                                        if(
                                                (
                                                        inverted &&
                                                        (
                                                                (sampleCounter == 256 && inValue < ANALOG_IN_HIGH) ||
                                                                (sampleCounter == 768 && inValue > ANALOG_IN_LOW)
                                                        )
                                                ) || (
                                                        !inverted &&
                                                        (
                                                                (sampleCounter == 256 && inValue > ANALOG_IN_LOW) ||
                                                                (sampleCounter == 768 && inValue < ANALOG_IN_HIGH)
                                                        )
                                                )
                                        )
                                        {
                                                rt_printf("Analog FAIL [output %d, input %d] -- output %s input %f %s\n",
                                                        k % outChannels,
                                                        k,
                                                        (sampleCounter == 256 && inverted) || (sampleCounter == 768 && !inverted) ? "HIGH" : "LOW",
                                                        inValue,
                                                        inverted ? "(inverted channel)" : "");
                                                gAnalogTestSuccessCounter = 0;
                                        } else {
                                                ++gAnalogTestSuccessCounter;
                                        }
                                }
                        }
 
                        if(++sampleCounter >= 1024) {
                                sampleCounter = 0;
                                invertChannel++;
                                if(invertChannel >= 8)
                                        invertChannel = 0;
                        }
                        if(gAnalogTestSuccessCounter >= 500) {
                                static bool notified = false;
                                if(!notified)
                                {
                                        rt_printf("Analog test successful\n");
                                        gAudioTestState = kStateTestingAnalogDone;
 
                                }
                                notified = true;
                        }
                }
        }
}
 
{
        delete led1;
        delete led2;
}
int open(unsigned int pin, Direction direction, bool unexport=true)
static float audioRead(BelaContext *context, int frame, int channel)
Read an audio input, specifying the frame number (when to read) and the channel.
Definition Bela.h:1458
static float analogRead(BelaContext *context, int frame, int channel)
Read an analog input, specifying the frame number (when to read) and the channel.
Definition Bela.h:1480
static void audioWrite(BelaContext *context, int frame, int channel, float value)
Write an audio output, specifying the frame number (when to write) and the channel.
Definition Bela.h:1469
static void analogWriteOnce(BelaContext *context, int frame, int channel, float value)
Write an analog output, specifying the frame number (when to write) and the channel.
Definition Bela.h:1491
void render(BelaContext *context, void *userData)
User-defined callback function to process audio and sensor data.
Definition render.cpp:68
bool setup(BelaContext *context, void *userData)
User-defined initialisation function which runs before audio rendering begins.
Definition render.cpp:51
void cleanup(BelaContext *context, void *userData)
User-defined cleanup function which runs when the program finishes.
Definition render.cpp:96
Structure holding audio and sensor settings and pointers to I/O data buffers.
Definition Bela.h:231
const uint32_t audioOutChannels
The number of audio output channels.
Definition Bela.h:326
const uint32_t audioFrames
The number of audio frames per block.
Definition Bela.h:322
const uint32_t audioInChannels
The number of audio input channels.
Definition Bela.h:324
const float audioSampleRate
The audio sample rate in Hz (currently always 44100.0).
Definition Bela.h:328
const uint32_t analogFrames
The number of analog frames per block.
Definition Bela.h:341
const uint32_t analogOutChannels
The number of analog output channels.
Definition Bela.h:351
const uint32_t analogInChannels
The number of analog input channels.
Definition Bela.h:346
const uint64_t audioFramesElapsed
Number of elapsed audio frames since the start of rendering.
Definition Bela.h:379