What kind of synthesis is this?

That Heinrich Schwarzer track is awesome! Thanks! Was not familiar with their work.

Second Woman also have similar-ish timbres:

They have several interviews with FACT, Native Instruments, etc, and it seems like a lot of the tonal stuff was NI’s Razor, plus Max and Ableton for a lot of the sequencing. Razor is an additive synth with an interesting interface for setting the overtone structure.

I think timing patterns are crucial for these timbral effects. Without the time distortion, it it’d sort of plonky, Buchla bongo-ish, but the speeding up and slowing down plays such a huge role in it.

I do wonder whether nearly any short tonal percussive like sound could get the point across too…? Just sort of rambling, but does the rhythm create more distinction for this than the actual sound source?

Anyway, not much to contribute otherwise at the moment other than to say I’m enjoying your tracks! Hope to hear about them when you get them mastered and properly released!

Also, I think “very different”, “not much”, “just a bit”, “almost” would be very fun controls for a GUI, obscuring number readouts or bars in a grid.

3 Likes

Thats also really Great That (yGrid/D#) (Second Woman Remix) - YouTube

1 Like

Thanks for your kind words, I’ll let you know when it’s ready!

Thanks also for the Second Woman link, I had heard something from him a while ago but then I quickly dismissed it because I wanted that extremely reductionist sound from Mark Fell. But this is sounding really nice! I love Razor, and I can hear it a lot in the third track. I think Razor’s most interesting sounds are difficult to work with in most contexts, because they end up occupying a lot of the spectrum. That’s why I think Gabor Lazar is a genius in using it (or something very similar to it) on its own. Kindohm makes some mindboggling sounds with Harmor, which is more or less the same thing.

Is there BTW something similar out-of-the-box in SC? I tried to control additive synthesis with a few hundred partials in Max and I quickly hit a wall. I managed to produce similar spectra with an oscillator bank, but I couldn’t get it to sound as crisp as Razor – and trying to modulate the partials in realtime would kill my CPU, so I ended up using Razor itself.

Regarding the interface, that would be nice! I like more conceptual approaches to interfaces, and this reminds me of this “magazine interpolation” interface from Mark Fell (from 12:15):

Thanks @dietcv, that’s really great!

1 Like

Oh man nathan, that is real pretty. First of all, I gotta pull Pluck out of the closet and play around. I feel like I haven’t used K-S in 15 years. Second of all, that Sweep/Hasher trick to get the same noise profile every time is a beauty. Thanks for this.

4 Likes

It’s to hard to mention ‘genius’ and ‘SC’ in the same sentence without refering
to hjh directly… he basically invented the term.

He is the in-house & on-call professor here, an all-time legend of SC’s development (class source, reference, and lower level), and beyond a shadow of a doubt, a guru of all things SC.

He’s also the sole author of the entire ddw Quarks extension library.

All of this is done by purely by choice… he has since stepped down (all gratitude and respect, no ends) from his role as lead developer several months ago… around the same time that we lost a lead developer from Ableton, who’s no longer with us.

Currently we have two long time and well experienced contributors currently turning legends who’ve recently undertaken their roles as executives of the dev team… see 3.12 Final Release thread.

SC 3.12 is here after 3.4, 3.6.6, 3.7, 3.8, 3.9.3, etc… we’re still improving on SC3, we haven’t fully realized what SC4 will look like yet… and it’s A LOT of work too.

The best thing you can do as a new user is not to sweat it, enjoy the language as you will… it is extremely helpful if you log issues on GitHub, as you may come across them, and that goes for pretty much everyone, including myself… there’s a fill-in template for SV version, OS, code, post error.

This is all entirely open-source… the original creator is no longer involved at this point.

Everyone is free to do what they want and no one is obligated to do anything they don’t care to… we’re all still here because we want to be here… and because SC is such an incredibly powerful & expressive language.

3 Likes

Hahaha! Magazine interpolation. I love it! A good review in The Wire vs Sound on Sound reader excitement. Mixmag and CMJ. I also am a big fan of that dance slider right before. And Mark Fell using Max in place of powerpoint is just wonderful! Great video.

Additive synthesis can be so unwieldy. More control usually somehow means less control as there are so many parameters to set. I haven’t used Razor much, but I did find it a very interesting way to deal with this dilemma.

Second Woman make some lovely stuff. I listened to their album during a nice long night drive through the mountains on a road trip once. Really solidified it. Though I haven’t listened back much since then. For instance I sort of remembered more of the bouncing ball time dilation effect than early this morning when listening again.

I haven’t messed with it much, but there’s the DynKlang UGen, it should be possible to create a few different preset arrays similar to Razor’s partial presets, and even interpolate between them. I don’t know what it’ll do at a few hundred partials though.

2 Likes

Would also be really interested in a sc Razor emulation or xaoc odessa. Anyone? :slight_smile:

found this in another thread:

(
{
	var f0 = MouseY.kr(50, 2000);
	var n = 200;
	var freqs = (1..n) * f0;
	var amps = 0.5 / (1..n) ** 2;
	var indicator = freqs < MouseX.kr(100, 20000);
	var sig = Mix.ar(SinOsc.ar(freq: freqs, mul: indicator * amps));
	Pan2.ar(sig * 0.5, 0.0);
}.freqscope;
)
1 Like

@nathan absolutely nailed the “upper pegwheel” part! Here is my humble attempt at the “lower pegwheel” part:

(
{
    arg mratio=4, amp=0.2, boost=2;
    var env, freq, freqenv, trig, index, sig;
    trig = Impulse.ar(LFNoise2.kr(1).linexp(-1, 1, 1, 100));
    env = Env.perc(0.0001, 1.0, curve: -8).ar(0, trig);
    freqenv = Env.perc(0.0001, 0.4, curve: -8).ar(0, trig);
    freq = 60.5.midicps / 16;
    freq = freq * freqenv.linexp(0, 1, 1, 40);
    index = MouseY.kr(0, 2);
    sig = SinOsc.ar(freq, SinOsc.ar(freq * mratio) * index);
    (sig!2 * boost).tanh * env * amp;
}.play;
)

It needs some work, and I can never get bass resonance quite right, but if you mix it with @nathan’s part, I think it comes pretty close to parts of the original piece.

3 Likes

Thanks a lot, this is already sounding super nice when using a lower index value!

Thanks a lot @thresholdpeople, I’ll try it!

DynKlang is just a sum of SinOscs (check its class implementation to confirm that). It doesn’t have any optimization magic.

You could get 3 independent partials from one UGen by creating two single sine wavetable buffers and using them with VOsc3 (the VOsc family requires at least 2 consecutive wavetables, but that’s a minor concern) – then instead of 320 oscillators, you’d need 107. That would save some overhead. But you don’t have independent control over the 3 waves’ amplitudes (though each VOsc3 instance would be independent, which would already allow a lot of control).

I don’t know of any UGens that have been optimized for massive additive synthesis. If someone wanted to create one, a good way might be a single UGen that makes 10 totally independent sine partials (to balance the overhead of multiple UGens against the width of the graph).

hjh

1 Like

I played around a bit with the pew-pew sound on this track and I think I got it pretty good. I am doing some stuff with Splay that may be gratuitous (as in not faithful to the original), but I really like that sound. Every time I work on this micro-level I am reminded of Schaeffer’s writing about attack. Just the subtlest change in envelope alters the entire timbre, especially when phase is so exposed. Two things that are really fun in this sound (which I figured out by looking at the spectrogram): 1) the partials are the [ 4.0, 7.0, 10.0, 13.0, 16.0 ] partials of non-existent fundamental 2) the freq envelope for the 5 oscillators takes 0.001 seconds longer as each partial gets higher. This contributes to the overall timbre.

