During the past few months I dove into audio loops, both from musicians and makers perspective. Mainly because of some unused SDRAM on the daisy seed board i decided to implement a looper functionality. This has proven to be rather simple from a programming perspective. When playing around with the looper it has proved to be a useful musical tool and fun to play with. One thing a added which is not commonly present at least on smaller loopers is a retrigger function. This I added to be able to manually sync to loop to an external one. It has proved to be really useful for a two-person ambient project i’m part of. The video demonstrates the looper function and briefly explains the theory of operation.
Theory
A looper is essentially a very long delay with a “freeze” function. The sample processing method of the looper is as follows
float LooperProcessSample(float sampleIn, LooperDataType* data)
{
float sampleOut;
if (data->looperState == LOOPER_STATE_STOPPED)
{
return sampleIn;
}
if (data->looperState != LOOPER_STATE_RECORDING)
{
sampleOut = sampleIn + *(data->memoryPointer + data->currentPosition)*data->playVolume;
}
else
{
sampleOut = sampleIn;
}
if (data->looperState == LOOPER_STATE_RECORDING)
{
*(data->memoryPointer + data->currentPosition) = sampleIn*data->recordingVolume;
}
if (data->looperState == LOOPER_STATE_OVERDUBBING)
{
*(data->memoryPointer + data->currentPosition) += sampleIn*data->recordingVolume;
}
if (++data->currentPosition >= data->indexEnd)
{
data->currentPosition = data->indexStart;
}
return sampleOut;
}Depending on the state of the looper we either add a sample from the delay line (data->memorypointer) to the input sample or don’t. Also, if the looper either recording or overdubbing we write into the delay line.
The whole handling of the looper revolves around a state machine with the following data structure.
typedef struct {
float * memoryPointer;
float playVolume;
float recordingVolume;
uint32_t indexStart;
uint32_t indexEnd;
uint32_t currentPosition;
uint8_t looperState;
uint8_t looperFunction;
} LooperDataType;Suprisingly the state changes are rather complex although the looper is rather simple to use. P1 to P3 denote the foot switches of the PiPicoFX from left to right.



