• SoftwareFaust
  • My experience with Faust, and some more general observations

looks like --faust is not an option for main.cpp (I'll look at that later).

    DragonSF looks like --faust is not an option for main.cpp (I'll look at that later).

    correct:

    giuliomoro if you compiled the FAUST-generated C++ code, then you would not be loading a .dsp file at runtime, therefore the --faust filename.dsp option is not supported, but that options is probably still in your IDE settings and you should remove it.

      giuliomoro : yes, the flute example needs a GUI action. My folder (nfaust) is actually the same as your github folder. I replaced the main.cpp with the mentioned code and render.cpp with the bela.cpp code. In render.cpp I added $include "faust.,h", which contains the compiled faust.dsp code. That's it. If you want, I can upload the whole project. But without GUI, Faust is meaningless.
      Any idea, what's the problem with the GUI is?

      FAUST on Bela is meant to run without GUI, using Bela's inputs as controllers.

      These lines in the faust.dsp file

      freq = hslider("[1]Frequency[BELA:ANALOG_0]", 440,460,1500,1):smooth(0.999);
      pressure = hslider("[2]Pressure[style:knob][BELA:ANALOG_4]", 0.96, 0.2, 2.0, 0.01):smooth(0.999):min(0.99):max(0.2);

      mean (as far as I understand, as I know nothing about FAUST) that you can use either an hslider or the Bela analog inputs in order to control freq and pressure. In fact here I am playing titanic on it using a breath sensors and a slider:

      In the future there may be a GUI (e.g.: as an additional tab in the IDE), which would make tweaking parameters easier during prototyping, but ultimately, I think that the final objective of running some program on Bela is to run it embedded, controlled by the sensors.

      Thanks for the advice. I neither do know anything about Faust programming, but I'm trying to learn. I could connect my BSP (which luckily has analog outputs) and get some sound. And also I solved the mystery with the Faust file as command options. Works now as expected.
      And yes, a GUI would be awesome. If you need help with that, I'm willing to do whatever is necessary.

        DragonSF And yes, a GUI would be awesome. If you need help with that, I'm willing to do whatever is necessary.

        I think the steps needed here are to generate a web-based GUI and then serve it from a tab in the browser.
        The faust playground can generate GUIs from FAUST code. I have no idea how that is done, but going through its source code you may find a way of generating the GUI and serve it as a page (either with a python server, as they do, or plugging into our node server). Once that is done, the sliders on the GUI can be hooked up to send OSC messages to the running audio backend (perhaps similarly to what we did here with NexusUI).

        I don't think this is easy or straightforward, but if you really have time to dig into this, then I think the above sums it up well. @sletz - who is one of the developers of FAUST - will have a better idea than I have on the subject.

        Yes, I'll try to dig into that. Have enough time at the moment.

        @sletz suggests:

        We already have a « server a web-based GUI to the user » model. On server side we use libmicrohttpd (https://www.gnu.org/software/libmicrohttpd/) to have the Web server running, wrapping/controlling the running DSP, delivering a HTML + SVG + CSS page to the browser. Then messages are sent/received using HTTP requests (which is a bit heavy but works…) This could be a starting point, possibly using OSC an an alternate protocol later on.

        You can see this HTML + SVG + CSS code used in another context here : http://faust.grame.fr/modules/. In this case we just generated static pages, but you can see the kind of UI we get.

        To activate HTTP UI control you will have to follow what is done in other architecture files, like : https://github.com/grame-cncm/faust/blob/master-dev/architecture/jack-qt.cpp

        So adding in the bela.cpp template file:

        #include "faust/gui/httpdUI.h"
        
         httpdUI httpdinterface(name, fDSP.getNumInputs(), fDSP.getNumOutputs(), argc, argv);
         fDSP.buildUserInterface(&httpdinterface);
         ...
        httpdinterface.run(); 

        Then you'll have to compile the code in faust source tree: /architecture/httpdlib and link also with libmicrohttpd (https://www.gnu.org/software/libmicrohttpd/)

        Then starting the program will start a libmicrohttpd based server at http://127.0.0.1:5510, that should display the UI to control the DSP running on the Bela card.

        A bit of work but not impossible...

        Do you mean render.cpp (instead of bela.cpp)?
        I found a gem: if (p == '.' | p == ',') (really?) ;-)

        So, I got the /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so, how do I have to link this to the bela project?
        (I guess, I have to change the Makefile, but what will be the code for including the shared lib)?

          I finally got around adding the so file, but now I'm lost (again):
          /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to jsscripts_len'
          /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to
          stylesheet_len'
          /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to stylesheet'
          /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to
          jsscripts'

          This variables are defined as 'extern', but in what library?
          This is the line in Makefile, I'm using:
          LDFLAGS += $(DEFAULT_XENOMAI_LDFLAGS) -Llib/ -lasound -lsndfile -lseasocks -L/root/faust/architecture/httpdlib/ -lHTTPDFaust /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so

          It may be that they are referenced here?
          https://github.com/grame-cncm/faust/blob/master-dev/architecture/httpdlib/src/html/htmlpage.cpp#L122-L144

          It seems that if you #define LOADSCRIPTS then a number of external .js and .css files are loaded, but if you don't, you should have in your code some variables stylesheet_len, stylesheet, jsscripts, jsscripts_len which should point to some appropriate scripts (which you are probably supposed to provide yourself?).

          I'd recommend you #define LOADSCRIPTS at the top of that file and try to rebuild and see what happens.

          DragonSF Do you mean render.cpp (instead of bela.cpp)?

          The render.cpp that is in the bela-faust-jit repo is based on the bela.cpp that you find in the FAUST repo. The former allows dynamic loading and just-in-time compilation of FAUST code, while the latter is meant to be used with some FAUST-generated C++ code. The GUI/libmicrohttpd issue you are facing now should be independent of which of the two you use.

          (remember that to get that render.cpp to work with the latest FAUST you'd need this I think:

          giuliomoro Perhaps just adding virtual void addSoundfile(const char label, const char filename, Soundfile** sf_zone) {} inside class BelaUI : public UI would have fixed this.

          )

          Your adviced worked so far, that I can link and run the application:
          Faust httpd server version 0.73 is running on TCP port 5510
          But when I try to connect, I'm getting: Unable to connect. Strange.
          When I use the 'ss' command, I can't see any app listen to port 5510.

          What address are you trying to connect to?

          Maybe try curl from the board itself? like curl localhost:5510 or try telnet localhost 5510 then from the host telnet 192.168.7.2 5510

            using strace:
            open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 10
            fstat64(10, {st_mode=S_IFREG|0644, st_size=124, ...}) = 0
            read(10, "127.0.0.1\tlocalhost\n127.0.1.1\tbe"..., 4096) = 124
            read(10, "", 4096) = 0
            close(10) = 0
            socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 10
            setsockopt(10, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
            bind(10, {sa_family=AF_INET, sin_port=htons(5510), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
            listen(10, 128) = 0
            fcntl64(10, F_GETFL) = 0x2 (flags O_RDWR)
            fcntl64(10, F_SETFL, O_RDWR|O_NONBLOCK) = 0
            mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb5282000
            mprotect(0xb5282000, 4096, PROT_NONE) = 0
            clone(child_stack=0xb5a80f88, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb5a814b8, tls=0xb5a81910, child_tidptr=0xb5a814b8) = 5768
            fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
            write(1, "Faust httpd server version 0.73 "..., 60Faust httpd server version 0.73 is running on TCP port 5510
            ) = 60
            shutdown(10, SHUT_RDWR) = 0
            close(10) = 0
            Doesn't seem correct to me.

            giuliomoro I tried taht, no avail. No process is listen at port 5510.
            root@bela:~/Bela/projects/nfaust# Faust httpd server version 0.73 is running on TCP port 5510
            curl localhost:5510
            curl: (7) Failed to connect to localhost port 5510: Connection refused
            same with local telnet:
            root@bela:~/Bela/projects/nfaust# telnet localhost 5510
            Trying ::1...
            Trying 127.0.0.1...
            telnet: Unable to connect to remote host: Connection refused

            Yeah it seems the socket gets shutdown.
            Maybe HTTPDControler::stop() is being called somewhere? Is your httpdUI object global? I guess if it goes out of scope, the destructor is called and the server is killed.

            That's an idea. I'll try that.
            Yes, that was the reason. Now I see something, but not as expected. I'll come back tomorrow.
            ATM the page source is:

            <html>
              <head>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/jquery-1.7.1.min.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/jquerysvg/jquery.svg.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/jquerysvg/jquery.svgdom.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_proto.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_jquery_svg_backend.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_mobile.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_inits.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_load_external_file.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_objects.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_builder.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_interact.js"></script>
                <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_server_communication.js"></script>
                <link rel="stylesheet" type="text/css" href="http://www.mikesolomon.org/faust/svg/faust_css.css"></link>
              </head>
              <body>
                <script type="text/javascript">
                  _f4u$t.server_update_function = _f4u$t.main('{  "name": "bela render",  "address": "127.0.1.1",  "port": "5510",  "inputs": "0",  "outputs": "2",  "ui": [   {    "type": "vgroup",    "label": "WaveGuide_Sitar",    "items": [     {      "type": "vgroup",      "label": "Physical_Parameters",      "items": [       {        "type": "hslider",        "label": "Resonance",        "address": "/WaveGuide_Sitar/Physical_Parameters/Resonance",        "meta": [          { "2": ""},         { "tooltip": "A value between 0 and 1"}        ],        "init": "0.7",        "min": "0",        "max": "1",        "step": "0.01"       }      ]     },     {      "type": "hgroup",      "label": "Reverb",      "meta": [        { "3": ""}      ],      "items": [       {        "type": "hgroup",        "label": "Freeverb",        "items": [         {          "type": "vgroup",          "label": "0x00",          "meta": [            { "0": ""}          ],          "items": [           {            "type": "vslider",            "label": "Damp",            "address": "/WaveGuide_Sitar/Reverb/Freeverb/0x00/Damp",            "meta": [              { "0": ""},             { "style": "knob"},             { "tooltip": "Somehow control the   density of the reverb."}            ],            "init": "0.5",            "min": "0",            "max": "1",            "step": "0.025"           },           {            "type": "vslider",            "label": "RoomSize",            "address": "/WaveGuide_Sitar/Reverb/Freeverb/0x00/RoomSize",            "meta": [              { "1": ""},             { "style": "knob"},             { "tooltip": "The room size   between 0 and 1 with 1 for the largest room."}            ],            "init": "0.5",            "min": "0",            "max": "1",            "step": "0.025"           },           {            "type": "vslider",            "label": "Stereo_Spread",            "address": "/WaveGuide_Sitar/Reverb/Freeverb/0x00/Stereo_Spread",            "meta": [              { "2": ""},             { "style": "knob"},             { "tooltip": "Spatial   spread between 0 and 1 with 1 for maximum spread."}            ],            "init": "0.5",            "min": "0",            "max": "1",            "step": "0.01"           }          ]         },         {          "type": "vslider",          "label": "Wet",          "address": "/WaveGuide_Sitar/Reverb/Freeverb/Wet",          "meta": [            { "1": ""},           { "tooltip": "The amount of reverb applied to the signal   between 0 and 1 with 1 for the maximum amount of reverb."}          ],          "init": "0.3333",          "min": "0",          "max": "1",          "step": "0.025"         }        ]       }      ]     },     {      "type": "vgroup",      "label": "Spat",      "items": [       {        "type": "hslider",        "label": "pan_angle",        "address": "/WaveGuide_Sitar/Spat/pan_angle",        "init": "0.6",        "min": "0",        "max": "1",        "step": "0.01"       },       {        "type": "hslider",        "label": "spatial_width",        "address": "/WaveGuide_Sitar/Spat/spatial_width",        "init": "0.5",        "min": "0",        "max": "1",        "step": "0.01"       }      ]     },     {      "type": "hslider",      "label": "ON_OFF_(ASR_Envelope)",      "address": "/WaveGuide_Sitar/ON_OFF_(ASR_Envelope)",      "meta": [        { "0": ""},       { "BELA": "ANALOG_0"}      ],      "init": "0",      "min": "0",      "max": "1",      "step": "1"     },     {      "type": "hslider",      "label": "Frequency",      "address": "/WaveGuide_Sitar/Frequency",      "meta": [        { "1": ""},       { "BELA": "ANALOG_0"}      ],      "init": "440",      "min": "460",      "max": "1500",      "step": "1"     },     {      "type": "hslider",      "label": "Pressure",      "address": "/WaveGuide_Sitar/Pressure",      "meta": [        { "2": ""},       { "BELA": "ANALOG_4"},       { "style": "knob"}      ],      "init": "0.96",      "min": "0.2",      "max": "2",      "step": "0.01"     }    ]   }  ] } ', null, _f4u$t.faust_server_handler);
                </script>
              </body>
            </html>