Merge branch 'clients/inter_client_comms' into refactor/macro-purge

nix
Owen Green 5 years ago
commit b5bb48b53a

@ -34,8 +34,9 @@ public:
static void setup(InterfaceTable* ft, const char* name) static void setup(InterfaceTable* ft, const char* name)
{ {
ft->fDefineUnitCmd(name, "latency", doLatency);
registerUnit<RealTime>(ft,name); registerUnit<RealTime>(ft,name);
ft->fDefineUnitCmd(name, "latency", doLatency);
} }
static void doLatency(Unit* unit, sc_msg_iter*) static void doLatency(Unit* unit, sc_msg_iter*)
@ -47,7 +48,7 @@ public:
std::stringstream ss; std::stringstream ss;
ss << '/' << Wrapper::getName() << "_latency"; ss << '/' << Wrapper::getName() << "_latency";
std::cout << ss.str() << std::endl; // std::cout << ss.str() << ": " << l[0] << std::endl;
ft->fSendNodeReply(&unit->mParent->mNode, -1, ss.str().c_str(), 1, l); ft->fSendNodeReply(&unit->mParent->mNode, -1, ss.str().c_str(), 1, l);
} }

@ -1,6 +1,6 @@
FluidBufLoudness : FluidBufProcessor{ FluidBufLoudness : FluidBufProcessor{
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, trig = 1, blocking = 0| *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, padding = 1, trig = 1, blocking = 0|
var maxwindowSize = windowSize.nextPowerOfTwo; var maxwindowSize = windowSize.nextPowerOfTwo;
source = source.asUGenInput; source = source.asUGenInput;
@ -8,12 +8,12 @@ FluidBufLoudness : FluidBufProcessor{
source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; source.isNil.if {"FluidBufPitch: Invalid source buffer".throw};
features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw};
^FluidProxyUgen.kr(\FluidBufLoudnessTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, trig, blocking); ^FluidProxyUgen.kr(\FluidBufLoudnessTrigger, -1, source, startFrame, numFrames, startChan, numChans, features,padding, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, trig, blocking);
} }
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, freeWhenDone = true, action| *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, padding = 1, freeWhenDone = true, action|
var maxwindowSize = windowSize.nextPowerOfTwo; var maxwindowSize = windowSize.nextPowerOfTwo;
source = source.asUGenInput; source = source.asUGenInput;
@ -21,16 +21,16 @@ FluidBufLoudness : FluidBufProcessor{
source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; source.isNil.if {"FluidBufPitch: Invalid source buffer".throw};
features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw};
^this.new( ^this.new(
server, nil, [features] server, nil, [features]
).processList( ).processList(
[source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize,0],freeWhenDone,action [source, startFrame, numFrames, startChan, numChans, features, padding, kWeighting, truePeak, windowSize, hopSize, maxwindowSize,0],freeWhenDone,action
); );
} }
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, freeWhenDone = true, action| *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, padding = 1, freeWhenDone = true, action|
var maxwindowSize = windowSize.nextPowerOfTwo; var maxwindowSize = windowSize.nextPowerOfTwo;
source = source.asUGenInput; source = source.asUGenInput;
@ -38,11 +38,11 @@ FluidBufLoudness : FluidBufProcessor{
source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; source.isNil.if {"FluidBufPitch: Invalid source buffer".throw};
features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw};
^this.new( ^this.new(
server, nil, [features] server, nil, [features]
).processList( ).processList(
[source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize,1],freeWhenDone,action [source, startFrame, numFrames, startChan, numChans, features,padding, kWeighting, truePeak, windowSize, hopSize, maxwindowSize,1],freeWhenDone,action
); );
} }
} }

@ -23,7 +23,7 @@
mfcc = FluidBufMFCC.kr(src, startFrame:start, numFrames:num, numChans:1, features:~mfccbuf[voice], trig:1, blocking: 1); mfcc = FluidBufMFCC.kr(src, startFrame:start, numFrames:num, numChans:1, features:~mfccbuf[voice], trig:1, blocking: 1);
stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], trig:Done.kr(mfcc), blocking: 1); stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], trig:Done.kr(mfcc), blocking: 1);
flatten = FluidBufFlatten.kr(~statsbuf[voice], ~flatbuf[voice], trig:Done.kr(stats), blocking: 1); flatten = FluidBufFlatten.kr(~statsbuf[voice], ~flatbuf[voice], trig:Done.kr(stats), blocking: 1);
writer = FluidDataSetWr.kr(~ds, label, -1, ~flatbuf[voice], trig: Done.kr(flatten), blocking: 1) writer = FluidDataSetWr.kr(~ds, label, nil, ~flatbuf[voice], trig: Done.kr(flatten), blocking: 1)
}); });
) )
@ -166,4 +166,4 @@ Routine{
dur.wait; dur.wait;
}; };
}.play; }.play;
) )

