Does seem neat! Very fun
I think this has alot of potential to be kick-arce!
A few things:
1) I'm not sure what the waveshaper does? Control the sample buffer's amp, EQ, freq? Plus I think the GUI doesn't make it clear that the EQ is before it in the audio chain.
2) Feedback is often way loud past 50%, to the point of clipping. Might be worth putting the the GUI that it is - % on the left, + % on the right.
3) Having a graphic spline EQ (looking like the waveshaper) would be really neat to simulate damping inside the delay.
Cheers for the feedback:
1) The waveshaper modifies the signals amp passing through it . You read the input sample along the x axis, and the corresponding y value is the output sample. So a straight diagonal line from bottom-left to top-right will do nothing to the sample (output = input). Different shapes will distort the signal in different ways: the default is set to mimic a sort of tape saturation, as rl suggests..
2) The max feedback is 100%, however if any of the waveshaper graph is above the diagonal line it will amplify as well, so you may get clipping because of that..
3) Good idea.. I may use the parametric EQ instead to allow more complex damping..
oddson wrote:This is extremely cool but I can't make heads nor tails out of the delay code... Confused
Any chance you might add some comments to it sometime?
Also, I think 'ratio' is a bit misleading as a label for what I take to be a playback speed variable (on the tape delay analogy).
Thanks! I'll post some commented code.. I was just making sure it was working, and yup, labelling it 'speed' would be a bit more sensible..
With a standard delay you read a sample from an array, write a new sample to the array then increase the array pointer by 1 sample. This creates a simple delay of the length of the array..
With this delay, the array size is fixed, but the size of the step that the pointer makes is defined by the ratio, this has implications for reading and writing to the array.
- Code: Select all
ratio = min(ratio,10);
ratio = max(ratio,0.1);
/* This is to limit the range of the ratio values..*/
rp = rp + ratio;
rp = rp - (rp>=SIZEDEL)&SIZEDEL;
/*advance the pointer by the ratio, and if it exceeds the delay size, start back again at zero..*/
rpi = rp - 0.5;
rpi = rndint(rpi);
frac = rp - rpi;
/*extract the integer and fractional part of the pointer*/
When reading, it's now possible to have fractional pointers eg 23.45, so we need to interpolate the data, as you would with a wav file
- Code: Select all
rpi1 = rpi + 1;
rpi1 = rpi1 - (rpi1>=SIZEDEL)&SIZEDEL;
rpi2 = rpi1 + 1;
rpi2 = rpi2 - (rpi2>=SIZEDEL)&SIZEDEL;
out = (1 - frac) * dubdelay[rpi1] + frac * dubdelay[rpi2];
/*The output is standard linear interpolation between the values rpi1 and rpi2 (pointer +1 and pointer +2) we read from +1 so we don't read the sample we've just written(which can happen with ratios<1)..*/
When writing to the array, we only want to write to integer sample values that the pointer passes:
for example if the old sample position 23.45 and the ratio is 0.3, the new sample position will be 23.75, in this case we havn't crossed a sample, so we we shouldnt write any data..
If on the other hand the old position is 23.45 and th ratio in 2.7, the new sample position will be 26.15, in this case we've crossed 3 sample's 24, 25 and 26 so we should write to these samples using linear interpolation..
The number of samples crossed is calculated with the countback variable, if it's less than zero no samples are crossed, 0-1 1 sample crossed, 1-2 2 samples crossed.. etc
I'll go over the writing code in a bit.. I've got some chores to do now