Add RT query proto-examples to help files

nix
Owen Green 6 years ago
parent 806a3414d7
commit 6a9e91cb5a

@ -72,7 +72,7 @@ fork{
)
// Make a new tree, and fit it to the dataset
~tree = FluidKDTree(s);
~tree = FluidKDTree(s,numNeighbours:5,lookupDataSet:~ds);
//Fit it to the dataset
~tree.fit(~ds);
@ -83,23 +83,57 @@ fork{
//Return labels of k nearest points to a new point
(
~p = [ 1.0.linrand,1.0.linrand ];
~tree.numNeighbours = 5;
~tmpbuf = Buffer.loadCollection(s, ~p, 1, {
~tree.kNearest(~tmpbuf,5, { |a|~nearest = a;})
~tree.kNearest(~tmpbuf,{ |a|a.postln;~nearest = a;})
});
)
// Labels of nearest points
~nearest.postln;
// Values
(
fork{
~nearest.do{|n|
~nearest.do{|n|
~ds.getPoint(n, ~tmpbuf, {~tmpbuf.getn(0, 2, {|x|x.postln})});
s.sync;
}
}
}
)
//Distances of the nearest points
~tree.kNearestDist(~tmpbuf, 5, { |a| a.postln });
~tree.kNearestDist(~tmpbuf, { |a| a.postln });
::
subsection:: Server Side Queries
code::
(
~inputPoint = Buffer.alloc(s,2);
~predictPoint = Buffer.alloc(s,10);
~pitchingBus = Bus.control;
~catchingBus = Bus.control;
)
(
~tree.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~inputPoint).outBuffer_(~predictPoint);
{
var trig = Impulse.kr(ControlRate.ir/2);
var point = 2.collect{TRand.kr(0,1,trig)};
point.collect{|p,i| BufWr.kr([p],~inputPoint,i)};
Poll.kr(trig,point);
Out.kr(~pitchingBus.index,[trig]);
Poll.kr(In.kr(~catchingBus.index),BufRd.kr(1,~predictPoint,Array.iota(5)));
Silent.ar;
}.play(~tree.synth,addAction:\addBefore);
)
::

