Instr 


An Instrument is a function that has a unique name attached to it.

It is stored in the Library by its name and can be retrieved by that name.


Storing:

(

Instr(\sin, { arg freq,amp;

SinOsc.ar(freq,0.0, amp)

});

)

Retreiving:


Instr.at(\sin)


or:


Instr(\sin)


Patch uses Instr This are principally used for 

These functions and the storage system may be used for anything you like, but its 


If the Instr is not found already loaded into the Library it will search in the Instr directory and load it from a file.

So you may also store your instruments in text files and build up a large library of resuable functions.  


Instr("TheArrogator")


will look for a file called "TheArrogator.scd" or .rtf or .txt


It will look in your Instr directory which is set by default to "build/Instr".  You may set this in your startup to something else:


Instr.dir = "~/Documents/SuperCollider/Instr";


Quarks can also contain Instr, so the loading function will also look through your installed quarks for any folder called Instr.

The cxaudio quark has lots of Instr.



Specify by dot notation to look for a file named 'oscillators' :


Instr( "oscillators.sin")

Instr( "folder.subfolder.oscillators.sin")


It will look for the files oscillators.rtf, oscillators.txt, oscillators.sc or oscillators


it expects to find in one of those files an Instr named "oscillators.sin"


The older form array notation also works:


Instr([\oscillators,\sin])



Instr(name,function,inputSpecs.outputSpec);


name - \sin

"oscillators.sin"

in file oscillators

"folder.subfolder.oscillators.sin"

in folder/subfolder/oscillators

[\oscillators, \sin]

function - the Instr's ugenFunc

When using your Instrument with Patch THERE IS NO NEED TO USE Out.ar

though you may explicitly use it if you wish.

It will be appended to your ugen graph func if needed.


inputSpecs

Specify what kind of input is required, and the working range of values.

somewhat optional - these can be guessed from the argnames.


see [Spec] and  [ControlSpec]

if no spec is supplied, Instr will use the function's argument name to

lookup a spec in Spec.specs.  eg arg  freq ->  looks for Spec.specs.at(\freq)

If nothing is found there, it will default to a  ControlSpec with a range of 0 .. 1


These specs are used by Patch to determine the suitable type of input.

They may be used in many other situations, and you will find many uses

where you will wish to query the specs.


The default/initial value for the Spec is taken from the function defaults.


different lazy ways to specify the spec...

(

Instr("minimoog.one",{ arg freq=440,int1=5,int2 = -5,

width1=0.1,width2=0.1,width3=0.1,

ffreqInterval=0,rq=0.4;

var p;

p=Pulse.ar([ freq  * int1.midiratio, freq, freq * int2.midiratio],

[ width1,width2,width3],0.3);

RLPF.ar(Mix.ar(p),freq * ffreqInterval.midiratio,rq)

},#[ 

nil, // nil, so use function's arg name (\freq) 

// to look up in Spec.specs

[-48,48,\linear,1], // as(Spec,[-48,48,\linear,1]) 

//   =>   ControlSpec.new(-48,48,\linear,1)

[-48,48,\linear,1],

\unipolar, // try Spec.specs.at(\unipolar)

nil, // try the argname width2, that fails,

//  so the default is ControlSpec(0,1,\linear)

\unipolar,

[-48,48,\linear,1]

]);

)


outSpec

optional - InstrSynthDef can determine the outputSpec by evaluating the ugenGraph

and finding what the spec of the result is.

An Instr can be .ar, .kr or can even return an object, a player, or a pattern.


Playing



(

Instr.new("minimoog.two",{ arg freq=440,int1=5,int2 = -5,

width1=0.1,width2=0.1,width3=0.1,

ffreqInterval=0,rq=0.4;

var p;

p=Pulse.ar([ freq  * int1.midiratio, freq, freq * int2.midiratio],

[ width1,width2,width3],0.3);

RLPF.ar(Mix.ar(p),freq * ffreqInterval.midiratio,rq)

},#[ // specs

\freq,

[-48,48,\linear,1],

[-48,48,\linear,1],

\unipolar,

\unipolar,

\unipolar,

[-48,48,\linear,1]

]);


)


(

Instr.at("minimoog.two").play

)


