Comparator - Wave switching / Wave slicing

There have been these threads:

I also just released a bunch of Unit Shapers with my Grain Utils library and there are more to come.

some phase shaping, phase increment distortion techniques below:

// vps with phase increment distortion

(
var triangle = { |phase, skew|
	Select.ar(phase > skew, [
		phase / skew,
		1 - ((phase - skew) / (1 - skew))
	]);
};


var vps = { |freq, skew, harm|

	var phase = Phasor.ar(DC.ar(0), freq * SampleDur.ir);

	var harm_even = harm.round(2);
	var harm_odd = ((harm + 1).round(2) - 1);

	var pmod = triangle.(phase, skew);

	var sig_even = cos(phase + (pmod * (harm_even - skew)) * 2pi).neg;
	var sig_odd = cos(phase + (pmod * (harm_odd - skew)) * 2pi).neg;

	LinXFade2.ar(sig_even, sig_odd, harm.fold(0, 1) * 2 - 1);
};

{
	var freq = 55;
	var skew = MouseX.kr(0, 1);
	var harm = MouseY.kr(1.0, 10.0);
	var sig = vps.(freq, skew, harm);
	sig = LeakDC.ar(sig);
	sig !2 * 0.1;
}.play;
)

// vps with phase shaping

(
var kink = { |phase, harm, skew|
	phase = phase.linlin(0, 1, skew.neg, 1 - skew);
	phase.bilin(0, skew.neg, 1 - skew, harm, 0, 1);
};

var vps = { |freq, skew, harm|

	var phase = Phasor.ar(DC.ar(0), freq * SampleDur.ir);

	var harm_even = harm.round(2);
	var harm_odd = ((harm + 1).round(2) - 1);

	var phasor_even = kink.(phase, harm_even, skew);
	var phasor_odd = kink.(phase, harm_odd, skew);

	var sig_even = cos(phasor_even * 2pi).neg;
	var sig_odd = cos(phasor_odd * 2pi).neg;

	LinXFade2.ar(sig_even, sig_odd, harm.fold(0, 1) * 2 - 1);
};

{
	var freq = 55;
	var skew = MouseX.kr(0.01, 0.99);
	var harm = MouseY.kr(1.0, 10.0);
	var sig = vps.(freq, skew, harm);
	sig = LeakDC.ar(sig);
	sig !2 * 0.1;
}.play;
)

///////////////////////////////////////////////////////////////

(
var raisedCos = { |phase, index|
	var cosine = cos(phase * 2pi);
	exp(index.abs * (cosine - 1));
};

var singleSideBandPM = { |freq, modRatio, index|
	var carrPhase = Phasor.ar(DC.ar(0), freq * SampleDur.ir);
	var modPhase = Phasor.ar(DC.ar(0), freq * modRatio * SampleDur.ir);
	var raisedCosWindow = raisedCos.(modPhase, index);
	var mod = sin(modPhase * 2pi);
	var carr = sin(carrPhase * 2pi + (mod * index));
	carr * raisedCosWindow;
};

SynthDef(\singleSidebandPM, {

	var freq, modPhase, grainFreqMod, index, sig, phase;

	freq = \freq.kr(110);

	modPhase = Phasor.ar(DC.ar(0), \freqMF.kr(0.3) * SampleDur.ir);
	grainFreqMod = SinOsc.ar(DC.ar(0), modPhase + [0.0, 0.5] * 2pi);

	index = [
		\indexA.kr(8) * (2 ** (grainFreqMod[1] * 3)),
		\indexB.kr(16) * (2 ** (grainFreqMod[0] * 1)),
	];

	sig = singleSideBandPM.(freq, \modRatio.kr(1), index).sum;

	sig = Pan2.ar(sig, \pan.kr(0));

	sig = sig * \amp.kr(-25.dbamp);

	sig = sig * Env.asr(0.001, 1, 0.001).ar(Done.freeSelf, \gate.kr(1));

	sig = LeakDC.ar(sig);
	Out.ar(\out.kr(0), sig);
}).add;
)

(
Routine({

	var ratios = [1.00, 1.04];
	var pan = [-1.0, 1.0];

	s.bind {
		ratios.collect{ |ratio, i|
			var freq = 125;

			Synth(\singleSidebandPM, [

				\freq, freq * ratio,
				\modRatio, 1,

				// amp & outs
				\amp, -25.dbamp,
				\pan, pan[i],
				\out, 0,

			]);
		};

	};

}).play;
)

/////////////////////////////////////////////////////////////////

(
var raisedCos = { |phase, index|
	var cosine = cos(phase * 2pi);
	exp(index.abs * (cosine - 1));
};

var crossfade_formants = { |phase, harm|
	var harmEven = harm.round(2);
	var harmOdd = ((harm + 1).round(2) - 1);
	var sigEven = sin(phase * 2pi * harmEven);
	var sigOdd = sin(phase * 2pi * harmOdd);
	LinXFade2.ar(sigEven, sigOdd, harm.fold(0, 1) * 2 - 1);
};

var modFM = { |freq, harm, index|
	var phase = Phasor.ar(DC.ar(0), freq * SampleDur.ir);
	var raisedCosWindow = raisedCos.(phase, index);
	var formants = crossfade_formants.(phase, harm);
	formants * raisedCosWindow;
};

SynthDef(\formant, {

	var sig, modPhase, grainFreqMod, harmonics;

	modPhase = Phasor.ar(DC.ar(0), \freqMF.kr(0.3) * SampleDur.ir);
	grainFreqMod = SinOsc.ar(DC.ar(0), modPhase + [0.0, 0.5] * 2pi);

	harmonics = [
		\harmA.kr(8) * (2 ** (grainFreqMod[1] * 3)),
		\harmB.kr(16) * (2 ** (grainFreqMod[0] * 1))
	];

	sig = modFM.(\freq.kr(440), harmonics, \index.kr(1)).sum;

	sig = Pan2.ar(sig, \pan.kr(0));

	sig = sig * \amp.kr(-25.dbamp);

	sig = sig * Env.asr(0.001, 1, 0.001).ar(Done.freeSelf, \gate.kr(1));

	sig = LeakDC.ar(sig);
	Out.ar(\out.kr(0), sig);
}).add;
)

