bandlimited waveforms for waveformMod ?

weasel

Active member
hey there,
i recently started experimenting with the audio library.

I am trying some basic synthesizer functions, currently a simple oscillator that has its frequency modulated by an LFO. Very common, basic synth use case. Now, using the waveformMod object makes the modulation part really easy. But unfortunately there are a lot of audible artifacts in higher frequency ranges. I am not a DSP guy but I assume these could be avoided with bandlimited waveforms, as they are available for the "regular" waveform object.

Is there any ready-made workaround for this? Like, an easy way to modulate the frequency of the waveform object, or to get the bandlimited waveforms into the waveformMod object? I am sure there were plenty people before me running into this problem but i couldn't find anything using the forum search.

So yeah, any hints for a clueless beginner would be much appreciated.

Thanks,
weasel.
 
Thanks for the response, later lastr night I did actually find this in the source for synth_waveform.cpp in the definition of AudioSynthWaveformModulated

While calling the waveformMod1.begin function with the WAVEFORM_BANDLIMIT_SAWTOOTH constant did not let me compile, it did when I just used the corresponding number "9" in the .begin call. But unfortunately I only got barely audible clicks on the audio output when trying to use those bandlimited waveforms. Same with other bandlimited waveforms. Whereas the regular waveforms produce the expected results, using all the same parameters and modulators.

It's convoluted and work in progress, but here is the source code I am working with, in case it helps:
https://pastebin.com/Efgzt59e
 
Code from msg #3:

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
#include <ResponsiveAnalogRead.h>
#include <CD74HC4067.h>
CD74HC4067 my_mux(0, 1, 2, 3);  // create a new CD74HC4067 object with its four control pins
const int g_common_pin = A1; // select a pin to share with the 16 channels of the CD74HC4067
 
ResponsiveAnalogRead analog(g_common_pin, true);
 
 
 
// GUItool: begin automatically generated code
AudioSynthWaveform       waveform1;      //xy=110,164
AudioSynthWaveformModulated waveformMod1;   //xy=307,171
AudioEffectWaveshaper    waveshape1;     //xy=485,209
AudioEffectFade          fade1;          //xy=594,281
AudioMixer4              mixer3;         //xy=743,257
AudioEffectDelay         delay1;         //xy=753,408
AudioMixer4              mixer2;         //xy=921,200
AudioOutputI2S           i2s1;           //xy=1116,197
AudioConnection          patchCord1(waveform1, 0, waveformMod1, 0);
AudioConnection          patchCord2(waveformMod1, 0, mixer2, 0);
AudioConnection          patchCord3(waveformMod1, 0, mixer3, 0);
//AudioConnection          patchCord4(waveshape1, fade1);
//AudioConnection          patchCord5(fade1, 0, mixer3, 0);
AudioConnection          patchCord6(mixer3, delay1);
AudioConnection          patchCord7(delay1, 0, mixer2, 1);
AudioConnection          patchCord8(delay1, 0, mixer3, 1);
AudioConnection          patchCord9(mixer2, 0, i2s1, 0);
AudioConnection          patchCord10(mixer2, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=289,433
// GUItool: end automatically generated code
 
 
 
int aread[10];
int areadNew[10];
int cycles[10];
int mincycles = 2;
int average[10][4];
int window = 2;
 
 
void setup()
{
  Serial.begin(9600);
 
  pinMode(g_common_pin, INPUT);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
 
  delay(300);
  Serial.println("horst hrubsesch");
 
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(200);
 
  // Comment these out if not using the audio adaptor board.
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5); // caution: very loud - use oscilloscope only!
  sgtl5000_1.lineOutLevel(23);
 
 
  waveformMod1.amplitude(1.0);
  waveformMod1.frequency(400);
  waveformMod1.frequencyModulation(4);
  waveform1.amplitude(0.0);
  waveform1.frequency(1);
 
  waveformMod1.begin(1);
  waveform1.begin(WAVEFORM_SINE);
 
  mixer2.gain(0, 1);
 
 
  delay1.delay(0, 330);
  mixer3.gain(0, 1);
  mixer3.gain(1, 0.5); //feedback
  mixer2.gain(1, 1); // wet mix
 
 
  Serial.println("setup");
}
 
