Accessing a Buffer in an Association

I am processing some sound files with FluCoMa and I think I must be hitting an error in accessing buffers I have stored in a set of associations/events but I can’t figure out how to get this to work correctly. I want the arguments to .process once since the values need to be the same to whatever process I’m using to get the data. It’s returning ERROR: FluidBufNoveltySlice: Invalid source buffer and I don’t understand why.

//Buffer load
(
var cleanup = Buffer.freeAll;

~samples = [
//paths to my samples
].collect{|path, i|
	var srcBuf = Buffer.read(s, path);
	var sliceBuf = Buffer(s);
	var featuresBuf = Buffer(s);
	(
		src: srcBuf,
		slices: sliceBuf,
		features: featuresBuf,
		path: path
	);
};
)

~samples[0][\src] //returns the audio buffer, as expected

//Analysis
(
var sampleIndex = 0; //set me

var sample = ~samples[sampleIndex];
var dictionary;
var process = { 
	
	var assoc = 
	//novelty
	(process: [FluidBufNoveltySlice, FluidBufNoveltyFeature], args: (server: Server.local, source: sample[\src], indices: sample[\slices], features: sample[\features], algorithm: \mfcc, kernelSize: 3, threshold: 0.5, filterSize: 1, minSliceLength: 100, windowSize: 1024, hopSize: -1, fftSize: -1));
	
	//amp
	// (process: [FluidBufAmpSlice, FluidBufAmpFeature], args: (server: Server.local, source: sample[\src], indices: sample[\slices], features: sample[\features], fastRampUp: 1, fastRampDown: 1, slowRampUp: 100, slowRampDown: 100, onThreshold: -144, offThreshold: -144, floor: -144, minSliceLength: 1, highPassFreq: 5));
	
	assoc[\process].do{|process|
		process.process(
			assoc[\args]
		);
	};
	
	\done.postln;
};

process.(); //ERROR: FluidBufNoveltySlice:  Invalid source buffer
)

Does

process.performWithEnvir(\process, assoc[\args])

Work instead?

:exploding_head: That’s pretty slick, thanks @jordan!

Just to fill out why it works…

You can imagine that when you write

obj.msg(arg1, arg2)

it is turned into*

obj.perform(\msg, arg1, arg2).

Thereby allowing you to change what message is sent programmatically.

var msgs = [\rrand, \pow];
msgs.collect( -1.0.perform(_, 2) );

There are a series of convenience functions for doing this with arguments — the only one I ever use is .performWithEnir as it allows you to use key value pairs where the key is the name of the argument and the value is the argument value.

42.performWithEnvir(\gaussCurve, (\a: 1.0, \b: 0.0, \c: 2.0))

This also works with custom functions

~f = {|meow, woof, bahh| [meow, woof, bahh].postln };

~f.performWithEnvir(\value, (\meow: 1.0, \woof: 0.0, \bahh: 2.0));
// or when using \value
~f.valueWithEnvir((\meow: 1.0, \woof: 0.0, \bahh: 2.0))

This is particularly useful if you have a bunch of default arguments and want to only change a few, and make it explicit how each call differs from the default.

var process = { 
	var processes = [FluidBufNoveltySlice, FluidBufNoveltyFeature];
	var default_args = (
		server: Server.local, 
		source: sample[\src], 
		indices: sample[\slices], 
		features: sample[\features], 
		algorithm: \mfcc, 
		kernelSize: 1, 
		threshold: 0.5, 
		filterSize: 1, 
		minSliceLength: 100, 
		windowSize: 1024, 
		hopSize: -1, 
		fftSize: -1
	);
	
	var override_args = (
		kernelSize: 3,
		threshold: 0.2 
	);
	
	var real_args = default_args ++ override_args; // has kernelSize: 3

	processes.do(
		_.performWithEnvir(\process, real_args)
	);
	
	\done.postln;
};

This is particuarly good if you have a lot of multichannel expansion going on in a synth and what to think about voices instead…

var voice_processor = {|freq, wobble, amp|
	... some ugen code
};

var default_arg = (
	\freq: 220,
	\wobble: PinkNoise.ar,
	\amp: 0.2
);

var voices_args = [
	(\freq: \freq1.kr),
	(\freq: 431, \amp, SinOsc.ar),
	(\wobble: 0.1)
];

voices_args.collect({|v_arg| 
	voice_processor.valueWithEnvir(default_arg ++ v_arg)
});

… got a little carried away because I really like this technique!


*its not, but they do the same thing from the users perspective.

1 Like