@ -23,10 +23,10 @@
var label, voice, mfcc, stats, flatten; var label, voice, mfcc, stats, flatten;
label = data.key; label = data.key;
voice = data.value[\voice]; voice = data.value[\voice];
mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:1,blocking: 1); mfcc = FluidBufMFCC.kr(src, startFrame:start, numFrames:num, numChans:1, features:~mfccbuf[voice], padding: 2, trig:1, blocking: 1);
stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], numDerivs: 1, trig:Done.kr(mfcc), blocking: 1); stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], numDerivs: 1, trig:Done.kr(mfcc), blocking: 1);
flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1); flatten = FluidBufFlatten.kr(~statsbuf[voice], ~flatbuf[voice], trig:Done.kr(stats), blocking: 1);
FluidDataSetWr.kr(~ds,label, -1, ~flatbuf[voice], Done.kr(flatten),blocking: 1); FluidDataSetWr.kr(~ds, label, nil, ~flatbuf[voice], Done.kr(flatten), blocking: 1);
}); });
// here we make another processor, this time with doing an amplitude weighing // here we make another processor, this time with doing an amplitude weighing
@ -34,12 +34,12 @@
var label, voice, loud, weights, mfcc, stats, flatten; var label, voice, loud, weights, mfcc, stats, flatten;
label = data.key; label = data.key;
voice = data.value[\voice]; voice = data.value[\voice];
mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:1,blocking: 1); mfcc = FluidBufMFCC.kr(src, startFrame:start, numFrames:num, numChans:1, features:~mfccbuf[voice], padding: 2, trig:1, blocking: 1);
loud = FluidBufLoudness.kr(src,startFrame:start,numFrames:num,numChans:1,features:~loudbuf[voice],trig:Done.kr(mfcc),blocking: 1); loud = FluidBufLoudness.kr(src, startFrame:start, numFrames:num, numChans:1, features:~loudbuf[voice], padding: 2, trig:Done.kr(mfcc), blocking: 1);
weights = FluidBufScale.kr(~loudbuf[voice],numChans: 1,destination: ~weightbuf[voice],inputLow: -70,inputHigh: 0, trig: Done.kr(loud),blocking: 1); weights = FluidBufScale.kr(~loudbuf[voice], numChans: 1, destination: ~weightbuf[voice], inputLow: -70, inputHigh: 0, trig: Done.kr(loud), blocking: 1);
stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], numDerivs: 1, weights: ~weightbuf[voice], trig:Done.kr(weights), blocking: 1); stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], numDerivs: 1, weights: ~weightbuf[voice], trig:Done.kr(weights), blocking: 1);
flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1); flatten = FluidBufFlatten.kr(~statsbuf[voice], ~flatbuf[voice], trig:Done.kr(stats), blocking: 1);
FluidDataSetWr.kr(~dsW,label, -1, ~flatbuf[voice], Done.kr(flatten),blocking: 1); FluidDataSetWr.kr(~dsW, label, nil, ~flatbuf[voice], Done.kr(flatten), blocking: 1);
}); });
// and here we make a little processor for loudness if we want to poke at it // and here we make a little processor for loudness if we want to poke at it
@ -47,10 +47,10 @@
var label, voice, loud, stats, flatten; var label, voice, loud, stats, flatten;
label = data.key; label = data.key;
voice = data.value[\voice]; voice = data.value[\voice];
loud = FluidBufLoudness.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:1,blocking: 1); loud = FluidBufLoudness.kr(src, startFrame:start, numFrames:num, numChans:1, features:~mfccbuf[voice], trig:1, padding: 2, blocking: 1);
stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], numDerivs: 1, trig:Done.kr(loud), blocking: 1); stats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsbuf[voice], numDerivs: 1, trig:Done.kr(loud), blocking: 1);
flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1); flatten = FluidBufFlatten.kr(~statsbuf[voice], ~flatbuf[voice], trig:Done.kr(stats), blocking: 1);
FluidDataSetWr.kr(~dsL,label, -1, ~flatbuf[voice], Done.kr(flatten),blocking: 1); FluidDataSetWr.kr(~dsL, label, nil, ~flatbuf[voice], Done.kr(flatten), blocking: 1);
}); });
) )
@ -150,10 +150,10 @@ FluidBufCompose.process(s,~loader.buffer,a,(b-a),numChans: 1, destination: ~targ
( (
{ {
var loud, weights, mfcc, stats, flatten, stats2, written; var loud, weights, mfcc, stats, flatten, stats2, written;
mfcc = FluidBufMFCC.kr(~targetsound,features:~mfccbuf[0],trig:1); mfcc = FluidBufMFCC.kr(~targetsound,features:~mfccbuf[0],padding: 2, trig:1);
stats = FluidBufStats.kr(~mfccbuf[0],stats:~statsbuf[0], numDerivs: 1,trig:Done.kr(mfcc)); stats = FluidBufStats.kr(~mfccbuf[0],stats:~statsbuf[0], numDerivs: 1,trig:Done.kr(mfcc));
flatten = FluidBufFlatten.kr(~statsbuf[0],~flatbuf[0],trig:Done.kr(stats)); flatten = FluidBufFlatten.kr(~statsbuf[0],~flatbuf[0],trig:Done.kr(stats));
loud = FluidBufLoudness.kr(~targetsound,features:~loudbuf[0],trig:Done.kr(flatten),blocking: 1); loud = FluidBufLoudness.kr(~targetsound,features:~loudbuf[0],padding: 2,trig:Done.kr(flatten),blocking: 1);
weights = FluidBufScale.kr(~loudbuf[0],numChans: 1,destination: ~weightbuf[0],inputLow: -70,inputHigh: 0,trig: Done.kr(loud),blocking: 1); weights = FluidBufScale.kr(~loudbuf[0],numChans: 1,destination: ~weightbuf[0],inputLow: -70,inputHigh: 0,trig: Done.kr(loud),blocking: 1);
stats2 = FluidBufStats.kr(~mfccbuf[0],stats:~statsbuf[0], numDerivs: 1, weights: ~weightbuf[0], trig:Done.kr(weights),blocking: 1); stats2 = FluidBufStats.kr(~mfccbuf[0],stats:~statsbuf[0], numDerivs: 1, weights: ~weightbuf[0], trig:Done.kr(weights),blocking: 1);
written = FluidBufFlatten.kr(~statsbuf[0],~flatbuf[1],trig:Done.kr(stats2)); written = FluidBufFlatten.kr(~statsbuf[0],~flatbuf[1],trig:Done.kr(stats2));

@ -38,19 +38,19 @@
pitchweights = FluidBufThresh.kr(~pitchbuf[voice], numChans: 1, startChan: 1, destination: ~weightPitchbuf[voice], threshold: 0.7, trig:Done.kr(pitch), blocking: 1);//pull down low conf pitchweights = FluidBufThresh.kr(~pitchbuf[voice], numChans: 1, startChan: 1, destination: ~weightPitchbuf[voice], threshold: 0.7, trig:Done.kr(pitch), blocking: 1);//pull down low conf
pitchstats = FluidBufStats.kr(~pitchbuf[voice], stats:~statsPitchbuf[voice], numDerivs: 1, weights: ~weightPitchbuf[voice], outliersCutoff: 1.5, trig:Done.kr(pitchweights), blocking: 1); pitchstats = FluidBufStats.kr(~pitchbuf[voice], stats:~statsPitchbuf[voice], numDerivs: 1, weights: ~weightPitchbuf[voice], outliersCutoff: 1.5, trig:Done.kr(pitchweights), blocking: 1);
pitchflat = FluidBufFlatten.kr(~statsPitchbuf[voice],~flatPitchbuf[voice],trig:Done.kr(pitchstats),blocking: 1); pitchflat = FluidBufFlatten.kr(~statsPitchbuf[voice],~flatPitchbuf[voice],trig:Done.kr(pitchstats),blocking: 1);
writePitch = FluidDataSetWr.kr(~pitchDS,label, -1, ~flatPitchbuf[voice], Done.kr(pitchflat),blocking: 1); writePitch = FluidDataSetWr.kr(~pitchDS,label, nil, ~flatPitchbuf[voice], Done.kr(pitchflat),blocking: 1);
// the mfcc need loudness to weigh, so let's start with that // the mfcc need loudness to weigh, so let's start with that
loud = FluidBufLoudness.kr(src,startFrame:start, numFrames:num, numChans:1, features:~loudbuf[voice], trig:Done.kr(writePitch), blocking: 1);//here trig was 1 loud = FluidBufLoudness.kr(src,startFrame:start, numFrames:num, numChans:1, features:~loudbuf[voice], trig:Done.kr(writePitch), blocking: 1);//here trig was 1
//we can now flatten and write Loudness in its own trigger tree //we can now flatten and write Loudness in its own trigger tree
statsLoud = FluidBufStats.kr(~loudbuf[voice], stats:~statsLoudbuf[voice], numDerivs: 1, trig:Done.kr(loud), blocking: 1); statsLoud = FluidBufStats.kr(~loudbuf[voice], stats:~statsLoudbuf[voice], numDerivs: 1, trig:Done.kr(loud), blocking: 1);
flattenLoud = FluidBufFlatten.kr(~statsLoudbuf[voice],~flatLoudbuf[voice],trig:Done.kr(statsLoud),blocking: 1); flattenLoud = FluidBufFlatten.kr(~statsLoudbuf[voice],~flatLoudbuf[voice],trig:Done.kr(statsLoud),blocking: 1);
writeLoud = FluidDataSetWr.kr(~loudDS,label, -1, ~flatLoudbuf[voice], Done.kr(flattenLoud),blocking: 1); writeLoud = FluidDataSetWr.kr(~loudDS,label, nil, ~flatLoudbuf[voice], Done.kr(flattenLoud),blocking: 1);
//we can resume from the loud computation trigger //we can resume from the loud computation trigger
mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:Done.kr(writeLoud),blocking: 1);//here trig was loud mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:Done.kr(writeLoud),blocking: 1);//here trig was loud
mfccweights = FluidBufScale.kr(~loudbuf[voice],numChans: 1,destination: ~weightMFCCbuf[voice],inputLow: -70,inputHigh: 0, trig: Done.kr(mfcc), blocking: 1); mfccweights = FluidBufScale.kr(~loudbuf[voice],numChans: 1,destination: ~weightMFCCbuf[voice],inputLow: -70,inputHigh: 0, trig: Done.kr(mfcc), blocking: 1);
mfccstats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsMFCCbuf[voice], startChan: 1, numDerivs: 1, weights: ~weightMFCCbuf[voice], trig:Done.kr(mfccweights), blocking: 1);//remove mfcc0 and weigh by loudness instead mfccstats = FluidBufStats.kr(~mfccbuf[voice], stats:~statsMFCCbuf[voice], startChan: 1, numDerivs: 1, weights: ~weightMFCCbuf[voice], trig:Done.kr(mfccweights), blocking: 1);//remove mfcc0 and weigh by loudness instead
mfccflat = FluidBufFlatten.kr(~statsMFCCbuf[voice],~flatMFCCbuf[voice],trig:Done.kr(mfccstats),blocking: 1); mfccflat = FluidBufFlatten.kr(~statsMFCCbuf[voice],~flatMFCCbuf[voice],trig:Done.kr(mfccstats),blocking: 1);
FluidDataSetWr.kr(~mfccDS,label, -1, ~flatMFCCbuf[voice], Done.kr(mfccflat),blocking: 1); FluidDataSetWr.kr(~mfccDS,label, nil, ~flatMFCCbuf[voice], Done.kr(mfccflat),blocking: 1);
}); });
) )

