[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[sc-dev] SF.net SVN: quarks:[2652] ListeningClocks



Revision: 2652
          http://sourceforge.net/p/quarks/code/2652
Author:   jrhb
Date:     2013-10-14 13:32:54 +0000 (Mon, 14 Oct 2013)
Log Message:
-----------
Start a better implementation of TelepathicClock

Modified Paths:
--------------
    ListeningClocks/ListeningClocks.sc
    ListeningClocks/TelepathicClock.sc

Added Paths:
-----------
    ListeningClocks/help/basic_telepathy_test.scd

Modified: ListeningClocks/ListeningClocks.sc
===================================================================
--- ListeningClocks/ListeningClocks.sc	2013-10-13 21:39:05 UTC (rev 2651)
+++ ListeningClocks/ListeningClocks.sc	2013-10-14 13:32:54 UTC (rev 2652)
@@ -1,5 +1,5 @@
 
-// implementation and concept by Alberto de Campo, Rainer Sch\x9Ftz, Julian Rohrhuber
+// implementation and concept by Alberto de Campo, Rainer Schütz, Julian Rohrhuber
 // developed for the virtual gamelan graz 2007
 
 
@@ -12,13 +12,13 @@
 	var fadeTask, fading=false, isPlaying=true;
 	var <rateOfChange = 1.0;
 	var <>minTempo = 0.01, <>maxTempo = 100;
-	
+
 	classvar <>all;
-	
+
 	add {
 		this.class.all = this.class.all.add(this);
 	}
-	
+
 	*stopAll {
 		this.all.do { |clock|
 			clock.permanent = false;
@@ -26,7 +26,7 @@
 		};
 		this.all = nil;
 	}
-	
+
 	stop {
 		this.stopListen;
 		isPlaying = false;
@@ -34,24 +34,24 @@
 		if(this.class.all.notNil) { this.class.all.take(this) };
 		if(verbose) { ("stopped clock:" + this).postln };
 	}
-	
+
 	tempo_ { arg newTempo;
 		newTempo = max(newTempo, 1e-256); // zero not allowed.
 		rateOfChange = newTempo / this.tempo;
 		super.tempo = newTempo;
 	}
-	
+
 	pause { arg dur = 0;
 		this.fadeTempo(0.0, dur)
 	}
-	
-	
+
+
 	fadeTempo { arg newTempo, dur = 1.0, warp = \cos, clock;
 		var start = this.tempo, interpol;
 		warp = warp.asWarp;
 		if (warp.isKindOf(ExponentialWarp)) { warp.spec.minval_(0.01) };
-		if (fading) { fadeTask.stop }; 
-		fadeTask = Task { 
+		if (fading) { fadeTask.stop };
+		fadeTask = Task {
 			fading = true;
 			"fadeTempo starts. going from: % to: %\n".postf(
 				start.round(0.001), newTempo.round(0.001));
@@ -65,28 +65,28 @@
 			fading = false;
 			"fadeTempo done. tempo was: % new tempo is: %\n".postf(
 				start.round(0.001), interpol.round(0.001));
-		}; 
+		};
 		clock = clock ? SystemClock;
 		fadeTask.play(clock);
 	}
-	
+
 	warpTempo { arg frac, beats = 1.0, warp = \cos;
 		this.fadeTempo(frac * this.tempo, beats, warp, this)
 	}
-	
+
 }
 
 
 
 ListeningClock : SoftClock {
-	
+
 	var <listener;
 	var <>empathy = 0.5, <>confidence=0.5;
 	var <>others, <>weights;
 	var <>phaseWrap, phaseOffset = 0.0;
-	
+
 	classvar <>all;
-	
+
 	adjust {
 		var tempo = this.othersMeanTempo;
 		var beats = this.othersMeanBeats;
@@ -94,21 +94,21 @@
 			this.prAdjust(beats - this.elapsedBeats, tempo)
 		}
 	}
-	
+
 	startListen {
 		listener.stop;
 		listener = this.makeTask({ others !? { this.adjust }; });
 		listener.play;
 	}
-	
+
 	stopListen {
 		listener.stop;
 	}
-	
+
 	isListening {
 		^listener.isPlaying
 	}
-	
+
 	makeTask { arg func;
 		^if(this.allPermanent) {
 			SkipJack({ if(isPlaying, func) }, { dt })
@@ -116,9 +116,9 @@
 			Task { loop { dt.wait; if(isPlaying, func) } }
 		}
 	}
