FluidBufCompose.kr - why not?

I don’t know if it isn’t there because you don’t want it or because it isn’t ready yet, but I am really jonesing for FluidBufCompose.kr right now.

From the example:

~extractor = FluidProcessSlices({|src,start,num,data|
var mfcc, stats, writer, flatten,mfccBuf, statsBuf, flatBuf, label, voice;
label = data.key;
voice = data.value[\voice];
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, -1, ~flatbuf[voice], Done.kr(flatten))
});

Yields a 91 element set. What I want are elements 2-13, so what I would like to do is this:

~extractor = FluidProcessSlices({|src,start,num,data|
var mfcc, stats, writer, flatten,mfccBuf, statsBuf, flatBuf, label, voice;
label = data.key;
voice = data.value[\voice];
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));
bufC1 = FluidBufCompose.kr(~flatbuf[voice], 0, -1, 1, 12, ~bufc1buf[voice], trig:Done.kr(flatten))
writer = FluidDataSetWr.kr(~ds,label, -1, ~bufc1buf[voice], Done.kr(bufC1))
});

Is this possible right now? Am I missing something? The solution I came up with is horrific.

Sorry for all the noise. I think I have figured out my issues.

I found the channel settings in FluidBufStats.

And now I found the example in the BufRd/BufWr example on reducing dimensions in the Standardize help file. Wow, that is a face melter of an example that shows me how to do most everything I have been trying to do. Virtuosic coding by @groma.

Sam

2 Likes

Greetings,

I’d like to revive this “why not?” It seems like that’s what I need here. I’d like to do an MFCC, Pitch, and SpectralShape analysis and put all that into my DataSet. How might I accomplish this?

Thanks!

~extractor = FluidProcessSlices({|src,start,num,data|
	//var mfcc, stats, writer, flatten,mfccBuf, statsBuf, flatBuf, label, voice;
	var flatten;
	var label = data.key;
	var voice = data.value[\voice];
	var mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccBuf[voice],trig:1);
	var pitch = FluidBufPitch.kr(src,start,num,0,1,~pitchBuf[voice],trig:Done.kr(mfcc));
	var spec = FluidBufSpectralShape.kr(src,start,num,0,1,~specBuf[voice],trig:Done.kr(pitch));
	
	var mfcc_stats = FluidBufStats.kr(~mfccBuf[voice],stats:~mfcc_stats[voice],trig:Done.kr(spec));
	var pitch_stats = FluidBufStats.kr(~pitchBuf[voice],stats:~pitch_stats[voice],trig:Done.kr(mfcc_stats));
	var spec_stats = FluidBufStats.kr(~specBuf[voice],stats:~spec_stats[voice],trig:Done.kr(pitch_stats));
	
	var mfcc_flat = FluidBufFlatten.kr(~mfcc_stats[voice],~mfcc_flat[voice],trig:Done.kr(spec_stats));
	var pitch_flat = FluidBufFlatten.kr(~pitch_stats[voice],~pitch_flat[voice],trig:Done.kr(mfcc_flat));
	var spec_flat = FluidBufFlatten.kr(~spec_stats[voice],~spec_flat[voice],trig:Done.kr(pitch_flat));
	
	// what should i do now?
	
// just checking that i know stuff about these bufs
	BufFrames.kr(~mfcc_flat[voice]).poll;
	BufFrames.kr(~pitch_flat[voice]).poll;
	BufFrames.kr(~spec_flat[voice]).poll;
	BufChannels.kr(~mfcc_flat[voice]).poll;
	BufChannels.kr(~pitch_flat[voice]).poll;
	BufChannels.kr(~spec_flat[voice]).poll;
	
	FluidDataSetWr.kr(~ds,label, -1, ~master_buf_that_theyre_composed_into[voice], Done.kr(spec_flat));
});

