Give the reverb delay lines one ring length for cursor and taps so no tap reads an unwritten slot (#421)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Valiantsin DzerakhandClaude Sonnet 5.5 committed 2026-11-02 03:16:58 +03:00
1 parent dd33a75ec4
commit d22a19c91d
2 files changed
+9 -6

No files matched your search

+7 -4
View File
@@ -22,8 +22,11 @@ struct AudioEffectDsp {
};
static int channel_ok(unsigned n) { return n==1 || n==2 || n==4 || n==6; }
static unsigned sample_count(unsigned rate, float ms) { return (unsigned)nearbyintf(rate*ms); }
/* The reference DelayLine wraps at CurrentSampleCount-1, including when its
backing allocation is larger. Preserve this timing for sample comparisons. */
/* The ring has `count` slots. The reference DelayLine wraps its cursor at
CurrentSampleCount-1 while its taps index modulo CurrentSampleCount, so once
per turn every tap reads a slot that is never written (a one-sample dropout
per tap, audible as grain). The cursor and the taps share one ring length here;
each delay is one sample longer than the reference. */
static void line_set(DelayLine *d, unsigned n) { d->count=n<d->max?n:d->max; d->at=0; }
static void line_init(DelayLine *d, unsigned rate, float ms) {
d->max=sample_count(rate,ms); d->data=calloc((size_t)d->max+1,sizeof(float));
@@ -32,12 +35,12 @@ static void line_init(DelayLine *d, unsigned rate, float ms) {
static float line_read(const DelayLine *d) { return d->data[d->at]; }
static float line_update(DelayLine *d,float v) {
float old=line_read(d);d->data[d->at++]=v;
if(d->at >= (d->count?d->count-1:0))d->at=0;
if(d->at >= d->count)d->at=0;
return old;
}
static float line_tap(const DelayLine *d,unsigned sample,int offset) {
int at=(int)d->at-(int)sample-offset;
if(at<0)at+=(int)d->count;
if(d->count){at%=(int)d->count;if(at<0)at+=(int)d->count;}
if(at<0 || (unsigned)at>d->max)rt_fatal("audio effect delay tap bounds");
return d->data[at];
}
+2 -2
View File
@@ -24,8 +24,8 @@ static void delay_set(Delay *d, unsigned n) { if (n > d->cap) rt_fatal("reverb d
static void delay_init(Delay *d, unsigned khz, float ms) { d->cap = samples(khz, ms); d->data = calloc(d->cap + 1, sizeof(float)); if (!d->data) rt_fatal("reverb delay allocation"); delay_set(d, d->cap); }
static float delay_update(Delay *d, float v) {
d->data[d->write++] = v; float out = d->data[d->read++];
if (d->read >= d->cap) d->read = 0;
if (d->write >= d->cap) d->write = 0;
if (d->read > d->cap) d->read = 0;
if (d->write > d->cap) d->write = 0;
return out;
}
static float delay_tap(const Delay *d, unsigned at) { int i = (int)d->write - (int)at - 1; if (i < 0) i += (int)d->cap + 1; return d->data[i]; }