Recent versions of Faust are broken on OWL/Magus

Faust version that is forked in Rebeltech github is 3+ years old, I suppose it’s what being used in web server. It also requires an ancient version of LLVM, which makes it not really suitable for compiling on a modern desktop.

  • With current version of Faust I get tons of errors even on a trivial program if I try to compile Faust patches (i.e. even compiling something like “process = 1” would fail): error.log · GitHub

Note that this is similar to issue that got fixed a while ago by including an extra header file - Faust problems

I’ve got a trivial Faust program working with this patch: broken_faust.diff · GitHub

This #include <algorithm> is being added by faust in autogenerated patch file, adding it earlier prevents the conflict but it also requires undefining min/max macros. Another option that seems to work is to remove that include from patch file manually. But it’s added by Faust and I’m not sure if this can cause some other issues.

  • When compiling non-trivial patches I get more conflicts - the exact errors depend on patch contents, but seem to be caused by Faust using trigonometric functions from std namespace, while they are defined in global namespace in basicmath.h . I may not understand this issue correctly, but at least replacing manually std::cos → cos, std::sin-> sin in FaustPatch.hpp resolved it.

Example error:

In file included from ./LibSource/Patch.h:5:0,
from ./Source/SampleBuffer.hpp:8,
from ./Source/PatchProgram.cpp:6:
./Build/Source/FaustPatch.hpp: In member function ‘virtual void mydsp::compute(int, float**, float**)’:
./LibSource/basicmaths.h:98:16: error: ‘arm_cos_f32’ is not a member of ‘std’
#define cos(x) arm_cos_f32(x)
^
./Build/Source/FaustPatch.hpp:1124:35: note: in expansion of macro ‘cos’
float fSlow19 = (fConst4 * std::cos((fConst5 * fSlow18)));
^~~
./LibSource/basicmaths.h:98:16: note: suggested alternative:
#define cos(x) arm_cos_f32(x)
^
./Build/Source/FaustPatch.hpp:1124:35: note: in expansion of macro ‘cos’
float fSlow19 = (fConst4 * std::cos((fConst5 * fSlow18)));

  • There’s some weirdness in reading parameters. Let’s say I move parameter with encoder from 0 to 0.5 and stop. If I move it backwards (towards 0), I see that it jumps in old direction (i.e. to 0.55) before it starts moving in reverse. This happens in Faust patches and in factory patches. I haven’t checked if actual numeric value is changed or it’s just a quirk in how values are displayed.

  • There’s another bug that only happens in Faust patches. Some parameters (A, C, E) are either stuck on min value when patch is initialized or stuck on max value if I move to it. This happens even I don’t use those parameters in patch.

  • If I read encoder parameter as gate, it works fine. But when I receive a gate from CV in one of the inputs, it looks like the value is constantly retriggering gate in my patch. I’m not sure why that would happen, but it looks like parameter value is getting reset. Haven’t tested this outside of Faust patches yet.

  • I’ve ran into situation where my parameters didn’t appear when program was running on device. Turns out, it happened due to this code: OwlProgram/owl.cpp at master · pingdynasty/OwlProgram · GitHub . Yes, “freq” and “gain” are fairly common parameter names.

@sletz suggested compiling -std=c++11 for this issue. Owl makefile specified -std=gnu++11 already (which should be pretty much the same ANSI standard with a few extensions) , changing it gives a few errors due to stpncpy/stpcpy/strlcpy functions not present. After replacing those functions with similar functions just to get past this errors, I get the same errors as before - both related to min/max conflict and trigonometric functions missing in std.

Regarding std::sin/std::cos being broken, apparently this is due to fast sin/cos defined as macros in basicmaths.h. If they get called from std namespace, they would call functions from CMSIS lib using std namespaces. I’ve tried replacing macros with inlined functions and that solves this. I think the issue for me. I think that we should at least do it conditionally if compiling Faust patches.

Several points:

  • I’ve just fixed a bug in the faust2owl script
  • I think we/you should start again from the last version of the Faust compiler (2.19.4 on master-dev branch here: GitHub - grame-cncm/faust: Functional programming language for signal processing and sound synthes)
  • for math functions the C++ backend now uses std::name everywhere since it is the proper way to generate C++ code that uses the polymorphic versions of those functions (that is when the code is generated in “float” to “double” mode)
  • It this cause new issues in the Owl context, note that pure C code could also be generated, in case it helps?
1 Like

I’ve just fixed a bug in the faust2owl script

Actually, I think that faust2owl is used when generating patches that are bundled with OwlWare firmware, but for user patches faust compiler is called directly using a custom arch file. So your changes to that script won’t fix my issue as I was not using faust2owl. For reference - OwlProgram/faust.mk at master · pingdynasty/OwlProgram · GitHub

I’m not sure that it is a good idea to have a separate copy of owl.cpp in OwlProgram instead of using the one that is bundled with Faust. They can get out of sync - in fact they already have some differences, i.e. OwlProgram/owl.cpp at master · pingdynasty/OwlProgram · GitHub , OwlProgram/owl.cpp at master · pingdynasty/OwlProgram · GitHub are not present in Faust repo.

I think we/you should start again from the last version of the Faust compiler (2.19.4 on master-dev branch here: GitHub - grame-cncm/faust: Functional programming language for signal processing and sound synthes)

I was already using this branch and just rebuilt it from latest commit, makes no difference. Also, I’ve confirmed that if I use faust2owl script and build resulting file as C++ file, I get the same errors.

for math functions the C++ backend now uses std::name everywhere since it is the proper way to generate C++ code that uses the polymorphic versions of those functions (that is when the code is generated in “float” to “double” mode)

