Skip to content

Commit 11bb901

Browse files
authored
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
1 parent 4e5f0e4 commit 11bb901

File tree

4 files changed

+86
-23
lines changed

4 files changed

+86
-23
lines changed

include/wrapper/ArgsFromClient.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ struct ParamReader<impl::FloatControlsIter>
7777
return args.next();
7878
}
7979

80+
static auto fromArgs(Unit*, Controls& args, typename ChoicesT::type, int)
81+
{
82+
return typename ChoicesT::type(std::size_t(static_cast<index>(args.next())));
83+
}
84+
8085
static SCBufferAdaptor* fetchBuffer(Unit* x, index bufnum)
8186
{
8287
if(bufnum >= x->mWorld->mNumSndBufs)
@@ -280,6 +285,12 @@ struct ParamReader<sc_msg_iter>
280285
return res;
281286
}
282287

288+
static auto fromArgs(World*, sc_msg_iter& args, typename ChoicesT::type, int)
289+
{
290+
int x = args.geti();
291+
return typename ChoicesT::type(asUnsigned(x));
292+
}
293+
283294
template<typename T>
284295
static auto fromArgs(World* w, sc_msg_iter& args, Optional<T>, int)
285296
{

release-packaging/Classes/FluidBufSpectralShape.sc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,26 @@ FluidBufSpectralShape : FluidBufProcessor {
44
^\FluidBufSpecShp
55
}
66

7-
*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|
7+
*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|
88

99
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
10+
var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)};
1011

1112
source = source.asUGenInput;
1213
features = features.asUGenInput;
1314

1415
source.isNil.if {"FluidBufSpectralShape: Invalid source buffer".throw};
1516
features.isNil.if {"FluidBufSpectralShape: Invalid features buffer".throw};
1617

17-
^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking);
18+
19+
^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);
1820

1921
}
2022

21-
*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|
23+
*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|
2224

2325
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
26+
var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)};
2427

2528
source = source.asUGenInput;
2629
features = features.asUGenInput;
@@ -31,13 +34,14 @@ FluidBufSpectralShape : FluidBufProcessor {
3134
^this.new(
3235
server, nil, [features]
3336
).processList(
34-
[source, startFrame, numFrames, startChan, numChans, features, padding, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone, action
37+
[source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone, action
3538
);
3639
}
3740

38-
*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|
41+
*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|
3942

4043
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
44+
var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)};
4145

4246
source = source.asUGenInput;
4347
features = features.asUGenInput;
@@ -48,7 +52,7 @@ FluidBufSpectralShape : FluidBufProcessor {
4852
^this.new(
4953
server, nil, [features]
5054
).processList(
51-
[source, startFrame, numFrames, startChan, numChans, features, padding, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone, action
55+
[source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone, action
5256
);
5357
}
5458
}

release-packaging/Classes/FluidBufStats.sc

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,71 @@
11
FluidBufStats : FluidBufProcessor {
22

3-
*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|
4-
3+
const <stats=#[\mean,\std,\skewness,\kurtosis,\low,\mid,\high];
4+
classvar statslookup;
5+
6+
*prWarnUnrecognised {|sym| ("WARNING: FluidBufStats -" + sym + "is not a recognised option").postln}
7+
8+
*prProcessSelect {|a|
9+
var bits;
10+
a.asBag.countsDo{|item,count,i|
11+
if(count > 1) { ("Option '" ++ item ++ "' is repeated").warn};
12+
};
13+
bits = a.collect{ |sym|
14+
(statslookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0})
15+
}.reduce{|x,y| x | y};
16+
^bits
17+
}
18+
19+
*initClass {
20+
statslookup = Dictionary.with(*this.stats.collect{|x,i| x->(1<<i)});
21+
}
22+
23+
*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|
24+
25+
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.stats)};
526
source = source.asUGenInput;
627
stats = stats.asUGenInput;
728
weights = weights.asUGenInput;
829