(

{

"minimoog.two".ar( LFNoise1.kr(0.1,300,700) )

}.play

)


(

{

Instr.at("minimoog.two")

.ar( LFNoise1.kr(0.1,300,700) );

}.play

)


(

{

Instr.ar(

"minimoog.two",

[ LFNoise1.kr(0.1,300,700) ]

);  

}.play

)



but by far the best way is to use Patch :


Patch("minimoog.two",[1000]).play


Patch("minimoog.two").gui



Patterns


(

Instr([\minimoog,\two],{ arg freq=440,int1=5,int2 = -5,width1=0.1,width2=0.1,width3=0.1,

ffreqInterval=0,rq=0.4;

var p;

p=Pulse.ar([ freq  * int1.midiratio, freq, freq * int2.midiratio],

[ width1,width2,width3],0.3);

RLPF.ar(Mix.ar(p),freq * ffreqInterval.midiratio,rq)

* EnvGen.kr(Env.perc,doneAction: 2)

});


p = Patch([\minimoog,\two]); // no args, Patch automagically creates KrNumberEditors


// this writes it to disk

d = p.asSynthDef.store;


Pbind(

\instrument, d.name,

// note is converted to freq by things in NotePlayer

\note,Prand([10,20,30],inf),

// args are passed into the function

\int1, Prand([-3,0,7,11,13],inf)

).play

)


see also InstrGateSpawner and InstrSpawner



An Instr is not a SynthDef


An Instr creates an InstrSynthDef  (a subclass of SynthDef)


Each argument in the function for a SynthDef creates a Control input to the Synth that will eventually play on the server.  


An Instr can also include extra arguments that will be used in building the synth def, but will not be Control inputs in the final synth.


For instance an Integer may be passed in:


// caution: mind the feedback. AudioIn

(

Instr(\qAllpassA,{ arg audio,decay=1,maxDelay=0.3,quantity=4,chanDiff=0.1;


(quantity.asInteger).do({

var x; 

audio = 

  AllpassL.ar(audio, maxDelay, 

  [rrand(0.01,maxDelay),rrand(0.01,maxDelay)],

  decay)

  });

audio

});


Patch(\qAllpassA,[

{ AudioIn.ar([1,2]) },

1,

0.3,

8

]).play


)


The first input to the synth is a stereo audio rate input, the others were fixed floats that did not require synth inputs.


Envelopes, fixed floats, fixed integers, Samples etc. can be passed into Instr functions.


When Patch is used to specify the inputs to the function some of these inputs will be reduced to fixed values (integers, floats, Envelopes etc.), and the resulting SynthDef will contain those inputs hard-coded.  Using different Patches, it is possible to write many SynthDefs from the same Instr.


Instr(\rlpf,{ arg input,ffreq=400,rq=0.1;

RLPF.ar( input, ffreq, rq )

});

If the input supplied is stereo, the synthDef produced will be stereo.  

(

Patch(\rlpf,[

Patch({ Saw.ar([400,440],0.1) }) // in stereo

]).play

)

It is possible to play another Instr inside of your Instr:


(

Instr(\sawfilter,{ arg freq,ffreq,rq;

Instr.ar(\rlpf, [ Saw.ar(freq,0.1) , ffreq, rq ])

})

)

and thus get further reuse out of your library of functions.  Here the \rlpf that is used inside doesn't produce a synth def, but is used as a simple function in the ugenGraph of the \sawfilter Instr which does make a synthDef.


It is not generally possible to use the .ar method on a player inside of an Instrument function.  This was possible in sc2.   You cannot use a sound file player in this way:


sfp = SFP("path/to/soundfile");

Instr('no-can-do',{ arg sfp,amp=1.0;

sfp.ar * amp

});


Because an SFP (soundfile player) will require a buffer, a bus, and various stages of preparation.  It is a complex process that cannot be compiled into a SynthDef.


the better approach is :


Instr("can-do",{ arg input,amp=1.0;

  input * amp

});

Patch("can-do",[

SFP("path/to/soundfile")

])




.gui


The gui for Instr is a simple display of the arguments and specs.



// default gui display for Instr

Instr.at("minimoog.one").gui




see [Patch] [InstrGateSpawner]