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);
Click image for larger version. 

Name:	IMG_0986.jpg 
Views:	0 
Size:	126.0 KB 
ID:	29255

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
Click image for larger version. 

Name:	IMG_0987.jpg 
Views:	0 
Size:	136.0 KB 
ID:	29256

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;

Click image for larger version. 

Name:	1007D4A9-CD68-4DC7-BB04-193FEBE4A39D.jpg 
Views:	0 
Size:	133.7 KB 
ID:	29257

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;
  }
}