Faust problems

Home Forums OWL Patches Faust problems

Tagged: 

This topic contains 46 replies, has 3 voices, and was last updated by  Martin Klang 5 months, 3 weeks ago.

Viewing 15 posts - 16 through 30 (of 47 total)
  • Author
    Posts
  • #2915

    Stas Shtin
    Participant

    Faust support MIDI the same way as it does OWL CV inputs – using parameter metadata. It’s actually has decent MIDI integration IMO – http://faust.grame.fr/news/2016/01/14/controlling-with-midi.html . If you look into physmodels.lib, most of the instruments defined there also have a MIDI-enabled frontend.

    I haven’t tried using it on OWL yet, but I will eventually want to write a few patches controllable with faders, i.e. a filterbank and maybe some additive oscillators.

    #2916

    Stas Shtin
    Participant

    Here’s an example of clarinet patch based on physmodels lib.

    import("stdfaust.lib");
    
    process = pm.clarinetModel(freq : pm.f2l, pressure, reedStiffness, bellOpening)
    with{
            freq = hslider("Frequency[OWL:PARAMETER_A]",440,50,1000,0.01);
            reedStiffness = hslider("Reed stiffnes[OWL:PARAMETER_B]",0.5,0,1,0.01);
            bellOpening = hslider("Bell opening[OWL_PARAMETER_C]",0.5,0,1,0.01);
            breathGain = hslider("Breath gain[OWL:PARAMETER_D]", 0.1,0,1,0.01)*0.05;
            pressure = hslider("pressure[OWL:PARAMETER_E]", 0, 0, 1, 0.01) : si.smoo;
            blow = pm.blower(pressure, 0.05, breathGain,vibratoFreq,vibratoGain);
            // Don't bother with vibrato - we can modulate frequency instead
            vibratoFreq = 0.1;
            vibratoGain = 0.1;
    };
    

    I plan to convert all instruments from that lib to OWL (15 in total, although 6 of them are different bell models). Then I’ll look into creating custom firmware (I’ve understood how to do it from reading docs). I will consider porting some from faust-stk code as well, but it doesn’t have a very a proper model separation and may require some refactoring .

    #2920

    Stas Shtin
    Participant

    I will certainly try using push button. Regarding output – the only other possibility I can think of would be by using foreign function calls API. But I’m not sure if we can expose patch object state like that and I AM sure that it would be more cumbersome to use. Example for this feature:

    SR = fconstant(int fSamplingFreq, <math.h>);
    BS = fvariable(int count, <math.h>);
    tanh = ffunction(float tanhf (float), <math.h>,"");

    As for oscillator’s memory usage – I suppose you mean sinwaveform table. To make things worse, I was using oscp function that also ends up creating another table for cosine data. I will try to rewrite my code to use a single table instead of oscp. That should cut memory by 65k and I can likely use a smaller table size. Calculating sines on the fly could be a bad idea in this particular case, because I want to use 10-20 oscillators as partials at once for this patch.

    Maybe you’ll have to use a patched oscillators.lib on server that would create smaller tables if there won’t be noticable degradation.

    #2924

    Martin Klang
    Keymaster

    Edit: I was wrong about tables being generated for sin or other math calls. Certain oscillators e.g. osci will generate tables. But the default osc will not.

    Incidentally sin and cos calls are very efficient on the OWL, as we have implementations optimised for the hardware.

    Foreign functions – I didn’t know about these. Looks interesting, we can probably use them to set output parameters.

    #2933

    Stas Shtin
    Participant

    Haven’t found any issues with latest update and gate input works as expected.

    If we’ll end up using foreign function calls for gate output, it makes sense to add a library that would have a wrapper for this. That would be slightly prettier. But I don’t quite see how this can be handled without performance overhead. We’d still be streaming data into that unit for every sample, because that’s how Faust works.

    And we’ll have to check if output button’s state changed for every sample, it could be that runnning a single pass over the whole buffer gives a smaller performance hit. The good thing here is that it happens only if gate out function call is actually used by the patch.

    But I have another concern about using FFI call. If it would send the gate immediately, that could bring audio and gate output out of sync. For example, I was thinking about a patch where we have a clocked output with divider/multiplier settings and want to send triggers when a new cycle begins. Or is there some buffering for sending gate and audio outputs at the same time?

    #2935

    Martin Klang
    Keymaster

    gate/button output ->
    I’ve pushed an update with a foreign function that you can use like this:

    
    push = ffunction(int owl_pushbutton(int), <owl.h>,"");
    process = hslider("Frequency[OWL:PARAMETER_A]",0,0,1,0.01) : int : push;
    

    (idiot patch, sorry!)

    The return value is simply the current state: 0 or 1. Any non-zero value turns the LED red and gate on.
    The function is called every sample, but registers changes which are propagated to the firmware along with the current sample count. Should be very efficient and accurate.

    I’ve done a bit of testing with the latest faust2 and it seems pretty solid.
    @stas if you are using faust2 let me know if you come across any problems.

    If there are no obvious issues I’d like to push the latest faust2 to the live server, and update our sample patches. Help with the latter would be much appreciated!

    #2936

    Stas Shtin
    Participant

    Ok, I’ve made a few tests. It certainly does work (and I am running it on faust2 branch). But I’ve noticed a few issues. It’s up to you to decide if they’re severe enough to fix, because it’s still better than having no gate output. So here’s the test patch I’ve used:

    import("stdfaust.lib");
    
    push = ffunction(int owl_pushbutton(int), <owl.h>,"");
    freq = hslider("Frequency[OWL:A]", 120, 20, 220, 1);
    process = ba.pulsen(100, ma.SR / freq : int) : push;
    

    That’s basically 100 samples wide pulse sent with 20-220 Hz frequency. Here’s what I’ve noticed:

    1. There’s a lag behind audio and gate out
    2. Lag duration depends on output buffer size – the bigger buffer, the later arrives gate signal, as expected
    3. On large buffer size, there’s some obvious jitter in gate output.

    It’s an unrealistic code, just something I came up to test current implementation under extreme conditions.

    And I’ve noticed another problem when testing this patch. Here’s how to reproduce it:

    1. Set frequency to miniumum, buffer size to 2.
    2. Now set frequency to maximum and try switching buffer size to anythnig else.

    What happens for me is that the patch seems to retrigger (i.e. there’s about 25 ms silence), but buffer size stays the same in over 95% cases. Sometimes it does changes though and everything works fine if clock frequency is reduced. The same happens if I try to switch to another patch. CPU usage stays below 10% all the time. I’m not sure if that’s even a problem with IO in OWL itself or it could be something related to Linux USB stack. But remote control works and I can toggle device polling.

    #2937

    Stas Shtin
    Participant

    I’ll be testing faust patches in OwlPatches repo, will leave you a PR with fixes if necessary.

    #2938

    Martin Klang
    Keymaster

    ok great – I’ve just pushed some changes I’ve done to OwlPatches/Faust, so make sure you pull.

    #2939

    Martin Klang
    Keymaster

    So to receive midi note messages in faust it seems you make a slider or button for each note.
    The only use of midi:key{on,off,press} I can find in the examples is in midiTester.dsp and it only seems to display the
    value pressed.
    Am I right in assuming that to handle all MIDI notes you would need 128 voices running in parallel, unless you use the experimental mute branch of Faust?

    The CC handling is nice. Control change messages are already mapped to OWL parameters so not sure we need [midi:ctrl]. Could add support for all 40 MIDI-enabled OWL parameters though.

    Regarding push output: yes, synchronising outgoing button/gate changes to the audio stream is on the firmware todo list.

    #2940

    Stas Shtin
    Participant

    As far as I understand, incoming midi MIDI note would be automatically mapped to a control with label “freq” and would be converted from midi note number to herz. And instruments from physical modeling library have MIDI-enabled models defined in that file i.e. https://github.com/grame-cncm/faust/blob/master-dev/libraries/physmodels.lib#L809-L823

    I think there used to be no good solution for MIDI-based polyphony and you’d have to define each voice separately and handle voice allocation outside of faust. Seems like there’s proper support for this now, but it must be done from architecture file. See some info here – https://github.com/grame-cncm/faust/tree/master-dev/architecture/api#midi-enabled-polyphonic-object

    #2941

    Stas Shtin
    Participant

    documentation/faust-quick-reference.pdf has some info regarding MIDI&polyphony in chapters 8&9. But it’s mostly written for users. After looking through architecture/jack-qt.cpp, it seems to be pretty easy to implement. I guess owl’s own MIDI code would somewhat complicate things, since you’d have to coordinate its host MIDI code with faust’s rtmidi library? Seems to be what architecture/faust/midi/jack-midi.h does for JACK MIDI connectivity.

    Here’s another useless fun fact I came up with: connecting OWL to Experst Sleepers FH-1 + 7x FH-1x expanders could give you up to 64 channels of CV controllable by MIDI. For now I can confirm that FH-1 can see Owl if I connect it by USB – but that should happen for any class compliant USB device.

    I don’t understand if there’s any way to generate MIDI events in faust. Even if not, it could probably be done by writing a faust library for exposing OWL’s MIDI host implementation via FFI.

    #2942

    Stas Shtin
    Participant

    I’ve been rebuilding latest Faust2 and ended up with a failure related to min/max macro clashing with some stuff from libnewlib sources. Rolling back to a version about a week older fixed it for me.

    For reference, this is the error log I’ve got:

    Building patch AutoWah
    In file included from /usr/include/newlib/c++/5.4.1/bits/char_traits.h:39:0,
                     from /usr/include/newlib/c++/5.4.1/string:40,
                     from ./Build/Source/FaustPatch.hpp:84,
                     from ./Build/registerpatch.h:1,
                     from ./Source/PatchProgram.cpp:7:
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:243:56: error: macro "min" passed 3 arguments, but takes just 2
         min(const _Tp& __a, const _Tp& __b, _Compare __comp)
                                                            ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:265:56: error: macro "max" passed 3 arguments, but takes just 2
         max(const _Tp& __a, const _Tp& __b, _Compare __comp)
                                                            ^
    In file included from ./LibSource/Patch.h:4:0,
                     from ./Source/SampleBuffer.hpp:6,
                     from ./Source/PatchProgram.cpp:3:
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:195:5: error: expected unqualified-id before 'const'
         min(const _Tp& __a, const _Tp& __b)
         ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:195:5: error: expected ')' before 'const'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:195:5: error: expected ')' before 'const'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:195:5: error: expected initializer before 'const'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:219:5: error: expected unqualified-id before 'const'
         max(const _Tp& __a, const _Tp& __b)
         ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:219:5: error: expected ')' before 'const'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:219:5: error: expected ')' before 'const'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:219:5: error: expected initializer before 'const'
    In file included from /usr/include/newlib/c++/5.4.1/bits/char_traits.h:39:0,
                     from /usr/include/newlib/c++/5.4.1/string:40,
                     from ./Build/Source/FaustPatch.hpp:84,
                     from ./Build/registerpatch.h:1,
                     from ./Source/PatchProgram.cpp:7:
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:243:5: error: 'std::min' declared as an 'inline' variable
         min(const _Tp& __a, const _Tp& __b, _Compare __comp)
         ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:246:7: error: expected primary-expression before 'if'
           if (__comp(__b, __a))
           ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:246:7: error: expected '}' before 'if'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:246:7: error: expected ';' before 'if'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:248:7: error: expected unqualified-id before 'return'
           return __a;
           ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:265:5: error: 'max' declared as an 'inline' variable
         max(const _Tp& __a, const _Tp& __b, _Compare __comp)
         ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:268:7: error: expected primary-expression before 'if'
           if (__comp(__a, __b))
           ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:268:7: error: expected '}' before 'if'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:268:7: error: expected ';' before 'if'
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:270:7: error: expected unqualified-id before 'return'
           return __a;
           ^
    /usr/include/newlib/c++/5.4.1/bits/stl_algobase.h:271:5: error: expected declaration before '}' token
         }
         ^
    compile.mk:97: recipe for target 'Build/PatchProgram.o' failed
    #2943

    Martin Klang
    Keymaster

    That’s odd, I’m not seeing the same error.

    I’ve just updated to latest faust2 branch, Version 2.1.1

    What version of the gcc toolchain are you compiling with?

    I’ve pushed a small change to OwlProgram which might help, try pulling and recompiling (changed the include file order).

    #2944

    Stas Shtin
    Participant

    Did you happen to forget to push that OwlProgram update? I don’t see anything but docs update in master branch.

    FYI, I did remove FaustPatch.cpp in OwlProgram after each upgrade and toolchain version used was arm-none-eabi-gcc (15:5.4.1+svn241155-1) 5.4.1 20160919

    I’ve made a few tests and I think I can tell you how to reproduce this. The problem seems to happen only if I create Build/Source/FaustPatch.hpp from faust2 branch. If I compile patches with that file created on master branch of faust, everything is fine no matter which version of faust I use at patch compile time. So you have to delete FaustPatch.hpp and use faust2 in order to get this failure.

Viewing 15 posts - 16 through 30 (of 47 total)

You must be logged in to reply to this topic.


Latest News

Links

Follow us on Twitter