Yeah, this just got broken in Owl accidentally, I’m not sure if there’s anything to be fixed on Faust side. OTOH, Owl uses macros for calculating trigonometric functions that are optimized for ARM and they are available for floats only. I think that we generally don’t won’t to use doubles on Owl as that would require either running code that is not optimized for this CPU or simply casting results of optimized calculation from float to double.

It this cause new issues in the Owl context, note that pure C code could also be generated, in case it helps?

I don’t think it’s a good idea to do that - the proper fix would be to resolve clashes with std namespace. But having non-polymorphic calls to math stuff may be useful.

I think we need to hear something from @mars - are there plans to upgrade Faust version used on Owl platform anytime soon?

Yes I see now that Faust owl.cpp is an older version. Obviously we should find a way to keep the files synchronized.

I’ve noticed that faust has -fm switch for specifying custom fast math file. This replaces function calls that use std namespace, i.e. instead of std::XXX for sin/cos in generated code it would call fast_XXX. The fast math file that is used by default mentions being adapted from Owl and I see that there are some function present in Owl’s basicmath file. I think that if Owl defined remaining platform specific stuff missing in basicmath file under the same names that faust uses in its default file, it would be possible to compile patches using fast functions from that file.

Yes, very good idea indeed: -fm was actually added for that kind of use-case. But not so really used in real for now. Time is now…:wink:

I’ve experimented with this approach and can confirm that it solves issues I was having. Ended up with something like this: Resolve fast functions conflict · antisvin/OwlProgram@c210d6e · GitHub

It works and I can compile patches. I’ll spend some more time testing this code before submitting PR.

One minor but very annoying issue that was present in Owl’s Faust patches is that default values set in Faust were discarded. It didn’t matter for Owl as it had potentiometers, but Magus has encoders and that means we always get min values instead of defaults. It was straightforward to get it to work - Pass default values from Faust widgets · antisvin/OwlProgram@baff7fe · GitHub

Also, while looking in current Owl code, I’ve realized that there are other places that could be improved. It stores parameters values as floats in 0.0-1.0 range and user can define accessor objects for parameters. The latter supports scaling values to specific range, default values, smoothing, hysteresis, scaling algorithms (log/lin/exp scaling). Faust’s owl.cpp just reads parameter values reimplements a subset of parameter processing functionality (setting min/max values and now setting defaults). Using Owl’s native parameter calculation could simplify Owl’s arch file. It would also make it possible to support scaling algorithm via Faust labels (scale:xxx metadata) and expose additional options as custom metadata labels.

@antisvin has made a wonderful pull request for this which is now merged. In other words: Stas has contributed a code update!

I’m working to get this deployed on our dev server so we can test it with the online compiler.

1 Like

Here’s a sample patch for testing this : https://www.rebeltech.org/patch-library/patch/New_Faust_Features .

@mars I’ve noticed that OwlProgram repo has some unit tests in TestPatches dir that are not documented in README file. I’ve tried running them one of them like “make test TEST=FloatArrayTest” , but it failed. Am I doing something wrong or are those tests broken?

Log at test_error.log · GitHub

On the Faust repository we have an older version of the owl.cpp file (see faust/owl.cpp at master-dev · grame-cncm/faust · GitHub) that is then used the the online compiler (GitHub - grame-cncm/faustservice). This is bad for people using the online compiler…

I’m not clear in how people are using your toolchain. Are they supposed to use the faust2owl tool manually ? Should we completely remove the “OWL” target from the faustservice ? Or do you think your owl.cpp version could be used in the faustservice tool (and thus a PR to update the owl.cpp file would be helpfull…)

I think it would be nice to keep the OWL target in the faustservice, so people have options for how they use it.
Most of our users either use our online compiler or the OwlProgram build environment, which atm includes its own owl.cpp. This has been so that we could version it independently of FAUST, but now that it is not changing much it would make sense to unify the two.
I was going to have a look at this next, but I’ve become a bit stuck with upgrading FAUST on our online compiler server, which is Ubuntu based. There’s no LTS version with FAUST > 0.9.4, and I’m getting out of memory errors building it from source due to the limited resources on the AWS instance. Is there not somewhere a .deb of a recent FAUST for Ubuntu 16.04, or failing that, 18.04?

Thanks for considering the “great unification” :wink:. Concerning packaging I’m not too much following that, so you’ll have to ask on the Faust mailing list again, to other channels.

Martin,
there’s a build of recent Faust for Ubuntu 18.04 at State of xUbuntu_18.04 for home:aggraef:pure / faust - openSUSE Build Service , direct download link is https://download.opensuse.org/repositories/home:/aggraef:/pure/xUbuntu_18.04/amd64/faust+llvm35_2.11.14+git20190822+10160-1_amd64.deb . I’m not using Ubuntu, so no idea if it works or not.

2 Likes

I’ve managed to build faust from master-dev branch on the live server now, so everything is up to date on the online compiler.

Recent versions of Faust required a few extra functions for fast math (since we use that as a workaround to avoid conflicts with min/max macros). I’ve prepared them as part of next update (it will also add support for VOct calculations using calibration data!). I don’t expect Faust to be heavily used and it may not occur in every patch - so it may not be a big deal now. But I can create separate PR for this quickly if anyone would report failures.

Please contact me if you want us to deploy an updated version of the OWL target on our remote compiler service.

1 Like

@sletz, I have another update in the works, I think it would be better to wait until it’s merged unless you’re ok with extra work for updating remote compiler twice.

The update I’ve mentioned exposes volts per octave scaling for device inputs and outputs. This allows using eurorack sequencers or writing one to run on Owl.

Also, FYI https://faust.grame.fr/tools/onlinecompiler/ is currently returning PHP file as text instead of executing it.

1 Like