Wavetable Synth with step sequencer, TFT ILI9341 and Audio Shield volume issue

Status
Not open for further replies.

topicbird

Active member
Hello guys!

Currently, I am working on a step sequencer with a wavetable synthesizer. I want to draw the individual waves on a TFT ILI9341 Display and put them anywhere I want along 16 steps. I already managed to draw the waves and get an output with my Audio Shield, but now I am facing a weird problem. As soon as I try to implement my wave-synthesizer code into the step sequencer, it gets very quiet. As soon as I try to draw anything on the screen, the volume becomes high again and it begins to stutter. The LEDs which indicate the steps don't stop though. I am not sure whether it's a hard- or a software problem.. I apologize for my messy code, without any classes or sophisticated solutions, I began 1-2 months ago.. I would be very thankful about any kind of help from you! Thanks! :)

Be careful, it gets pretty loud as soon as I begin to draw! :D

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

#include <ILI9341_t3.h>
#include <font_Arial.h> // from ILI9341_t3
#include <XPT2046_Touchscreen.h>


#define CS_PIN  8
#define TFT_DC  9
#define TFT_CS 10
// MOSI=11, MISO=12, SCK=13

XPT2046_Touchscreen ts(CS_PIN);
#define TIRQ_PIN  2

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

namespace modulo4 {
float map(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
} //Funktionen innerhalb der Klammern nur aufrufbar, wenn modulo4:: davor steht

int width = 2;
constexpr int arrayLength = 257; // const kannst du während des programms initialisieren --> constexp liegt schon von Anfang an fest
int16_t anArray_X[arrayLength] = {0};
float anArray1[arrayLength] = {0};
int X, Y;
int Y_old;
int X_old;
boolean previous_is_touched;

typedef struct {
  int x;
  int y;
} points_t;
// int16_t anArray_Y[257] = {0};

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform2;      //xy=161,336
AudioSynthWaveform       waveform3;      //xy=161,367
AudioSynthWaveform       waveform4;      //xy=161,398
AudioSynthWaveform       waveform1;      //xy=162,304
AudioEffectEnvelope      envelope4;      //xy=297,396
AudioEffectEnvelope      envelope3;      //xy=299,366
AudioEffectEnvelope      envelope1;      //xy=301,303
AudioEffectEnvelope      envelope2;      //xy=301,334
AudioMixer4              mixer1;         //xy=439,347
AudioOutputI2S           i2s1;           //xy=633,351
AudioConnection          patchCord1(waveform2, envelope2);
AudioConnection          patchCord2(waveform3, envelope3);
AudioConnection          patchCord3(waveform4, envelope4);
AudioConnection          patchCord4(waveform1, envelope1);
AudioConnection          patchCord5(envelope4, 0, mixer1, 3);
AudioConnection          patchCord6(envelope3, 0, mixer1, 2);
AudioConnection          patchCord7(envelope1, 0, mixer1, 0);
AudioConnection          patchCord8(envelope2, 0, mixer1, 1);
AudioConnection          patchCord9(mixer1, 0, i2s1, 0);
AudioConnection          patchCord10(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=289,51
// GUItool: end automatically generated code

int b1 = 0;
int b2 = 0;
int b3 = 0;
int b4 = 0;

float att1 = 50;
float dec1 = 200;
float sus1 = 200;
float rel1 = 200;

float att2 = 50;
float dec2 = 200;
float sus2 = 200;
float rel2 = 200;

float att3 = 50;
float dec3 = 200;
float sus3 = 200;
float rel3 = 200;

float att4 = 50;
float dec4 = 200;
float sus4 = 200;
float rel4 = 200;

float att = 200;
float dec = 200;
float sus = 200;
float rel = 200;


int led3 = 3;
int led4 = 4;
int led5 = 5;
int led6 = 6;

int amp1 = 1;
int amp2 = 1;
int amp3 = 1;
int amp4 = 1;

int freq1 = 500;
int freq2 = 700;
int freq3 = 900;
int freq4 = 1100;

//-------- MILLIS STEP --------//

int m_step = 0;
unsigned long m_interval = 200;
int m_STEPNUM = 4; // Amount of steps
unsigned long m_lastMillis;

float fourth = 1.0 / 4.0;
float one_sixth = 1.0 / 6.0;
int bpm = 120;
int modulo = 1000 * (60.0 / bpm); // in milli
// int fourth_modulo = fourth * modulo;
int previousA2 = 0; // previously sent poti values, to detect changes
int minBPM = 30;
int maxBPM = 220;

const int numReadings = 5;     // Anzahl der Readings
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int inputPin = A1;              // Analog input
int average_bpm = 0;
int average_bpm_alt = 0;

int16_t AudioWaveformSineyes[257] = {
  0,   804,  1608,  2410,  3212,  4011,  4808,  5602,  6393,  7179,
  7962,  8739,  9512, 10278, 11039, 11793, 12539, 13279, 14010, 14732,
  15446, 16151, 16846, 17530, 18204, 18868, 19519, 20159, 20787, 21403,
  22005, 22594, 23170, 23731, 24279, 24811, 25329, 25832, 26319, 26790,
  27245, 27683, 28105, 28510, 28898, 29268, 29621, 29956, 30273, 30571,
  30852, 31113, 31356, 31580, 31785, 31971, 32137, 32285, 32412, 32521,
  32609, 32678, 32728, 32757, 32767, 32757, 32728, 32678, 32609, 32521,
  32412, 32285, 32137, 31971, 31785, 31580, 31356, 31113, 30852, 30571,
  30273, 29956, 29621, 29268, 28898, 28510, 28105, 27683, 27245, 26790,
  26319, 25832, 25329, 24811, 24279, 23731, 23170, 22594, 22005, 21403,
  20787, 20159, 19519, 18868, 18204, 17530, 16846, 16151, 15446, 14732,
  14010, 13279, 12539, 11793, 11039, 10278,  9512,  8739,  7962,  7179,
  6393,  5602,  4808,  4011,  3212,  2410,  1608,   804,     0,  -804,
  -1608, -2410, -3212, -4011, -4808, -5602, -6393, -7179, -7962, -8739,
  -9512, -10278, -11039, -11793, -12539, -13279, -14010, -14732, -15446, -16151,
  -16846, -17530, -18204, -18868, -19519, -20159, -20787, -21403, -22005, -22594,
  -23170, -23731, -24279, -24811, -25329, -25832, -26319, -26790, -27245, -27683,
  -28105, -28510, -28898, -29268, -29621, -29956, -30273, -30571, -30852, -31113,
  -31356, -31580, -31785, -31971, -32137, -32285, -32412, -32521, -32609, -32678,
  -32728, -32757, -32767, -32757, -32728, -32678, -32609, -32521, -32412, -32285,
  -32137, -31971, -31785, -31580, -31356, -31113, -30852, -30571, -30273, -29956,
  -29621, -29268, -28898, -28510, -28105, -27683, -27245, -26790, -26319, -25832,
  -25329, -24811, -24279, -23731, -23170, -22594, -22005, -21403, -20787, -20159,
  -19519, -18868, -18204, -17530, -16846, -16151, -15446, -14732, -14010, -13279,
  -12539, -11793, -11039, -10278, -9512, -8739, -7962, -7179, -6393, -5602,
  -4808, -4011, -3212, -2410, -1608,  -804,     0
};

int16_t anArray_Y[arrayLength] = {0};

boolean wastouched = true;

void redrawButtons() {
  /* tft.fillRoundRect(xStartingPointBefore, yStartingPointBefore, LengthOfSquare, WidthOfSquare, RadiusOfRoundCorner, colorOfSquare);
    xStartingPointAfter = map(xStartingPointBefore, 0, 3482, 0, (arrayLength - 1));
    yStartingPointAfter = map(yStartingPointBefore, */

  tft.fillRoundRect(0, 224, 76, 14, 3, CL(0, 0, 0));
  tft.fillRoundRect(0, 224, 76, 14, 3, CL(250, 100, 0));
  tft.setCursor(0 + 23, 227);
  tft.print("Clear");
}


void clearDisplay() {
  tft.fillScreen(ILI9341_BLACK);
  redrawButtons();
  tft.drawLine(0, 120, 320, 120, CL(255, 255, 255));
  tft.drawLine(0, 121, 320, 121, CL(255, 255, 255));
  tft.drawLine(0, 119, 320, 119, CL(255, 255, 255));
}

void clearArray() {
  for (X = 0; X < arrayLength; X++) {
    anArray1[X] = 0;
  }
}


boolean pointInRect(int x, float y, float rectX, float rectY, float rectW, float rectH) {
  boolean ret = false;
  if ((x >= rectX) && (x <= (rectX + rectW)) && (y >= rectY) && (y <= (rectY + rectH))) {
    ret = true;
  }
  return ret;
}


void setup() {
  Serial.begin(38600); // 38600 symbols per second
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);

  pinMode(1, INPUT_PULLUP); // b1
  pinMode(2, INPUT_PULLUP); // b2
  pinMode(3, INPUT_PULLUP); // b3
  pinMode(4, INPUT_PULLUP); // b4

  AudioMemory(20);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0);
  mixer1.gain(0, 0.5);
  mixer1.gain(1, 0.5);
  mixer1.gain(2, 0.5);
  mixer1.gain(3, 0.5);
  waveform1.begin(WAVEFORM_ARBITRARY); // WAVE 1
  waveform1.amplitude(amp1);
  waveform1.frequency(freq1);
  waveform2.begin(WAVEFORM_SINE); // WAVE 2
  waveform2.amplitude(amp2);
  waveform2.frequency(freq2);
  waveform3.begin(WAVEFORM_SINE); // WAVE 3
  waveform3.amplitude(amp3);
  waveform3.frequency(freq3);
  waveform4.begin(WAVEFORM_SINE); // WAVE 4
  waveform4.amplitude(amp4);
  waveform4.frequency(freq4);