@ -95,7 +95,7 @@ fork{
// Fit into 4 clusters
(
~kmeans.fitPredict(~dataset,~clusters, 4, action: {|c|
~kmeans.fitPredict(~dataset,~clusters,action: {|c|
"Fitted.\n # Points in each cluster:".postln;
c.do{|x,i|
("Cluster" + i + "->" + x.asInteger + "points").postln;
@ -145,23 +145,23 @@ w.refresh;
w.front;
)
//Querying on the server using busses and buffers:
//This is the equivalent of predictPoint, but wholly on the server
//FluidKMeans is accessed via its own synth, so we need to use
//a bus to communicate with it. The inBus receives a trigger to query, using data
//from inBuffer; a trigger is then send to outBus with the prediction in outBuffer
::
subsection:: Server Side Queries
This is the equivalent of predictPoint, but wholly on the server
FluidKMeans is accessed via its own synth, so we need to use
a bus to communicate with it. The inBus receives a trigger to query, using data
from inBuffer; a trigger is then send to outBus with the prediction in outBuffer
code::
(
~ib = Bus.audio(s); // input bus must be audio (for now)
~ib = Bus.control(s); // input bus must be audio (for now)
~ob = Bus.control(s); //output bus can be kr
~tempPoint = Buffer.alloc(s,1,2);
~inpPoint = Buffer.alloc(s,2);
~outPoint = Buffer.alloc(s,1);
)
~tempPoint.getn(0,2,{|x|x.post})
~inpPoint.getn(0,2,{|x|x.post})
//We make two Synths. One, before FluidKMeans, generates a random point and sends
//a trigger to query. The second, after FluidKMeans, gives us the predicted cluster //triggering upadtes from the outBus
(
@ -169,13 +169,12 @@ w.front;
~kmeans.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
//pitching
{
var trig = Impulse.kr(1);
var trig = Impulse.kr(100);
var point = WhiteNoise.kr(1.dup);
var copied;
BufWr.kr(point,~tempPoint,0);
Poll.kr(trig, point, [\pointX,\pointY]);
copied = Done.kr(FluidBufFlatten.kr(~tempPoint, ~inpPoint, trig: trig));
Out.ar(~ib.index,K2A.ar(copied > Delay1.kr(copied)));
point.collect{ |p,i| BufWr.kr([p],~inpPoint,i)};
Out.kr(~ib.index,[trig]);
}.play(~kmeans.synth,addAction:\addBefore);
//catching
{
@ -183,20 +182,17 @@ w.front;
}.play(~kmeans.synth,addAction:\addAfter);
)
// to sonify the output, here are random values alternating quadrant.
// to sonify the output, here are random values alternating quadrant, generated more quickly as the cursor moves rightwards
(
//Set properties on FluidKMeans:
~kmeans.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
//pitching
{
var count, trig, point, copied;
trig = Impulse.kr(MouseX.kr(0,1).exprange(0.5,1000).poll);
count = Stepper.kr(trig,0,0,3);
point = Latch.kr(WhiteNoise.ar([0.1,0.1],[count.div(2)-0.5,count.mod(2)-0.5]),trig);
BufWr.kr(point,~tempPoint,0);
copied = Done.kr(FluidBufFlatten.kr(~tempPoint, ~inpPoint, trig: trig));
Out.ar(~ib.index,K2A.ar(copied > Delay1.kr(copied)));
trig*0.1;
var trig = Impulse.kr(MouseX.kr(0,1).exprange(0.5,ControlRate.ir / 2));
var point = 2.collect{ TIRand.kr(0,3,trig).linlin(0,3,-1,1) };
point.collect{|p,i| BufWr.kr([p],~inpPoint,i)};
Out.kr(~ib.index,[trig]);
T2A.ar(trig)*0.1;
}.play(~kmeans.synth,addAction:\addBefore);
//catching
{

@ -145,5 +145,58 @@ w.drawFunc = {
w.refresh;
w.front;
)
::
subsection::Server Side Queries
This is the equivalent of predictPoint, but wholly on the server
FluidKMeans is accessed via its own synth, so we need to use
a bus to communicate with it. The inBus receives a trigger to query, using data
from inBuffer; a trigger is then send to outBus with the prediction in outBuffer
code::
(
~ib = Bus.control(s); // input bus must be audio (for now)
~ob = Bus.control(s); //output bus can be kr
~inpPoint = Buffer.alloc(s,2);
~outPoint = Buffer.alloc(s,1);
)
//We make two Synths. One, before FluidKMeans, generates a random point and sends
//a trigger to query. The second, after FluidKMeans, gives us the predicted cluster //triggering upadtes from the outBus
(
//Set properties on FluidKMeans:
~classifier.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
//pitching
{
var trig = Impulse.kr(100);
var point = WhiteNoise.kr(1.dup);
Poll.kr(trig, point, [\pointX,\pointY]);
point.collect{ |p,i| BufWr.kr([p],~inpPoint,i)};
Out.kr(~ib.index,[trig]);
}.play(~classifier.synth,addAction:\addBefore);
//catching
{
Poll.kr(In.kr(~ob),Latch.kr(BufRd.kr(1,~outPoint,0,interpolation:0),In.kr(~ob)),\cluster);
}.play(~classifier.synth,addAction:\addAfter);
)
// to sonify the output, here are random values alternating quadrant.
(
//Set properties on FluidKMeans:
~classifier.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
//pitching
{
var trig = Impulse.kr(MouseX.kr(0,1).exprange(0.5,ControlRate.ir /2).poll);
var point = 2.collect{TIRand.kr(0,3,trig).linlin(0,3,-1,1)};
point.collect{|p,i| BufWr.kr([p],~inpPoint,i)};
Out.kr(~ib.index,[trig]);
T2A.ar(trig)*0.1;
}.play(~classifier.synth,addAction:\addBefore);
//catching
{
SinOsc.ar((Latch.kr(BufRd.kr(1,~outPoint,0,interpolation:0),In.kr(~ob)) + 69).midicps,mul: 0.1);
}.play(~classifier.synth,addAction:\addAfter);
)
::

@ -89,15 +89,13 @@ d = Dictionary.with(
~testdata.collect{|x, i| [i.asString, [x]]}.flatten)])
);
~targetdata.plot
~source.print;
~target.print;
~test.print;
)
// Now make a regressor and fit it to the source and target, and predict against test
//grab the output data whilst we're at it, so we can inspect
(
@ -110,8 +108,45 @@ d = Dictionary.with(
});
)
//We should see a single cycle of a chirp
~outputdata.plot;
::
subsection:: Server Side Queries
code::
//Setup
(
~inputPoint = Buffer.alloc(s,1);
~predictPoint = Buffer.alloc(s,2);
~avgBuf = Buffer.alloc(s,10,2);
~pitchingBus = Bus.control;
~catchingBus = Bus.control;
)
(
~regressor.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~inputPoint).outBuffer_(~predictPoint);
~inputSynth = {
var input = Saw.kr(2).linlin(-1,1,0,1);
var trig = Impulse.kr(ControlRate.ir/10);
BufWr.kr(input,~inputPoint,0);
Out.kr(~pitchingBus.index,[trig]);
};
~inputSynth.play(~regressor.synth,addAction:\addBefore);
~outputSynth = {
Poll.kr(In.kr(~catchingBus.index),BufRd.kr(1,~predictPoint,0),"mapped value")
};
~outputSynth.play(~regressor.synth,addAction:\addAfter);
~outputSynth.scope
)
::

@ -64,6 +64,7 @@ EXAMPLES::
code::
s.boot;
//Preliminaries: we want some audio, a couple of FluidDataSets, some Buffers and a FluidNormalize
// FluidNormalize.dumpAllMethods
(
~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav";
~raw = FluidDataSet(s,\norm_help_raw);
@ -123,4 +124,40 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature);
~plot2 = ~normedarray.flatten(1).unlace.plot("Normalized",Rect(410,0,400,400)).plotMode=\bars;
)
//Server side queries
//Setup
(
~tempPoint = Buffer.alloc(s,2);
~predictPoint = Buffer.alloc(s,2);
~avgBuf = Buffer.alloc(s,10,2);
~pitchingBus = Bus.control;
~catchingBus = Bus.control;
)
(
~normalizer.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~tempPoint).outBuffer_(~predictPoint);
//Pitching (no pun intended): read frames out of buffer and pass to standardize
{
var audio = BufRd.ar(1,~audio,LFSaw.ar(BufDur.ir(~audio).reciprocal).range(0, BufFrames.ir(~audio)));
var counter = Stepper.ar(Impulse.ar(ControlRate.ir),max:9);
var trig = HPZ1.ar(counter) < 0;
//average 10 frames: one could use the MovingAverage extension here
var avg;
BufWr.kr(FluidPitch.kr(audio),~avgBuf,phase:counter);
avg = Mix.new(BufRd.kr(2, ~avgBuf, phase:10.collect{|x|x})) * 0.1;
//assemble data point
BufWr.kr(avg[0],~tempPoint,0);
BufWr.kr(avg[1],~tempPoint,1);
Poll.kr(T2K.kr(trig),BufRd.kr(1,~tempPoint,[0,1]),["pitch (raw)", "confidence (raw)"]);
Out.kr(~pitchingBus.index,[T2K.kr(trig)]);
}.play(~normalizer.synth,addAction:\addBefore);
{
Poll.kr(In.kr(~catchingBus.index),BufRd.kr(1,~predictPoint,[0,1]),["pitch (normalized)", "confidence (normalized)"])
}.play(~normalizer.synth,addAction:\addAfter);
)
::

