Advanced stats ordering

Hi, I noticed for what I want to do I can’t use bufstats~. It’s way to slow if you have many slices. I guess it’s all this repeated buffer handling. I’m trying to calculate the stats myself currently with a js. Later I want to normalize and do distance calculations. I came up with some questions:

  1. What are the derivative values? How to calculate and what do they describe?
  2. How do I absolutely normalize skewness and kurtosis? Are they in the same unit as the feature? What is the minimum / maximum of it?(for any input) And is it linear?

Here is the script for the stats per slice output. Only kurtosis results seem to slightly differ from bufstats~ results. (Couldn’t find the actual formula on flucoma github code) Hence my question 1, I was wondering if I should add derivative calculation when I understand what it is…

outlets=2;


function get(sourcebuf, slicebuf, featbuf, featbufchan, hopsize)
{
	var source_buffer = new Buffer(sourcebuf);
	var slice_buffer = new Buffer(slicebuf);
	var feat_buffer = new Buffer(featbuf);
	
	var numOfSlices = slice_buffer.framecount();
	var onsetArr = slice_buffer.peek(0, 0, numOfSlices);
	
	
	//post ("\nnum of slices: "+ numOfSlices);
	//post("\nfeat frames: "+ feat_buffer.framecount());
	
	//for every onset 	
	for (i = 0; i < numOfSlices; i++)
	{
		
		var onsetTimeInSamples = onsetArr[i];
		var lengthInSamples; 
		if (i == numOfSlices-1)//last one
		{
			lengthInSamples = source_buffer.framecount()-onsetTimeInSamples;
		}
		else
		{
			lengthInSamples = onsetArr[i+1]-onsetTimeInSamples;
		}
		var start = ~~(onsetTimeInSamples / hopsize);
		var length = ~~(lengthInSamples / hopsize);
		
		//post ("\nslice: "+ i +" feat start: "+start+" len: "+length );
		
		var featArr = feat_buffer.peek(featbufchan, start, length);
		
		
		// skewness
		// kurtosis
		delta = 0,
		delta_n = 0,
		delta_n2 = 0,
		term1 = 0,
		N = 0,
		mean2 = 0,
		M2 = 0,
		M3 = 0,
		M4 = 0,
		sk_g = 0,
		ku_g = 0;
		
		var mean = 0;
		var minimum =  (Math.pow(2, 53) - 1);
		var maximum = -(Math.pow(2, 53) - 1);
		var stddev = 0;
		var skewness = 0;
		var kurtosis = 0;
		var median = 0;
		
		for (var j = 0 ; j < length; j++) 
		{
			var value = featArr[j];
			
			if (value > maximum) 
				maximum = value;
			if (value < minimum) 
				minimum = value;
			mean+=value;
			
			N += 1;

			delta = value - mean2;
			delta_n = delta / N;
			delta_n2 = delta_n * delta_n;

			term1 = delta * delta_n * (N-1);

			M4 += term1*delta_n2*(N*N - 3*N + 3) + 6*delta_n2*M2 - 4*delta_n*M3;
			M3 += term1*delta_n*(N-2) - 3*delta_n*M2;
			M2 += term1;
			mean2 += delta_n;
			
		}
		mean /= length;
		sk_g = Math.sqrt( N )*M3 / Math.pow( M2, 3/2 );
		ku_g = N*M4 / ( M2*M2 ) - 3;
		skewness = Math.sqrt( N*(N-1))*sk_g / (N-2);
		kurtosis = (N-1) / ( (N-2)*(N-3) ) * ( (N+1)*ku_g + 6 );
		
		//post ("  mean: "+ mean +" maximum: "+maximum+" minimum: "+minimum );
		for (var j = 0 ; j < length; j++) 
		{
			var value = featArr[j];
			
			stddev += Math.pow((value - mean),2);
			
		}
		stddev = Math.sqrt(stddev/length);
		
		featArr.sort( function(a, b){return a - b} );
		// Get the middle index:
		id = Math.floor( length / 2 );
		if ( length % 2 ) 
		{
		// The number of elements is not evenly divisible by two, hence we have a middle index:
		median = featArr[ id ];
		}
		else
			// Even number of elements, so must take the mean of the two middle values:
			median = ( featArr[ id-1 ] + featArr[ id ] ) / 2.0;
		
		outlet(1, i, mean, stddev, skewness, kurtosis, minimum, median, maximum);
	
		
	}// end loop over onsets
	
	

	
	outlet(0, "bang");
}
1 Like