@ -38,11 +38,11 @@ a = Slider(w, Rect(10, 20, 330, 20))
features = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1, numCoeffs: 20, features:~featuresbuf[voice],trig:1,blocking: 1); features = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1, numCoeffs: 20, features:~featuresbuf[voice],trig:1,blocking: 1);
stats = FluidBufStats.kr(~featuresbuf[voice],stats:~statsbuf[voice],trig:Done.kr(features),blocking: 1); stats = FluidBufStats.kr(~featuresbuf[voice],stats:~statsbuf[voice],trig:Done.kr(features),blocking: 1);
flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1); flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1);
writer = FluidDataSetWr.kr(~slicesMFCC,label, -1, ~flatbuf[voice], Done.kr(flatten),blocking: 1); writer = FluidDataSetWr.kr(~slicesMFCC,label, nil, ~flatbuf[voice], Done.kr(flatten),blocking: 1);
features = FluidBufSpectralShape.kr(src,startFrame:start,numFrames:num,numChans:1, features:~featuresbuf[voice],trig:Done.kr(writer),blocking: 1); features = FluidBufSpectralShape.kr(src,startFrame:start,numFrames:num,numChans:1, features:~featuresbuf[voice],trig:Done.kr(writer),blocking: 1);
stats = FluidBufStats.kr(~featuresbuf[voice],stats:~statsbuf[voice],trig:Done.kr(features),blocking: 1); stats = FluidBufStats.kr(~featuresbuf[voice],stats:~statsbuf[voice],trig:Done.kr(features),blocking: 1);
flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1); flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats),blocking: 1);
writer = FluidDataSetWr.kr(~slicesShapes,label, -1, ~flatbuf[voice], Done.kr(flatten),blocking: 1); writer = FluidDataSetWr.kr(~slicesShapes,label, nil, ~flatbuf[voice], Done.kr(flatten),blocking: 1);
}); });
) )

