Steve wrote his own tremolo effect for our guitar pedal hardware.. Check it out on Github. Here is the source code inline:

#include <Audio.h>
#include "effect_tremolo.h"

AudioControlSGTL5000 codec;

AudioInputI2S audioInput;
AudioEffectTremolo tremolo;
AudioMixer4 mixer;
AudioOutputI2S audioOutput;

AudioConnection inToTrem(audioInput, 0, tremolo, 0);
AudioConnection inToMixer(audioInput, 0, mixer, 0);
AudioConnection tremToMixer(tremolo, 0, mixer, 1);
AudioConnection mixerToOut(mixer, 0, audioOutput, 1);

float depth = 0.7;
int speed = 100;

void setup() {
    AudioMemory(8); // Set the buffer size;


    mixer.gain(0, 1 - depth);
    mixer.gain(1, depth);


void loop() {
    // This is where we would read user interface elements to control the speed and depth.

Wrapping this up into Smalltalk syntax required some small extensions to the parser and Smalltalk to C++ compiler. I won't go over the parser and generator source code changes, as they were minor, but I'll show you the new Smalltalk code:

codec : AudioControlSGTL5000

input : AudioInputI2S
tremolo : AudioEffectTremolo
mixer : AudioMixer4
output : AudioOutputI2S

input.0 -> tremolo.0 -> mixer.0 -> output.0
input.0 -> mixer.1

setup : codec enable ; inputSelect 0 ; muteHeadphone ; micGain 0; lineInLevel 5; lineOutLevel 20 . mixer gain 0 0.3 ; gain 1 0.7 . tremolo begin 100

There are a handful of points of interest here. First, I removed the redundant commas in effect names, for instance Audio:Output:I2S is now just AudioOutputI2S. Since they are already in camel case, the extra ":" wasn't doing anything interesting.

Second, I had to expand the signal flow syntax in order to accommodate Steve's signal routing. If you add .# to any instance name, it specifies a channel. So, for instance, input.0 -> output.0 will route the 0 channel for the input device to the 0 channel for the output device.

Finally, I introduced a new syntactic operator, ";" for reuse of subjects. Examples of all of the current syntactic operators is action:

setup : AudioControlSGTL5000 enable . AudioEffectTremolo begin 100

Here the "." operator separates two unrelated statements. Next the ";" operator:

setup : AudioControlSGTL5000 enable ; inputSelect 0

Here the ";" reuses the subject for two messages, which in this case is "AudioControlSGTL5000". This is the equivalent to the following:

setup : AudioControlSGTL5000 enable . AudioControlSGTL5000 inputSelect 0

Finally, the "|" operator uses the output of one message send as the subject of the next:

setup : AudioControlSGTL5000 enable | not

Here the result of the "enable" message is a boolean value, which is sent the "not" message to invert it's value, true becoming false and vice versa.

So here is the C++ code output for our Smalltalk program:

#include <Arduino.h>
#include "Audio.h"

AudioControlSGTL5000 codec;
AudioControlSGTL5000Module codecModule(&codec);
AudioControlSGTL5000Universe codecUniverse(&codecModule);
AudioInputI2S input;
AudioInputI2SModule inputModule(&input);
AudioInputI2SUniverse inputUniverse(&inputModule);
AudioEffectTremolo tremolo;
AudioEffectTremoloModule tremoloModule(&tremolo);
AudioEffectTremoloUniverse tremoloUniverse(&tremoloModule);
AudioMixer4 mixer;
AudioMixer4Module mixerModule(&mixer);
AudioMixer4Universe mixerUniverse(&mixerModule);
AudioOutputI2S output;
AudioOutputI2SModule outputModule(&output);
AudioOutputI2SUniverse outputUniverse(&outputModule);

AudioConnection connection0_0a(input, 0, tremolo, 0);
AudioConnection connection0_1a(tremolo, 0, mixer, 0);
AudioConnection connection0_2a(mixer, 0, output, 0);
AudioConnection connection1_0a(input, 1, mixer, 1);

void setup()
    mixerUniverse.gain(0, 0.3);
    mixerUniverse.gain(1, 0.7);

void loop()

Still lots to do, but this shows how we can start with a small base language and extend it to cover everything we need to do with the Arduino Audio library (eventually) without the need to reproduce all of C++ (yet).

Code Generation for Arduino Audio - Tremolo Effect