/** 
Axel, Stefan, Alberto, Thomas, Florian! 

Data on PLoop bins [-1,0,1] are physical values, 
	2 is filtered data (can be ignored)

KV, 02/2010, prepared for SBEII (Data by Christof Gattringer)
**/

	// alle datenfiles sofort lesen. dauert ca 1 min.
(
q = q ?? ();
q.myPath = Document.current.dir; 
q.ttcs = [0.63, 0.69, 0.75, 0.82, 0.89, 0.97, 1.01, 1.05, 1.13, 1.22, 1.32].collect(_.asSymbol);
q.confs = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10"].collect(_.asSymbol);

q.allData = (); 
q.ttcs.do { |ttc, i| 
	var dict = (); q.allData.put(ttc, dict); 
	
	q.confs.do { |conf, j| 
		var path = q.myPath ++ "/files_gattringer/intsect_TTC_" 
			++ ttc ++ "_conf_" ++ conf ++".dat";
		dict.put(conf, FileReader.read(path, true, true, _.asInteger, $\n).unbubble.clump(40).clump(40));
	}
};
)
	// tests
q.allData['0.69']['01'].shape // -> [ 40, 40, 40 ]
q.allData['0.69']['01']; 		// -> [ [ [ 2, 2, 2, 2, 0, -1, 1, 2, 2 ... ]]]

	// rekursiv cluster finden, entlang jedem zweig weitergehen.
	// geht systematisch ueber den ganzen datenfile.
	// findet alle cluster, auch die kleinen bei hohen temperaturen.
//	// Mappings: 
		Ein cluster ist ein kontinuierlicher Sound, x, y z werden auf drei formanten gemappt.
		sollten eigentlich ausdehnung des clusters in xyz anzeigen, war aber zu schwer zu bauen
		in der gegebenen Zeit. 
		Je laenger der cluster, desto schneller wird er durchgegangen, dabei steigt die Tonhoehe analog mit. 
		
		Alteres Mapping: x, y, z sind drei 3 tonhoehen, bilden kleinen akkord. 

(
/**** 
	// umschalten zwischen datensets UND SPIELEN!
q.conf = q.allData['0.69']['01'];	Tdef(\cluster).stop.play; // kleine cluster
q.conf = q.allData['1.01']['01']; 	Tdef(\cluster).stop.play; // groessere cluster
q.conf = q.allData['1.32']['05']; 	Tdef(\cluster).stop.play; // ein grosser cluster, ein paar kleinere
q.conf = q.allData['1.22']['05']; 	Tdef(\cluster).stop.play; // einige groessere

q.conf = q.allData['0.63']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['0.69']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['0.75']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['0.82']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['0.89']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['0.97']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['1.01']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['1.05']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['1.13']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['1.22']['01'];	Tdef(\cluster).stop.play; 
q.conf = q.allData['1.32']['01'];	Tdef(\cluster).stop.play; 

***/ 

// orig sound - chords, base sollte 60 sein
/*
	// ausfuehren, um auf die dreiton-variante umzuschalten
(
q.basepitch = 60; 
q.deltaT = 0.02;
Ndef(\tri).clear;
Ndef(\tri, { |x, y, z, base = 60| 
	Splay.ar(Formant.ar(base.midicps * [x, y, z].midiratio, [500, 1250, 3000], 400))
	+ (Ringz.ar(Impulse.ar(0), 2000, 0.1) * GrayNoise.ar) * 0.3;
});
);
*/
	// zweite sound variante - default. grundton geht rauf wenn fast forward
	// xyz sind drei formanten - sollte eigentlich x, y, z ausdehnung des clusters sein.
(
q.basepitch = 40; 
q.deltaT = 0.02;
Ndef(\tri, { |x, y, z, base = 40| 
	Splay.ar(Formant.ar(base.midicps, 500 * ([x, y, z] * 1.5).midiratio, 500))
	+ (Ringz.ar(Impulse.ar(0), 2000, 0.05) * GrayNoise.ar) * 0.3;
});
);

(
Tdef(\cluster, { 
	var clusterID = 1000; 
	var clusterCount; 
	var basepitch = q.basepitch; 
	var deltaT = q.deltaT; 
	var tempconf = q.conf.deepCopy;
	var startPos, val, valAt, valPut; 
	var nextAddrs, neighbourOffsets, neighbours;
	var floodCluster; 
	
	neighbourOffsets = [ 
		[0,0,1],
		[0,1,0],
		[1,0,0],
		[0,0,-1],
		[0,-1,0],
		[-1,0,0]
	];
	nextAddrs = { |pos| neighbourOffsets.collect(_ + pos).wrap(0, 40) }; 
	valAt = { |pos| tempconf.wrapAt(pos[0]).wrapAt(pos[1]).wrapAt(pos[2]) };
	valPut = { |pos, val| tempconf.wrapAt(pos[0]).wrapAt(pos[1]).wrapPut(pos[2], val) };
	
	floodCluster = { |addr, valToFind| 
				
				var myval = valAt.(addr);
				if (myval == valToFind) { 
					valPut.(addr, clusterID);
					Ndef(\tri).set(\x, addr[0].wrap(0, 10), 
						\y, addr[1].wrap(0, 10),
						\z, addr[2].wrap(0, 10), 
						\base, basepitch = (basepitch + 0.01).min(60)
					);
					neighbours = nextAddrs.value(addr)
						.select({ |nextaddr| valAt.(nextaddr) == valToFind });
					if (neighbours.notEmpty) { 
						
						neighbours.do { |neighbour| 
							neighbour.postln;
							floodCluster.value(neighbour, valToFind);
						};
						deltaT.wait;
						deltaT = (deltaT * 0.95).max(0.0003);
					};
				}
				};
	
			// alle gitterpunkte ausprobieren, 
			// nach finden mit clusterID ueberschreiben
	40.do { |i| 
		40.do { |j| 
			40.do { |k| 
				startPos = [i, j, k]; 
				val = valAt.(startPos);
				if (val < 2) { 
					Ndef(\tri).fadeTime = 0.001;
					
					Ndef(\tri).play; 
										
					floodCluster.value(startPos, val);					clusterID = clusterID + 1;
					deltaT = q.deltaT; 
					basepitch = 40;
					Ndef(\tri).stop;
					0.1.wait;
					"\n\n////////////// CLUSTERID: %\n".postf(clusterID);
				}
			}
		}
	};
}).play; 
)
)