@ -31,7 +31,7 @@ FluidBufMelBands.process(s,~audio, features: ~melfeatures,action: {\done.postln;
40.do{|i| 40.do{|i|
bufWr = BufWr.kr(rd[i], buf, DC.kr(i)); bufWr = BufWr.kr(rd[i], buf, DC.kr(i));
}; };
dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); dsWr = FluidDataSetWr.kr(~raw, buf: buf, idNumber: count, trig: Done.kr(stats));
LocalOut.kr( Done.kr(dsWr)); LocalOut.kr( Done.kr(dsWr));
FreeSelf.kr(count - 99); FreeSelf.kr(count - 99);
Poll.kr(trig,(100-count)); Poll.kr(trig,(100-count));

@ -51,6 +51,9 @@ ARGUMENT:: windowSize
ARGUMENT:: hopSize ARGUMENT:: hopSize
How much the buffered window moves forward, in samples. By default 512 to be similar with all other FluCoMa objects, the EBU specifies other values as per the examples below. How much the buffered window moves forward, in samples. By default 512 to be similar with all other FluCoMa objects, the EBU specifies other values as per the examples below.
ARGUMENT:: padding
Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centering the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material.
ARGUMENT:: freeWhenDone ARGUMENT:: freeWhenDone
Free the server instance when processing complete. Default true Free the server instance when processing complete. Default true

@ -77,7 +77,16 @@ The link::Classes/FluidLabelSet:: from which to retrieve the point's IDs associa
ARGUMENT:: action ARGUMENT:: action
A function to run when the import is done. A function to run when the import is done.
METHOD:: getIds
Export to the dataset IDs to a link::Classes/FluidLabelSet::.
ARGUMENT:: labelSet
The link::Classes/FluidLabelSet:: to export to. Its content will be replaced.
ARGUMENT:: action
A function to run when the export is done.
METHOD:: merge METHOD:: merge
Merge sourceDataSet in the current DataSet. It will update the value of points with the same label if overwrite is set to 1. To add columns instead, see the 'transformJoin' method of link::Classes/FluidDataSetQuery:: Merge sourceDataSet in the current DataSet. It will update the value of points with the same label if overwrite is set to 1. To add columns instead, see the 'transformJoin' method of link::Classes/FluidDataSetQuery::
@ -136,7 +145,7 @@ fork{
var count = PulseCount.kr(trig) - 1; var count = PulseCount.kr(trig) - 1;
var buf = LocalBuf(1); var buf = LocalBuf(1);
BufWr.kr(count, buf); BufWr.kr(count, buf);
FluidDataSetWr.kr(~ds.asUGenInput, buf: buf, trig: trig); FluidDataSetWr.kr(~ds.asUGenInput, idNumber: count, buf: buf, trig: trig);
FreeSelf.kr(count - 8); FreeSelf.kr(count - 8);
}.play.onFree{~ds.dump{|o| o.postln;~ds.free}} }.play.onFree{~ds.dump{|o| o.postln;~ds.free}}
) )

