yeah, exactly, Nes2Square wants a trigger. a ‘trigger’ in SC just means a transition from <=0, to >0. Impulse.kr is one of many UGens that produces signals that go high for one sample / control block, and then return to zero - ideal for trigger inputs.

so, indeed, if you want to “bang” the Nes2Square with a single command, i’d do this:

  • add a control bus variable to the engine like var trig_b, initialize like trig_b = Bus.control(server, 1)
  • replace Nes2Square.ar(gate...) with Nes2Square.ar(InTrig.kr(trig_b)...)
  • in the ‘bang’ command do trig_b.set(1)
3 Likes

Rockin. Thank you! That looks like a key peice of info I’d not picked up yet from the tutorials, etc. I’ve been looking at.

Followup - I will want to add 3 more variations of this - Nes2Triangle etc. Do I define those as separate “synths” or is there a better way to do that (like a case statement inside the synth object)?

up to you. you could use SelectX in the synthdef to crossfade between array of sources, or make different Ugens in one synth sharing inputs but with arbitrary levels, or make different Synths with totally different inputs. different complexity, different limitations, none is ‘better’

1 Like

sorry… one more q:
for trig_b = Bus.control(server, 1); what’s my server here? context?

and does that go inside the alloc { ?

sorry, i meant that generically, it’s Crone.server in a norns engine

yes that’ll work

but with this in the engine, is the server variable now context? Or is that something different and I should just use trig_b = Bus.control(Crone.server, 1);?

Sorry again for all the Noob-ness here.

Oooh… found it in another engine example. I want context.server

I got it working! :tada:

1 Like

rad, congrats

yeah actually you’re right , context.server is more correct than Crone.server. in practice they are the same. but the latter is a global, so it’s worse. my bad.

(i’ve said it before but really should clean up unecessary cruft from Crone ecosystem. it’s left over from the heavier lifting done by SC components pre-2.0.)

1 Like

Here’s one i think would make a nice Norns

(
~trig = { |dens=10| Impulse.kr(dens) };
~freq = { MouseX.kr(100, 2000, 1) * LFNoise1.kr(1).range(0.25, 1.75) };
~moddepth = { LFNoise1.kr(20).range(1, 10) };
~modfreq = 200;
~graindur = 0.1;

~grain = { arg envbuf = -1;
GrainFM.ar(2, ~trig.kr, ~graindur.kr,
~freq.kr, ~modfreq.kr, ~moddepth.kr,
pan: WhiteNoise.kr, envbuf: envbuf) * 0.2
};
~grain.play;
)
// change control ugens:
~modfreq = { ~freq.kr * LFNoise2.kr(1).range(0.5, 2.0) }; // modfreq roughly follows freq
~trig = { |dens=10| Dust.kr(dens)}; // random triggering, same density
~freq = { LFNoise0.kr(0.3).range(200, 800) };
~moddepth = 3; // fixed depth
~graindur = { LFNoise0.kr.range(0.01, 0.1) };

// bonus: blend dust and impulse triggers

~trig = { |dens=20, bal=0.2| Dust.kr(dens * (1-bal)) + Impulse.kr(dens * bal) };
~trig.set(\bal, 0.1);
~trig.set(\bal, 0.5);
~trig.set(\bal, 0.9);

ProxyMixer§;

3 Likes

i am just having some fun running some old supercollider code
Does the Norns SC have Quarks capacity? I would love a BBcut Norns

(
var sf, clock1, clock2;

clock1= ExternalClock(TempoClock(0.6));
clock2= ExternalClock(TempoClock(0.7));

Routine.run({

sf=BBCutBuffer.array([Platform.resourceDir +/+ “sounds/breaks.wav”,Platform.resourceDir +/+ “sounds/breaks2.wav”],[8,4]);

s.sync; //this forces a wait for the Buffer to load

BBCut2([CutBuf1(sf[0]),CutMixer(0,0.5,1.0,-1.0)], ChooseCutProc(0.25,{[4,2].choose})).play(clock1);
BBCut2([CutBuf1(sf[1]),CutMixer(0,0.5,1.0,1.0)], ChooseCutProc(0.25,{[4,2].choose})).play(clock2);
});

clock1.play;
clock2.play;
)

(
var sf, clock;

clock= ExternalClock(TempoClock(0.5));

clock.play;

Routine.run({

sf= BBCutBuffer(Platform.resourceDir +/+ “sounds/breaks2.wav”,8);

s.sync; //this forces a wait for the Buffer to load

g=CutGroup(CutBuf1(sf));

a=BBCut2(g, BBCutProc11.new).play(clock);
});

)

The quarks syaytem works on norna, sans gui.

But I’m not sure how well it does with installing plugins on arm64

BBcut is the only “quark” i usually use/install
There’s always something to learn :slight_smile:
Those redfred tweets look awesome
i have the schemawounds n stuff too. Back in 2004/5 we successfully [with cylobs help] got SC working on ipad and they were so much fun to layer

//snakefinger bass

(
SynthDef(“bass”,{arg bus= 2, note=60, dur=0.2, pan=0.0, chorus=0.02,filtfreq=4000, filtq=0.1;
var v;
v=Mix.ar(LFSaw.ar([note-chorus,note+chorus].midicps,[pi.rand,pi.rand], 0.25)); //(([Rand(0.25,0.4),Rand(0.25,0.4)]));
v= v*EnvGen.ar(Env.perc(Rand(0.01,0.02),dur,0.5), doneAction:2);
//v=Resonz.ar(v, filtfreq, filtq);
Out.ar(0,Pan2.ar(v,pan));
}).load(s);

SynthDef(“sweepy”,
{ arg busNumber=0, busInNumber=0, rate=0.5;
var in, proc;
in = In.ar(busInNumber, 2);
proc=Limiter.ar(Resonz.ar(in*8, SinOsc.kr(LFNoise0.kr(rate,0.25,0.3), 2.0.rand, 2000, 2200), 0.4), 0.999, 0.1);

	ReplaceOut.ar(busNumber,proc);

}).load(s);

SynthDef(“delay”,
{ arg busNumber=0, busInNumber=0;
var in, proc;
in = In.ar(busInNumber, 2);
proc=CombN.ar(in,0.25,0.125,1.0);
ReplaceOut.ar(busNumber,proc);
}).load(s);
)

(
var func, fxsynth, fxsynth2;

fxsynth=Synth(\sweepy);
fxsynth2=Synth.after(fxsynth,\delay);

func= {
arg basefreq=36, rate=0.125;
var p, r, durs, pan, ff, fq, chor;

durs= exprand(0.1,0.8);
pan= 1.0.rand2;
ff= rrand(1000,4000);
fq= exprand(0.1,0.5);
chor= exprand(0.01,0.2);

p= Pseq([Pn(basefreq, rrand(9,19)), Plazy({Pseries(basefreq, [-0.25,-0.5,-0.75].choose, rrand(3,18))})],inf).asStream;

r=Routine({

rrand(50,100).do(
{
Synth.before(fxsynth,\bass,[\note, p.next, \dur, durs, \pan, pan, \chorus, chor, \filtfreq, ff, \filtq, fq]);
rate.wait;
});

});

r.play;
};

Routine(
{

10.do({func.value(([0,12,24].choose)+([36,36.1,36.2,36.4,36.75].choose), [0.125,0.15,0.175].choose);

fxsynth.run(if(0.4.coin,true,false));
if(0.3.coin,{fxsynth2.run(fxsynth2.isRunning.not);});

[0.75,2.0,4.0,5.0].choose.wait
});

}).play;

)

dropping these old nuggets here. any other pointers for first time engine-ers ?

here’s the manual

also: I already like sc a lot

6 Likes

Is there an existing engine that would be a good template to use for adapting an “audio processing” supercollider script to norns?

Looking for the basic framework needed to deal with the incoming audio.

would this work?

2 Likes

This is one I put together, using the decimator ugen.

3 Likes

i really want to make a Gnedyn Norns application but with sound coming from norns but with selectable distrubutions of stochastic LFOs going to crow
Is there a tutorial for Nornsing a SC patch? i guess i can adapt one i just dont know how to get started

2 Likes

away from norns but just attempted to wrap Convolution2L ugen into an engine

it’s my first time trying so i’m curious…
does anybody spot obvious errors? i expect this will be a learning experience


inspiration is taken from a supercollider based effect built for 2018 rbma participants

from public info and emails with a member of the design team this is what i can gather about how it works:

  • user records a sound snippet to one of 20 slots (max length 20s per slot)
  • the sampled audio from current slot is fed into a granular engine
  • select a grain (ranging from 7-700ms in size) which is then convolved with the real-time audio input
  • the spectral overlap of the two sounds is output (think…grain timbre w/ input envelope)

additional details from the devs:

  • the convolution is done using Convolution2L since it allows for seamless transition between grains (convolution kernels)

  • it doesn’t support proper time-partitioned convolution so to keep the input-output delay small they manually delayed the input signal and fed it to several Convolution2L that all ran at a small framesize (& got a different part of the grain as convolution kernel)

two challenges they faced [1] each grain needs to have an envelope applied [2] the energy of the output needs to be controlled…

  • they used a short single sided hand window to fade in/out

  • they ended up normalizing with the RMS of the grain (capped at some higher / lower limit)

Any time a new grain was selected (either by shifting the position of grain window or by changing its length), it was prepared (applied window, calculated gain, loaded into all convolves) and then a trigger signal was sent to all convolvers to switch to the new grain


@andrew I’m trying to work out whether all of that is possible with just one Convolution2L in a norns engine (my guess is no) or whether i’ll need to hack an existing granular engine like Glut to handle some of the features

6 Likes

i can probably help a little this weekend. Sounds like they did stuff that isn’t directly possible with built-in grain UGens.

I’m still not totally clear in the spec. Every time a grain fires, instead of being played back directly, it should be used as real-time convo kernel on live input? Or both? Or some kinda crossfade? (Feel free to dm or email)

3 Likes

Typo on the first alloc: convulution2L ?

1 Like