({
	var sweep, synth, trig, back, freqs;

	trig = Delay2.ar(Impulse.ar(1));
	sweep = (Env([0,1], [0.01]).ar*(1-Sweep.ar(trig, 0.25).clip(0,1))).linexp(0,1,0.001,1)**8;

	synth = Array.fill(5, {|i|
		var sweep0 = LagUD.ar(sweep, 0.001*i, 1/SampleRate.ir);
		var sine = SinOsc.ar((i*1.5+2)*sweep0.linlin(0,1,60.5.midicps/4,60.5.midicps*8), 0, 0.2);
		sine*sweep0
	});
	synth = Splay.ar(TScramble.ar(synth, trig))
	+Splay.ar(Delay1.ar(TScramble.ar(synth, trig)))
	+Splay.ar(Delay2.ar(TScramble.ar(synth, trig)));
	
	synth+DelayC.ar(synth, 0.026, 0.026, 0.05)
}.play)
5 Likes

where do i get the TScramble? Im using SC 3.12.0 with SC3 Plugins

I had this problem too, it’s in wslib

1 Like

thanks!

maybe this is obvious but whats the best way to use Maths to trigger the \dur inside Pbind. Ive looked at Event patterns and LFOs | SuperCollider 3.11.2 Help should i put an amplitude envelope into the trig argument of Maths or could i use SharedOut.kr, or better stick with Pmono in this case?
i was also trying to replicate the Impulse.ar(LFNoise2.kr(1).linexp(-1, 1, 1, 100)); for use inside a Pbind and was trying something like \dur, Pseq((0..25).linexp(0, 25, 1, 75), inf).reciprocal, what would be an exact replication?

