diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index f480e4b..711b5fa 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -1213,6 +1213,12 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase using IndexList = typename Client::MessageSetType::template MessageDescriptorAt< N>::IndexList; + if(!x->init) + { + std::cout << "ERROR: Synth constructor not yet called" << std::endl; + return; + } + launchMessageImpl(x, args, IndexList()); } @@ -1421,6 +1427,7 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase << std::endl; } + bool init{false}; public: using Client = C; @@ -1432,6 +1439,7 @@ public: { client().setParams(params()); //<-IMPORTANT: client's ref to params is by address, and this has just changed impl::FluidSCWrapperBase::init(); + init = true; } ~FluidSCWrapper() diff --git a/include/clients/rt/FluidDataSetWr.hpp b/include/clients/rt/FluidDataSetWr.hpp index 7058289..1fbb006 100644 --- a/include/clients/rt/FluidDataSetWr.hpp +++ b/include/clients/rt/FluidDataSetWr.hpp @@ -39,7 +39,11 @@ public: if (auto datasetPtr = dataset.lock()) { std::stringstream ss; - ss << get<1>() << get<2>() + (mCounter++); + ss << get<1>(); + + index labelOffset = get<2>(); + if(labelOffset >= 0) ss << labelOffset + (mCounter++); + auto buf = get<3>(); return datasetPtr->addPoint(ss.str(), buf); } diff --git a/release-packaging/Classes/FluidBufAudioTransport.sc b/release-packaging/Classes/FluidBufAudioTransport.sc index 52069e6..8085c6f 100644 --- a/release-packaging/Classes/FluidBufAudioTransport.sc +++ b/release-packaging/Classes/FluidBufAudioTransport.sc @@ -1,59 +1,40 @@ FluidBufAudioTransport : UGen{ - - var <>synth, <>server; - - *kr { |source1, startFrame1 = 0, numFrames1 = -1, startChan1 = 0, numChans1 = -1, source2, startFrame2 = 0, numFrames2 = -1, startChan2 = 0, numChans2 = -1, destination, interpolation=0.0, bandwidth=255, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1| + *new1 { |rate, source1, startFrame1 = 0, numFrames1 = -1, startChan1 = 0, numChans1 = -1, source2, startFrame2 = 0, numFrames2 = -1, startChan2 = 0, numChans2 = -1, destination, interpolation=0.0, bandwidth=255, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking=0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; - var blocking = 0; - source1.isNil.if {"FluidAudioTransport: Invalid source 1 buffer".throw}; - source2.isNil.if {"FluidAudioTransport: Invalid source 2 buffer".throw}; + source2.isNil.if {"FluidAudioTransport: Invalid source 2 buffer".throw}; source1 = source1.asUGenInput; - source2 = source2.asUGenInput; + source2 = source2.asUGenInput; + + destination.isNil.if {"FluidAudioTransport: Invalid destination buffer".throw}; + destination = destination.asUGenInput; - destination.isNil.if {"FluidAudioTransport: Invalid destination buffer".throw}; - destination = destination.asUGenInput; //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) + ^super.new1(rate,source1, startFrame1, numFrames1, startChan1, numChans1, source2, startFrame1, numFrames1, startChan2, numChans2, destination, interpolation, bandwidth, windowSize, hopSize, fftSize, maxFFTSize, trig,blocking) - ^this.multiNew(\control, source1, startFrame1, numFrames1, startChan1, numChans1, source2, startFrame1, numFrames1, startChan2, numChans2, destination, interpolation, bandwidth, windowSize, hopSize, fftSize,maxFFTSize, trig,blocking); } - - *process { |server, source1, startFrame1 = 0, numFrames1 = -1, startChan1 = 0, numChans1 = -1, source2, startFrame2 = 0, numFrames2 = -1, startChan2 = 0, numChans2 = -1, destination, interpolation=0.0, bandwidth=255, windowSize = 1024, hopSize = -1, fftSize = -1, action| - var synth, instance; - - - source1.isNil.if {"FluidAudioTransport: Invalid source 1 buffer".throw}; - source2.isNil.if {"FluidAudioTransport: Invalid source 2 buffer".throw}; - - destination.isNil.if {"FluidAudioTransport: Invalid destination buffer".throw}; + *kr { |source1, startFrame1 = 0, numFrames1 = -1, startChan1 = 0, numChans1 = -1, source2, startFrame2 = 0, numFrames2 = -1, startChan2 = 0, numChans2 = -1, destination, interpolation=0.0, bandwidth=255, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1| + ^this.new1(\control, source1, startFrame1, numFrames1, startChan1, numChans1, source2, startFrame1, numFrames1, startChan2, numChans2, destination, interpolation, bandwidth, windowSize, hopSize, fftSize, trig); + } - source1 = source1.asUGenInput; - source2 = source2.asUGenInput; - destination = destination.asUGenInput; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = { instance = FluidBufAudioTransport.kr(source1, startFrame1, numFrames1, startChan1, numChans1, source2, startFrame1, numFrames1, startChan2, numChans2, destination, interpolation, bandwidth, windowSize, hopSize, fftSize, trig:1)}.play(server); - forkIfNeeded{ - synth.waitForFree; - server.sync; - if (destination != -1) {destination = server.cachedBufferAt(destination); destination.updateInfo; server.sync;} {destination = nil}; - action.value(destination); - }; - instance.synth = synth; - instance.server = server; - ^instance; + *process { |server, source1, startFrame1 = 0, numFrames1 = -1, startChan1 = 0, numChans1 = -1, source2, startFrame2 = 0, numFrames2 = -1, startChan2 = 0, numChans2 = -1, destination, interpolation=0.0, bandwidth=255, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [destination] + ).process( + source1, startFrame1, numFrames1, startChan1, numChans1, source2, startFrame2, numFrames2, startChan2, numChans2, destination, interpolation, bandwidth, windowSize, hopSize, fftSize + ) } - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } + *processBlocking { |server, source1, startFrame1 = 0, numFrames1 = -1, startChan1 = 0, numChans1 = -1, source2, startFrame2 = 0, numFrames2 = -1, startChan2 = 0, numChans2 = -1, destination, interpolation=0.0, bandwidth=255, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [destination],blocking:1 + ).process( + source1, startFrame1, numFrames1, startChan1, numChans1, source2, startFrame2, numFrames2, startChan2, numChans2, destination, interpolation, bandwidth, windowSize, hopSize, fftSize + ) + } } + diff --git a/release-packaging/Classes/FluidCorpusBuilders.sc b/release-packaging/Classes/FluidCorpusBuilders.sc index 0c6bf3b..af7d58f 100644 --- a/release-packaging/Classes/FluidCorpusBuilders.sc +++ b/release-packaging/Classes/FluidCorpusBuilders.sc @@ -83,14 +83,13 @@ FluidSliceCorpus { var rawPoints = Array.newFrom(a).asInteger; if(rawPoints[0] != [v[\bounds][0]]){rawPoints = [v[\bounds][0]] ++ rawPoints}; if(rawPoints.last != [v[\bounds][1]]){rawPoints=rawPoints ++ [v[\bounds][1]]}; + rawPoints.doAdjacentPairs{|a,b| var dict; if ((b - a) >= 1){ dict = IdentityDictionary(); dict.putAll(v); dict[\bounds] = [a,b]; - dict[\prefix] = k; - dict[\index] = sliceindex; index.add(((k ++ "-" ++sliceindex).asSymbol)->dict); sliceindex = sliceindex + 1; } @@ -141,7 +140,7 @@ FluidProcessSlices{ counter = counter + 1; ("Processing" + counter ++ "/" ++ total).postln; idx = counter; - v[\allindex] = counter; + v[\index] = counter; v[\voice] = jobID; OSCFunc({ completed = completed + 1; diff --git a/release-packaging/Examples/dataset/demo-dataset-maker-utilities.scd b/release-packaging/Examples/dataset/demo-dataset-maker-utilities.scd index 16827b0..4d0e313 100644 --- a/release-packaging/Examples/dataset/demo-dataset-maker-utilities.scd +++ b/release-packaging/Examples/dataset/demo-dataset-maker-utilities.scd @@ -23,7 +23,7 @@ mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:1); stats = FluidBufStats.kr(~mfccbuf[voice],stats:~statsbuf[voice],trig:Done.kr(mfcc)); flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats)); - writer = FluidDataSetWr.kr(~ds,label,buf: ~flatbuf[voice],trig:Done.kr(flatten)) + writer = FluidDataSetWr.kr(~ds,label, -1, ~flatbuf[voice], Done.kr(flatten)) }); ) diff --git a/release-packaging/HelpSource/Classes/FluidAmpGate.schelp b/release-packaging/HelpSource/Classes/FluidAmpGate.schelp index 880a960..8fdee5f 100644 --- a/release-packaging/HelpSource/Classes/FluidAmpGate.schelp +++ b/release-packaging/HelpSource/Classes/FluidAmpGate.schelp @@ -19,16 +19,16 @@ ARGUMENT:: in The audio to be processed. ARGUMENT:: rampUp - The number of samples the absolute envelope follower will take to reach the next value when raising. + The number of samples the envelope follower will take to reach the next value when raising. ARGUMENT:: rampDown - The number of samples the absolute envelope follower will take to reach the next value when falling. + The number of samples the envelope follower will take to reach the next value when falling. ARGUMENT:: onThreshold - The threshold in dB of the absolute envelope follower to trigger an onset, aka to go ON when in OFF state. + The threshold in dB of the envelope follower to trigger an onset, aka to go ON when in OFF state. ARGUMENT:: offThreshold - The threshold in dB of the absolute envelope follower to trigger an offset, , aka to go ON when in OFF state. + The threshold in dB of the envelope follower to trigger an offset, , aka to go ON when in OFF state. ARGUMENT:: minSliceLength The length in samples that the Slice will stay ON. Changes of states during that period will be ignored. @@ -37,10 +37,10 @@ ARGUMENT:: minSilenceLength The length in samples that the Slice will stay OFF. Changes of states during that period will be ignored. ARGUMENT:: minLengthAbove - The length in samples that the absolute envelope have to be above the threshold to consider it a valid transition to ON. The Slice will start at the first sample when the condition is met. Therefore, this affects the latency. + The length in samples that the envelope have to be above the threshold to consider it a valid transition to ON. The Slice will start at the first sample when the condition is met. Therefore, this affects the latency. ARGUMENT:: minLengthBelow - The length in samples that the absolute envelope have to be below the threshold to consider it a valid transition to OFF. The Slice will end at the first sample when the condition is met. Therefore, this affects the latency. + The length in samples that the envelope have to be below the threshold to consider it a valid transition to OFF. The Slice will end at the first sample when the condition is met. Therefore, this affects the latency. ARGUMENT:: lookBack The length of the buffer kept before an onset to allow the algorithm, once a new Slice is detected, to go back in time (up to that many samples) to find the minimum amplitude as the Slice onset point. This affects the latency of the algorithm. @@ -49,7 +49,7 @@ ARGUMENT:: lookAhead The length of the buffer kept after an offset to allow the algorithm, once the Slice is considered finished, to wait further in time (up to that many samples) to find a minimum amplitude as the Slice offset point. This affects the latency of the algorithm. ARGUMENT:: highPassFreq - The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. + The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. A frequency of 0 bypasses the filter. ARGUMENT:: maxSize How large can the buffer be for time-critical conditions, by allocating memory at instantiation time. This cannot be modulated. @@ -129,7 +129,7 @@ b = Buffer.read(s,File.realpath(FluidAmpGate.class.filenameSymbol).dirname.withT //have fun with a gate (explore lookahead and lookback, but correct for latency, which will be the greatest of the lookahead and lookback) ( {var env, source = PlayBuf.ar(1,b); - env = FluidAmpGate.ar(source, rampUp:441, rampDown:2205, onThreshold:-27, offThreshold: -31, minSilenceLength:1100, lookBack:441, highPassFreq:20); + env = FluidAmpGate.ar(source, rampUp:441, rampDown:2205, onThreshold:-27, offThreshold: -31, minSilenceLength:4410, lookBack:441, highPassFreq:20); [DelayN.ar(source,delaytime:441/44100), env] }.plot(2, separately:true); ) diff --git a/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp index 72d87e8..347ddf2 100644 --- a/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp @@ -43,7 +43,7 @@ ARGUMENT:: minSliceLength The length in samples that the Slice will stay ON. Changes of states during that period will be ignored. ARGUMENT:: highPassFreq - The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. + The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. A frequency of 0 bypasses the filter. RETURNS:: An audio stream with square envelopes around the slices. The latency between the input and the output is dependant on the relation between the two envelope followers. diff --git a/release-packaging/HelpSource/Classes/FluidAudioTransport.schelp b/release-packaging/HelpSource/Classes/FluidAudioTransport.schelp index d973cd8..b8099e6 100644 --- a/release-packaging/HelpSource/Classes/FluidAudioTransport.schelp +++ b/release-packaging/HelpSource/Classes/FluidAudioTransport.schelp @@ -44,5 +44,5 @@ EXAMPLES:: code:: //the mouse X axis interpolates between the two sinewaves -{FluidAudioTransport.ar(SinOsc.ar(220),SinOsc.ar(440),MouseX.kr())}.play; +{FluidAudioTransport.ar(SinOsc.ar(220,mul: 0.1),SinOsc.ar(440,mul: 0.02),MouseX.kr())}.play; :: diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp index 438208a..70a137f 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp @@ -41,16 +41,16 @@ ARGUMENT:: indices The index of the buffer where the indices (in sample) of the estimated starting points of slices will be written. The first and last points are always the boundary points of the analysis. ARGUMENT:: rampUp - The number of samples the absolute envelope follower will take to reach the next value when raising. + The number of samples the envelope follower will take to reach the next value when raising. ARGUMENT:: rampDown - The number of samples the absolute envelope follower will take to reach the next value when falling. + The number of samples the envelope follower will take to reach the next value when falling. ARGUMENT:: onThreshold - The threshold in dB of the absolute envelope follower to trigger an onset, aka to go ON when in OFF state. + The threshold in dB of the envelope follower to trigger an onset, aka to go ON when in OFF state. ARGUMENT:: offThreshold - The threshold in dB of the absolute envelope follower to trigger an offset, , aka to go ON when in OFF state. + The threshold in dB of the envelope follower to trigger an offset, , aka to go ON when in OFF state. ARGUMENT:: minSliceLength The length in samples that the Slice will stay ON. Changes of states during that period will be ignored. @@ -59,10 +59,10 @@ ARGUMENT:: minSilenceLength The length in samples that the Slice will stay OFF. Changes of states during that period will be ignored. ARGUMENT:: minLengthAbove - The length in samples that the absolute envelope have to be above the threshold to consider it a valid transition to ON. The Slice will start at the first sample when the condition is met. Therefore, this affects the latency. + The length in samples that the envelope have to be above the threshold to consider it a valid transition to ON. The Slice will start at the first sample when the condition is met. Therefore, this affects the latency. ARGUMENT:: minLengthBelow - The length in samples that the absolute envelope have to be below the threshold to consider it a valid transition to OFF. The Slice will end at the first sample when the condition is met. Therefore, this affects the latency. + The length in samples that the envelope have to be below the threshold to consider it a valid transition to OFF. The Slice will end at the first sample when the condition is met. Therefore, this affects the latency. ARGUMENT:: lookBack The length of the buffer kept before an onset to allow the algorithm, once a new Slice is detected, to go back in time (up to that many samples) to find the minimum amplitude as the Slice onset point. This affects the latency of the algorithm. @@ -71,7 +71,7 @@ ARGUMENT:: lookAhead The length of the buffer kept after an offset to allow the algorithm, once the Slice is considered finished, to wait further in time (up to that many samples) to find a minimum amplitude as the Slice offset point. This affects the latency of the algorithm. ARGUMENT:: highPassFreq - The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. + The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. A frequency of 0 bypasses the filter. ARGUMENT:: action A Function to be evaluated once the offline process has finished and indices instance variables have been updated on the client side. The metric will be passed indices as an argument. diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp index 1cdf44b..f5739cc 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp @@ -65,7 +65,7 @@ ARGUMENT:: minSliceLength The length in samples that the Slice will stay ON. Changes of states during that period will be ignored. ARGUMENT:: highPassFreq - The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. + The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. A frequency of 0 bypasses the filter. ARGUMENT:: action A Function to be evaluated once the offline process has finished and indices instance variables have been updated on the client side. The metric will be passed indices as an argument. @@ -86,7 +86,7 @@ c = Buffer.new(s); b.play b.plot -// +//process with symmetrical thresholds FluidBufAmpSlice.process(s, b,indices: c,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 10,floor: -60); c.query c.getn(0,c.numFrames,{|item|item.postln;}) diff --git a/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp b/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp index eea567a..6177727 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp @@ -81,7 +81,7 @@ code:: //Make 2 sources to be interpolated ( b = Buffer.loadCollection(s, FloatArray.fill(44100, {|a|(a / pi).sin * 0.1})); -c = Buffer.loadCollection(s, FloatArray.fill(44100, {|a|(a / pi / 2).sin * 0.1})); +c = Buffer.loadCollection(s, FloatArray.fill(44100, {|a|(a / pi / 2).sin * 0.02})); d = Buffer.new ) diff --git a/release-packaging/HelpSource/Classes/FluidBufPitch.schelp b/release-packaging/HelpSource/Classes/FluidBufPitch.schelp index f202e83..4caac6a 100644 --- a/release-packaging/HelpSource/Classes/FluidBufPitch.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufPitch.schelp @@ -156,7 +156,7 @@ d.postln e = Array.new; d.do({ arg val, i; - if ((val[0] > 500) && (val[1] > 0.666)) {e = e.add(i)}; // if pitch is greater than 500Hz and confidence higher than 0.666, keep the index + if ((val[0] > 500) && (val[1] > 0.98)) {e = e.add(i)}; // if pitch is greater than 500Hz and confidence higher than 0.98, keep the index }); ) e.postln; diff --git a/release-packaging/HelpSource/Classes/FluidBufStats.schelp b/release-packaging/HelpSource/Classes/FluidBufStats.schelp index 6b9cf4c..02ab8c8 100644 --- a/release-packaging/HelpSource/Classes/FluidBufStats.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufStats.schelp @@ -175,5 +175,5 @@ FluidBufStats.process(s, b, stats:c, numDerivs:1, action:{c.getn(0,c.numFrames * //looking at the result is not easy to grasp, since it is interleaved: first number is mean of L, second is mean of R, third is stddev of L, fourth is stddev or R //this will make it tidier - the first value of each line is Left, the second is Right -d.reshape(14,2).do({|x,i|["mean\t\t","stddev\t\t","skew\t\t\t", "kurtosis\t", "min\t\t\t", "median\t\t", "max\t\t\t","d-mean\t","d-stddev\t","d-skew\t\t", "d-kurtosis", "d-min\t\t", "d-median\t", "d-max\t\t"].at(i).post;x.round(0.01).postln}) +d.reshape(14,2).do({|x,i|["mean\t\t","stddev\t\t","skew\t\t\t", "kurtosis\t", "min\t\t\t", "median\t\t", "max\t\t\t","d-mean\t","d-stddev\t","d-skew\t\t", "d-kurtosis", "d-min\t\t", "d-median\t", "d-max\t\t"].at(i).post;x.round(0.01).postln});"".postln; :: diff --git a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp index 99427b3..ea798a9 100644 --- a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp @@ -60,8 +60,8 @@ FluidBufThreadDemo.process(s, b, 1000, {|x|x.get(0,{|y|y.postln});}); // as the 'process' returns its parent UGen, we can cancel the process easily c = FluidBufThreadDemo.process(s, b, 100000, {|x|x.get(0,{|y|y.postln});}); -c.cancel +c.cancel //it stops silently for now but check the synth count going down by 1. -// if a simple call to the UGen is used, the progress can be monitored +// if a simple call to the UGen is used, the progress can be monitored. The usual cmd. will cancel the job by freeing the synth. {c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf); Poll.kr(Impulse.kr(2),c);}.scope; :: diff --git a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp index e39eb1d..3605a23 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp @@ -4,7 +4,17 @@ categories:: FluidManipulation related:: Classes/FLuidDataSet DESCRIPTION:: -A UGen that writes to a link::Classes/FluidDataSet:: +A UGen that adds labelled points to a link::Classes/FluidDataSet:: + +By default the object generates a numerical index that gets used for the point labels. This index starts counting from link::#offset#labelOffset:: and increments each time the Ugen is retriggered with a zero to non-zero transition. The label is then concatenated with the code::labelPrefix:: symbol, which is fixed at instantiation. In this way, one can make custom, incrementing labels, e.g. + +code:: +FluidDataSetWr.kr(~somedataset,"my_data",0,~somebuffer,trig) +:: + +would add points like code::my_data0, mydata1, mydata2...:: if successively retriggered. + +Alternatively, for one shot use you may not want a numerical suffix at all. Setting code::indexLabel:: < 0 will bypass this and use only the labelPrefix. As such, any retriggering will result in a complaint from the link::Classes/FluidDataSet:: that the requested label is already present. CLASSMETHODS:: @@ -20,12 +30,14 @@ ARGUMENT:: labelPrefix A string or symbol with a prefix for generated labels ARGUMENT:: labelOffset -An integer with the offset to start labeling from. If the UGen is run in a server-side loop (i.e. repeatedly retriggered), the generated labels will count upwards from this offset. +ANCHOR::offset:: +An integer with the offset to start labeling from. If the UGen is run in a server-side loop (i.e. repeatedly retriggered), the generated labels will count upwards from this offset. If < 0, then no numerical index will be applied to the generated label (i.e. only the labelPrefix is used). ARGUMENT:: buf The link::Classes/Buffer:: containing the data point. ARGUMENT:: trig + A kr trigger signal EXAMPLES:: diff --git a/release-packaging/HelpSource/Classes/FluidLoudness.schelp b/release-packaging/HelpSource/Classes/FluidLoudness.schelp index 9a6ffdc..769b236 100644 --- a/release-packaging/HelpSource/Classes/FluidLoudness.schelp +++ b/release-packaging/HelpSource/Classes/FluidLoudness.schelp @@ -32,7 +32,7 @@ ARGUMENT:: maxwindowSize How large can the windowSize be, by allocating memory at instantiation time. This cannot be modulated. RETURNS:: - A 2-channel KR signal with the [pitch, confidence] descriptors. The latency is windowSize. + A 2-channel KR signal with the [loudness, peak] descriptors. The latency is windowSize. EXAMPLES:: diff --git a/release-packaging/HelpSource/Classes/FluidMFCC.schelp b/release-packaging/HelpSource/Classes/FluidMFCC.schelp index 4fb62cf..b799bbb 100644 --- a/release-packaging/HelpSource/Classes/FluidMFCC.schelp +++ b/release-packaging/HelpSource/Classes/FluidMFCC.schelp @@ -61,7 +61,7 @@ a.reference_(Array.fill(13,{0.5})); //make a center line to show 0 //run the window updating routine. ( -~winRange = 500; +~winRange = 200; r = Routine { { @@ -89,7 +89,7 @@ x = {arg type = 0; // change the wave types, observe the amplitude invariance of the descriptors, apart from the leftmost coefficient x.set(\type, 1) -~winRange = 100; //adjust the range above and below 0 to zoom in or out on the MFCC +~winRange = 50; //adjust the range above and below 0 to zoom in or out on the MFCC x.set(\type, 2) x.set(\type, 0) // free this source @@ -106,6 +106,7 @@ x = {arg bands = 40, low = 20, high = 20000; source.dup; }.play; ) +~winRange = 10; //adjust the range above and below 0 to zoom in or out on the MFCC // observe the number of bands. The unused ones at the top are not updated x.set(\bands,20) diff --git a/release-packaging/HelpSource/Classes/FluidNMFFilter.schelp b/release-packaging/HelpSource/Classes/FluidNMFFilter.schelp index a5efa31..fbe8375 100644 --- a/release-packaging/HelpSource/Classes/FluidNMFFilter.schelp +++ b/release-packaging/HelpSource/Classes/FluidNMFFilter.schelp @@ -89,11 +89,11 @@ Routine { e.plot //listen how the filter isolates each component and places them in each channel separately. -{FluidNMFFilter.ar(SinOsc.ar(500),e,2)}.play +{FluidNMFFilter.ar(SinOsc.ar(500, mul: 0.1),e,2)}.play -{FluidNMFFilter.ar(SinOsc.ar(5000),e,2)}.play +{FluidNMFFilter.ar(SinOsc.ar(5000, mul: 0.1),e,2)}.play -{FluidNMFFilter.ar(SinOsc.ar([500,5000]).sum,e,2)}.play +{FluidNMFFilter.ar(SinOsc.ar([500,5000], mul: 0.1).sum,e,2)}.play :: STRONG::A guitar processor:: diff --git a/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp b/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp index d4202e2..9c44521 100644 --- a/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp +++ b/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp @@ -216,7 +216,7 @@ FluidBufSpectralShape.process(s, c, features: ~spectralshapes, action:{ }); ) -//7 shapes (track) x 8 components (tracks) x 7 stats(frames) +//the interleave format is 7 stats(frames) x 8 components in the source as tracks x 7 shapes (tracks) ~stats.query ~centroids.size() @@ -230,8 +230,8 @@ x = { var sound = PlayBuf.ar(1,b,loop:1); var harm, perc; # harm, perc = FluidHPSS.ar(sound, maskingMode:1, harmThreshFreq1: 0.005869, harmThreshAmp1: -9.6875, harmThreshFreq2: 0.006609, harmThreshAmp2: -4.375, hopSize:256); - Out.ar(~splitaudio, harm); - Out.kr(~nmfenvs, FluidNMFMatch.kr(sound, ~bases, maxComponents:8, hopSize:256, fftSize:2048)); + Out.ar(~splitaudio, (harm / 4) + perc); + Out.kr(~nmfenvs, FluidNMFMatch.kr(DelayN.ar(sound,delaytime: ((17-1)*256)/44100), ~bases, maxComponents:8, hopSize:256, fftSize:2048)); Out.ar(0,perc.dup) }.play; ) @@ -241,7 +241,7 @@ x = { 8.do({ arg i; { - var audio = BPF.ar(In.ar(~splitaudio,1), ~centroids[i],0.01,LagUD.kr(In.kr(~nmfenvs,8)[i],0.001,0.01,0.1)); + var audio = BPF.ar(In.ar(~splitaudio,1), ~centroids[i],0.0015,Lag.kr(In.kr(~nmfenvs,8)[i] * 2,0.022)); Out.ar(0,Pan2.ar(audio, (i / 14) - 0.25)); }.play(x,addAction: \addAfter); }); diff --git a/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp b/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp index 727a30a..4fcee45 100644 --- a/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp +++ b/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp @@ -107,13 +107,12 @@ s.reboot; //write pitch statistics into a dataset ( ~extractor = FluidProcessSlices({|src,start,num,data| - var pitch, stats, labelPrefix, labelIndex, i; + var pitch, stats, label,i; i = data.value[\voice]; - labelPrefix = data.value[\prefix]; - labelIndex = data.value[\index]; + label = data.key; pitch = FluidBufPitch.kr(src,start,num,features:~pitchbufs[i]); stats = FluidBufStats.kr(~pitchbufs[i],stats:~statsbufs[i],trig:Done.kr(pitch)); - FluidDataSetWr.kr(~pitchdata,labelPrefix,labelIndex,buf:~statsbufs[i],trig:Done.kr(stats)) + FluidDataSetWr.kr(~pitchdata,label,-1,buf:~statsbufs[i],trig:Done.kr(stats)) }); ) diff --git a/release-packaging/HelpSource/Classes/FluidSines.schelp b/release-packaging/HelpSource/Classes/FluidSines.schelp index f419a7c..c34d207 100644 --- a/release-packaging/HelpSource/Classes/FluidSines.schelp +++ b/release-packaging/HelpSource/Classes/FluidSines.schelp @@ -82,6 +82,12 @@ b = Buffer.read(s,File.realpath(FluidSines.class.filenameSymbol).dirname.withTra // as the algorithm resynthesize the sinusoidal peaks, we would expect to get it to work almost perfectly on a sine wave, with these settings that tell the process to tolerate everything as a sinusoid, even short and quiet peaks {FluidSines.ar(SinOsc.ar(mul: 0.1),detectionThreshold: -144,birthLowThreshold: -144,birthHighThreshold: -144,minTrackLen: 1,trackMagRange: 200,trackFreqRange: 1000,trackProb: 0)}.play; +// we can listen to the artefact in solo, amplifying it by 30dB, to hear the 'lobes' - not bad at all! +{FluidSines.ar(SinOsc.ar(mul: 0.1),detectionThreshold: -144,birthLowThreshold: -144,birthHighThreshold: -144,minTrackLen: 1,trackMagRange: 200,trackFreqRange: 1000,trackProb: 0)[1].dup * Line.ar(0,30,1).dbamp}.play; + // as this is a windowed process, the frequency of the peak is good for that full window, and therefore interesting artefacts appear when the pitch is changing. {FluidSines.ar(SinOsc.ar(LFTri.kr(0.1).exprange(220,880),mul: 0.1),detectionThreshold: -144,birthLowThreshold: -144,birthHighThreshold: -144,minTrackLen: 1,trackMagRange: 300,trackFreqRange: 1000,trackProb: 0)}.play; + +// if we solo and amplify the artefacts, they are much more apparent (and interesting) +{FluidSines.ar(SinOsc.ar(LFTri.kr(0.1).exprange(220,880),mul: 0.1),detectionThreshold: -144,birthLowThreshold: -144,birthHighThreshold: -144,minTrackLen: 1,trackMagRange: 300,trackFreqRange: 1000,trackProb: 0)[1].dup * Line.ar(0,30,1).dbamp}.play; ::