Two Small Questions about the 2D Corpus Explorer Tutorial for SuperCollider

Hi all -
As mentioned previously, I’ve been following along with the 2D Corpus Example provided by FluCoMa. There were two small modifications that I would find very useful - but I’m not entirely sure how to add them to the overall data structure.

The first is that I would like to include mapping of the overall duration of the slice in the Plotter. I know that the durations can easily be found - but as they are not written into a buffer using any of the FluidBuf tools, I’m not sure how to append this data into my overall plot.

The second thing that I was hoping to get information about is how one might control the FluidPlotter externally - or if it is possible, as it seems designed explicitly to work with mouse input.

Thanks!

Hi,

The first is that I would like to include mapping of the overall duration of the slice in the Plotter

Do you mean you’d like the duration to have so
me impact on how the points are positioned? If so, you can include them in the ~analyses as another column:

(
~analyses = FluidDataSet(s);
~durations = Dictionary(); 
~indices.loadToFloatArray(action:{
	arg fa;
	var mfccs = Buffer(s);
	var stats = Buffer(s);
	var flat = Buffer(s);
	var flatPlusDur = Buffer.alloc(s,14); //alloc num features + 1 to also record duration 

	fa.doAdjacentPairs{
		arg start, end, i;
		var num = end - start;

		FluidBufMFCC.processBlocking(s,~src,start,num,features:mfccs,numCoeffs:13,startCoeff:1);
		FluidBufStats.processBlocking(s,mfccs,stats:stats,select:[\mean]);
		FluidBufFlatten.processBlocking(s,stats,destination:flat);		
		FluidBufCompose.processBlocking(s,flat,destination: flatPlusDur); //copy the flattened MFFC stats to our final buffer
		flatPlusDur.set(13,num); //set the last sample of flatPlusDur to the duration 
		~analyses.addPoint(i,flatPlusDur);
		
		"analyzing slice % / %".format(i+1,fa.size-1).postln;

		if((i%100) == 99){s.sync;}
	};

	s.sync;

	~analyses.print;
});
)

On the other hand, if you mean you want to use the duration to, e.g., scale the points – let’s say that you record a language side Dictionary with the durations and slice labels in (i.e. i and num in the analysis code block (e.g. ~durations.put(i, num). Then you could use this in the rendering

(
~normed.dump({
	arg dict;
	var point = Buffer.alloc(s,2);
	var previous = nil;

	defer{
		var plt = FluidPlotter(dict:dict,mouseMoveAction:{
			arg view, x, y;
			[x,y].postln;
			point.setn(0,[x,y]);
			~tree.kNearest(point,1,{
				arg nearest;
				if(nearest != previous){
					nearest.postln;
					view.highlight_(nearest);
					~play_slice.(nearest.asInteger);
					previous = nearest;
				}
			});
		});
                // separate IDs and durations, scale the durs (probably a nicer way to do this)
		var durations_delaced = ~durations.asPairs.clump(2).flop; 
		durations_delaced[1] = durations_delaced[1].normalize(min:0.25, max:5);
		durations_delaced.flop.do{ |a|
			plt.pointSize_(a[0], a[1]); 
		};
		plt.refresh; 
	}
});
)

Which maybe gives an indication of talking to the plotter through code as well?

1 Like

This is awesome, thanks! It clarifies a lot of the lesson to be able to see how something like this could be added.

1 Like

Maybe we could think with @tedmoore of a few extensions to the tutorial indeed… we should start a wishlist and maybe we can make a video that demos a few extensions (audio query is another one) and then give the code here… let me think about it