Closed sadko4u closed 4 years ago
You can use the Faust Web IDE here to look at the black diagram.
(or open your exemple code are: https://faust.grame.fr/ide/index.html?autorun=1&voices=0&name=untitled1&inline=aW1wb3J0KCJzdGRmYXVzdC5saWIiKTsKCmluX2MgPSBfOwppbl9iID0gXzsKaW5fYSA9IF87Cgpwcm9jZXNzID0gKyhpbl9hLCBpbl9iKSwgXyA6ICooaW5fYyk7)
Then first first (the top one) will the first input (= input0 in generated code and so on. So basically you'll have to think in term of input/output order in the block diagram you're describing, that will corresponds to inputs/outputs 0...N in the generated code.
That's not good if I use the generated code as embedded into other code or if I create series of DSP processors that have strictly identified functional inputs. I don't want to watch block diagrams. I want to create *.dsp file with set of inputs, automatically generate a C++-file and then pass the signals to respective inputs knowing their indices. The lack of such functionality is ridiculous reprectively to all things were done to develop and populate FAUST language.
Basically in Faust, you are describing a signal processor, as a function taking a set of input signals (conceptually as infinite streams of samples) and producing a set of output signals. For instance if you write:
process = +;
you are describing a block that takes 2 inputs, add them and produce one output. The 2 inputs will be "connected" in their respective order on left and right channel of a stream input audio card for instance. So basically you describe an explicit ordering. Then the way the actual C++ generated code is connected to the external world (audio driver and UI) is written in so-called "architecture files", see: https://github.com/grame-cncm/faust/blob/master-dev/documentation/faust-quick-reference.pdf and possibly https://hal.archives-ouvertes.fr/hal-02159003
What is the lacking functionality?
This is true only when I have two inputs. It is not true when I have set of processors with varying input functions. Consider some filter with varying F and Q parameters where F and Q are control signals which are non-trivial. And consider some another device which also has F and Q parameters which also affect it's behaviour. And now we have some outer device which routes IN, F and Q to some abstract device which can be a filter or some another device. The operation becomes impossible since we don't know which input is IN, which is F and which is Q.
In other words, I can map a parameter:
in_param = hslider("in_param", dfl, min, max, step);
But can not map input:
input0 = _ ; // Which actually input is this? 0, 1, 2, or something else?
It would be nice to have:
input0 = dspinput(0);
Or at least:
input0 = _0; // or _1 or _2, etc...
The same for outputs
inputs(block)
and outputs(block)
primitives
select
like functions in the libraries here https://faust.grame.fr/doc/libraries/index.html#ba.selectorfoo(in0,in1,in2) = something;
import("stdfaust.lib");
// Get the 'i' output of a arbitrary block 'b' outputN(i, b) = b : ba.selector(i, outputs(b));
// Test block block = (1,2,3,4);
output0 = outputN(0,block); output1 = outputN(1,block); output2 = outputN(2,block); output3 = outputN(3,block);
process = output0,output2;
Seems to be working improperly:
import("stdfaust.lib");
inputN(i, b) = b: ba.selector(i, outputs(b));
input = ( _,_,_ ) ;
in_c = inputN(0, input);
in_b = inputN(1, input);
in_a = inputN(2, input);
process = (in_a, in_b : +), in_c : *;
Now it considers 9 inputs:
virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) {
//zone1
//zone2
//zone2b
//zone3
FAUSTFLOAT* input0 = input[0];
FAUSTFLOAT* input1 = input[1];
FAUSTFLOAT* input2 = input[2];
FAUSTFLOAT* input3 = input[3];
FAUSTFLOAT* input4 = input[4];
FAUSTFLOAT* input5 = input[5];
FAUSTFLOAT* input6 = input[6];
FAUSTFLOAT* input7 = input[7];
FAUSTFLOAT* input8 = input[8];
FAUSTFLOAT* output0 = output[0];
//LoopGraphScalar
for (int i=0; i<count; i++) {
output0[i] = (FAUSTFLOAT)((double)input6[i] * ((double)input2[i] + (double)input4[i]));
}
}
OK, so why not using this approach:
foo1(in_a, in_b, in_c) = (in_a, in_b : +), in_c : *;
foo2(in_a, in_b, in_c) = (in_c, in_b : +), in_a : *;
foo3(in_a, in_b, in_c) = (in_c, in_c : +), in_c : *;
foo4 = \(in_a, in_b, in_c).((in_c, in_b : +), in_a : *);
//process = foo1;
//process = foo2;
//process = foo3;
process = foo4;
where you name inputs are arguments of a function and use them where you need in the function body ?
This looks out like a serious code duplication. Also, what should I do if I want to inject one of the inputs directly into the middle of the processing chain? Rewrite the previous part of the chain to add this argument? Rewrite all affected functions to pass this parameter as an Nth argument? That's not a good idea.
Sorry but this is not a forum to learn how to program in Faust, but to report bugs. Please read the tutorials and documentation available on https://faust.grame.fr.
@orlarey So, you have no good solution now and just closing the issue? Seriously?
For programming questions, better use the mailings lists https://faust.grame.fr/community/mailing-lists/ or possibly the Faust Slack channel: https://join.slack.com/t/faustaudio/shared_invite/enQtNzk2ODMxMzM4MzExLTdjYmUyZmQ4MzRkMWY5OTFhNTIzYmMwMDQ2YmM5M2VlYjU1YjBlYjg4OTQxM2RjMGM5Njc0NjVmZGJjY2E3MDI
My usual approach to naming signals goes like this:
inSigs = , ; leftChannel = inSigs : , !; rightChannel = inSigs : !, ; process = leftChannel, rightChannel;
Does this apply for you? (Buzzed through email history very quickly)
On Thu, Jan 16, 2020 at 1:55 AM Stéphane Letz notifications@github.com wrote:
For programming questions, better use the mailings lists https://faust.grame.fr/community/mailing-lists/ or possibly the Faust Slack channel: https://join.slack.com/t/faustaudio/shared_invite/enQtNzk2ODMxMzM4MzExLTdjYmUyZmQ4MzRkMWY5OTFhNTIzYmMwMDQ2YmM5M2VlYjU1YjBlYjg4OTQxM2RjMGM5Njc0NjVmZGJjY2E3MDI
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/grame-cncm/faust/issues/385?email_source=notifications&email_token=AAQZKFNW5WJHN33MQT3VYVLQ6AVHFA5CNFSM4KG2PYYKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJDOY3Q#issuecomment-575073390, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQZKFJKDOV5DGSUIPO4XKDQ6AVHFANCNFSM4KG2PYYA .
Julius O. Smith III jos@ccrma.stanford.edu Professor of Music and, by courtesy, Electrical Engineering CCRMA, Stanford University http://ccrma.stanford.edu/~jos/
This end up with a block with 4 inputs and 2 outputs, which is not what was wanted AFAICS:
virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
FAUSTFLOAT* input0 = inputs[0];
FAUSTFLOAT* input1 = inputs[1];
FAUSTFLOAT* input2 = inputs[2];
FAUSTFLOAT* input3 = inputs[3];
FAUSTFLOAT* output0 = outputs[0];
FAUSTFLOAT* output1 = outputs[1];
for (int i = 0; (i < count); i = (i + 1)) {
output0[i] = FAUSTFLOAT(float(input0[i]));
output1[i] = FAUSTFLOAT(float(input3[i]));
}
}
@sletz , right. I mean if the language follows some kind of digital schematics, then at least this should be possible:
Better use the Faust Slack channel (faustaudio.slack.com).
Consider this code:
The generated C++ code:
Seems that Faust provides no way to identify that 'in_c' is input2 but not input0. Is there any way to strictly define index of input in Faust code?