@ -114,7 +114,7 @@ OSCFunc({
var buf = LocalBuf.newFrom([0,1,2,3]); var buf = LocalBuf.newFrom([0,1,2,3]);
var noise = 4.collect{WhiteNoise.kr()}; var noise = 4.collect{WhiteNoise.kr()};
var trig = Impulse.kr(2); var trig = Impulse.kr(2);
var count = PulseCount.kr(trig,); var count = PulseCount.kr(trig);
4.do{|i| 4.do{|i|
BufWr.kr(noise[i], buf, DC.kr(i)); BufWr.kr(noise[i], buf, DC.kr(i));
}; };

@ -25,18 +25,18 @@ INSTANCEMETHODS::
PRIVATE::k PRIVATE::k
METHOD:: fit METHOD:: fit
Identify code::k:: clusters in a link::Classes/FluidDataSet:: Identify code::numClusters:: clusters in a link::Classes/FluidDataSet::. It will optimise until no improvement is possible, or up to code::maxIter::, whichever comes first. Subsequent calls will continue training from the stopping point with the same conditions.
ARGUMENT:: dataSet ARGUMENT:: dataSet
A link::Classes/FluidDataSet:: of data points. A link::Classes/FluidDataSet:: of data points.
ARGUMENT:: action ARGUMENT:: action
A function to run when fitting is complete, taking as its argument an array with the number of data points for each cluster. A function to run when fitting is complete, taking as its argument an array with the number of data points for each cluster.
METHOD:: predict METHOD:: predict
Given a trained object, return the cluster ID for each data point in a DataSet to a label set. Given a trained object, return the cluster ID for each data point in a link::Classes/FluidDataSet:: to a link::Classes/FluidLabelSet::.
ARGUMENT:: dataSet ARGUMENT:: dataSet
a link::Classes/FluidDataSet:: containing the data to predict. A link::Classes/FluidDataSet:: containing the data to predict.
ARGUMENT:: labelSet ARGUMENT:: labelSet
a link::Classes/FluidLabelSet:: to retrieve the predicted clusters. A link::Classes/FluidLabelSet:: to retrieve the predicted clusters.
ARGUMENT:: action ARGUMENT:: action
A function to run when the server responds. A function to run when the server responds.
@ -52,59 +52,55 @@ A function to run when the server responds
METHOD:: predictPoint METHOD:: predictPoint
Given a trained object, return the cluster ID for a data point in a link::Classes/Buffer:: Given a trained object, return the cluster ID for a data point in a link::Classes/Buffer::
ARGUMENT:: buffer ARGUMENT:: buffer
a link::Classes/Buffer:: containing a data point. A link::Classes/Buffer:: containing a data point.
ARGUMENT:: action ARGUMENT:: action
A function to run when the server responds, taking the ID of the cluster as its argument. A function to run when the server responds, taking the ID of the cluster as its argument.
METHOD:: predict METHOD:: transform
Report cluster assignments for previously unseen data. Given a trained object, return for each item of a provided link::Classes/FluidDataSet:: its distance to each cluster as an array, often reffered to as the cluster-distance space.
ARGUMENT:: dataSet ARGUMENT:: srcDataSet
A link::Classes/FluidDataSet:: of data points. A link::Classes/FluidDataSet:: of data points to transform.
ARGUMENT:: labelSet ARGUMENT:: dstDataSet
A link::Classes/FluidLabelSet:: to contain assignments. A link::Classes/FluidDataSet:: to contain the new cluster-distance space.
ARGUMENT:: action ARGUMENT:: action
A function to run when complete, taking an array of the counts for each category as its argument. A function to run when complete.
METHOD:: fitTransform METHOD:: fitTransform
Run link::Classes/FluidKMeans#*fit:: and link::Classes/FluidKMeans#*predict:: in a single pass: i.e. train the model on the incoming link::Classes/FluidDataSet:: and then return the learned clustering to the passed link::Classes/FluidLabelSet:: Run link::Classes/FluidKMeans#*fit:: and link::Classes/FluidKMeans#*transform:: in a single pass: i.e. train the model on the incoming link::Classes/FluidDataSet:: and then return its cluster-distance space in the destination link::Classes/FluidDataSet::
ARGUMENT:: srcDataSet ARGUMENT:: srcDataSet
a link::Classes/FluidDataSet:: containing the data to fit and predict. A link::Classes/FluidDataSet:: containing the data to fit and transform.
ARGUMENT:: dstDataSet ARGUMENT:: dstDataSet
a link::Classes/FluidLabelSet:: to retrieve the predicted clusters. A link::Classes/FluidDataSet:: to contain the new cluster-distance space.
ARGUMENT:: action ARGUMENT:: action
A function to run when the server responds A function to run when complete.
METHOD:: transformPoint METHOD:: transformPoint
Given a trained object, return the cluster ID for a data point in a link::Classes/Buffer:: Given a trained object, return the distance of the provided point to each cluster. Both points are handled as link::Classes/Buffer::
ARGUMENT:: sourceBuffer ARGUMENT:: sourceBuffer
a link::Classes/Buffer:: containing a data point. A link::Classes/Buffer:: containing a data point to query.
ARGUMENT:: targetBuffer ARGUMENT:: targetBuffer
a link::Classes/Buffer:: containing a data point. A link::Classes/Buffer:: containing a the distance of the source point to each cluster.
ARGUMENT:: action
A function to run when the server responds, taking the ID of the cluster as its argument.
METHOD:: transform
Report cluster assignments for previously unseen data.
ARGUMENT:: srcDataSet
A link::Classes/FluidDataSet:: of data points.
ARGUMENT:: dstDataSet
A link::Classes/FluidLabelSet:: to contain assignments.
ARGUMENT:: action ARGUMENT:: action
A function to run when complete, taking an array of the counts for each category as its argument. A function to run when complete.
METHOD:: getMeans METHOD:: getMeans
Report cluster assignments for previously unseen data. Given a trained object, retrieve the means (centroids) of each cluster as a link::Classes/FluidDataSet::
ARGUMENT:: dataSet ARGUMENT:: dataSet
A link::Classes/FluidDataSet:: of data points. A link::Classes/FluidDataSet:: of clusers with a mean per column.
ARGUMENT:: action ARGUMENT:: action
A function to run when complete, taking an array of the counts for each category as its argument. A function to run when complete.
METHOD:: setMeans METHOD:: setMeans
Report cluster assignments for previously unseen data. Overwrites the means (centroids) of each cluster, and declare the object trained.
ARGUMENT:: dataSet ARGUMENT:: dataSet
A link::Classes/FluidDataSet:: of data points. A link::Classes/FluidDataSet:: of clusers with a mean per column.
ARGUMENT:: action
A function to run when complete.
METHOD:: clear
Reset the object status to not fitted and untrained.
ARGUMENT:: action ARGUMENT:: action
A function to run when complete, taking an array of the counts for each category as its argument. A function to run when complete.
EXAMPLES:: EXAMPLES::
code:: code::
@ -192,30 +188,40 @@ subsection:: Accessing the means
We can get and set the means for each cluster, their centroid. We can get and set the means for each cluster, their centroid.
code:: code::
// with the dataset and kmeans generated and trained in the code above
~centroids = FluidDataSet(s); ~centroids = FluidDataSet(s);
~kmeans.getMeans(~centroids, {~centroids.print}); ~kmeans.getMeans(~centroids, {~centroids.print});
// We can also set them to arbitrary values to seed the process
~centroids.load(Dictionary.newFrom([\cols, 2, \data, Dictionary.newFrom([\0, [0.5,0.5], \1, [-0.5,0.5], \2, [0.5,-0.5], \3, [-0.5,-0.5]])])); ~centroids.load(Dictionary.newFrom([\cols, 2, \data, Dictionary.newFrom([\0, [0.5,0.5], \1, [-0.5,0.5], \2, [0.5,-0.5], \3, [-0.5,-0.5]])]));
~centroids.print ~centroids.print
~kmeans.setMeans(~centroids, {~kmeans.predict(~dataSet,~clusters,{~clusters.dump{|x|var count = 0.dup(4); x["data"].keysValuesDo{|k,v|count[v[0].asInteger] = count[v[0].asInteger] + 1;};count.postln}})}); ~kmeans.setMeans(~centroids, {~kmeans.predict(~dataSet,~clusters,{~clusters.dump{|x|var count = 0.dup(4); x["data"].keysValuesDo{|k,v|count[v[0].asInteger] = count[v[0].asInteger] + 1;};count.postln}})});
~kmeans.clear // We can further fit from the seeded means
~kmeans.predict(~dataSet,~clusters) ~kmeans.fit(~dataSet)
// then retreive the improved means
~kmeans.getMeans(~centroids, {~centroids.print});
//subtle in this case but still.. each quadrant is where we seeded it.
:: ::
subsection:: Cluster-distance Space subsection:: Cluster-distance Space
You can get the euclidian distance of a given point to each cluster. We can get the euclidian distance of a given point to each cluster. This is often referred to as the cluster-distance space as it creates new dimensions for each given point, one distance per cluster.
code:: code::
// with the dataset and kmeans generated and trained in the code above
b = Buffer.sendCollection(s,[0.5,0.5]) b = Buffer.sendCollection(s,[0.5,0.5])
c = Buffer(s) c = Buffer(s)
// get the distance of our given point (b) to each cluster, thus giving us 4 dimensions in our cluster-distance space
~kmeans.transformPoint(b,c,{|x|x.query;x.getn(0,x.numFrames,{|y|y.postln})}) ~kmeans.transformPoint(b,c,{|x|x.query;x.getn(0,x.numFrames,{|y|y.postln})})
// we can also transform a full dataset
~srcDS = FluidDataSet(s)
~cdspace = FluidDataSet(s)
// make a new dataset with 4 points
~srcDS.load(Dictionary.newFrom([\cols, 2, \data, Dictionary.newFrom([\pp, [0.5,0.5], \np, [-0.5,0.5], \pn, [0.5,-0.5], \nn, [-0.5,-0.5]])]));
~kmeans.transform(~srcDS, ~cdspace, {~cdspace.print})
:: ::
subsection:: Queries in a Synth subsection:: Queries in a Synth

@ -89,14 +89,14 @@ FluidBufMFCC.process(s,~audio, features: ~mfcc_feature);
var chunkLen = (~mfcc_feature.numFrames / 100).asInteger; var chunkLen = (~mfcc_feature.numFrames / 100).asInteger;
var stats = FluidBufStats.kr( var stats = FluidBufStats.kr(
source: ~mfcc_feature, startFrame: count * chunkLen, source: ~mfcc_feature, startFrame: count * chunkLen,
startChan:1, numFrames: chunkLen, stats: ~stats, trig: trig,blocking:1 startChan:1, numFrames: chunkLen, stats: ~stats, trig: trig, blocking:1
); );
var rd = BufRd.kr(12, ~stats, DC.kr(0), 0, 1); var rd = BufRd.kr(12, ~stats, DC.kr(0), 0, 1);
var bufWr, dsWr; var bufWr, dsWr;
12.do{|i| 12.do{|i|
bufWr = BufWr.kr(rd[i], buf, DC.kr(i)); bufWr = BufWr.kr(rd[i], buf, DC.kr(i));
}; };
dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats),blocking:1); dsWr = FluidDataSetWr.kr(~raw, buf: buf, idNumber: count, trig: Done.kr(stats),blocking:1);
LocalOut.kr(Done.kr(dsWr)); LocalOut.kr(Done.kr(dsWr));
FreeSelf.kr(count - 99); FreeSelf.kr(count - 99);
Poll.kr(trig,(100-count)); Poll.kr(trig,(100-count));

