Hi,

We are aware of this kind of problems on embedded platforms, since issues are 
similar on the Daisy (https://daisy.audio). The thing is that most of the 
architecture files have not been designed and implemented with the this kind of 
memory limitations in mind, and using the C++ libraries (for instance just the 
«  stdio » one) can produce « huge » binaries »…. 

The proper solution would probably be to rethink all that and have a new set of 
« embedded hardware aware » architectures files, even possibly using raw C code 
in some cases.

Can Gemini help ((-: ? 

Stéphane  

> Le 5 mars 2026 à 04:57, Tejas Rode <[email protected]> a écrit :
> 
> This time, Gemini’s response sounds a bit more helpful! In the fourth way, it 
> suggests defining the variables as global inputs:
> 
> process(freq, duty, phase) = …;
> 
> Being new to Faust, I’ve not seen this syntax with process. How could I 
> change my Faust code (which I previously shared) to have this format? 
> 
> Thanks,
> Tejas 
> 
> 
> On Wed, Mar 4, 2026 at 5:58 PM Julius Smith <[email protected]> wrote:
> More:
> 
> Tejas is correct that the issue is likely tied to how the Teensy Audio 
> Library architecture handles Faust UI elements, rather than raw DSP memory.
> 
> When you use hslider, nentry, or vslider in Faust, the faust2teensy compiler 
> generates specific "metadata" and control structures in the C++ class to make 
> these variables accessible via the setParamValue method. If you have many 
> instances, each with multiple UI elements, you can hit a limit in the way the 
> Teensy Audio Library manages its internal "patch cord" connections or the 
> metadata table size.
> 
> Since you are targeting a Teensy and don't need a graphical interface, here 
> are the ideal ways to initialize and control these variables without using 
> standard UI primitives:
> 
> 1. The "Function Argument" Approach (Best for flexibility)
> Instead of defining freq as a UI element globally, define your triangle wave 
> as a function that takes these values as arguments. You can then "map" these 
> arguments to something that doesn't trigger UI generation.
> 
> Code snippet
> 
> 
> // Instead of: freq = hslider("freq", 440, 20, 20000, 1);
> // Use a function that expects arguments:
> myTriangle(f, d, p) = ... your DSP code using f, d, and p ...;
> 
> // Then instantiate it with specific values or "external" signals
> process = myTriangle(440, 0.5, 0.5);
> 
> 2. Use checkbox for "Invisible" metadata (If you still need setParamValue)
> Sometimes nentry and hslider carry more overhead because they require range 
> checking and step logic. If you only have a few parameters but many 
> instances, you might try using checkbox or a very simple button if the logic 
> allows, but this is usually a stopgap.
> 
> 3. Use arg (C++ Style Arguments)
> If you are comfortable with the generated C++ code, you can use the -args 
> compilation flag with the Faust compiler. This allows you to pass values 
> directly to the DSP's instanceInit function. However, this is less 
> "Faust-native" than the other methods.
> 
> 4. Direct Variable Injection via library
> If you want to keep the variables "tunable" from your .ino sketch without the 
> UI overhead, the most robust way is to define them as global inputs to your 
> process and connect them in the Teensy Audio Tool to a "DC" object or a 
> control signal.
>       • In Faust: process(f, d, p) = ...; (This creates a 3-input DSP object).
>       • In Teensy: Use the AudioSynthWaveformDC object to send a constant 
> value into those inputs. This bypasses the Faust UI metadata entirely but 
> keeps the values changeable at runtime.
> Why removing hslider fixed it:
> The Faust Teensy tutorial mentions that setParamValue uses string matching or 
> index matching against a table. Each hslider adds an entry to this table. By 
> switching to constants, you removed the metadata table and the associated 
> string-handling overhead, which is likely where the "upper limit" was being 
> hit.
> 
> Recommendation for Tejas: If you need to change these values at runtime but 
> want to avoid the UI limit, Solution #4 is the most "Teensy-native" way. By 
> defining your freq, duty, and phase as inputs to your process function (e.g., 
> process = myTriangle;), they become standard audio-rate or control-rate 
> inputs in the Teensy Audio System. You can then use the Teensy Audio 
> Library's AudioConnection to plug control values into them.
> 
> 
> On Wed, Mar 4, 2026 at 4:56 PM Julius Smith <[email protected]> wrote:
> Gemini replies:
> 
> It appears Tejas has identified a crucial bottleneck: the Teensy Audio 
> Library’s metadata and memory overhead for UI elements.
> 
> When you use hslider, nentry, or vslider in Faust, the compiler generates 
> metadata strings and internal variables to map these to a UI. On a 
> microcontroller like the Teensy, each of these elements consumes a portion of 
> the DMAMEM or RAM used by the Audio Library to manage the "patch cord" 
> system. If you have many instances of a Faust object, ...
> 
> 
> On Tue, Mar 3, 2026 at 8:28 PM Tejas Rode <[email protected]> wrote:
> Haha! Thank you for sharing that! :)
> 
> Unfortunately, neither of the recommendations of Gemini worked. What worked, 
> again weirdly, is removing hslider() from the code. When I set freq, duty and 
> phase to constants (namely 440, 0.5 and 0.5), I was able to create 
> innumerable instances of triangle. I think what's coming in the way is not 
> related to Teensy memory at all, but related to Faust's UI, where there's 
> probably an upper limit on the number of UI elements that Faust allows. Since 
> teensy doesn't need UI elements, I removed them from the code. However, I 
> obviously don't want freq, duty and phase to have fixed values. I tried 
> nentry(), but that being a UI element too, has the same problem. What is the 
> ideal way I could initialize the three variables in this case? 
> 
> I'll get to smoothing once this gets fixed. 
> 
> Thanks!
> Tejas
> 
> On Tue, Mar 3, 2026 at 7:29 PM Julius Smith <[email protected]> wrote:
> Being obsessed with AI assistance nowadays, I had Gemini answer this one 
> directly in Chrome.  Gemini clearly knows more than me about life on a 
> Teensy, so I delegate that, but the topics I do know about sound correct to 
> me, so consider those "checked by someone who should know presuming he really 
> paid attention" :-).
> 
> Regarding the smoothing making the artifact worse, please post a standalone 
> Faust program that illustrates it as simply as possible.  There's probably a 
> simple problem to fix.  We smoothly use interpolated delay lines all the time.
> 
> --- Begin Gemini Weigh-In ---
> 
> Based on the Faust documentation for Teensy, the issue Tejas is experiencing 
> with the fourth instance of the triangle wave is likely related to RAM 
> (memory) constraints.
> 
> Here is a breakdown of why this is happening and how to address it:
> 
> Why the limit exists
> While the Teensy 4.1 is powerful, it has limited internal RAM. 
> Faust-generated objects, especially those using delay-based oscillators or 
> high-order interpolation (like squareND which Julius suggested), can have a 
> larger memory footprint than expected.
>       • If your code compiles but fails to execute (e.g., stops at the "Test" 
> print or crashes before setup), it usually means the global objects are 
> exceeding the available DTCM (Data Tightly Coupled Memory), causing the 
> microcontroller to hang during initialization.
> Potential Solutions
>       • Reduce Table Sizes: If your triangle wave uses a large lookup table, 
> reduce its size. The default Faust oscillators often use a table size of 
> $2^{16}$ (65,536 samples), which is too large for multiple instances on a 
> Teensy. You can try reducing it to $2^{15}$ or $2^{14}$ in your .dsp file:
> Code snippet
> 
> 
> // Example: reducing table size to 32768
> tablesize = 1 << 15; 
> 
>       • Optimize Delay Lines: Since Tejas mentioned using fdelay, it's 
> important to know that every delay line allocates memory based on its maximum 
> delay length. If you don't specify a maximum, Faust might default to a large 
> value. You can use the -dlt (delay line threshold) compiler option to manage 
> how memory is allocated for these.
>       • Check Memory Usage: In the Arduino IDE, check the memory report after 
> compilation. If "Global variables use..." is very high (near 100%), adding 
> one more instance will push it over the edge.
>       • Use AudioMemory: Ensure you have enough audio blocks allocated in 
> your .ino file. While Tejas's snippet doesn't show the AudioMemory() call for 
> the triangle instances, the tutorial recommends increasing this number if you 
> have multiple audio inputs/outputs.
> C++
> 
> 
> void setup() 
> {
>   AudioMemory(
> 12); // Try increasing this value
> 
>   Serial.begin(
> 115200
> );
>   Serial.println(
> "Test"
> );
> }
> 
> For more details on managing memory for Faust on Teensy, you can refer to the 
> Notes About Computational Power and Memory Footprint section of the official 
> tutorial.
> 
> 
> On Tue, Mar 3, 2026 at 4:00 PM Tejas Rode <[email protected]> wrote:
> Thank you for the suggestion, Julius! I tried using both fdelay and 
> si.smoo(), but it worsened the artifact. I guess it's because the phase 
> changed more often with those approaches, as compared to using just delay.
> 
> On a different note, I'm trying to run this on teensy 4.1. I've followed this 
> approach: https://faustdoc.grame.fr/tutorials/teensy/ . There is a weird 
> problem, though, where I'm able to create at most three instances of the 
> triangle. If I create a fourth instance, the code compiles, but doesn't do 
> anything. Is there really an upper limit on the number of instances that 
> could be created? How could I change the limit, if any? Here is the code:
> 
> #include <Audio.h>
> #include "FaustTriangle.h"
> FaustTriangle faustTriangle[4];  // "Test" is printed only when the number of 
> instances here are <= 3
> void setup() { 
>   Serial.begin(115200);
>   Serial.println("Test");
> }
> void loop() {}
> 
> Regards,
> Tejas
> 
> On Thu, Feb 26, 2026 at 1:57 AM Julius Smith <[email protected]> wrote:
> N is the order of interpolation.  It sounds like you want N=1, but maybe 
> compare to higher N when everything is done.
> 
> Instead of delay, use fdelay, and run its delay parameter through a smoother 
> (e.g., si.smoo(), IIRC)
> 
> On Thu, Feb 26, 2026 at 12:49 AM Tejas Rode <[email protected]> wrote:
> Thanks for the hint! This is what I have put together. It runs, but I have 
> further questions.
> 
> import("stdfaust.lib");
> freq = hslider("freq", 440, 11, 880, 1);
> N = 1;  // tried up to 4
> duty = hslider("duty", 0.5, 0, 1, 0.01);
> phase = hslider("phase", 0.5, 0, 1, 0.001);
> triangleND(N,freq,duty,phase) = squareND(N,freq,duty,phase) : fi.pole(p) : 
> *(gain) with {
>   gain = 4.0*freq/ma.SR; 
>   p = 0.999;
> };
> squareND(N,freq,duty,phase) = os.pulsetrainN(N,freq,duty) @ 
> round(phase*ma.SR/freq);  // phase has audible jumps
> process = triangleND(N,freq,duty,phase);
> 
> I have two questions. 
> 1. How does the value of N affect how the output sounds? I tried N=1 to N=4, 
> but didn't hear an audible difference. What value of N should I set as 
> default?
> 2. When I move the phase slider, there are audible jumps. It's probably 
> because the phase is rounding to the nearest integer. Is there a way to make 
> the phase change sound smooth?
> 
> I'm quite new to FAUST. Thank you for all the help!
> 
> Regards,
> Tejas
> 
> On Sun, Feb 22, 2026 at 2:11 AM Julius Smith <[email protected]> wrote:
> I think I would just use a delay.  Search for "phase" in oscillators.lib and 
> you'll see various approaches.
> 
> On Sat, Feb 21, 2026 at 9:43 PM Tejas Rode <[email protected]> wrote:
> Hi Julius,
> 
> I have a followup question. If I want to add phase value as an argument to 
> this triangleND function, what is the best way to do that? 
> 
> Thanks!
> Tejas
> 
> On Fri, Feb 13, 2026 at 4:08 PM Julius Smith <[email protected]> wrote:
> Hi Tejas,
> 
> You might try modifying os.triangleN(N,freq) to add a duty factor, where N is 
> the order of the aliasing suppression.
> It's based on the paper "Alias-Suppressed Oscillators based on Differentiated 
> Polynomial Waveforms" by Valimaki et al.
> 
> My guess:
> 
> triangleND(N,freq,duty) = squareND(N,freq,duty) : fi.pole(p) : *(gain) with {
>   gain = 4.0*freq/ma.SR; // for aproximate unit peak amplitude
>   p = 0.999;
> };
> squareND(N,freq,duty) = pulsetrainN(N,freq,duty);
> 
> Then your 25% case would be os.triangleND(N,freq,0.25);
> 
> Cheers,
> - Julius
> 
> 
> On Fri, Feb 13, 2026 at 10:39 AM Tejas Rode <[email protected]> wrote:
> Hello,
> 
> I want to create an anti-aliased dfdsdg triangle wave with 25% duty cycle for 
> use in a teensy project. I'm new to faust. Is there a resource that I can 
> refer to? Any ideas that can help me start implementing this? 
> 
> Thanks,
> Tejas
> _______________________________________________
> Faudiostream-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/faudiostream-users
> 
> 
> -- 
> AI has taken my job, but only I know what it is.
> 
> 
> -- 
> AI has taken my job, but only I know what it is.
> 
> 
> -- 
> AI has taken my job, but only I know what it is.
> 
> 
> -- 
> AI has taken my job, but only I know what it is.
> 
> 
> -- 
> AI has taken my job, but only I know what it is.
> 
> 
> -- 
> AI has taken my job, but only I know what it is.
> _______________________________________________
> Faudiostream-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/faudiostream-users



_______________________________________________
Faudiostream-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/faudiostream-users

Reply via email to