@ -121,7 +121,6 @@ FluidBufMFCC.process(s,~audio, features: ~mfcc_feature);
)
//Visualise the 2D projection of our original 12D data
(
d = ~reducedarray.flatten(1).unlace.deepCollect(1, { |x| x.normalize});
@ -141,3 +140,36 @@ w.refresh;
w.front;
)
::
subsection:: Server Side Queries
Let's map our learned PCA dimensions to the controls of a processor
code::
(
~inputPoint = Buffer.alloc(s,12);
~predictPoint = Buffer.alloc(s,2);
~pitchingBus = Bus.control;
~catchingBus = Bus.control;
)
(
~pca.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~inputPoint).outBuffer_(~predictPoint);
{
var mapped;
var audio = BufRd.ar(1,~audio,LFSaw.ar(BufDur.ir(~audio).reciprocal).range(0, BufFrames.ir(~audio)));
var mfcc = FluidMFCC.kr(audio)[1..12];
var smoothed = LagUD.kr(mfcc,1*ControlDur.ir,500*ControlDur.ir);
var trig = Impulse.kr(ControlRate.ir / 2);
smoothed.collect{|coeff,i| BufWr.kr([coeff],~inputPoint,i)};
Out.kr(~pitchingBus,[trig]);
mapped = Latch.kr(BufRd.kr(2,~predictPoint).linlin(-3,3,0,3),In.kr(~catchingBus));
CombC.ar(audio,3,mapped[0],mapped[1]*3)
}.play(~pca.synth,addAction:\addBefore);
)
::

