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;

    codec.enable();
    codec.inputSelect(AUDIO_INPUT_LINEIN);
    codec.muteHeadphone();
    codec.micGain(0);
    codec.lineInLevel(5);
    codec.lineOutLevel(20);

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

    tremolo.begin(speed);
}

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()
{
    codecUniverse.enable();
    codecUniverse.inputSelect(0);
    codecUniverse.muteHeadphone();
    codecUniverse.micGain(0);
    codecUniverse.lineInLevel(5);
    codecUniverse.lineOutLevel(20);
    mixerUniverse.gain(0, 0.3);
    mixerUniverse.gain(1, 0.7);
    tremoloUniverse.begin(100);
}

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