Overflow Errors when using AudioSynthWaveform & pt8211 for creating Stereo Signals
Hi Everyone
With some colleagues I'm working on a haptic feedback application. We're using the audio library to generate the control signals of the haptic actuators. We're running into bugs that look like overflow issues somewhere in the audio library.
If we work in mono, things are fine. In the below example, the signal path is
Waveform1 --> Envelope1 --> pt8211:

If we split the signal, so that it is output both right and left, things are fine too.
In the below example, the signal path is
Waveform1 --> Envelope1 --> pt8211_left
____________________\----> pt8211_right
Things are still fine

However, if we do a full stereo chain, things are very much not fine:
Waveform1 --> Envelope1 --> pt8211_left
Waveform2 --> Envelope2 --> pt8211_right
I would expect to see the same waveform as shown in the other pictures in the top channel, and nothing in the bottom. Instead we get this;

We've removed all non-relevant bits of the code to create a super stripped down example, but still get this error.
I'm sharing the full code for reproducing this below. We tested this on Teensy 4.0 and Teensy 3.5 and get the same behavior.
Any recommendations on how to solve this are valued.
Full code for producing the overflow example:
Hi Everyone
With some colleagues I'm working on a haptic feedback application. We're using the audio library to generate the control signals of the haptic actuators. We're running into bugs that look like overflow issues somewhere in the audio library.
If we work in mono, things are fine. In the below example, the signal path is
Waveform1 --> Envelope1 --> pt8211:
Code:
AudioSynthWaveform waveform1;
AudioEffectEnvelope envelope1;
AudioOutputPT8211 pt8211_1;
AudioConnection patchCord1(waveform1, envelope1);
AudioConnection patchCord2(envelope1, 0, pt8211_1, 0);

If we split the signal, so that it is output both right and left, things are fine too.
In the below example, the signal path is
Waveform1 --> Envelope1 --> pt8211_left
____________________\----> pt8211_right
Code:
AudioSynthWaveform waveform1;
AudioEffectEnvelope envelope1;
AudioOutputPT8211 pt8211_1;
AudioConnection patchCord1(waveform1, envelope1);
AudioConnection patchCord2(envelope1, 0, pt8211_1, 0);
AudioConnection patchCord3(envelope1, 0, pt8211_1, 1);
Things are still fine

However, if we do a full stereo chain, things are very much not fine:
Waveform1 --> Envelope1 --> pt8211_left
Waveform2 --> Envelope2 --> pt8211_right
Code:
AudioSynthWaveform waveform1;
AudioSynthWaveform waveform2;
AudioEffectEnvelope envelope1;
AudioEffectEnvelope envelope2;
AudioOutputPT8211 pt8211_1;
AudioConnection patchCord2(waveform1, envelope1);
AudioConnection patchCord1(waveform2, envelope2);
AudioConnection patchCord3(envelope1, 0, pt8211_1, 0);
AudioConnection patchCord4(envelope2, 0, pt8211_1, 1);
I would expect to see the same waveform as shown in the other pictures in the top channel, and nothing in the bottom. Instead we get this;

We've removed all non-relevant bits of the code to create a super stripped down example, but still get this error.
I'm sharing the full code for reproducing this below. We tested this on Teensy 4.0 and Teensy 3.5 and get the same behavior.
Any recommendations on how to solve this are valued.
Full code for producing the overflow example:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
AudioSynthWaveform waveform2;
AudioSynthWaveform waveform1;
AudioEffectEnvelope envelope1;
AudioEffectEnvelope envelope2;
AudioOutputPT8211 pt8211_1;
AudioConnection patchCord1(waveform2, envelope2);
AudioConnection patchCord2(waveform1, envelope1);
AudioConnection patchCord3(envelope1, 0, pt8211_1, 0);
AudioConnection patchCord4(envelope2, 0, pt8211_1, 1);
float freq = 170.f;
uint32_t grain_duration_us = (1e6/freq) * 2; // 2 cycles at 170Hz
bool left_is_playing = false;
bool right_is_playing = false;
elapsedMicros timer_left;
elapsedMicros timer_right;
elapsedMicros trigger_left;
elapsedMicros trigger_right;
void start(bool is_left) {
if (is_left) {
waveform1.phase(0.0);
envelope1.noteOn();
} else {
waveform2.phase(0.0);
envelope2.noteOn();
}
}
void stop(bool is_left) {
if (is_left) {
envelope1.noteOff();
} else {
envelope2.noteOff();
}
}
void setup() {
Serial.begin(115200);
while (!Serial && millis() < 2000) {
;
}
AudioMemory(20);
delay(50);
waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(freq);
waveform1.amplitude(1.f);
waveform2.begin(WAVEFORM_SINE);
waveform2.frequency(freq);
waveform2.amplitude(1.f);
envelope1.attack(0.f);
envelope1.hold(0.f);
envelope1.decay(0.f);
envelope1.sustain(1.f);
envelope1.release(1.f);
envelope2.attack(0.f);
envelope2.hold(0.f);
envelope2.decay(0.f);
envelope2.sustain(1.f);
envelope2.release(1.f);
timer_left = 0;
timer_right = 0;
trigger_left = 0;
trigger_right = 0;
Serial.println("=========== Stereo ===========\n\n");
}
void loop() {
if (left_is_playing && timer_left > grain_duration_us) {
stop(true);
left_is_playing = false;
Serial.printf("%d \t stop \t left\n", millis());
}
if (trigger_left > 1e5 + random(1e4)) {
Serial.printf("%d \t trigger \t left\n", millis());
start(true);
left_is_playing = true;
trigger_left = 0;
timer_left = 0;
}
if (right_is_playing && timer_right > grain_duration_us) {
stop(false);
right_is_playing = false;
Serial.printf("%d \t stop \t right\n", millis());
}
if (timer_right > 2e5 + random(1e4)) {
Serial.printf("%d \t trigger \t right\n", millis());
start(false);
right_is_playing = true;
trigger_right = 0;
timer_right = 0;
}
}