930
source.isNil.if {"FluidBufStats: Invalid source buffer".throw};
1031
stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw};
1132
weights = weights ? -1;
12-
13-
^FluidProxyUgen.kr(\FluidBufStatsTrigger, -1, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high, outliersCutoff, weights, trig, blocking);
33+
34+
^FluidProxyUgen.kr(\FluidBufStatsTrigger, -1, source, startFrame, numFrames, startChan, numChans, stats, selectbits, numDerivs, low, middle, high, outliersCutoff, weights, trig, blocking);
1435
}
1536

16-
*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|
17-
37+
*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|
38+
39+
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.stats)};
1840
source = source.asUGenInput;
1941
stats = stats.asUGenInput;
2042
weights = weights.asUGenInput;
2143

2244
source.isNil.if {"FluidBufStats: Invalid source buffer".throw};
2345
stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw};
2446
weights = weights ? -1;
25-
47+
2648
^this.new(
2749
server, nil, [stats]
2850
).processList(
29-
[source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, outliersCutoff, weights, 0], freeWhenDone, action
51+
[source, startFrame, numFrames, startChan, numChans, stats, selectbits, numDerivs, low, middle, high, outliersCutoff, weights, 0], freeWhenDone, action
3052
);
3153
}
3254

33-
*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|
34-
55+
*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|
56+
57+
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.stats)};
3558
source = source.asUGenInput;
3659
stats = stats.asUGenInput;
3760
weights = weights.asUGenInput;
38-
3961
source.isNil.if {"FluidBufStats: Invalid source buffer".throw};
4062
stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw};
4163
weights = weights ? -1;
42-
64+
4365
^this.new(
4466
server, nil, [stats]
4567
).processList(
46-
[source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, outliersCutoff, weights, 1], freeWhenDone, action
68+
[source, startFrame, numFrames, startChan, numChans, stats, selectbits, numDerivs, low, middle, high, outliersCutoff, weights, 1], freeWhenDone, action
4769
);
4870
}
4971

release-packaging/Classes/FluidSpectralShape.sc

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,42 @@
11
FluidSpectralShape : FluidRTMultiOutUGen {
22

3-
*kr { arg in = 0, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = 16384;
4-
^this.multiNew('control', in.asAudioRateInput(this), minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize);
3+
const <features=#[\centroid,\spread,\skewness,\kurtosis,\rolloff,\flatness,\crest];
4+
classvar featuresLookup;
5+
6+
*initClass {
7+
featuresLookup = Dictionary.with(*this.features.collect{|x,i| x->(1<<i)});
8+
}
9+
10+
*prWarnUnrecognised {|sym| ("WARNING: FluidSpectralShape -" + sym + "is not a recognised option").postln}
11+
12+
*prProcessSelect {|a|
13+
var bits;
14+
a.asBag.countsDo{|item,count,i|
15+
if(count > 1) { ("Option '" ++ item ++ "' is repeated").warn};
16+
};
17+
bits = a.collect{ |sym|
18+
(featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0})
19+
}.reduce{|x,y| x | y};
20+
^bits
21+
}
22+
23+
24+
*kr { arg in = 0, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = 16384;
25+
26+
var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)};
27+
28+
^this.multiNew('control', in.asAudioRateInput(this), selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize);
529
}
630

731
init {arg ...theInputs;
32+
var numChannels;
833
inputs = theInputs;
9-
^this.initOutputs(7,rate);
34+
numChannels = inputs.at(1).asBinaryDigits.sum;
35+
^this.initOutputs(numChannels,rate);
1036
}
1137

1238
checkInputs {
13-
if(inputs.at(9).rate != 'scalar') {
39+
if(inputs.at(10).rate != 'scalar') {
1440
^(": maxFFTSize cannot be modulated.");
1541
};
1642
^this.checkValidInputs;

0 commit comments

Comments
 (0)