-	
+
 	allPermanent { ^if(others.isNil) { true } { others.every(_.permanent) && this.permanent } }
-	
+
 	addClock { arg clock, weight;
 		others = others.add(clock);
 		if(weight.notNil) {
@@ -126,7 +126,7 @@
 			// todo: make weights un-normalized!
 		};
 	}
-	
+
 	setClocks { arg clocks, argWeights, start=true;
 		var listening = start or: { this.isListening };
 		this.stopListen;
@@ -137,8 +137,8 @@
 		argWeights !? { weights = argWeights.normalizeSum };
 		if(listening) { this.startListen };
 	}
-	
-	
+
+
 	othersMeanTempo {
 		if(others.isNil or: { others.isEmpty }) { ^nil };
 		^if(weights.isNil) {
@@ -147,7 +147,7 @@
 			others.collect(_.tempo).mean {|x, i| x * weights[i] } * weights.size
 		}
 	}
-	
+
 	othersMeanBeats {
 		if(others.isNil or: { others.isEmpty }) { ^nil };
 		^if(weights.isNil) {
@@ -156,9 +156,9 @@
 			others.collect(_.elapsedBeats).mean {|x, i| x * weights[i] } * weights.size
 		}
 	}
-	
+
 	// private implementation
-	
+
 	prWrapPhase { |beats|
 		var wrapped;
 		if(phaseWrap.isNil) { ^beats };
@@ -167,17 +167,17 @@
 		//if(verbose) { [\beats, beats, \wrapped, wrapped, \phaseOffset, phaseOffset].postln; };
 		^wrapped.postln
 	}
