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

I debugged the webpage and found this:

 _f4u$t.server_update_function = _f4u$t.main(...);
-> 
var URLParams = _f4u$t.parseURLParams(document.URL);
->
 if (query === url || query === "") return;

query and url are both "http://192.168.7.2:5510/"
in that case:

  if (URLParams) {
 ...
 }
  else {
    _f4u$t.make_ui(svg, raw_json);

raw_json is null and therefore to ui.
Please advise.

Please use Markdown to format your posts in order to make them more comprehensible. In particular, use lines with ``` to surround blocks of code (see my edits above to your latest posts).

it looks like the _f4u$t.main() call is passing a json as first argument, while the _f4u$t.main() definition in http://www.mikesolomon.org/faust/svg/faust_proto.js expects function(svg, raw_json), so it seems that there is a mismatch there between the two files.

The faust_proto.jsin faust/architecture/httpdlib/html/js/svg/faust_proto.js instead seems to accept the same arguments that are passed in the html file, so you should probably use this instead of the mikesolomon one. In order to use this you probably have to remove the #define LOADSCRIPTS line you added in https://github.com/grame-cncm/faust/blob/master-dev/architecture/httpdlib/src/html/htmlpage.cpp following my above suggestion and probably you will have to declare stylesheet_len, stylesheet, jsscripts, jsscripts_len in your .cpp file instead. They are declared as

// in faust/architecture/httpdlib//src/html/stylesheet.h
extern unsigned char stylesheet[];
extern unsigned int  stylesheet_len;
// in faust/architecture/httpdlib//src/html/jsscripts.h
extern unsigned char jsscripts[];
extern unsigned int  jsscripts_len;

Judging by the way they are being parsed in https://github.com/grame-cncm/faust/blob/master-dev/architecture/httpdlib/src/html/htmlpage.cpp, these should be char[] which should contain actual css and js code. I have no idea how you would generate that.

So here is another trick: change the generated html (or even better the faust/architecture/httpdlib/src/html/htmlpage.cpp file) so that it does not use those remote URLs but the local files with the same name provided by faust in faust/architecture/httpdlib/html/js/svg/. The relative paths to the files will depend on where the root of the http server is. Something like this may work, or try changing the prefix to svg/...

  <script type="text/javascript" src="js/svg/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="js/svg/jquerysvg/jquery.svg.js"></script>
    <script type="text/javascript" src="js/svg/jquerysvg/jquery.svgdom.js"></script>
    <script type="text/javascript" src="js/svg/faust_proto.js"></script>
    <script type="text/javascript" src="js/svg/faust_jquery_svg_backend.js"></script>
    <script type="text/javascript" src="js/svg/faust_mobile.js"></script>
    <script type="text/javascript" src="js/svg/faust_ui_inits.js"></script>
    <script type="text/javascript" src="js/svg/faust_load_external_file.js"></script>
    <script type="text/javascript" src="js/svg/faust_ui_objects.js"></script>
    <script type="text/javascript" src="js/svg/faust_ui_builder.js"></script>

with your html file appropriately placed in a local http server, the above works for me and I get displayed a GUI (no idea if the backend communication works though).

Thanks a lot. I&ll take care of that (had the same idea about local scripts). And sorry about not correctly formatted code. I'll try to get better.

So far so good, the local js storage is working now and also the parameters are fine (raw_json is correct). But now I'm only getting a black background. Reason:
these lines in faust_proto.js:

    if (callback) {
        _f4u$t.HANDLER_CALLBACKS.push(function(address, value) {
                                      if (_f4u$t.first_part_matches(address, hash)) {
                                      return callback(_f4u$t.remove_from_head_of_string(address, hash), value);
                                      }
                                      });
    }

prevent the building of the svg controls.
When commented,the page shows the svg controls. But no callback action.

alt text

I have no idea what svg is supposed to appear there, but given that the call to _f4u$t.main passes null as the svg argument, I am not sure I would expect anything different really!

do you manage to control the sound parameters with the sliders?

Yes, all I had to do to add another js script to the page:

<script type="text/javascript" src="/js/svg/faust_ui_audio_bridge.js"></script> =>

<html>
  <head>
    <script type="text/javascript" src="/js/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="/js/svg/jquerysvg/jquery.svg.js"></script>
    <script type="text/javascript" src="/js/svg/jquerysvg/jquery.svgdom.js"></script>
    <script type="text/javascript" src="/js/svg/faust_proto.js"></script>
    <script type="text/javascript" src="/js/svg/faust_ui_audio_bridge.js"></script>
    <script type="text/javascript" src="/js/svg/faust_jquery_svg_backend.js"></script>
    <script type="text/javascript" src="/js/svg/faust_mobile.js"></script>
    <script type="text/javascript" src="/js/svg/faust_ui_inits.js"></script>
    <script type="text/javascript" src="/js/svg/faust_load_external_file.js"></script>
    <script type="text/javascript" src="/js/svg/faust_ui_objects.js"></script>
    <script type="text/javascript" src="/js/svg/faust_ui_builder.js"></script>
    <script type="text/javascript" src="/js/svg/faust_ui_interact.js"></script>
    <script type="text/javascript" src="/js/svg/faust_server_communication.js"></script>
    <link rel="stylesheet" type="text/css" href="/js/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": "hgroup",      "label": "Basic_Parameters",      "items": [       {        "type": "nentry",        "label": "freq",        "address": "/WaveGuide_Sitar/Basic_Parameters/freq",        "meta": [          { "1": ""},         { "tooltip": "Tone frequency"},         { "unit": "Hz"}        ],        "init": "440",        "min": "20",        "max": "20000",        "step": "1"       },       {        "type": "nentry",        "label": "gain",        "address": "/WaveGuide_Sitar/Basic_Parameters/gain",        "meta": [          { "1": ""},         { "tooltip": "Gain (value between 0 and 1)"}        ],        "init": "1",        "min": "0",        "max": "1",        "step": "0.01"       },       {        "type": "button",        "label": "gate",        "address": "/WaveGuide_Sitar/Basic_Parameters/gate",        "meta": [          { "1": ""},         { "tooltip": "noteOn = 1, noteOff = 0"}        ]       }      ]     },     {      "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"       }      ]     }    ]   }  ] } ', null, _f4u$t.faust_server_handler);
    </script>
  </body>
</html> 

It's working now (sounds a little bit different compared to faust playground, but essentially it's fine.
ToDo: add a symbolic link to the js directory in projects/<proj name>, so you don't need to copy those scripts there.
This directory is the root of the faust webserver.
And next, how to include this server as a tab into the Bela IDE (I have no idea).

    DragonSF It's working now

    good news!

    DragonSF ounds a little bit different compared to faust playground,

    hmmm maybe you have some analog inputs being used in your dsp scripts and these are not connected to anything and left floating on the board?

    DragonSF And next, how to include this server as a tab into the Bela IDE (I have no idea).

    I guess we can think about that in a larger revision of the IDE we are going to do in the next few months. I guess in the meantime it is fine to have it in a different tab?

      giuliomoro Yes, I'm fine with having the GUI for Faust in a different tab. And think about creating a symbolic link for a new Faust project directly in the project directory. We need also some sort of automatic faust compile of the DSP file. JIT takes too long or doesn't load correctly.

      Oh what do you mean "JIT doesn't load correctly"?

      We expect JIT to be faster than Faust->C++->binary, but I have not really benchmarked that yet. The jit-generated binary could then be cached to disk for faster startups (i.e.: comparable to the C++-generated binary) after the first compilation.

      Maybe there is a way to start the webserver with a different root, without the need to create symlinks, will have to check the docs/source.

        That's strange, when I run this as jit, it took about 10min to start.

        giuliomoro We expect JIT to be faster than Faust->C++->binary, but I have not really benchmarked that yet

        I mean that the time it takes to do the JIT should be faster than compiling dsp to C++ and C++ to binary, but the JIT happens when you start the program (and needs to be cached to disk: it is not being cached currently), while the C++ way happens before you start it.

        How long does it take to compile the same FAUST code to C++ and compile the C++ code? Can you post the example dsp file?

        DSP file:

        declare name "WaveGuide Sitar";
        declare author "Romain Michon (rmichon@ccrma.stanford.edu)";
        declare copyright "Romain Michon";
        declare version "1.0";
        declare licence "STK-4.3"; // Synthesis Tool Kit 4.3 (MIT style license);
        declare description "This instrument implements a sitar plucked string physical model based on the Karplus-Strong algorithm using a randomly modulated delay line.";
        
        import("music.lib");
        import("instrument.lib");
        
        //==================== GUI SPECIFICATION ================
        
            freq = nentry("h:Basic Parameters/freq [1][unit:Hz] [tooltip:Tone frequency]",440,20,20000,1);
        	gain = nentry("h:Basic Parameters/gain [1][tooltip:Gain (value between 0 and 1)]",1,0,1,0.01); 
        	gate = button("h:Basic Parameters/gate [1][tooltip:noteOn = 1, noteOff = 0]");
        //freq = hslider("[1]Frequency[BELA:ANALOG_0]", 440,460,1500,1):smooth(0.999);
        //gain = 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);
        
        //gate = hslider("[0]ON/OFF (ASR Envelope)[BELA:ANALOG_0]",0,0,1,1);
        
        resonance = hslider("v:Physical Parameters/Resonance
        	[2][tooltip:A value between 0 and 1]",0.7,0,1,0.01)*0.1;
        
        //==================== SIGNAL PROCESSING ================
        
        //stereoizer is declared in instrument.lib and implement a stereo spacialisation in function of 
        //the frequency period in number of samples 
        stereo = stereoizer(SR/freq);
        
        //excitation envelope (adsr)
        envelope = adsr(0.001,0.04,0,0.5,gate);
        
        //the delay length is randomly modulated
        targetDelay = SR/freq;
        delayLength = targetDelay*((1+(0.5*noise)) : smooth(0.9992));
        	delayLine = delay(4096,delayLength);
        
        //the loop gain control the resonance duration
        loopGain = 0.895 + resonance + (freq*0.0000005);
        amGain = 0.1*gain;
        
        //feedback filter is a one zero (declared in instrument.lib)
        filter = oneZero1(b0,b1)
        	with{
        			zero = 0.01;
        					b0 = 1/(1 + zero);
        							b1 = -zero*b0;
        								};
        
        process = (*(loopGain) : filter + (envelope*noise*amGain))~delayLine : *(8) : 
        	stereo : hgroup("Reverb[3]",component("freeverb.dsp"));

        compiling with faust: root@bela:~/Bela/projects/nfaust# time faust sitar.dsp >sitar.h

        real 0m2.095s
        user 0m0.952s
        sys 0m1.000s

        making with the IDE: about 2-3 min.

        To speed up JIT compilation, one could imagine to develop a "remote cross-compilation service":

        • the Bela card would access a distant server (that could be remote or running on the machine running Bela IDE), send the Faust DSP and a description of its architecture (CPU...)
        • the server does cross compilation that is: Faust DSP ==> LLVM IR ==> machine code, for the requesting machine
        • send back the machine code on the Bela card
        • have the Bela card dynamically load the machine code and execute it.

        I already tested the path : Faust DSP ==> LLVM IR ==> machine code ==> other machine ==> dynamic load/execute in another context, so in theory it should work also on the Bela card.

        We'll probably explore that starting in may.

        BTW nice to see the httpUI control working !

        I can give you my changed sources (if you want), but it actually wasn't that many changes. Most work was the correct installation of all the libraries involved and find the culprit.

        8 months later

        Sorry I am late to the game.

        Did this again and found that the painless way of building HTTPDFaust is to use the provided Makefile in faust/architectures/httpdlib/src/Makefile instead of using the cmake file in faust/architectures/httpdlib/cmake/CMakeLists.txt. The provided Makefile links in the files in hexa/ which provide definitions for jsscripts, jsscripts_len, stylesheet, stylesheet_len. Run with make dynamic and generates a dynamic library faust/architecture/httpdlib/libHTTPDFaust.so.

        Reported here https://github.com/grame-cncm/faust/issues/232

        Yes, we have to fix that. Thanks also for your various fixes. I'll try to make the FaustEditor export to bela work again next week.