@ -97,7 +97,7 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature);
var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence
var wr1 = BufWr.kr(rd[0], buf, DC.kr(0)); var wr1 = BufWr.kr(rd[0], buf, DC.kr(0));
var wr2 = BufWr.kr(rd[1], buf, DC.kr(1)); var wr2 = BufWr.kr(rd[1], buf, DC.kr(1));
var dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); var dsWr = FluidDataSetWr.kr(~raw, buf: buf, idNumber: count, trig: Done.kr(stats));
LocalOut.kr( Done.kr(dsWr)); LocalOut.kr( Done.kr(dsWr));
Poll.kr(trig,count,\count); Poll.kr(trig,count,\count);
FreeSelf.kr(count - 9); FreeSelf.kr(count - 9);

@ -59,7 +59,7 @@ Run when done. The function is passed code::destBuffer:: as argument.
EXAMPLES:: EXAMPLES::
code:: code::
s.boot; s.reboot;
//Preliminaries: we want some audio, a couple of FluidDataSets, some Buffers, a FluidStandardize and a FluidPCA //Preliminaries: we want some audio, a couple of FluidDataSets, some Buffers, a FluidStandardize and a FluidPCA
( (
~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"; ~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav";
@ -99,7 +99,7 @@ FluidBufMFCC.process(s,~audio, features: ~mfcc_feature,action:{"Done MFCCs".post
12.do{|i| 12.do{|i|
bufWr = BufWr.kr(rd[i], buf, DC.kr(i)); bufWr = BufWr.kr(rd[i], buf, DC.kr(i));
}; };
dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); dsWr = FluidDataSetWr.kr(~raw, buf: buf, idNumber: count, trig: Done.kr(stats));
LocalOut.kr( Done.kr(dsWr)); LocalOut.kr( Done.kr(dsWr));
FreeSelf.kr(count - 99); FreeSelf.kr(count - 99);
Poll.kr(trig,(100 - count)); Poll.kr(trig,(100 - count));

@ -52,7 +52,7 @@ code::
statsbuf = LocalBuf(7); statsbuf = LocalBuf(7);
pitch = FluidBufPitch.kr(src,start,num,numChans:1,features:~featurebuffers[voice]); pitch = FluidBufPitch.kr(src,start,num,numChans:1,features:~featurebuffers[voice]);
stats = FluidBufStats.kr(~featurebuffers[voice],numChans:1, stats:statsbuf,trig:Done.kr(pitch)); stats = FluidBufStats.kr(~featurebuffers[voice],numChans:1, stats:statsbuf,trig:Done.kr(pitch));
FluidDataSetWr.kr(label,statsbuf,~mydataset,Done.kr(stats)) FluidDataSetWr.kr(~mydataset, label, nil, statsbuf,Done.kr(stats))
}; };
:: ::
@ -112,7 +112,7 @@ s.reboot;
label = data.key; label = data.key;
pitch = FluidBufPitch.kr(src,start,num,features:~pitchbufs[i]); pitch = FluidBufPitch.kr(src,start,num,features:~pitchbufs[i]);
stats = FluidBufStats.kr(~pitchbufs[i],stats:~statsbufs[i],trig:Done.kr(pitch)); stats = FluidBufStats.kr(~pitchbufs[i],stats:~statsbufs[i],trig:Done.kr(pitch));
FluidDataSetWr.kr(~pitchdata,label,-1,buf:~statsbufs[i],trig:Done.kr(stats)) FluidDataSetWr.kr(~pitchdata,label,nil,buf:~statsbufs[i],trig:Done.kr(stats))
}); });
) )