Indeed that would make sense… @weefuzzy I can’t remember why we don’t have a trigger-based one, is it just because bufcompose does not have the same class def as the other objects? It is in the .sc but is commented out…

It’s commented out because, pre-triggers, it didn’t make any sense to use BufCompose in a UGen (because it always runs synchronously w/r/t the server command thread). However, it makes sense now. It’s quite possible that uncommenting it and recompilng the class library will Just Work (i.e. give it a try, let me know).

1 Like

Here’s what I put together, but I got an error (also below) that confused me. Thanks for looking into it!

(
~extractor = FluidProcessSlices({|src,start,num,data|
	var label = data.key;
	var voice = data.value[\voice];
	var mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccBuf[voice],trig:1);
	var pitch = FluidBufPitch.kr(src,start,num,0,1,~pitchBuf[voice],trig:Done.kr(mfcc));
	var spec = FluidBufSpectralShape.kr(src,start,num,0,1,~specBuf[voice],trig:Done.kr(pitch));

	var mfcc_stats = FluidBufStats.kr(~mfccBuf[voice],stats:~mfcc_stats[voice],trig:Done.kr(spec));
	var pitch_stats = FluidBufStats.kr(~pitchBuf[voice],stats:~pitch_stats[voice],trig:Done.kr(mfcc_stats));
	var spec_stats = FluidBufStats.kr(~specBuf[voice],stats:~spec_stats[voice],trig:Done.kr(pitch_stats));

	var mfcc_flat = FluidBufFlatten.kr(~mfcc_stats[voice],~mfcc_flat[voice],trig:Done.kr(spec_stats)); // 91
	var pitch_flat = FluidBufFlatten.kr(~pitch_stats[voice],~pitch_flat[voice],trig:Done.kr(mfcc_flat)); // 14
	var spec_flat = FluidBufFlatten.kr(~spec_stats[voice],~spec_flat[voice],trig:Done.kr(pitch_flat)); // 49

	// what should i do now?
	//|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, trig = 1|
	//
	var mfcc_comp = FluidBufCompose.kr( ~mfcc_flat[voice], 0,-1,0,-1,1,~master_buf[voice],0,      0,0,Done.kr(spec_flat));
	var pitch_comp = FluidBufCompose.kr(~pitch_flat[voice],0,-1,0,-1,1,~master_buf[voice],91,     0,0,Done.kr(mfcc_comp));
	var spec_comp = FluidBufCompose.kr( ~spec_flat[voice], 0,-1,0,-1,1,~master_buf[voice],91 + 14,0,0,Done.kr(pitch_comp));


	// just checking that i know stuff about these bufs
	// BufFrames.kr(~mfcc_flat[voice]).poll;
	// BufFrames.kr(~pitch_flat[voice]).poll;
	// BufFrames.kr(~spec_flat[voice]).poll;
	// BufChannels.kr(~mfcc_flat[voice]).poll;
	// BufChannels.kr(~pitch_flat[voice]).poll;
	// BufChannels.kr(~spec_flat[voice]).poll;

	FluidDataSetWr.kr(~ds,label, -1, ~master_buf[voice], Done.kr(spec_comp));
});
)

~extractor.play(s,~loader.buffer,~loader.index,action:{(Main.elapsedTime - t).postln;"Features done".postln});

ERROR POST WINDOW:

bufnum: 0
numFrames: 81805906
numChannels: 1
sampleRate: 44100.0

0.66788071800011
Loaded
-> a FluidProcessSlices
Processing 1/127
WARNING: keyword arg 'blocking' not found in call to Meta_UGen:multiNew
WARNING: keyword arg 'blocking' not found in call to Meta_UGen:multiNew
WARNING: keyword arg 'blocking' not found in call to Meta_UGen:multiNew
FluidBufCompose arg: '11' has bad input: nil
 ARGS:
   source: 25 Integer
   startFrame: 0 Integer
   numFrames: -1 Integer
   startChan: 0 Integer
   numChans: -1 Integer
   gain: 1 Integer
   destination: 37 Integer
   destStartFrame: 0 Integer
   destStartChan: 0 Integer
   destGain: 0 Integer
   trig: a Done Done
   11: nil Nil
