faust
faust copied to clipboard
attach'ed hbargraph is removed if first bus gets terminated
Example code: process = _, (2.0 <: _, hbargraph("test", 0, 5) : attach) : _,!;
Diagram: 
Expected: I would expect that an attached signal is getting exposed to the ui, even if it gets later on terminated Actual: attached signal is getting removed, even if it's part of the diagram
But not exposed in ui: 
The SVG diagram is a bit misleading here: in this cas the compiler actually remove the attached part and generates this C++ code:
virtual void compute(int count, FAUSTFLOAT** RESTRICT inputs, FAUSTFLOAT** RESTRICT outputs) {
FAUSTFLOAT* input0 = inputs[0];
FAUSTFLOAT* output0 = outputs[0];
for (int i0 = 0; i0 < count; i0 = i0 + 1) {
output0[i0] = FAUSTFLOAT(float(input0[i0]));
}
}
Yes, attach must attach to a signal that survives. It would be nice to have a primitive that works like you expected, e.g., hbargraph("test", 0, 5) : persist.
Yes,
attachmust attach to a signal that survives. It would be nice to have a primitive that works like you expected, e.g.,hbargraph("test", 0, 5) : persist.
Yes I think something like this would be really helpful. Would this be hard to implement? I tried looking for where the logic for attach is defined, buuuut after the 5th page of search results i gave up :D
Read the attach primitive documentation again: https://faustdoc.grame.fr/manual/syntax/#attach-primitive. Since your program finally compute an output, you should be able to use if in the attach expression right?
Read the attach primitive documentation again: https://faustdoc.grame.fr/manual/syntax/#attach-primitive. Since your program finally compute an output, you should be able to use if in the attach expression right?
I'm currently writing a mixer with peak/dbmeter. It has 4 stereo buses for the channel, but they get terminated once they got mixxed down for the main output. So those signals don't survive, and also the attach primitive doesn't. Probably I stumbled on this problem because I did the db metering after the mixdown, maybe it would survive if i would do it before the mixdown. But anyways, I worked around this by keeping all the buses, as I write the interaction with the jack audio api myself, i can hide them there. I think now that it's clear that this is the intended behaviour of attach, It's more about an persist primitive would be helpful for faust and if it's possible to implement.
But you need to get the result of peak/dbmeter in a bargraph right? Why cant you attach them to the signal which is then mixe to main output ? Any "simplest" piece of code that should the problem?
But you need to get the result of peak/dbmeter in a bargraph right? Why cant you attach them to the signal which is then mixe to main output ? Any "simplest" piece of code that should the problem?
As I said, I guess I could make it work somehow, doing the metering before the mixdown. But my code would look something like this:
_,_ <: _,_,_,_ : _,_ (_,_:>_) : _, (_, (_metering : hbargraph(...)) : attach) : _,_
With a possible persist primtive
_,_ <: _,_,_,_ : _,_ (_,_:>_:metering:hbargraph(...):persist:!) : _,_
With persist i think it's more clear what happens. With attach it's why 2 inputs? What is the sense of feeding the right channel into it?
Coincidentally, I just wrote a library to solve this problem: https://github.com/nuchi/faust-tap-library/
Actually I wanted something slightly different than a persist primitive — I wanted to route deeply nested signals to output without manually dealing with crossings, but when I saw this issue it was only a few extra lines to add persist functionality.
The name ("tap.lib") comes from tapping a delay line.
Please make sure to look at the "Limitations" section in the readme, there are some situations that it can't handle.
Example code:
tap = library("tap.lib");
A(k) = *(k);
complicatedExpression = _,_,_,_ : (
(A(1) <: _,(hbargraph("first", 0, 1) : tap.T1)),
A(2),
A(3),
(A(4) <: _,(hbargraph("second", 0, 1) : tap.T2)),
A(5)
) ~ (_,_,_,_,_ :> _ <: _,tap.T3)
: si.block(5)
;
process = tap.persist(
tap.extract(complicatedExpression, tap.T3),
(tap.T1, tap.T2)
);
Resulting block diagram:
EDIT: Your example:
process = _, (2.0 <: _, hbargraph("test", 0, 5) : attach) : _,!;
would be written like the following, assuming I understand correctly (I think you want a signal going straight through, and then a constant signal 2 feeding directly into an hbargraph which doesn't interact with the first signal):
tap = library("tap.lib");
process = tap.persist(
(_, (2.0 : hbargraph("test", 0, 5) : tap.T1) : _)
// or just (_, (2.0 : hbargraph("test", 0, 5) : tap.T1))
, tap.T1
);
Nice! I've often needed such taps