[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[sc-dev] SF.net SVN: quarks:[2652] ListeningClocks
- To: sc-dev@xxxxxxxxxxxxxxxx
- Subject: [sc-dev] SF.net SVN: quarks:[2652] ListeningClocks
- From: jrhb@xxxxxxxxxxxxxxxxxxxxx
- Date: Mon, 14 Oct 2013 13:32:58 +0000
- Dkim-signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:Content-Type:Subject:To:From:MIME-Version:Date; bh=6WAl1P13C7G1JZ6zrTfjPi/vZ/e9UtyDoAxMp2yILBw=; b=dT/xorK4AFgjewyIRZyOaPamCc7JLWsatZ0PqtLSet3Oh1Wm3BJ4Wx0B6t1fScdGzqvoWLhTF1ADGJLhZ5aSdMQFDqmMzcqXxAH1qpzDtHOPDNwRo+k4eewQc0Ip4XdMOxQqxyXzuBoyKwWE3WvWN2bbK382CYB6HhA/ZiK7d9w=;
- Dkim-signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x; h=Content-Transfer-Encoding:Content-Type:Subject:To:From:MIME-Version:Date; bh=6WAl1P13C7G1JZ6zrTfjPi/vZ/e9UtyDoAxMp2yILBw=; b=X8bSfpsaIT+OeiXkfh5A/jluTOe3+8DYJoh6haysGRFSuT/sByHAUm1u4qc/qn+6eFy20LEQ54prdi5TnoANZ8i03B7qnGFbnpMo4zf1JLEFC1mejO3HkyD2ZLYo9u8Xpfx6qcL2ZCUb6pFr/ZWKk/qeiPeG8ly7g65TobUajVM=;
- List-id: SuperCollider developers mailing list <sc-devel.create.ucsb.edu>
- Reply-to: sc-dev@xxxxxxxxxxxxxxxx
- Sender: owner-sc-dev@xxxxxxxxxxxxxxxx
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/