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 <https://faustdoc.grame.fr/tutorials/teensy/>
> 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
>>>> <https://faustdoc.grame.fr/tutorials/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
>>>>
>>>>    1.
>>>>
>>>>    *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;
>>>>
>>>>    2.
>>>>
>>>>    *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.
>>>>    3.
>>>>
>>>>    *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.
>>>>    4.
>>>>
>>>>    *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
>>>> <https://www.google.com/search?q=https://faustdoc.grame.fr/tutorials/teensy/%23notes-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

Reply via email to