Supercollider tips, Q/A


#285

Take a look at the helpfule for Pbindef I believe that will allow you to change only one key value at a time.


#286

Saw this video by Eli Fieldsteel recently, maybe the linked scripts in the description will be useful?


#287

hi keno,

considering context here, i assume that by changing a single key in your Pdef, you mean modulating it in response to MIDI data.

you can’t change a key in Pbind after it’s been created and started playing. when you write e.g. \dur, 0.1 in a Pbind, that \dur will always be 0.1 — it can’t be changed externally. instead, you can plug special patterns into keys so that you can modulate the parameters you want.

the quickest way in the context of a Pbind is to use Pfuncn, which executes a function over and over again. in this case we write a function which repeatedly returns the value of a variable. changing that variable modulates the parameter in the Pbind:

var dur = 1.0;

Pbind(*[
    instrument: \synth,
    dur: Pfuncn({ dur }, inf)
]).play;

// now setting 'dur' modulates the \dur key. example:
MIDIdef.cc(\dur, { |val, num, chan, src|
    dur = val.linlin(0, 255, 1.0, 3.0);
}, 14);

this is convenient enough when you only have one parameter to deal with, but it gets out of hand when you have 20 of them. for a more scalable approach, i would lump all modulatable keys into a single big event that you can modify at will. use Pfuncn to return it repeatedly and ensure you’re getting the latest updates, and then use Pbindf to supply additional keys.

var baseEvent;

baseEvent = (
    dur: 1.0,
    freq: 440,
    amp: 0.1
);

Pbindf(Pfuncn({ baseEvent }, inf), *[
    instrument: \pad,
    filterfreq: Pexprand(1000, 8000, inf)
]).play;

// now setting baseEvent[\dur] modulates the \dur key. example:
MIDIdef.cc(\dur, { |val, num, chan, src|
    baseEvent[\dur] = val.linlin(0, 255, 1.0, 3.0);
}, 14);

an important limitation is that this will not modulate parameters continuously — parameters are only read at the beginning of each note. the patterns system is a discrete sequencer and doesn’t really have a conception of continuously running control signals. if you do want continuous modulation, let me know and i can describe how to do that instead. (my solution involves instantiating all synths inside a Group and calling .set on that Group, which automatically broadcasts parameter modulations to the synths.)


#288

Thank you so much for your answer, @nathan! I was hesitating to use a global variable as described in the documentation because I considered it bad style.
Continous modulation sounds awesome. If you can spare some time, I’d like to have a look at your approach.


#289

Wow, haven’t discovered it yet!


#290

Couldn’t you use Buses and change the values of the buses using MIDI and then use the Bus.index.asMap functionality to link the buses to the Pbind? That way you’d get continuous changes.


#291

I’m a beginner at SC, and trying to figure BeatTrack out.
I want to track the bpm of an incoming signal in realtime. I’ve got this modified example code to work (a bit wonky, but still it works):

(
a = SynthDef(\help_beattrack, { |out, vol=0.0, beepvol=1.0, lock=0|
    var in, fft, resample;
    var trackb, trackh, trackq, tempo;
    var beeper;
    
    in = SoundIn.ar(0);
    fft = FFT(LocalBuf(1024), in);

	#trackb, trackh, trackq, tempo = BeatTrack.kr(fft, lock);

    beeper = SinOsc.ar(423, 1.0, Decay.kr(trackb, 0.15));

    Out.ar(out, Pan2.ar((vol * in) + (beepvol * beeper), 0.0))

}).play
)

Now, my question is: how do I use the bpm extracted from the input in a sequence, using Pbind for instance? trackb, trackh and trackq each represent quarter notes, eight notes and sixteenth notes. But I don’t understand how to use their values in a sequence. Is there a way to simply convert trackb etc to a float or integer, and then insert it into TempoClock?


#292

Yes, the best (simplest?) way to continuously change parameters of running synths in response to incoming midi (or other) data is to change the value of a control bus in response to the data, and map (.asMap) the control bus to whatever parameter you want to modulate.

Using events you can only change the value on the evaluation of the event, not continuously, so even if you use a Pfunc it’s still only updated at the start of an event.


#293

For this you’ll want to use SendTrig to pass a value from the server to the client.

I haven’t used BeatTrack in a long time, but I think this should work for what you want to do:

(

t = TempoClock(120/60);

a = SynthDef(\help_beattrack, { |out, vol=0.0, beepvol=1.0, lock=0|
    var in, fft, resample;
    var trackb, trackh, trackq, tempo;
    var beeper;
    
    in = SoundIn.ar(0);
    fft = FFT(LocalBuf(1024), in);

	#trackb, trackh, trackq, tempo = BeatTrack.kr(fft, lock);

    beeper = SinOsc.ar(423, 1.0, Decay.kr(trackb, 0.15));
	
	SendTrig.kr(trackb, 0, tempo);

    Out.ar(out, Pan2.ar((vol * in) + (beepvol * beeper), 0.0))

}).play;


o = OSCFunc({ arg msg, time;
    [time, msg].postln;
	t.tempo = msg[3];
},'/tr', s.addr);


)

o.free

t.tempo.postln // post current tempo

This will set the tempo of TempoClock ‘t’ to whatever the currently detected tempo is on every quarter note tick of ‘trackb’.

If you aren’t familiar with the client/server relationship (it caused me, and every other beginner I know, lots of grief), check out Client vs. Server reference in SCDocs.

[edit]

Oh also, I recommend using OSCdef for managing your OSC responders in the client.

OSCFunc is just there in the example because I cribbed the code for SendTrig help file, but I’ve had orphan OSC responders laying around causing me grief in the past using OSCFunc directly.


#295

Thanks a lot, this was super helpful!
I got it working as I wanted it with a pbind-sequence by changing your code to:

t = TempoClock.default.tempo = 120/60;

I’m still new to both programming in general and supercollider in particular, and I’m sure there can be better ways than to change the default tempo, but hey it works!


#296

Installed SuperCollider on my ChromeBook (Samsung Chromebook Plus V1 (with ARM processor)). The application installed through the CLI fine but I can’t seem to get the server running. I’ve tried a few things from googling but had no luck so far. Curious if anyone with a more thorough understanding of the Linux implementation in ChromeOS and SuperColliders operating requirements could help me figure out if this is possible or not!


#297

hey SC users – sorry if this is a bit off topic, but some of us SC devs have put together a SuperCollider user survey:

would be appreciated if you could fill it out to help us decide on the best directions of development :slight_smile:

(let me know if this isn’t the right place to post and/or overall inappropriate for this forum)


#298

SC runs fine on my chromebook, running Ubuntu 14.04, and I don’t remember any server hiccups in installation… What distro are you running? If Ubuntu, maybe this is helpful:


#299

i’ve been trying to run it in ChromeOS. i’m not sure what the limitations are on Linux applications in ChromeOS at this point but i would imagine it has something to do with that or the ARM processor.


#300

Which Chromebook do you have? Crouton or Crostini? Built-in audio?

I’m Chromebook shopping but I’m a bit hesitant to commit as it seems that Crostini has not yet implemented the AC97 codec required for onboard audio. This might be a non-issue with external USB audio, though.