void readpots()
{
 
 
  for (int i = 0; i < 10; i++) {
    my_mux.channel(i);
    analogRead(g_common_pin);
    delayMicroseconds(1500);
    areadNew[i] = analogRead(g_common_pin);
 
 
    if (areadNew[i] != aread[i]) {
      //average[i][cycles[i]] = areadNew[i];
      cycles[i]++;
 
    }
    else cycles[i] = 0;
 
    if (cycles[i] >= mincycles) {
      cycles[i] = 0;
 
      //areadNew[i] = (average[i][0] + average[i][1] + average[i][2] + average[i][3]) >> 2;
 
 
 
      if ((areadNew[i] < aread[i] - window) || (areadNew[i] > aread[i] + window)) {
        aread[i] = (aread[i] + areadNew[i]) >> 1;
        if (aread[i] < 3) {
          aread[i] = 0;
        }
        if (aread[i] > 1020) {
          aread[i] = 1023;
        }
      }
 
    }
    Serial.print(aread[i]);
    Serial.print(" - ");
  }
  Serial.println();
 
}
 
void loop()
{
  readpots();
 
  if (!digitalRead(4)) {
    Serial.println("fire");
    mixer2.gain(0, 1);
    mixer3.gain(0, 1);
  }
  else {
    Serial.println("no");
    mixer2.gain(0, 0);
    mixer3.gain(0, 0);
  }
 
 
 
 
  waveform1.amplitude((float)aread[8] / 1023);
  waveform1.frequency((float)aread[9] / 50);
  mixer2.gain(1, (float)aread[4] / 1023);  //delay wet
  mixer3.gain(1, (float)aread[5] / 512);  //delay feedback
  delay1.delay(0, (aread[6] >> 2) + 50); //delay time
  waveformMod1.amplitude((float) aread[2] / 1023);  //main vol
  waveformMod1.frequency((aread[0] << 2)  + 40); // vco freq
 
  //Serial.println("x");
 
}

Can you be specific about the source for CD74HC4067.h?

Or even better, can you compose a smaller program which doesn't depend on reading any inputs? For the sake of testing and especially if this turns out to be a bug in the audio library, a test case that always runs the same way with fixed numbers makes debugging and testing much better.
 
Makes sense, I will try to run some tests on a barebones sketch later today with no additional libraries or physical inputs. That being said, the same sketch runs perfectly fine with the standard waveforms. only if I switch to waveforms 9-12, the bandlimited ones, I start losing audio.

edit: fwiw the multiplexer library is this one:
https://github.com/waspinator/CD74HC4067
 
Ok so I tested this real quick, a very basic audio.h-only sketch shows the same issues: no audio output when using bandlimited waveforms on waveformMod1


Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform1;      //xy=110,164
AudioSynthWaveformModulated waveformMod1;   //xy=307,171
AudioOutputI2S           i2s1;           //xy=523,162
AudioConnection          patchCord1(waveform1, 0, waveformMod1, 0);
AudioConnection          patchCord2(waveformMod1, 0, i2s1, 0);
AudioConnection          patchCord3(waveformMod1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=381,293
// GUItool: end automatically generated code


void setup()
{
  Serial.begin(9600);
  delay(300);

  AudioMemory(200);

  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5); 
  sgtl5000_1.lineOutLevel(23);

  waveformMod1.amplitude(1.0);
  waveformMod1.frequency(400);
  waveformMod1.frequencyModulation(4);
  waveform1.amplitude(0.5);
  waveform1.frequency(3);

  waveformMod1.begin(1);  // 1-8 do work here, the bandlimited ones 9-12 produce no audible output
  waveform1.begin(WAVEFORM_SINE);



  Serial.println("setup complete");
}

void loop(){
  
}

I just tried the following:
using a bandlimited waveform for the modulator waveform1 object - this turns the waveformMod1 output into weird noise, even though i guess waveform1 should still output a sawtooth in the same frequency. Again, the teensyduino IDE seems not to recognize the WAVEFORM_BANDLIMIT_SAWTOOTH constant, I have to enter a number.

As I said, everything else from the audio library seems to be working perfectly, otherwise I would have started to assume something with my toolchain or library installations might be wrong?

EDIT. ok i am pretty sure i have an outdated teensyduino install... in my local files the synth_waveform.cpp does not have any bandlimited stuff... sorry for the confusion, will confirm when i got it running
 
Last edited:
Running perfectly smooth now.. again, sorry for the confusion. As per usual with teensy problems, the issue was once again the user.

So thanks Mr. Stoffregen (such a weird word in german) for the amazing audio library and for always taking time on the forums, espeically for audio stuff.

On the plus side, I wasn't aware of arduino 2.0 so now at least I finally have a somewhat real code editor.
 
Back
Top