FluidBufCompose arg: '11' has bad input: nil
 ARGS:
   source: 29 Integer
   startFrame: 0 Integer
   numFrames: -1 Integer
   startChan: 0 Integer
   numChans: -1 Integer
   gain: 1 Integer
   destination: 37 Integer
   destStartFrame: 91 Integer
   destStartChan: 0 Integer
   destGain: 0 Integer
   trig: a Done Done
   11: nil Nil
FluidBufCompose arg: '11' has bad input: nil
 ARGS:
   source: 33 Integer
   startFrame: 0 Integer
   numFrames: -1 Integer
   startChan: 0 Integer
   numChans: -1 Integer
   gain: 1 Integer
   destination: 37 Integer
   destStartFrame: 105 Integer
   destStartChan: 0 Integer
   destGain: 0 Integer
   trig: a Done Done
   11: nil Nil
SynthDef temp__0 build failed
ERROR: FluidBufCompose arg: '11' has bad input: nil

PROTECTED CALL STACK:
	SynthDef:checkInputs	0x113ee4c00
		arg this = SynthDef:temp__0
		var firstErr = FluidBufCompose arg: '11' has bad input: nil
	SynthDef:finishBuild	0x113edea00
		arg this = SynthDef:temp__0
	a FunctionDef	0x113ed1840
		sourceCode = "<an open Function>"
	Function:prTry	0x11209f780
		arg this = a Function
		var result = nil
		var thread = a Thread
		var next = nil
		var wasInProtectedFunc = false
	
CALL STACK:
	Exception:reportError
		arg this = <instance of Error>
	Nil:handleError
		arg this = nil
		arg error = <instance of Error>
	Thread:handleError
		arg this = <instance of Thread>
		arg error = <instance of Error>
	Object:throw
		arg this = <instance of Error>
	Function:protect
		arg this = <instance of Function>
		arg handler = <instance of Function>
		var result = <instance of Error>
	SynthDef:build
		arg this = <instance of SynthDef>
		arg ugenGraphFunc = <instance of Function>
		arg rates = nil
		arg prependArgs = nil
	Function:play
		arg this = <instance of Function>
		arg target = <instance of Group>
		arg outbus = 0
		arg fadeTime = 0.02
		arg addAction = 'addToHead'
		arg args = nil
		var def = nil
		var synth = nil
		var server = <instance of Server>
		var bytes = nil
		var synthMsg = nil
	Integer:do
		arg this = 4
		arg function = <instance of Function>
		var i = 0
	FluidProcessSlices:play
		arg this = <instance of FluidProcessSlices>
		arg server = <instance of Server>
		arg sourceBuffer = <instance of Buffer>
		arg bufIdx = <instance of IdentityDictionary>
		arg action = <instance of Function>
		arg tasks = 4
		var counter = 1
		var perf = <instance of Function>
		var jobs = <instance of List>
		var total = 127
		var uid = 1010
		var completed = 0
	Interpreter:interpretPrintCmdLine
		arg this = <instance of Interpreter>
		var res = nil
		var func = <instance of Function>
		var code = "~extractor.play(s,~loader.bu..."
		var doc = nil
		var ideClass = <instance of Meta_ScIDE>
	Process:interpretPrintCmdLine
		arg this = <instance of Main>
^^ The preceding error dump is for ERROR: FluidBufCompose arg: '11' has bad input: nil

Hi Ted,

Not SC’s finest error message. I think what’s happening is that FluidBufCompose is calling UGen.multiNew (for no particularly good reason) but also using a keyword to pass the blocking argument (also for no particularly good reason). Either of the following should fix it, but both is probably better

  1. Don’t call this.multiNew in kr, call this.new1 instead
  2. Don’t use a keyword for the blocking argument (we’re passing the whole set anyway, so it’s not needed), just pass the 1 rather than blocking:1. Alternatively, change new1's signature so that blocking defaults to 1

