i’m not sure i totally get it, but seems like head[0] is the write head and head[1] is the read head.
then yeah, to actually hear a delay, the read head position must be behind the write head position.
re: feedback
i had to look up buffer_head_mix in your repo. for the benefit of others, it is
void buffer_head_mix(bufferHead *head, fract32 sample, fract32 preLevel) {
head->buf->data[head->idx] = add_fr1x32(mult_fr1x32x32(head->buf->data[head->idx], preLevel), sample);
}
so, you are implementing the form of feedback known as overdubbing or “sound on sound,” mixing the new input with the signal from the previous pass. this makes most sense in a “looping” application where the read/write heads aren’t constantly moving in a fixed relationship; instead you might have the read head always/arbitrarily running, and then do “one-shot” passes of the write head to overlay new signal (or punch in/out on the current read head position, whatever)
when you do SOS and also have moving read/write heads, you get some strange timing effects; the interval at which old signals recur is a more complex function of both the delay time (distance between heads) and the start/end points of the buffer. this can be interesting, and it’s fun to make use of it (in aleph-lines, say, or using looping RecordBuf and PlayBuf in supercollider,) but it might not be what you are after.
(in fact you have opened up even more weird territory by allowing the read/write heads to have separate endpoints!)
to me, “feedback” (vs. “sos” or “overdub”) implies the kind of literal feedback algorithm you would see in an analog delay pedal - mixing some of the output from the read head with the input, like so:
// showing more steps for clarity
bufferHead *writeHead = &(c->head[0]);
bufferHead *readHead = &(c->head[1]);
fract32 *pWrite = &(writeHead->buf->data[writeHead->idx]);
fract32 read = readHead->buf->data[readHead->idx];
*pWrite = add_fr1x32(mult_fr1x32x32(read, c->feedback), sample);
to set the delay time, simply place the read head index behind the write head index:
set_delay_time_samples(prgmChn *c, int delayTimeSamples) {
c->head[1].idx = c->head[0].idx - delayTimeSamples;
// ... OMITTED: wrap the read head index to the buffer start/end points...
}
and update the indices as you’re doing
you should then have 100% wet output plus feedback.