Hi!
I spent some time searching for answers to this specific question but I didn’t find any. I’m sorry if I missed any relevant posts.
I want to create a tape delay emulation that behaves exactly like an actual tape delay (e.g. space echo) when the delay time is modulated during performance. Here is an example (things like multitap aside):
- Set the delay time to 0.5 secs and the feedback to something between 0.9 and 0.95.
- Play some high notes.
- Within about 0.5 secs, modulate the delay time to 5 secs. You hear a short chirp, as the high notes get pitched down.
When the modulation is done, the notes drone along, now with low pitch. This is because the distance between the write head and the read head is static and the modulation is done by reducing the tape speed. Write and read speeds are coupled.
Any implementation that modulates the delay time by adjusting the time delta between the write head and the read head behaves differently: The short chirping sound that is created by modulating the read speed gets fed into the feedback loop and is played back repeatedly, because the write speed didn’t change along with the read speed.
So I thought I could model the desired behaviour by using a Buffer, BufRd, BufWr and modulating the delaytime via the rate of a Phasor that drives both the read and write positions. But this doesn’t work. I suppose, the problem is that BufRd has interpolation and BufWr doesn’t. Not sure though…
Any help would be very much appreciated. Thanks in advance!
(
// tapedelay
// instantiate and play annoying test signal through delay
r = Routine({
SynthDef(\tapedelay1, {
var in, send, buf, numChan, bufSize, writePos, write, readPos, read, time, sig;
in = Saw.ar({LFNoise0.kr(0.25, 24, 72).round.lag(0.4).midicps}!4)
* Decay2.ar(Impulse.ar(0.25), 0.5, 2)
* -18.dbamp;
in = in.sum;
send = BLowShelf.ar(in, \loShlv.kr(300), 1, -6);
send = BHiShelf.ar(send, \hiShlv.kr(1500), 1, -6);
numChan = 1;
bufSize = (s.sampleRate * 10);
buf = LocalBuf(bufSize, numChan);
//buf = Buffer.alloc(s, max, numChan);
buf.clear;
//time = (10 / \time.kr(2)).lag(0.4).round;
time = (5 / \time.kr(1)).lag(0.4);
writePos = Phasor.ar(0.0, time, 0.0, bufSize).poll;
readPos = (writePos + (bufSize * 0.5)).wrap(0, bufSize).poll;
read = BufRd.ar(numChan, buf, phase: readPos, loop: 1, interpolation: 4);
send = send + (read * \fb.kr(0.5));
write = BufWr.ar(inputArray: [send], bufnum: buf, phase: writePos, loop: 1.0);
sig = in + read;
sig = sig!2;
Out.ar(0, sig);
}).add;
s.sync;
v = Synth(\tapedelay1);
});
r.play;
)
// then modulate the delay time and enjoy the artifacts
v.set(\time, 10);
v.set(\time, 8);
v.set(\time, 5);
v.set(\time, 3);
v.set(\time, 1);
v.set(\time, 0.75);
v.set(\time, 0.5);
v.set(\time, 0.4);
v.set(\time, 0.2);
v.set(\time, 0.1);
v.set(\time, 0.05);
v.set(\time, 10);
v.set(\fb, 0.0);
v.set(\fb, 0.95);