I'm working on my own version of a sound recorder similar to the OP. I took a break from C programming to do some javascript/web work for my undergrad capstone, and now I'm using Bela as a way to re-familiarize myself with C and C++ specifics, and venture into audio/DSP territory as well.
My code below is a quick adaptation/combination of the basic sine-tone and the sample-streamer examples, along with an auxiliary function to handle writing the WAV file with libsndfile. The main issue I'm having is that my resulting Wav file is silence, except for what appears to be the very last chunk written to the file by the buffer. I've also attached a screenshot from the file loaded into a Max/MSP buffer display, labeled in milliseconds. My buffer is 22050 samples long (like the sample streamer example), so based on the display, it does look like only the last time through the buffer is being written.
What am I missing? I'm sure it's some small silly error or misunderstanding of libsndfile's writing operations on my part

#include <Bela.h>
#include <cmath>
#include <SampleData.h>
#include <sndfile.h>
#include <cstdlib>
#define NUM_CHANNELS 1
#define BUFFER_LEN 22050
float gFrequency = 440.0;
float gPhase;
float gInverseSampleRate;
float gDuration = 5 * 44100;
float gCount = 0;
SampleData gSampleBuf[2][NUM_CHANNELS];
int gPos = 0;
int gActiveBuffer = 0;
int gDoneLoadingBuffer = 1;
int gChunk = 0;
AuxiliaryTask gFillBufferTask;
void writeFile(float *buf, int startSamp, int endSamp){
SF_INFO sfinfo ;
sfinfo.channels = NUM_CHANNELS;
sfinfo.samplerate = 44100;
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
const char* path = "./test.wav";
int frameLen = endSamp - startSamp;
SNDFILE * outfile = sf_open(path, SFM_WRITE, &sfinfo);
sf_seek(outfile, startSamp, SEEK_SET);
sf_count_t count = sf_write_float(outfile, &buf[0], frameLen);
sf_write_sync(outfile);
sf_close(outfile);
}
void fillBuffer(void*) {
gChunk += BUFFER_LEN;
int end = gChunk + BUFFER_LEN;
writeFile(gSampleBuf[!gActiveBuffer][0].samples, gChunk, end);
gDoneLoadingBuffer = 1;
}
bool setup(BelaContext *context, void *userData) {
gInverseSampleRate = 1.0 / context->audioSampleRate;
gPhase = 0.0;
if((gFillBufferTask = Bela_createAuxiliaryTask(&fillBuffer, 90, "fill-buffer")) == 0) {
return false;
}
for(int ch=0;ch<NUM_CHANNELS;ch++) {
for(int i=0;i<2;i++) {
gSampleBuf[i][ch].sampleLen = BUFFER_LEN;
gSampleBuf[i][ch].samples = new float[BUFFER_LEN];
}
}
return true;
}
void render(BelaContext *context, void *userData) {
for(unsigned int n = 0; n < context->audioFrames; n++) {
float out = 0.8f * sinf(gPhase);
gPhase += 2.0f * (float)M_PI * gFrequency * gInverseSampleRate;
if(gPhase > M_PI) {
gPhase -= 2.0f * (float)M_PI;
}
if(gPos == 0) {
if(!gDoneLoadingBuffer && gCount <= gDuration) {
printf("increase buffer size!\n");
}
gDoneLoadingBuffer = 0;
gActiveBuffer = !gActiveBuffer;
if (gCount <= gDuration) {
Bela_scheduleAuxiliaryTask(gFillBufferTask);
}
}
if (gCount > gDuration) {
for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
audioWrite(context, n, channel, 0);
}
} else {
gSampleBuf[gActiveBuffer][0].samples[gPos] = out;
for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
audioWrite(context, n, channel, out);
}
}
gCount++;
gPos = (gPos + 1)%BUFFER_LEN;
}
}
void cleanup(BelaContext *context, void *userData) {
for(int ch=0;ch<NUM_CHANNELS;ch++) {
for(int i=0;i<2;i++) {
delete[] gSampleBuf[i][ch].samples;
}
}
}