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