(
Routine({

	var ratios = [1.00, 1.04];
	var pan = [-1.0, 1.0];

	s.bind {
		ratios.collect{ |ratio, i|
			var freq = 125;

			Synth(\formant, [

				\freq, freq * ratio,
				\index, 8,

				\amp, -25.dbamp,
				\pan, pan[i],
				\out, 0,

			]);

		};
	};

}).play;
)

/////////////////////////////////////////////////////////////////////////////

(
var raisedCos = { |phase, index|
	var cosine = cos(phase * 2pi);
	exp(index.abs * (cosine - 1));
};

var crossfade_formants = { |phase, harm|
	var harmEven = harm.round(2);
	var harmOdd = ((harm + 1).round(2) - 1);
	var sigEven = sin(phase * 2pi * harmEven);
	var sigOdd = sin(phase * 2pi * harmOdd);
	LinXFade2.ar(sigEven, sigOdd, harm.fold(0, 1) * 2 - 1);
};

var modFM = { |freq, harm, index|
	var phase = Phasor.ar(DC.ar(0), freq * SampleDur.ir);
	var raisedCosWindow = raisedCos.(phase, index);
	var formants = crossfade_formants.(phase, harm);
	formants * raisedCosWindow;
};

SynthDef(\formant, {

	var trig, sustain, gainEnv, harmEnv, harmonics, sig;

	trig = \trig.tr(1);
	sustain = \sustain.kr(1);

	gainEnv = EnvGen.ar(Env(
		[0, 1, 0],
		[\atk.kr(0.01), \rel.kr(0.99)],
		[\atkCurve.kr(45.0), \relCurve.kr(-24.0)]
	), trig, timeScale: sustain);

	harmEnv = EnvGen.ar(Env(
		[0, 1, 0],
		[\fAtk.kr(0.01), \fRel.kr(0.99)],
		[\fAtkCurve.kr(45.0), \fRelCurve.kr(-24.0)]
	), trig, timeScale: sustain);

	harmonics = harmEnv.linlin(0, 1, 1, \harmEnvAmount.kr(50));

	sig = modFM.(\freq.kr(103.826), harmonics, \index.kr(1));

	sig = sig * gainEnv;

	sig = Pan2.ar(sig, \pan.kr(0));

	sig = sig * \amp.kr(-15.dbamp);

	sig = sig * Env.asr(0.001, 1, 0.001).ar(Done.freeSelf, \gate.kr(1));

	sig = LeakDC.ar(sig);
	Out.ar(\out.kr(0), sig);
}).add;
)

(
Pdef(\laser,
	Pmono(\formant,

		\trig, 1,
		\legato, 0.8,
		\dur, 8,

		\atk, 0.005,
		\rel, 0.995,
		\atkCurve, 45.0,
		\relCurve, -24.0,

		\fAtk, 0.001,
		\fRel, 0.999,
		\fAtkCurve, 45.0,
		\fRelCurve, -24.0,

		\time, Pfunc { |ev| ev.use { ~sustain.value } / thisThread.clock.tempo },

		\freq, [44, 54, 60].midicps,

		\harmEnvAmount, 50,
		\index, 2,

		\amp, -15.dbamp,
		\out, 0,
	);
).play;
)

/////////////////////////////////////////////////////////////////////////////

//not so much phase shaping haha :slight_smile: ...

(
SynthDef(\lax, {

	var tFreq = \tFreq.kr(12);
	var trig = Impulse.ar(tFreq);
	var lfo = LFSaw.ar(0.3 * (1 + (LFNoise2.kr(0.3) * 0.5)));

	var sig = SinOsc.ar(lfo.linexp(-1, 1, 100, 8000)) + SinOsc.ar(lfo.linexp(-1, 1, 1000, 4000));
	sig = Pluck.ar(sig, trig, \maxDel.kr(0.1), \freq.kr(50).reciprocal, \decTime.kr(0.1), \coef.kr(0.5));

	sig = Pan2.ar(sig, \pan.kr(0));

	sig = sig * \amp.kr(-15.dbamp);

	sig = Limiter.ar(sig);
	Out.ar(\out.kr(0), sig);
}).add;
)

(
Routine {

	var freqs = [125, 130];
	var pan = [-1, 1];

	s.bind {
		freqs.collect{ |freq, i|

			Synth(\lax, [

				\tFreq, 12,

				\freq, freq,
				\maxDel, 0.1,
				\decTime, 0.2,
				\coef, 0.5,
				\rate, 0.3,

				\amp, -20.dbamp,
				\pan, pan[i],
				\out, 0,

			]);

		};
	};

}.play;
)