test-case:
// arbitrary kSamp signal
delay = ba.time : max(0) : min(10);
process = @(delay) <: _,_;
result:
iRec0[0] = ...;
output0[i] = FAUSTFLOAT(fVec0[std::min<int>(10, std::max<int>(0,
(iRec0[0] + -1)))]);
output1[i] = FAUSTFLOAT(fVec0[std::min<int>(10, std::max<int>(0,
(iRec0[0] + -1)))]);
you can see that "delay" is evaluated twice. Not really a bug, but doesn't look
good performance wise.
Similarly,
delay = ffunction(int func(),"","") : max(0) : min(10);
process = @(delay) <: _,_;
results in
output0[i] = FAUSTFLOAT(fVec0[std::min<int>(10, std::max<int>(0,
int(func())))]);
output1[i] = FAUSTFLOAT(fVec0[std::min<int>(10, std::max<int>(0,
int(func())))]);
and this is worse in that func() may have side effects, it shouldn't be called
twice.
This is because generateFixDelay() "ignores" getSharingCount(sig) so for example
process = mem <: _,_;
doesn't imply generateVariableStore() and this is fine. However this also means
that "delay" will be evaluated every time, its getSharingCount() == 1 unless it
has another user; sharingAnnotation(sig) will not look at getSubSignals(ig) if
getSharingCount(sig) is already non zero.
With the "patch" below
delay = ffunction(int func(),"","") : max(0) : min(10);
process = @(delay) <: _,_;
compiles to
int iTemp0 = std::min<int>(10, std::max<int>(0, int(func())));
output0[i] = FAUSTFLOAT(fVec0[iTemp0]);
output1[i] = FAUSTFLOAT(fVec0[iTemp0]);
and this is what I think faust should actually do.
Oleg.
--- a/compiler/generator/instructions_compiler.cpp
+++ b/compiler/generator/instructions_compiler.cpp
@@ -697,6 +697,9 @@ ValueInst* InstructionsCompiler::generateFixDelay(Tree sig,
Tree exp, Tree delay
}
}
+if (getSharingCount(delay)==1 && getSharingCount(sig)>1)
+ setSharingCount(delay, 2);
+
if (mxd == 0) {
return InstBuilder::genLoadStackVar(vname);
} else if (mxd < gGlobal->gMaxCopyDelay) {
_______________________________________________
Faudiostream-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/faudiostream-users