@ -96,7 +96,7 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature);
var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence
var wr1 = BufWr.kr(rd[0], buf, DC.kr(0)); var wr1 = BufWr.kr(rd[0], buf, DC.kr(0));
var wr2 = BufWr.kr(rd[1], buf, DC.kr(1)); var wr2 = BufWr.kr(rd[1], buf, DC.kr(1));
var dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); var dsWr = FluidDataSetWr.kr(~raw, buf: buf, idNumber: count, trig: Done.kr(stats));
LocalOut.kr( Done.kr(dsWr)); LocalOut.kr( Done.kr(dsWr));
Poll.kr(trig,count,\count); Poll.kr(trig,count,\count);
FreeSelf.kr(count - 9); FreeSelf.kr(count - 9);

@ -90,7 +90,7 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature,action:{"Analysed Pitch
var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence
var wr1 = BufWr.kr(rd[0], buf, DC.kr(0)); var wr1 = BufWr.kr(rd[0], buf, DC.kr(0));
var wr2 = BufWr.kr(rd[1], buf, DC.kr(1)); var wr2 = BufWr.kr(rd[1], buf, DC.kr(1));
var dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); var dsWr = FluidDataSetWr.kr(~raw, buf: buf, idNumber: count, trig: Done.kr(stats));
LocalOut.kr( Done.kr(dsWr)); LocalOut.kr( Done.kr(dsWr));
FreeSelf.kr(count - 9); FreeSelf.kr(count - 9);
Poll.kr(trig,count, \count); Poll.kr(trig,count, \count);

Loading…
Cancel
Save