  //------Touch---------//
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);
  tft.drawLine(0, 120, 320, 120, CL(255, 255, 255));
  tft.drawLine(0, 121, 320, 121, CL(255, 255, 255));
  tft.drawLine(0, 119, 320, 119, CL(255, 255, 255));
  ts.begin();
  ts.setRotation(1);
  while (!Serial && (millis() <= 1000)); // weiß nicht was das ist
  clearDisplay();
  redrawButtons();

}
void loop() {

  int att = analogRead(A2);
  int dec = analogRead(A0);
  int rel = analogRead(A4);
  int sus = analogRead(A3);


  ADSR(att, dec, rel, sus);

  // ----------------- SMOOTHING TEMPLATE -----------------

  static float bpm = {120}; // wird wegen static nur einmal initialisiert
  // int modulo = 1000 * (60.0 / average_bpm); // in milli
  // int fourth_modulo = fourth * modulo;
  int n1 = analogRead(A1);
  //  int current_time = millis();
  // int modulo_time = current_time % modulo;

  // subtract the last reading:
  total = total - readings[readIndex] ; // Alle Analoge inputwerte zusammenaddiert, wobei der Wert der neuen Loop abgezogen wird (zieht den nullten Wert ab)
  // read from the sensor:
  readings[readIndex] = analogRead(inputPin);

  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;

    // calculate the average:
    average = total / numReadings;
    average_bpm = map(average, 0, 1023, 50, 280);
    if (average_bpm != average_bpm_alt) {
      // Serial.println(average_bpm);

    }
    average_bpm_alt = average_bpm;
    //  Serial.println(average_bpm);

    // -------- ARBITRARY WAVE --------
    boolean istouched = ts.touched();
    int X;
    float Y;
    if (istouched) {

      TS_Point p = ts.getPoint(); // point getter function
      //   X = map(p.x - 320, 3482, 0, 0, 320);
      X = map(p.x - 320, 3482, 0, 0, arrayLength - 1);
      if (X < 0) {
        X = 0;
      }
      Y = modulo4::map(p.y - 240.0, 3465.0, 0.0, 1.0, -1.0); //davor 240
      anArray1[X] = Y;
      /* if (previous_is_touched) {
         for ( int i {X_old}; i < X; (X_old <= X) ? (++i) : (--i) ) {    // conditional operator
           anArray1[i] = modulo4::map(i, X_old, X, anArray1[X_old], anArray1[X]);
         }
        }
        X_old = X; */
      if (previous_is_touched) {
        for ( int i = X_old ; i < X;) {
          if (X_old <= X) {
            i++;
          }
          else {
            i--;
          }
          anArray1[i] = modulo4::map(i, X_old, X, anArray1[X_old], anArray1[X]);

        }
      }

      X_old = X;

      if (pointInRect(X, Y, 0.0, -1.0, 76.0, 0.1)) {
        clearDisplay();
        clearArray();
      }

      clearDisplay();
      for (int i {0}; i < arrayLength; ++i) {
        tft.fillCircle(map(i, 0, 256, 0, 320), modulo4::map(anArray1[i], 1.0, -1.0, 0.0, 240.0), width, CL(255, 0, 0));
        anArray_Y[i] = modulo4::map(anArray1[i], 1.0, -1.0, -32767, 32767);
      }

      waveform1.arbitraryWaveform(anArray_Y, 20000);

      if ( X > arrayLength ) {
        X = 256;
      }
      Serial.print("X: ");
      Serial.print(X);
      Serial.println();
      Serial.print("Y: ");
      Serial.print(anArray_Y[X]);
      Serial.println();
      Serial.println();
    } 
    previous_is_touched = istouched; 


    // ----------------- MILLIS BASED SEQUENCER -----------------//
    if ((millis() - m_lastMillis) > m_interval)
    {
      if (m_step == m_STEPNUM)
      {
        m_step = 0;
      }
      m_step++;
      /*  Serial.print("Millis:");
        Serial.print(millis());
        Serial.println();
        Serial.print("Last Millis:");
        Serial.print(m_lastMillis);
        Serial.println();
        Serial.println(); */
      Serial.println(m_step);

      m_lastMillis = millis();
    }

    if (m_step == 1) {
      digitalWrite(led3, HIGH);
      digitalWrite(led6, LOW);

      envelope4.noteOff();
      envelope1.noteOn();

      waveform1.amplitude(amp1);
      waveform1.frequency(freq1);

    }

    else if (m_step == 2) {
      digitalWrite(led3, LOW);
      digitalWrite(led4, HIGH);

      envelope1.noteOff();
      envelope2.noteOn();

      waveform2.amplitude(amp2);
      waveform2.frequency(freq2);

    }
    else if (m_step == 3) {
      digitalWrite(led4, LOW);
      digitalWrite(led5, HIGH);

      envelope2.noteOff();
      envelope3.noteOn();

      waveform3.amplitude(amp3);
      waveform3.frequency(freq3);

    }
    else if (m_step == 4) {
      digitalWrite(led5, LOW);
      digitalWrite(led6, HIGH);

      envelope3.noteOff();
      envelope4.noteOn();

      waveform4.amplitude(amp4);
      waveform4.frequency(freq4);
    }
  }
}

ADSR:

Code:
void ADSR(float att, float dec, float sus, float rel) { //HIGH and LOW are not boolean values.. they are integers, where HIGH = 1 and LOW = 0.

  b1 = digitalRead(1);
  b2 = digitalRead(2);
  b3 = digitalRead(3);
  b4 = digitalRead(4);


  if (b1 == 0) {
      att = att1;
      dec = dec1;
      sus = sus1;
      rel = rel1; 
  }
  else if (b2 == 0) {
      att = att2;
      dec = dec2;
      sus = sus2;
      rel = rel2;
  }
      
  else if (b3 == 0) {
      att = att3;
      dec = dec3;
      sus = sus3;
      rel = rel3;
  }
      
  else if (b4 == 0) {
      att = att4;
      dec = dec4;
      sus = sus4;
      rel = rel4;
  }
  
  envelope1.attack(att1);    // ADSR 1
  envelope1.decay(dec1);
  envelope1.sustain(sus1);
  envelope1.release(rel1);
  envelope2.attack(att2);    // ADSR 2
  envelope2.decay(dec2);
  envelope2.sustain(sus2);
  envelope2.release(rel2);
  envelope3.attack(att3);    // ADSR 3
  envelope3.decay(dec3);
  envelope3.sustain(sus3);
  envelope3.release(rel3);
  envelope4.attack(att4);    // ADSR 4
  envelope4.decay(dec4);
  envelope4.sustain(sus4);
  envelope4.release(rel4);
}
 
I just realized that the change in loudness is caused by the envelope.noteOff(), which I turned off now. I have still no idea about the reason behind the stutter effect though..
 
Status
Not open for further replies.
Back
Top