Hello! Thank you very much for the link. I tried it with this example and playing the file back works. Now I want to speed up the file by playing back only every nth sample. I tried it with the following code and it works for 2x, 3x, and 4x faster, but from 5x and higher it sounds like it doesn't read in enough samples and then starts playing back some of the already played samples ... it sound like a sort of echo. I read the code multiple times but I can't wrap my head around why ... do you maybe have an idea what it could be? Thank you so much for your help already!
#include <Bela.h>
#include <libraries/AudioFile/AudioFile.h>
#include <vector>
#include <string>
std::vector<AudioFileReader> gReaders(2);
std::vector<std::string> gFilenames = {
"20241008_192123.WAV",
"20241012_000000.WAV",
};
size_t gLoadingFile;
size_t gCurrReader;
std::vector<float> gSamples;
size_t gFrameCount = 0;
AuxiliaryTask gStartLoadingFileTask;
int gSpeed = 10;
void loadNextFile(void*)
{
// start preloading the next file
gLoadingFile = (gLoadingFile + 1) % gFilenames.size();
size_t nextReader = (gCurrReader + 1) % gReaders.size();
gReaders[nextReader].setup(gFilenames[gLoadingFile], 16384);
rt_printf("Opening file [%zu] %s in reader %zu with a lentgh of %zu\n", gLoadingFile, gFilenames[gLoadingFile].c_str(),
nextReader, gReaders[nextReader].getLength());
}
bool setup(BelaContext *context, void *userData)
{
// create a task to load files
gStartLoadingFileTask = Bela_createAuxiliaryTask(loadNextFile, 1, "loadNextFile");
if(!gStartLoadingFileTask) {
fprintf(stderr, "Error creating file loading task\n");
return false;
}
gLoadingFile = -1;
gCurrReader = -1;
// open the first file
loadNextFile(NULL);
gCurrReader = 0;
// open the second file
loadNextFile(NULL);
gSamples.reserve(context->audioFrames * gReaders[gCurrReader].getChannels() * gSpeed);
return true;
}
void render(BelaContext *context, void *userData) {
AudioFileReader& reader = gReaders[gCurrReader];
// this call may allocate memory if getChannels() is larger than for
// all previous files
gSamples.resize(context->audioFrames * reader.getChannels() * gSpeed);
reader.getSamples(gSamples);
for(unsigned int n = 0; n < context->audioFrames; ++n)
{
float out = 0;
for(unsigned int c = 0; c < context->audioOutChannels; ++c)
{
// write each channel from the audio file to the
// output channels. If there are more output channels
// than channels in the file, copy the file's last
// channel to all remaining outputs
if(c < reader.getChannels())
out = gSamples[n * gSpeed * reader.getChannels() + c];
audioWrite(context, n, c, out);
}
// count samples played back for the existing file
gFrameCount += gSpeed;
if(gFrameCount >= reader.getLength())
{
// reached end of file
gFrameCount = 0;
// start playing the file we preloaded
gCurrReader = (gCurrReader + 1) % gReaders.size();
reader.getSamples(gSamples);
rt_printf("Playing from reader: %zu\n", gCurrReader);
// start loading next file in a real-time safe way
Bela_scheduleAuxiliaryTask(gStartLoadingFileTask);
}
}
}
void cleanup(BelaContext *context, void *userData)
{
}