@ -50,7 +50,7 @@ ARGUMENT:: destBuffer
A link::Classes/Buffer:: to contain the standardize value
ARGUMENT:: action
A function to run when processing is complete
[].unlace
EXAMPLES::
code::
@ -113,6 +113,44 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature);
~rawarray.flatten(1).unlace.plot("Unstandardized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars;
~plot2 = ~stdarray.flatten(1).unlace.plot("Standardized",Rect(410,0,400,400)).plotMode=\bars;
)
::
subsection::Server Side Querying
Because FluidStandardize runs in its own link::Classes/Synth:: on the server, communication is done via control-rate link::Classes/Bus:: objects for triggering and link::Classes/Buffer:: objects for passing and retreiving data.
code::
//Setup
(
~tempPoint = Buffer.alloc(s,2);
~predictPoint = Buffer.alloc(s,2);
~avgBuf = Buffer.alloc(s,10,2);
~pitchingBus = Bus.control;
~catchingBus = Bus.control;
)
(
~standardizer.inBus_(~pitchingBus).outBus_(~catchingBus).inBuffer_(~tempPoint).outBuffer_(~predictPoint);
//Pitching (no pun intended): read frames out of buffer and pass to standardize
{
var audio = BufRd.ar(1,~audio,LFSaw.ar(BufDur.ir(~audio).reciprocal).range(0, BufFrames.ir(~audio)));
var counter = Stepper.ar(Impulse.ar(ControlRate.ir),max:9);
var trig = HPZ1.ar(counter) < 0;
//average 10 frames: one could use the MovingAverage extension here
var avg;
BufWr.kr(FluidPitch.kr(audio),~avgBuf,phase:counter);
avg = Mix.new(BufRd.kr(2, ~avgBuf, phase:10.collect{|x|x})) * 0.1;
//assemble data point
BufWr.kr(avg[0],~tempPoint,0);
BufWr.kr(avg[1],~tempPoint,1);
Poll.kr(T2K.kr(trig),BufRd.kr(1,~tempPoint,[0,1]),["pitch (raw)", "confidence (raw)"]);
Out.kr(~pitchingBus.index,[T2K.kr(trig)]);
}.play(~standardizer.synth,addAction:\addBefore);
//catching
{
Poll.kr(In.kr(~catchingBus.index),BufRd.kr(1,~predictPoint,[0,1]),["pitch (standardized)", "confidence (standardized)"])
}.play(~standardizer.synth,addAction:\addAfter);
)
::

Loading…
Cancel
Save