Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
vitreo12 committed Mar 10, 2022
2 parents 37b59c3 + b2e10ef commit b9ae5d6
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 43 deletions.
2 changes: 1 addition & 1 deletion AlgaLib.quark
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
summary: "Interpolating live coding environment",
author: "vitreo12",
helpdoc: "HelpSources/Classes/Alga.schelp",
version: 1.1,
version: 1.1.1,
)
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 1.1.1

## Bug fixes

- `AlgaBlock`: check for new connections to trigger a re-order, and not just for `upperMostNodes`.

- `AlgaBlock`: fix `findAllUnusedFeedback` in order to be used on any new connection.

- `AlgaNode`: trigger `addActiveInOutNodes` on `replace` for old input connections.

# 1.1.0

- Added the `interpShape` option. This allows to specify an interpolation shape in the form of an
Expand Down
39 changes: 19 additions & 20 deletions Classes/AlgaBlock.sc
Original file line number Diff line number Diff line change
Expand Up @@ -249,22 +249,29 @@ AlgaBlock {
rearrangeBlock { | sender, receiver |
var server, supernova;
var ignoreStages;
var newConnection = false;

//Update lastSender
lastSender = sender ? lastSender;

//Stage 1: detect feedbacks between sender and receiver (if they're valid)
if((sender != nil).and(receiver != nil), {
this.stage1(sender, receiver);
newConnection = true;
});

//Find unused feedback loops (from previous disconnections)
this.findAllUnusedFeedbacks;

//Find upper most nodes. This is done out of stage1 as it must always be executed,
//while stage1 might not be (sender == nil and receiver == nil). At the same time,
//this needs to happen before the other stages.
this.findUpperMostNodes;

//If upperMostNodes is 0, it's a full FB block. No need to run anything else.
ignoreStages = upperMostNodes.size == 0;
//Ignore the successive stages IF
//NOT a new connection AND
//upperMostNodes is 0 (full FB block)
ignoreStages = (newConnection.not).and(upperMostNodes.size == 0);
if(ignoreStages.not, {
//Stage 2: order nodes according to I/O
this.stage2;
Expand Down Expand Up @@ -309,9 +316,6 @@ AlgaBlock {
blockReceiver: receiver
);

//Find unused feedback loops (from previous disconnections)
this.findAllUnusedFeedbacks;

//Debug
if(Alga.debug, { this.debugFeedbacks });
}
Expand Down Expand Up @@ -382,8 +386,6 @@ AlgaBlock {

//Stage 2: order nodes
stage2 {
var visitedUpperMostNodes;

//Clear all needed stuff
visitedNodes.clear;
orderedNodes.clear;
Expand All @@ -392,13 +394,15 @@ AlgaBlock {
this.orderNodes;

//Need to know upperMostNodes' size
visitedUpperMostNodes = Array.newClear(upperMostNodes.size);
if(upperMostNodes.size > 0, {
var visitedUpperMostNodes = Array.newClear(upperMostNodes.size);

//Traverse branches from upperMostNodes
this.traverseBranches(visitedUpperMostNodes);
//Traverse branches from upperMostNodes
this.traverseBranches(visitedUpperMostNodes);

//Find blocks that should be separated
this.findBlocksToSplit(visitedUpperMostNodes);
//Find blocks that should be separated
this.findBlocksToSplit(visitedUpperMostNodes);
});

//Debug
if(Alga.debug, { this.debugOrderedNodes });
Expand Down Expand Up @@ -442,7 +446,6 @@ AlgaBlock {
//Only consider branches with more than one node
if(branch1.size > 1, {
var containsAnyOtherNode = false;

block { | break |
visitedUpperMostNodes.do({ | branch2 |
if(branch1 != branch2, {
Expand Down Expand Up @@ -748,7 +751,7 @@ AlgaBlock {
node.activeOutNodes.keys.do({ | receiver |
var visited = disconnectVisitedNodes.includes(receiver);

//Found a FB connection
//Found an old FB connection
if(this.isFeedback(node, receiver), {
//detectFeedback uses Class's visitedNodes and atLeastOneFeedback
visitedNodes.clear;
Expand All @@ -761,11 +764,7 @@ AlgaBlock {
blockReceiver: receiver
);

//atLeastOneFeedback.asString.error;

//If no feedbacks, the pair can be removed.
//Effectively, this means that the disconnection of the node in
//rearrangeBlock_disconnect freed this particular feedback loop
//If no feedbacks, the pair can be removed
if(atLeastOneFeedback.not, {
this.removeFeedback(node, receiver);
});
Expand All @@ -781,7 +780,7 @@ AlgaBlock {
//Running this on new connections?
findAllUnusedFeedbacks {
nodes.do({ | node |
disconnectVisitedNodes.clear;
disconnectVisitedNodes.clear; //per-node
this.findUnusedFeedbacks(node)
});
}
Expand Down
68 changes: 47 additions & 21 deletions Classes/AlgaNode.sc
Original file line number Diff line number Diff line change
Expand Up @@ -1812,14 +1812,32 @@ AlgaNode {

//Remove activeInNodes / outNodes and reorder block
removeActiveNodesAndRearrangeBlocks { | param, sender |
if(sender.isListPattern, {
sender.list.do({ | entry | this.removeActiveNodeAndRearrangeBlock(param, entry) });
}, {
if(sender.isFilterPattern, {
this.removeActiveNodesAndRearrangeBlocks(param, sender.pattern) //NOTE: plural form
}, {
this.removeActiveNodeAndRearrangeBlock(param, sender)
var wasPattern = false;

case
{ sender.isListPattern } {
sender.list.do({ | entry |
this.removeActiveNodesAndRearrangeBlocks(param, entry)
});
wasPattern = true;
}
{ sender.isFilterPattern } {
this.removeActiveNodesAndRearrangeBlocks(param, sender.pattern);
wasPattern = true;
}
{ sender.isPattern } {
sender.class.instVarNames.do({ | instVarName |
try {
var instVar = sender.perform(instVarName);
this.removeActiveNodesAndRearrangeBlocks(param, instVar);
} { | error | } //Don't catch errors
});
wasPattern = true;
};

//Bottom search: AlgaNode
if(wasPattern.not, {
this.removeActiveNodeAndRearrangeBlock(param, sender);
});
}

Expand Down Expand Up @@ -1887,16 +1905,14 @@ AlgaNode {
//If replace and sendersSet contains inNodes, connect back to the .synthBus of the AlgaNode.
//Note that an inNode can also be an AlgaArg, in which case it also gets unpacked accordingly
if(replace, {
var sendersSet = inNodes[paramName];

//Restoring a connected parameter, being it normal or mix
var sendersSet = inNodes[paramName];
if(sendersSet != nil, {
if(sendersSet.size > 0, {
var onlyEntry = false;

//if size == 1, index from \default
if(sendersSet.size == 1, { onlyEntry = true });
var onlyEntry = sendersSet.size == 1;

//Loop through
sendersSet.do({ | prevSender |
var interpBus, interpSynth, normSynth;
var interpSymbol, normSymbol;
Expand Down Expand Up @@ -2007,6 +2023,11 @@ AlgaNode {
waitForInst:false
);

//The activeInNode / activeOutNode counter MUST be updated on replace!
//AlgaPattern already does this with AlgaPatternInterpStreams.add
this.addActiveInOutNodes(prevSender, paramName);

//Normal param OR mix param
if(onlyEntry, {
//normal param
interpSynths[paramName][\default] = interpSynth;
Expand Down Expand Up @@ -3158,6 +3179,19 @@ AlgaNode {
});
}

//Add active in nodes connections
addActiveInOutNodes { | sender, param = \in |
//AlgaPattern handles it in its own addInNode, this would double it!
if(this.isAlgaPattern.not, {
//Don't add to active if sender == this
var connectionToItself = (this == sender);
if(connectionToItself.not, {
this.addActiveInNode(sender, param);
sender.addActiveOutNode(this, param);
});
});
}

//add entries to the inNodes / outNodes / connectionTimeOutNodes of the two AlgaNodes
addInOutNodesDict { | sender, param = \in, mix = false |
//This will replace the entries on new connection (when mix == false)
Expand All @@ -3175,15 +3209,7 @@ AlgaNode {
sender.calculateLongestConnectionTime(this.connectionTime);

//Like inNodes / outNodes. They get freed on the accoding interpSynth
//AlgaPattern handles it in its own addInNode, this would double it!
if(this.isAlgaPattern.not, {
//Don't add to active if sender == this
var connectionToItself = (this == sender);
if(connectionToItself.not, {
this.addActiveInNode(sender, param);
sender.addActiveOutNode(this, param);
});
});
this.addActiveInOutNodes(sender, param);
});
}

Expand Down
1 change: 0 additions & 1 deletion Classes/AlgaScheduler.sc
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,6 @@ AlgaPatch {
}, {
("Alga is not booted on server" + server.name).error;
});
^nil;
}
}

Expand Down
40 changes: 40 additions & 0 deletions Tests/TestAlgaBlockAboutToBail.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
(
Alga.boot({
Alga.debug = true;

a = AN.debug({\in.ar}, name: \a);
b = AN.debug({\in.ar}, name: \b, interpTime: 2);
c = AN.debug({\in.ar}, name: \c);
d = AN.debug({\in.ar}, name: \d);

e = AN.debug({\in.ar}, name: \e);

a >> b;
b >> c;
c >>+ b;
b >> d;
})
)

(
a.blockIndex.postln;
b.blockIndex.postln;
c.blockIndex.postln;
d.blockIndex.postln;
)

(
d.disconnect;
b.disconnect;
c.disconnect;
)

//Without the aboutToBail check in orderNodes, this fails
//as the c node is actually not feedback anymore, but still present
//in the block.
(
b >> c;
b >> d;
c >>+ b;
a >> b;
)

0 comments on commit b9ae5d6

Please sign in to comment.