"Fake" Feedback loop not permitted

Hello,
I’m facing a situation that I can’t really find a workaround for right now…

In an audio processor graph, I have the following setup :

Here is the connection setup : (Node:Channel > Node:Channel)
Metronome:1 > A:1
A:1 > B:1
B:1 > A:2
A:1&2 > Output:1&2 (for checking)

The problem is that Node B is not processing (I’ve read some things about audio cut off in case of feedback loop detected). If I remove the connection between B > A. the following happens and Node B is receiving data (blue bar showing rms), like below :

My problem is that this setup is NOT a feedback loop, as the
channels are going separate ways, so no audio is actually send back for processing into the same connection twice. But Juce will automatically clear the buffer for B, and I don’t know how I can bypass this behaviour.

Any idea ?

Thanks !

Hi,
I’ve never used the graph before, but there is some logic in the code for using empty buffers if a feedback loop is detected through the nodes (I think). I’d say set some breakpoints in there and see if your buffer is being cleared. If my hunch is right then it’s how the code this is implemented (there are some posts about this). You could add a summing stage for A & B which will avoid the need for a fake feedback loop.

Hopefully this helps

Thank you for the answer,
I already tried to find where it happens and could only find a break at this line when it happens :

This indeed provide a reference to an empty buffer if it couldn’t find a buffer index, but I’m kind of lost on why it would find the buffer. I think it goes deeper and I’m hoping some people here already have answers about that.

Even if this isn’t technically a feedback loop, the graph has no way of knowing this. A might be summing all of its input channels and passing the result to its output, for example. There’s also the question of feedback delay - the graph always processes a whole audio block at a time, which means that there would need to be an entire block of latency on either the input or output of B.

This isn’t configurable currently. In order to handle cycles ‘properly’, the graph would need to insert delays within any cycles, but it doesn’t do that currently. This would probably necessitate some new API so that users can choose where the delay is inserted.

Given that the graph doesn’t automatically introduce delays, it needs some way of producing a consistent output in a single pass over the graph. Nodes inside cycles are provided with silent inputs in order to break the cyclic dependency between their inputs and outputs.

If you really want to be able to process feedback loops, the path of least resistance is probably to add a ‘fake’ output node, have this node write into a stored buffer, and then to use a ‘fake’ input node to read from that same buffer. i.e. in the example you posted, B would output into a separate audio out, which would write into a buffer, and there’d be an audio in connected to A’s second input that would read from the same buffer. This approach will let you control exactly where in the graph the delay is introduced.

Thank you for your valuable feedback :slight_smile:

My goal is not to have delay whatsoever but to get closer to a modular synthetizer logic :

I have many nodes in my real setup, and I would like to be able to quickly switch the order of how those nodes are connected.

I have created a “Patch bay” node with an arbitrary number of inputs and outputs, and I want to be able to connect any input to any output with this node (basic audio routing).

But then I’d like to have my nodes to be able to receive and send to this main patch bay, like this :

A > PatchBay:Input 1 > PatchBay:Output 1 > B > PatchBay:Input 2 > PatchBay Output 3 > D

So i just have to change the configuration of this patch bay to change the flow of my nodes.

EDIT : My other use case is with containers :
I have a container containing multiple effects, and it’s convenient for managing things when the setup gets complex.
I want Node A to go into my container on channel 1, then channel 1 goes to FX1 that goes to Out channel 1 of the container, then Node B, that goes into channel 2 of the container > Fx2 > container out 2 > Node C, etc… and alongside with the patchbay, this would create a very efficient workflow.

Or is there a better solution for that ?

I think in your example A1 and A2 should probably be two separate nodes in the graph, or maybe duplicates, or they share some state between them, but in terms of processing to avoid the delays and/or feedback loops I think they should be explicitly separated.

In >> A1 >> Out
In >> A1 >> B >> A2 >> Out

You could probably also achieve the same thing with multiple passes of a graph, with it rewired on each pass, and the output of the one pass becomes the input to the next pass, but it’s harder to picture how you would generalise that solution.