-	
+
 	prAdjust { |deltaBeats, argTempo|
 		var phaseDiff = this.prWrapPhase(deltaBeats);
 		var myTempo = this.tempo;
-		var timeComp = (phaseDiff * this.empathy); 
+		var timeComp = (phaseDiff * this.empathy);
 		var newTempo = (blend(argTempo, myTempo, this.confidence) + timeComp)
 				.clip(minTempo, maxTempo);
-		if (verbose 
-			and: { (phaseDiff.abs > 0.001)  
-			or: { (newTempo - myTempo).abs > 0.001 } }) 
-		{ 
+		if (verbose
+			and: { (phaseDiff.abs > 0.001)
+			or: { (newTempo - myTempo).abs > 0.001 } })
+		{
 			"Clock - adjust - avgDeltaBeats: % 	avgTempo: % timeComp: % newTempo: %"
 			.format(*[deltaBeats, argTempo, timeComp, newTempo].round(0.0001)).postln;
 		};

Modified: ListeningClocks/TelepathicClock.sc
===================================================================
--- ListeningClocks/TelepathicClock.sc	2013-10-13 21:39:05 UTC (rev 2651)
+++ ListeningClocks/TelepathicClock.sc	2013-10-14 13:32:54 UTC (rev 2652)
@@ -1,13 +1,34 @@
 
 ReferenceClock {
-	var clock;
-	
+	var clock, <>offset = 0;
+
 	*new { arg tempo, beats;
-		^super.new.update(tempo, beats)	
+		^super.new.init(tempo, beats)
 	}
-	
-	update { arg tempo, beats;
-		var clockBeats, beatDifference;
+
+	elapsedBeats {
+		^clock.elapsedBeats + offset
+	}
+
+	tempo {
+		^clock.tempo
+	}
+
+	elapsedBeats_ { |beats|
+		offset = beats - clock.elapsedBeats
+	}
+
+	tempo_ { |tempo|
+		clock.tempo = tempo
+	}
+
+	adjust { arg tempo, beats;
+		beats !? { offset = beats - clock.elapsedBeats };
+		tempo !? { clock.tempo = tempo };
+	}
+
+	init { arg tempo, beats;
+		var clockBeats;
 		clock !? {
 			clockBeats = clock.elapsedBeats;
 			beats = beats ? clockBeats;
@@ -16,15 +37,7 @@
 		};
 		clock = TempoClock.new(tempo, beats).permanent_(true)
 	}
-	
-	elapsedBeats {
-		^clock.elapsedBeats
-	}
-	
-	tempo {
-		^clock.tempo	
-	}
-	
+
 	permanent { ^true }
 }
 
@@ -33,23 +46,25 @@
 
 	var <>name;
 	var responder;
-	
+
 	classvar <cmd = \refClockSet;
-	
+
 	*new { arg tempo, beats, name;
 		^super.new(tempo, beats).name_(name ? \telepathicClock)
 	}
-	
+
 	startListen {
 		// cmd, name, tempo, beats, beatWrap
 		responder = OSCresponderNode(nil, cmd, { |t, r, msg|
+			var name, tempo, beats, beatWrap;
 			if(msg[1] == name) {
-					this.update(msg[2], msg[3], msg[4]);
+				#tempo, beats, beatWrap = msg[2..];
+				this.adjust(tempo, beats, beatWrap);
 			}
 		});
 		responder.add;
 	}
-	
+
 	stopListen {
 		responder.remove;
 	}
@@ -57,23 +72,23 @@
 
 
 TelepathicClock : ListeningClock {
-	
+
 	var <>name = \telepathicClock, <responder;
-	
+
 	classvar <addClockSourceCmd = \addClockSource;
 
-	
+
 	addClockSource { |name|
 		var clock;
 		// allow other (local) clocks
-		if(others.isNil or: { others.any { |clock| try { clock.name == name } ? false }.not }) { 
+		if(others.isNil or: { others.any { |clock| try { clock.name == name } ? false }.not }) {
 			clock = TelepathicReferenceClock(this.tempo, this.elapsedBeats, name);
 			clock.startListen;
 			this.addClock(clock);
 			weights = nil; // for now.
 		}
 	}
-	
+
 	removeClockSource { |name|
 		var index, clock;
 		if(others.isNil) { ^this };
@@ -84,7 +99,7 @@
 			clock.stopListen;
 		};
 	}
-	
+
 	allowOthersToAdd { |flag = true|
 		if(flag) {
 			responder = OSCresponderNode(nil, addClockSourceCmd, { |t, r, msg, replyAddr|
@@ -98,44 +113,44 @@
 			});
 			responder.add;
 		} {
-			responder.remove;	
+			responder.remove;
 		}
 	}
-	
+
 	startListen {
 		super.startListen;
 		// cmd, name, flag (1= add, 0 = remove)
 		others.do { |clock| try { clock.startListen } };
 	}
-	
+
 	stopListen {
 		super.stopListen;
 		others.do { |clock| try { clock.stopListen } };
 		this.allowOthersToAdd(false);
 	}
-	
-	
-	
-		
+
+
+
+
 }
 
 
 + TempoClock {
-	
+
 	initTeleport { |addr, name = \telepathicClock|
 		addr.sendMsg(TelepathicClock.addClockSourceCmd, name, 1);
 	}
-	
+
 	endTeleport { |addr, name = \telepathicClock|
 		addr.sendMsg(TelepathicClock.addClockSourceCmd, name, 0);
 	}
-	
+
 	teleport { |addr, name = \telepathicClock, beatWrap|
 		addr.sendMsg(TelepathicReferenceClock.cmd, name, this.tempo, this.elapsedBeats, beatWrap)
 	}
-	
+
 	clearQueue {
-		queue.removeAllSuchThat(true);	
+		queue.removeAllSuchThat(true);
 	}
 }
 
@@ -175,7 +190,7 @@
 );
 
 (
-TempoClock.default.tempo = rrand(1.0, 2.0);
+TempoClock.default.tempo = rrand(1.0, 4.0);
 TempoClock.default.teleport(n, \test, 4);
 )
 

Added: ListeningClocks/help/basic_telepathy_test.scd
===================================================================
--- ListeningClocks/help/basic_telepathy_test.scd	                        (rev 0)
+++ ListeningClocks/help/basic_telepathy_test.scd	2013-10-14 13:32:54 UTC (rev 2652)
@@ -0,0 +1,24 @@
+/*
+The plan is to reimplement the not-quite-correct TelepathicClock
+as to match a future time sharing protocol for laptop ensembles.
+TelepathicClock may change implementation.
+ListeningClock and SoftClock will stay the same.
+*/
+
+(
+// basic test:
+a = ReferenceClock.new;
+b = ListeningClock.new;
+b.addClock(a, 1);
+b.startListen;
+b.verbose = true;
+);
+
+// push reference into the future
+a.adjust(1, b.elapsedBeats + 3);
+// push reference into the past
+a.adjust(1, b.elapsedBeats - 3);
+
+// regular updates
+fork { loop { 1.wait; a.adjust(1, b.elapsedBeats + 0.1.rand2) } }
+

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.


_______________________________________________
sc-dev mailing list

info (subscription, etc.): http://www.beast.bham.ac.uk/research/sc_mailing_lists.shtml
archive: https://listarc.bham.ac.uk/marchives/sc-dev/
search: https://listarc.bham.ac.uk/lists/sc-dev/search/