Vocoder experiments

Hi,
I’m happy to share some code I came up with to create a vocoder.
Here’s the code, let me know what do you think about it:

// 1. first: start the server
s.boot;


// 2. the load an audio file on a buffer (spoken words work better!)
b = Buffer.read(s,"/your/spoken/word/sample/here.wav"


// 3. create a group to put all the carrie synths inside
~grp_vocoders  = Group.new(s, \addToTail);


// 4. create a bus to connect the modulator synth to the carrier synths
~bus_modulator = Bus.audio(s,1);
// if you want you can debug the bus you hav just created
~bus_modulator.scope;


// 5. define the carrier synth
(
SynthDef(\vocoder_synth, {
	|
	out=0, in=2, amp=1.0, freq=440,
	atk=0.1, dcy=0.1, sus=0.7, rel=1,
	width=0.5, pan=0.0
	|
	var sig, env, chainMod, chainCarr, chain, input;
	env = EnvGen.ar(Env.perc(atk, rel), doneAction:2);
	sig = VarSaw.ar(freq, width:width);
	input = In.ar(in,1) * env;

	chainMod = FFT(LocalBuf(1024), input);
	// uncomment the line below if you want a gate-like effect
	//chainMod = PV_MagAbove(chainMod, 0.2);
    chainCarr = FFT(LocalBuf(1024), sig);
    chain  = PV_MagMul(chainCarr, chainMod);
    // I'm using the line below in order to limit the overall amplitude of the bins
	chain = PV_MagClip(chain, 50);

	sig = IFFT(chain);
	sig = sig * amp;

	Out.ar(out, Pan2.ar(sig, pan));
}).add;
)


// 6. define the modulator synth
(
SynthDef(\playbuffer, {
	|out=0, in=2, amp=1.0, bufnum|
	var sig = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum), loop: 1);
	Out.ar(out, sig);
}).add;
)


// 7. instantiate the carrier synth (here I'm using a Pbindef)
(
Pbindef(\chords,
	\instrument, \vocoder_synth,
	\scale, Scale.minor,
	\root, 1,
	\octave, Prand([[3,4,5,6]], inf),
	\degree, Prand([ [0,2,4,7] ], inf),
	\mtranspose, Pwhite(-0.02, 0.02, inf),
	\width, 0.01, //Pwhite(0.01, 0.5, inf),
	\in, ~bus_modulator,
	\atk, 0.5,
	\rel, 1,
	\amp, 0.125,
	\dur, Pseq([Pn(0.25,8)], inf),
	\group, ~grp_vocoders,
	\pan, Pwhite(-1.0, 1.0, inf).clump(4)
).quant_([4]).play;
)


// 8. instantiate the modulator synth
~voice = Synth(\playbuffer, [\bufnum, b, \out, ~bus_modulator], addAction:\addToHead);


// you can plot the tree in order to better understand what is happening
s.plotTree;


// try changing the chords
Pbindef(\chords, \degree, 0 + Prand([ [0,1,2] ], inf));
Pbindef(\chords, \degree, -1 + Prand([ [0,1,2] ], inf));
Pbindef(\chords, \degree, -2 + Prand([ [0,1,2] ], inf));
Pbindef(\chords, \degree, Prand([ [-1,0,2] ], inf));
Pbindef(\chords, \degree, Prand([ [0,2,3,6] ], inf));

// some clean up code
(
 ~voice.free;
 ~bus_modulator.free;
 Pbindef(\chords).stop;
 ~grp_vocoders.free;
)

Hello Moscardo,
thanks for sharing this, it’s really cool.
I’m a bit surprise about one thing, in your SynthDef \vocoder_synth, the last line is:

Out.ar(sig, Pan2.ar(sig, pan));

Is it normal ?
It looks like a typo to me, but maybe I missed something (cause it works), sorry if it is the case.
This is what I would expect here:

Out.ar(out, Pan2.ar(sig, pan));

If it’s not a typo, can you explain why is it like this ? How does this work ?
Thanks a lot

1 Like

Thank you so much @kesey,
you are totally right, This is a typo.
your last line of code is the correct way to do the thing.
I’ve just fixed it in the code.
Thank you so much for you help and your kind words
na