thanks a lot :slight_smile:

i was messing around a bit and would like to share this one, i think it sounds pretty sharp :slight_smile:

(
~numPartials = 10;
~bufAmps = Buffer.alloc(s, ~numPartials);

SynthDef(\additive, {
	arg shapeAmount=0.3, time=1, freq=150;

	var gainEnv = \gainEnv.ar(Env.newClear(8).asArray);
	var fltEnv = \fltEnv.ar(Env.newClear(8).asArray);
	var iEnv = \iEnv.ar(Env.newClear(8).asArray);

	var k = 2 * shapeAmount / (1 - shapeAmount);
	var numPartials = ~numPartials;
	var bufAmps = ~bufAmps;
	var trg = \gt.kr(1);
	var sig, mod;

	iEnv = EnvGen.kr(iEnv, trg, timeScale:time, doneAction:Done.none);
	fltEnv = EnvGen.kr(fltEnv, trg, timeScale:time, doneAction:Done.none);
	gainEnv = EnvGen.kr(gainEnv, trg, doneAction:Done.freeSelf);

	mod = SinOsc.ar(freq * \mRatio.kr(1), mul: iEnv);

	BufWr.ar(
		LFGauss.ar(
			duration: SampleDur.ir * numPartials * \factor.kr(1).reciprocal,
			width: gainEnv * LFNoise2.kr(1).linexp(-1, 1, \widthMin.kr(0.1, 0.5), \widthMax.kr(1.0, 0.5)),
			iphase: \phase.kr(0, 0.5).mod(4pi)
		),
		bufnum: bufAmps,
		phase: Phasor.ar(
			end: numPartials
		)
	);

	sig = Array.fill(numPartials, {
		arg i;
		SinOsc.ar(
			freq: ((i * 2) + 1) * freq * \cRatio.kr(1, 0.5),
			phase: mod.wrap(0, 4pi),
			mul: Index.ar(bufAmps, i)
		) / numPartials
	}).sum;

	sig = ((1 + k) * sig / (1 + (k * sig.abs)));
	sig = (sig * 2).tanh;
	sig = HPF.ar(sig, 75);

	sig = MoogFF.ar(sig, fltEnv * \fltFreq.kr(7500), 0);

	sig = sig * gainEnv;

	sig = Pan2.ar(sig, \pan.kr(0), \amp.kr(0.25));
	sig = LeakDC.ar(sig);
	OffsetOut.ar(\out.kr(0), sig);
}).add;

SynthDef(\combL, {
	arg in=0, out=0, mix=(-0.5), decay=1, amp=1, delHz=0.55, delStereoRatio=0.9, delMin=0.001, delMax=0.4;
	var sig, comb;
	sig = In.ar(in, 2);
	delHz = delHz * [1,delStereoRatio];
	comb = CombL.ar(
		sig,
		delMax,
		LFPar.kr(delHz,[0,pi/2]).exprange(delMin,delMax),
		decay,
	);
	sig = XFade2.ar(sig, comb, mix) * amp;
	Out.ar(out, sig);
}).add;
)

