Enhance/choices param (#78)

* NRTWrapper: Add choices param (long <-> bitset)

* Update `FluidBufStats` with `select` control

* BufStats class: Fix bitfield for `select` and warn on duplicate items

* Update SpectralShape classes for new param
nix
Owen Green 4 years ago committed by GitHub
parent 4e5f0e4070
commit 11bb9015e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -77,6 +77,11 @@ struct ParamReader<impl::FloatControlsIter>
return args.next();
}
static auto fromArgs(Unit*, Controls& args, typename ChoicesT::type, int)
{
return typename ChoicesT::type(std::size_t(static_cast<index>(args.next())));
}
static SCBufferAdaptor* fetchBuffer(Unit* x, index bufnum)
{
if(bufnum >= x->mWorld->mNumSndBufs)
@ -280,6 +285,12 @@ struct ParamReader<sc_msg_iter>
return res;
}
static auto fromArgs(World*, sc_msg_iter& args, typename ChoicesT::type, int)
{
int x = args.geti();
return typename ChoicesT::type(asUnsigned(x));
}
template<typename T>
static auto fromArgs(World* w, sc_msg_iter& args, Optional<T>, int)
{

@ -4,9 +4,10 @@ FluidBufSpectralShape : FluidBufProcessor {
^\FluidBufSpecShp
}
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0|
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)};
source = source.asUGenInput;
features = features.asUGenInput;
@ -14,13 +15,15 @@ FluidBufSpectralShape : FluidBufProcessor {
source.isNil.if {"FluidBufSpectralShape: Invalid source buffer".throw};
features.isNil.if {"FluidBufSpectralShape: Invalid features buffer".throw};
^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking);
^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking);
}
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action|
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)};
source = source.asUGenInput;
features = features.asUGenInput;
@ -31,13 +34,14 @@ FluidBufSpectralShape : FluidBufProcessor {
^this.new(
server, nil, [features]
).processList(
[source, startFrame, numFrames, startChan, numChans, features, padding, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone, action
[source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone, action
);
}
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action|
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)};
source = source.asUGenInput;
features = features.asUGenInput;
@ -48,7 +52,7 @@ FluidBufSpectralShape : FluidBufProcessor {
^this.new(
server, nil, [features]
).processList(
[source, startFrame, numFrames, startChan, numChans, features, padding, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone, action
[source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone, action
);
}
}

@ -1,7 +1,28 @@
FluidBufStats : FluidBufProcessor {
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, outliersCutoff = -1, weights, trig = 1, blocking = 0|
const <stats=#[\mean,\std,\skewness,\kurtosis,\low,\mid,\high];
classvar statslookup;
*prWarnUnrecognised {|sym| ("WARNING: FluidBufStats -" + sym + "is not a recognised option").postln}
*prProcessSelect {|a|
var bits;
a.asBag.countsDo{|item,count,i|
if(count > 1) { ("Option '" ++ item ++ "' is repeated").warn};
};
bits = a.collect{ |sym|
(statslookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0})
}.reduce{|x,y| x | y};
^bits
}
*initClass {
statslookup = Dictionary.with(*this.stats.collect{|x,i| x->(1<<i)});
}
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, select, numDerivs = 0, low = 0, middle = 50, high = 100, outliersCutoff = -1, weights, trig = 1, blocking = 0|
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.stats)};
source = source.asUGenInput;
stats = stats.asUGenInput;
weights = weights.asUGenInput;
@ -9,12 +30,13 @@ FluidBufStats : FluidBufProcessor {
source.isNil.if {"FluidBufStats: Invalid source buffer".throw};
stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw};
weights = weights ? -1;
^FluidProxyUgen.kr(\FluidBufStatsTrigger, -1, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high, outliersCutoff, weights, trig, blocking);
^FluidProxyUgen.kr(\FluidBufStatsTrigger, -1, source, startFrame, numFrames, startChan, numChans, stats, selectbits, numDerivs, low, middle, high, outliersCutoff, weights, trig, blocking);
}
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, outliersCutoff = -1, weights, freeWhenDone = true, action|
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, select, numDerivs = 0, low = 0, middle = 50, high = 100, outliersCutoff = -1, weights, freeWhenDone = true, action|
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.stats)};
source = source.asUGenInput;
stats = stats.asUGenInput;
weights = weights.asUGenInput;
@ -22,28 +44,28 @@ FluidBufStats : FluidBufProcessor {
source.isNil.if {"FluidBufStats: Invalid source buffer".throw};
stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw};
weights = weights ? -1;
^this.new(
server, nil, [stats]
).processList(
[source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, outliersCutoff, weights, 0], freeWhenDone, action
[source, startFrame, numFrames, startChan, numChans, stats, selectbits, numDerivs, low, middle, high, outliersCutoff, weights, 0], freeWhenDone, action
);
}
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, outliersCutoff = -1, weights, freeWhenDone = true, action|
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, select numDerivs = 0, low = 0, middle = 50, high = 100, outliersCutoff = -1, weights, freeWhenDone = true, action|
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.stats)};
source = source.asUGenInput;
stats = stats.asUGenInput;
weights = weights.asUGenInput;
source.isNil.if {"FluidBufStats: Invalid source buffer".throw};
stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw};
weights = weights ? -1;
^this.new(
server, nil, [stats]
).processList(
[source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, outliersCutoff, weights, 1], freeWhenDone, action
[source, startFrame, numFrames, startChan, numChans, stats, selectbits, numDerivs, low, middle, high, outliersCutoff, weights, 1], freeWhenDone, action
);
}

@ -1,16 +1,42 @@
FluidSpectralShape : FluidRTMultiOutUGen {
*kr { arg in = 0, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = 16384;
^this.multiNew('control', in.asAudioRateInput(this), minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize);
const <features=#[\centroid,\spread,\skewness,\kurtosis,\rolloff,\flatness,\crest];
classvar featuresLookup;
*initClass {
featuresLookup = Dictionary.with(*this.features.collect{|x,i| x->(1<<i)});
}
*prWarnUnrecognised {|sym| ("WARNING: FluidSpectralShape -" + sym + "is not a recognised option").postln}
*prProcessSelect {|a|
var bits;
a.asBag.countsDo{|item,count,i|
if(count > 1) { ("Option '" ++ item ++ "' is repeated").warn};
};
bits = a.collect{ |sym|
(featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0})
}.reduce{|x,y| x | y};
^bits
}
*kr { arg in = 0, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = 16384;
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)};
^this.multiNew('control', in.asAudioRateInput(this), selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize);
}
init {arg ...theInputs;
var numChannels;
inputs = theInputs;
^this.initOutputs(7,rate);
numChannels = inputs.at(1).asBinaryDigits.sum;
^this.initOutputs(numChannels,rate);
}
checkInputs {
if(inputs.at(9).rate != 'scalar') {
if(inputs.at(10).rate != 'scalar') {
^(": maxFFTSize cannot be modulated.");
};
^this.checkValidInputs;

Loading…
Cancel
Save