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

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.