(
// assist data-sharing in pbindfx creation
// pbindfx is wrapped in a private environment (Penvir)
// arguments are just pdef names
~pbindFx = {|srcName ... fxNames|
    // add private environment, shared between source and fxs
    Penvir(Event.new(parent:currentEnvironment),
        PbindFx(
            // source: record latest event in ~src
            *[Pdef(srcName).collect(~src=_)]
            // add all fx: they can access source event saved in ~src
            ++ fxNames.collect(Pdef(_))
        )
    )
};

~utils = ();
~utils.hasEnv = {
    // calc this event's duration in seconds
	var durSeconds = ~sustain.value / thisThread.clock.tempo;
    // find all parameters ending in env or Env
    var envKeys = currentEnvironment.keys.select{|k|"[eE]nv$".matchRegexp(k.asString)};
    envKeys.do{|param|
        var value = currentEnvironment[param];
        if (value.isArray.not) { value = [value] };
        value = value.collect {|v|
            // pass rests along...
            if (v.isRest) { v } {
                // convert non-env values to a continuous, fixed value env
                if (v.isKindOf(Env).not) { v = Env([v, v], [1]) }
            };
            // stretch env's duration
            v.duration = durSeconds;
        };
        currentEnvironment[param] = value;
    };
};

Event.addParentType(\hasEnv,(
    finish: ~utils[\hasEnv]
));

t = TempoClock.new(60/60).permanent_(true);
)

(
Pdef(\additive,
	Pbind(
		\type, \hasEnv,
		\instrument, \additive,

		\dur, (Pseq((0..25).linexp(0, 25, 1, 75), inf).reciprocal).trace,

		\midinote, Pdup(26, Pseq([60 + [0, 4, 7, 11]], inf))
		+ Pseq([Pdup(25, Pseq([0.25])), Pseq([0.1667])], inf),

		\factor, Pdup(26, Pseq([3,1],inf)),
		\phase, 1,
		\widthMin, 0.1,
		\widthMax, 0.5,

		\atk, 0.0001,
		\rel, 1,
		\gainEnv, Pfunc{|e|
			Env.perc(e.atk, e.rel, curve: -8.0);
		},
		\sustain, Pfunc { |ev| ev[\gainEnv].duration },

		//Phase Modulation
		\mRatio, 1.5,
		\cRatio, 1,
		\index, 1,
		\iScale, 2,

		\iAtk, 0.001,
		\iRel, 0.35,

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

		\iEnv, Pfunc{ |e|
			var cAtk = exprand(2,6);
			var cRel = exprand(-2,-6);
			Env([e.index, e.index * e.iScale, e.index], [e.iAtk, e.iRel], [cAtk, cRel])
		},

		\fAtk, 0.001,
		\fSus, 0.15,
		\fRel, 0.25,

		\fltFreq, 7500,

		\fltEnv, Pfunc{|e|
			var cAtk = exprand(2,6);
			var cRel = exprand(-2,-6);
			Env([0,1,1,0],[e.fAtk, e.fSus, e.fRel],[cAtk,0,cRel])
		},

		\pan, 0,
		\amp, 0.30,
		\out, 0,
		\finish, ~utils[\hasEnv],
		\cleanupDelay, Pkey(\sustain),
		\fxOrder, [1]
	)
);

Pdef(\additive_comb,
	Pbind(
		\fx, \combL,
        \mix, 0.5,
        \amp, 1,
        \delStereoRatio, 0.9,
        \delHz, 0.1,
        \delMin, Pfunc { (~src.dur == 1).if { 0.35 }{ 0.15 } },
		\delMax, Pkey(\delMin) + 0.01,
		\decay, Pfunc { (~src.dur == 1).if { 2 }{ 0.5 } },
        \cleanupDelay, Pkey(\decay)
));

Pdef(\additive_fx, ~pbindFx.(\additive, \additive_comb));
)

Pdef(\additive_fx).play(t, quant:1);
4 Likes

sounds good, Sam, thanks once more!

I am curious, but unfortunately I didn’t manage to make it work… this more Razor-like, right?

whats the problem? :slight_smile: not really i think haha, unfortunately more like fm/pm. maybe someone else has an idea how to adjust the code, so it has more this “plastic” character to it.

Hey dietcv, thanks, it says the number of interconnected buffers was exceeded.

I’m eager to listen to examples provided here, but I’m realizing I need to learn at least the basics of SC in order to get things going and troubleshoot the very basic problems without being a drag for the very helpful and knowledgeable people here, you included. I feel I am being a bit like the kindergarten kid that asks a scientist to explain quantum physics…