Yesterday when I was just jamming with some silly alphabet samples that comes with tidal, I suddenly felt it really need some vocoder action. So today I sat down to learn how to write synthdefs for tidal and converted some old pieces of code into these two synthdefs.
(
~dirt.addModule('vocoder', { |dirtEvent|
dirtEvent.sendSynth("vocoder" ++ ~dirt.numChannels,
[
vocoder:~vocoder,
out: ~out,
chord:~chord
]
)
}, { ~vocoder.notNil});
SynthDef("vocoder" ++ ~dirt.numChannels, {
|out, vocoder=1|
var car, vcar ,mod, sig;
mod = In.ar(out,~dirt.numChannels);
vcar = Saw.ar((60+\chord.kr(0)).midicps);
car = SelectX.ar((ZeroCrossing.ar(mod).cpsmidi.lag(0.05) > 5000.cpsmidi).lag(0.05), [vcar, PinkNoise.ar]) ;
sig = Vocoder.ar(car,mod,96);
sig = SelectX.ar(vocoder, [mod*0.15, sig]);
ReplaceOut.ar(out, sig);
}, [\ir]).add;
~dirt.addModule('pvocoder', { |dirtEvent|
dirtEvent.sendSynth("pvocoder" ++ ~dirt.numChannels,
[
pvocoder:~pvocoder,
out: ~out,
chord:~chord
]
)
}, { ~pvocoder.notNil });
SynthDef("pvocoder" ++ ~dirt.numChannels, {
|out, pvocoder=1|
var car, vcar ,mod, sig,chain, chain2, size=512;
mod = In.ar(out);
vcar = Saw.ar((60+\chord.kr(0)).midicps);
car = SelectX.ar((ZeroCrossing.ar(mod).cpsmidi.lag(0.05) > 15000.cpsmidi).lag(0.05), [vcar, PinkNoise.ar]) ;
chain = FFT(LocalBuf(size),mod);
chain2 = FFT(LocalBuf(size),car);
chain = chain.pvcalc2(chain2, size,
{
arg mag, phs, mag2, phs2;
[mag,phs2];
});
sig = IFFT(chain)!2;
sig = SelectX.ar(pvocoder, [mod*0.15, sig]);
ReplaceOut.ar(out, sig);
}, [\ir]).add;
)
For now, there's only two parameters, one for the type and dry-wet: pvocoder or vocoder for phase vocoder or classic band-pass filter based vocoder. and the other is the chord that the carrier plays.
vocoder = pF "vocoder"
pvocoder = pF "pvocoder"
chord = pF "chord"
d1
$ slow 1.5
$ n "21 14 2 14 3 4 17"
# s "alphabet"
# pvocoder "0.5"
-- # vocoder "1"
# chord "<d'min7'5'i2 g'dom7'5 c'maj7'5'i2>"
# legato 1
-- # coarse 5
# room 0.3
Hope some of you can have some fun with it and come up with some ideas and improvements!
One thing to notice: use legato to free samples more quickly so the filter-vocoder would not break your cpu. Also lower the third argument in the Vocoder.ar() helps, same goes for the size in the pvocoder synthdef.
At the time of writting this post I realized the crazy cpu consumption of the filter vocoder may be addressed by making it a global effect??(not exactly sure how that works, but i think similar to what i have seen in the mi-gens stuff) so that not every note comes with a dozen filters haha.