The whys:

  1. We don’t need to support multichannel expansion here (and I have no idea how it would make sense), so multiNew is overkill. Meanwhile, multiNew doesn’t have a keyword argument called blocking, so it makes SC sad (this not being python, where you can pass any old keyword arguments in)
  2. There’s no point launching a worker thread to run bufcompose, because this would always entail doing more work launching the thread than the plugin is doing anyway (because all the data gets copied).

That worked! Thanks for the speedy reply. Also, I eyeballed the json file of the dataset afterwards and can confirm that it looks like it’s all written correctly (as in not a bunch of zeros somewhere, the data is filled in).

For anyone else who might come along this way, my FluidBufCompose.sc file now looks like this:

FluidBufCompose : UGen {

    *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, trig = 1, blocking = 1|

		source = source.asUGenInput;
		destination = destination.asUGenInput;

		source.isNil.if {"FluidBufCompose:  Invalid source buffer".throw};
		destination.isNil.if {"FluidBufCompose:  Invalid destination buffer".throw};

        ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, trig, blocking);
	}

    *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, trig = 1|

        /*^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, trig, blocking:1);*/

		^this.new1('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, trig, 1);
	}

	*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action|
	^FluidNRTProcess.new(Ò
            server, this, action, [destination], blocking:1
		).process(
			source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain
		);

	}

   *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action|
    ^process(
	   source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain
      );
	}
}

and the FluidProcessSlices function I used is this:

~extractor = FluidProcessSlices({|src,start,num,data|
	var label = data.key;
	var voice = data.value[\voice];
	var mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccBuf[voice],trig:1);
	var pitch = FluidBufPitch.kr(src,start,num,0,1,~pitchBuf[voice],trig:Done.kr(mfcc));
	var spec = FluidBufSpectralShape.kr(src,start,num,0,1,~specBuf[voice],trig:Done.kr(pitch));

	var mfcc_stats = FluidBufStats.kr(~mfccBuf[voice],stats:~mfcc_stats[voice],trig:Done.kr(spec));
	var pitch_stats = FluidBufStats.kr(~pitchBuf[voice],stats:~pitch_stats[voice],trig:Done.kr(mfcc_stats));
	var spec_stats = FluidBufStats.kr(~specBuf[voice],stats:~spec_stats[voice],trig:Done.kr(pitch_stats));

	var mfcc_flat = FluidBufFlatten.kr(~mfcc_stats[voice],~mfcc_flat[voice],trig:Done.kr(spec_stats)); // 91
	var pitch_flat = FluidBufFlatten.kr(~pitch_stats[voice],~pitch_flat[voice],trig:Done.kr(mfcc_flat)); // 14
	var spec_flat = FluidBufFlatten.kr(~spec_stats[voice],~spec_flat[voice],trig:Done.kr(pitch_flat)); // 49

	var mfcc_comp = FluidBufCompose.kr( ~mfcc_flat[voice], 0,-1,0,-1,1,~master_buf[voice],0,      0,0,Done.kr(spec_flat));
	var pitch_comp = FluidBufCompose.kr(~pitch_flat[voice],0,-1,0,-1,1,~master_buf[voice],91,     0,0,Done.kr(mfcc_comp));
	var spec_comp = FluidBufCompose.kr( ~spec_flat[voice], 0,-1,0,-1,1,~master_buf[voice],91 + 14,0,0,Done.kr(pitch_comp));

	FluidDataSetWr.kr(~ds,label, -1, ~master_buf[voice], Done.kr(spec_comp));
});
1 Like

Thanks for the confirmation! We’ll get that changed for the next release.

1 Like

never mind. i forgot to capitalize something. dope! this works.