Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

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

  1. #1
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    15

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

    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!


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

  2. #2
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    15
    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..

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •