Audio board - fading

SteveCS

Well-known member
Hi

I have a 4.1 with the Teensy audio board

What command / method would I use to play an audio file starting on the right, and fading across to the left?

I know I could record the audio track with that effect already in place, but to do it in code would be beneficial for timing adjustment purposes.

Thanks!
 
I have set up the audio with a pair of faders, connected to the mixer and output.

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

// GUItool: begin automatically generated code
AudioPlaySdWav playSdWav1; //xy=116,304
AudioEffectFade fade1; //xy=286,273
AudioEffectFade fade2; //xy=287,338
AudioMixer4 mixer1; //xy=471,292
AudioMixer4 mixer2; //xy=472,358
AudioOutputI2S i2s1; //xy=663,318
AudioConnection patchCord1(playSdWav1, 0, fade1, 0);
AudioConnection patchCord2(playSdWav1, 1, fade2, 0);
AudioConnection patchCord3(fade1, 0, mixer1, 0);
AudioConnection patchCord4(fade2, 0, mixer2, 0);
AudioConnection patchCord5(mixer1, 0, i2s1, 0);
AudioConnection patchCord6(mixer2, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=372,166
// GUItool: end automatically generated code

How do write the fading command? (fading one up and one down at the same time)
 
I would start with:

Code:
  AudioNoInterrupts();
  fade1.fadeOut(1000); //uint32_t milliseconds
  fade2.fadeIn(1000);
  AudioInterrupts();

that assumes some things I don't know about your prior sound playing, but that is how to use the fade device.
I have determined that using a value below 1 will crash the program. IDK, maybe a divide-by-zero, but didn't look at the code in the library.

- Wes, W5ZZO
 
Thanks. I will have a play with those commands and then post the full code I end up with to see if I have any obvious errors!
 
Hi

Been playing with the fade function, but can't quite get what I want, so I am probably using the wrong command.

Code:
  AudioNoInterrupts();                               
  playSdWav1.play("Plane.WAV");               // Non-panning plane sound effect - 12s long
  fade1.fadeIn(8000);                              //  Now fade the audio track right to left in milliseconds
  fade2.fadeOut(8000);                               
  AudioInterrupts();

I am clearly not understanding how the fade function works.

I need the stereo sound file to start only on the right, and then fade across to the left.

What command should I be using? Anyone have a link to the syntax of the audio board commands that a simple guy can understand?
 
There is a full listing here of the keywords:

https://github.com/PaulStoffregen/Audio/blob/master/keywords.txt

Maybe I need to use the 'volumeRight' and 'volumeLeft' commands, but there are no indications of how to implement any of these commands. The examples show little of any use.
Does my head in why you would develop such a capable piece of kit, and then leave all us hobbyists in the dark on how to actually use it.
 
Be careful that your issue isn't audio hardware. I had my stuff plugged into an external USB adapter, and the fade (similar to what you are doing) did not work, simply because the jack I plugged into was a mono microphone device.
You could feed your output into two amp objects for stereo, but you would have to loop and send commands to the amps regularly to get the effect you want.
The 'volumeRight' and 'volumeLeft' you cited are for the AK4558 "HiFi Audio Codec Board". The sgtl500 Audio board has similar capability, implemented as dacVolume(left, right).

- Wes, W5ZZO
 
I can get left and right.

If I fade quickly left or right then play the file, I get the required channel to play.
But, I need it to start silent on one side and travel across to the other.

I just tried using mixer1.gain(0, #); but that doesn't work well either
 
As a mixer is used in almost any audio project, and so far nobody reported a bug, the mixer will do it.
If not, you're doing something wrong. Simple logic.
 
Well I used a for loop with 'mixer1.gain(0, #)'

Seemed a bit lumpy and crude

Code:
  for (float i = 0; i <= 1; i=i+0.1) {
    mixer1.gain(0, i);
    mixer2.gain(0, 1-i);
    delay(1000);
  }

Horrible and blocking, but still doesn't work anyway

Maybe it's just quicker for me to record the sound effect panning left to right in my sound editor over different time periods and play the required file instead.
 
just remove the loop, do it inside the arduino loop function.
Replace the delay, by using an interval timer or use millis() or elapsedMillis() or a lib or or....

(and use 0.1f - just to get used to it and to remember (in future) that "0.1" is a double - not float)
 
This works:

Code:
  mixer1.gain(0, 0);                            // Left mixer 1 channel.     gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
  mixer2.gain(0, 1);                            // Right mixer 2 channel.    gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal

  playSdWav1.play("PlaneM1.WAV");                 // Non-panning plane sound effect - 12s long
  
  for (float i = 0; i <= 1; i=i+0.0001) {
    mixer1.gain(0, i);
    mixer2.gain(0, 1-i);
    delay(1);
  }
 
Well I would prefer non-blocking, but I just cannot seem to get that to work.

The fade command seems to start mid (both channels) and fade out one channel and fade in the other.
I need to start fully faded out on one channel and fully faded in on the other, but I just cannot get that to be a thing
 
Same project, different question.

My SD card contains images and wav files.

After drawing an image to the TFT screen with...

Code:
  tft.fillScreen(ST77XX_BLACK);
  File root = SD.open("/");                                                    // open SD card main root
  bmpDraw("LOGO.BMP", 0, 0);                                               // Load  Logo
  root.close();                                                                // close the file
  delay(1000);

You can no longer get the audio board to play a file. Not exactly sure why, as it works earlier in the code.

Ideas?

I will tidy all the code and post it later today
 
Trouble I find is the code tags mess up the formatting....

Yes, it's not pretty.

All works except when you call to load the 'mainlogo();' after the left and right sound check, you can no longer use the audio board. I can't figure out why.
The call to playSdWav1.play("PlaneM1.WAV"); (just before end of setup) doesn't work unless you comment out the 'mainlogo()' request just before it.

Yes delays.... blah blah, I know.

The SD image loading code is lifted from an example and seems to work fine.

Code:
#include <TeensyDMX.h>                  // DMX library
#include <Audio.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <SerialFlash.h>
#include <Encoder.h>                    // Rotary encoder library
#include <Bounce2.h>                    // Button bouce library
#include <Adafruit_GFX.h>               // Core graphics library
#include <Adafruit_ST7735.h>            // Hardware-specific library for ST7735
#include <EEPROM.h>

namespace teensydmx = ::qindesign::teensydmx;

Bounce startbutton = Bounce();
Bounce stopbutton = Bounce();
Bounce encoderbutton = Bounce();

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

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=116,304
AudioEffectFade          fade1;          //xy=286,273
AudioEffectFade          fade2;          //xy=287,338
AudioMixer4              mixer1;         //xy=471,292
AudioMixer4              mixer2;         //xy=472,358
AudioOutputI2S           i2s1;           //xy=663,318
AudioConnection          patchCord1(playSdWav1, 0, fade1, 0);
AudioConnection          patchCord2(playSdWav1, 1, fade2, 0);
AudioConnection          patchCord3(fade1, 0, mixer1, 0);
AudioConnection          patchCord4(fade2, 0, mixer2, 0);
AudioConnection          patchCord5(mixer1, 0, i2s1, 0);
AudioConnection          patchCord6(mixer2, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=372,166
// GUItool: end automatically generated code


#define SDCARD_CS_PIN 10                        // SD on the audio card pins
#define SDCARD_MOSI_PIN 11
#define SDCARD_MISO_PIN 12
#define SDCARD_SCK_PIN 13

#define statusLED 27
#define fan 26
#define backlightpower 28

#define TFT_CS 36                              // 1.8" screen connections
#define TFT_RST 39
#define TFT_DC 38
#define SD_CS 37

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

Encoder encoderknob(34, 35);                   //  Encoder pins
long encoderposition  = -999;
long newencoderposition;

byte cursorX;                                  // Text position value
byte cursorY;
byte DMXaddress;

boolean triggered;                             // True when the start button has been pressed

unsigned long startMillis;                     // Timer values
unsigned long currentMillis;

boolean flashtext;                             // Toggle for flashing text

File root;

teensydmx::Sender dmxTx{Serial7};              // Create the DMX sender on Serial7.

//----------------------------------------------------------------------------------------------------------------
void setup() {

  Serial.begin(115200);
  Wire.begin();
  dmxTx.begin();

  pinMode(statusLED, OUTPUT);
  pinMode(fan, OUTPUT);
  pinMode(backlightpower, OUTPUT);

  startbutton.attach(31,  INPUT_PULLUP );                                                   // USE INTERNAL PULL-UP
  stopbutton.attach(32,  INPUT_PULLUP );                                                    // USE INTERNAL PULL-UP
  encoderbutton.attach(33,  INPUT_PULLUP );                                                 // USE INTERNAL PULL-UP

  startbutton.interval(5);                                                                  // interval in ms
  stopbutton.interval(5);                                                                   // interval in ms
  encoderbutton.interval(5);                                                                // interval in ms

  tft.initR(INITR_BLACKTAB);
  //tft.initR(INITR_REDTAB);   // initialize a ST7735R chip, red tab
  //tft.initR(INITR_GREENTAB); // initialize a ST7735R chip, green tab

  tft.setRotation(1);                                                                       // Set screen to Landscape
  tft.fillScreen(ST77XX_BLACK);

  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(0);

  delay(500);
  digitalWrite(backlightpower, LOW);                                                        // Backlight on

  //---------- Load EEPROM settings --------



  //---------------- Audio -----------------

  AudioMemory(8);                                                                           // Audio setup
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.6);

  //AudioNoInterrupts();
  //fade1.fadeOut(5);
  //fade2.fadeIn(5);
  //sgtl5000_1.dacVolume(1, 1);                     // dacVolume(left,right)
  //mixer1.gain(0, 0);                            // Left mixer 1 channel.     gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
  //mixer2.gain(0, 1);                            // Right mixer 2 channel.    gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
  //AudioInterrupts();

  delay(500);

  //---------------- SD CARD ---------------

  SPI.setMOSI(SDCARD_MOSI_PIN);                                                             // SD card setup
  SPI.setSCK(SDCARD_SCK_PIN);

  Serial.print(F("Initializing SD card..."));
  if (!(SD.begin(SDCARD_CS_PIN)))
  {
    while (1)
    {
      Serial.println(F("Unable to access the SD card"));
      delay(1000);
    }
  }
  Serial.println(F("SD card OK!"));

  delay(500);

  root = SD.open("/");                                                                      // open SD card main root
  printDirectory(root, 0);                                                                  // print all files names and sizes
  root.close();                                                                             // close the opened root
  Serial.println(F("ONLINE"));

  bmpDraw("LOGO1.BMP", 0, 0);                                                            // Load logo 1

  delay(3000);

  //-------------- Test DMX lighting --------------

  dmxTx.begin();
  
    Serial.println(F("Testing DMX channels..."));

    clearscreen();
    tft.setCursor(8, 10);
    tft.println("Testing DMX channels...");
    delay(500);

    tft.setTextColor(ST77XX_GREEN);
    tft.setCursor(8, 25);
    tft.println("Top light: ");
    cursorX = 110; cursorY = 25; DMXaddress = 1; testDMX();
    delay(500);

    tft.setCursor(8, 37);
    tft.println("Bottom light: ");
    cursorX = 110; cursorY = 37; DMXaddress = 2; testDMX();
    delay(500);

    tft.setCursor(8, 49);
    tft.println("Strobe 1: ");
    cursorX = 110; cursorY = 49; DMXaddress = 3; testDMX();
    delay(500);

    tft.setCursor(8, 61);
    tft.println("Strobe 2: ");
    cursorX = 110; cursorY = 61; DMXaddress = 4; testDMX();
    delay(500);

    tft.setCursor(8, 73);
    tft.println("Strobe 3: ");
    cursorX = 110; cursorY = 73; DMXaddress = 5; testDMX();
    delay(500);

    tft.setCursor(8, 85);
    tft.println("Strobe 4: ");
    cursorX = 110; cursorY = 85; DMXaddress = 6; testDMX();
    delay(500);

    tft.setCursor(8, 97);
    tft.println("Strobe 5: ");
    cursorX = 110; cursorY = 97; DMXaddress = 7; testDMX();
    delay(500);

    tft.setTextColor(ST77XX_RED);
    tft.setCursor(8, 112);
    tft.println("DMX Testing complete");

    //---------------- Flash status LED ---------------

    for (int i = 0; i <= 5; i++) {
      digitalWrite(statusLED, HIGH);
      delay(100);
      digitalWrite(statusLED, LOW);
      delay(100);
    }
 
  //---------------- Test sound system ---------------

  Serial.println(F("Testing sound channels..."));

  clearscreen();
  tft.setCursor(8, 10);
  tft.println("Testing sound channels..");
  delay(500);

  mixer1.gain(0, 1);                            // Left mixer 1 channel.     gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
  mixer2.gain(0, 0);                            // Right mixer 2 channel.    gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal

  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(8, 25);
  tft.println("Left channel: ");
  delay(300);
  playSdWav1.play("Lefttest.WAV");

  delay(3000);

  tft.setTextColor(ST77XX_YELLOW);
  tft.setCursor(120, 25);
  tft.println("OK");

  mixer1.gain(0, 0);                            // Left mixer 1 channel.     gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
  mixer2.gain(0, 1);                            // Right mixer 2 channel.    gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal

  delay(500);

  tft.setTextColor(ST77XX_GREEN);
  tft.setCursor(8, 37);
  tft.println("Right channel: ");
  delay(300);
  playSdWav1.play("Rightest.WAV");

  delay(3000);

  tft.setTextColor(ST77XX_YELLOW);
  tft.setCursor(120, 37);
  tft.println("OK");

  delay(500);

  tft.setTextColor(ST77XX_RED);
  tft.setCursor(8, 112);
  tft.println("Sound Testing complete");

  mixer1.gain(0, 1);                            // Left mixer 1 channel.     gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
  mixer2.gain(0, 1);                            // Right mixer 2 channel.    gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal

  delay(2000);
  mainlogo();                                                                               // Main screen logo
  delay(2000);

  Serial.println("ONLINE");

  startMillis = millis();

  playSdWav1.play("PlaneM1.WAV");                 // Non-panning plane sound effect - 12s long

} //-------------- End of setup--------------------

//------------- Send BMP to screen ------------------                                       // Display BMP file

#define BUFFPIXEL 20

void bmpDraw(char *filename, uint8_t x, uint16_t y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;               // W+H in pixels
  uint8_t  bmpDepth;                          // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;                    // Start of image data in file
  uint32_t rowSize;                           // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3 * BUFFPIXEL];           // pixel buffer (R+G+B per pixel)
  uint8_t  buffidx = sizeof(sdbuffer);        // Current position in sdbuffer
  boolean  goodBmp = false;                   // Set to true on valid header parse
  boolean  flip    = true;                    // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();

  if ((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print(F("Loading image '"));
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == 0) {
    Serial.print(F("File not found"));
    return;
  }

  // Parse BMP header
  if (read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if (read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
      if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print(F("Image size: "));
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        rowSize = (bmpWidth * 3 + 3) & ~3;

        if (bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if ((x + w - 1) >= tft.width())  w = tft.width()  - x;
        if ((y + h - 1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.startWrite();
        tft.setAddrWindow(x, y, w, h);

        for (row = 0; row < h; row++) { // For each scanline...

          if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if (bmpFile.position() != pos) { // Need seek?
            tft.endWrite();
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col = 0; col < w; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
              tft.startWrite();
            }

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            tft.pushColor(tft.color565(r, g, b));
          } // end pixel
        } // end scanline
        tft.endWrite();
        Serial.print(F("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if (!goodBmp) Serial.println(F("BMP format not recognized."));
}

uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}


//------------- Print SD card directory -------------                     // Obtain the contents of the SD card

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

// ----------- Test DMX ------------                                        // Test the DMX channel requested

void testDMX() {

  delay(200);

  for (int i = 0; i < 255; i = i + 10) {
    tft.fillRect(108, cursorY - 2, 25, 12, ST77XX_BLACK);
    tft.setCursor(cursorX, cursorY);
    tft.println(i);
    dmxTx.set(DMXaddress, i);
    delay(30);
  }

  delay(500);
  for (int i = 255; i > 0; i = i - 10) {
    tft.fillRect(108, cursorY - 2, 25, 12, ST77XX_BLACK);
    tft.setCursor(cursorX, cursorY);
    tft.println(i);
    dmxTx.set(DMXaddress, i);
    delay(30);
  }
  tft.setTextColor(ST77XX_YELLOW);
  tft.fillRect(108, cursorY - 2, 25, 12, ST77XX_BLACK);
  tft.setCursor(120, cursorY);
  tft.println("OK");
  tft.setTextColor(ST77XX_GREEN);


}

// ----------- Clear screen ------------                                     // Clear screen and draw standard border

void clearscreen() {

  tft.fillScreen(ST77XX_BLACK);
  tft.drawRect(1, 2 , 159, 126, ST77XX_WHITE);
  tft.drawRect(3, 4 , 155, 122, ST77XX_RED);

}

//----------- Flash waiting -------------

void waiting() {

  if (flashtext == true) {
    flashtext = false;
    tft.fillRect(10, 70, 140, 40, ST77XX_BLACK);                               // Awaiting button press text message
    tft.drawRoundRect(10, 70, 140, 40, 3, ST77XX_RED);

    tft.setTextColor(ST77XX_YELLOW);
    tft.setTextSize(2);
    tft.setCursor(33, 74);
    tft.println("AWAITING");
    tft.setCursor(39, 92);
    tft.println("TRIGGER");
  }
  else
  {
    tft.fillRect(12, 72, 136, 36, ST77XX_BLACK);                               // Awaiting button press text message
    flashtext = true;
  }
}

//----------- Flash plane approaching -------------

void approaching() {

  if (flashtext == true) {
    flashtext = false;
    tft.fillRect(10, 70, 140, 40, ST77XX_BLACK);                               // System running
    tft.drawRoundRect(10, 70, 140, 40, 3, ST77XX_RED);

    tft.setTextColor(ST77XX_YELLOW);
    tft.setTextSize(2);
    tft.setCursor(52, 74);
    tft.println("PLANE");
    tft.setCursor(15, 92);
    tft.println("APPROACHING");
  }
  else
  {
    tft.fillRect(12, 72, 136, 36, ST77XX_BLACK);                               // Awaiting button press text message
    flashtext = true;
  }
}

//--------- Main logo -----------

void mainlogo() {
  tft.fillScreen(ST77XX_BLACK);
  //root = SD.open("/");                                                         // open SD card main root
  bmpDraw("MAINLOGO.BMP", 0, 0);                                               // Load main Logo
  //root.close();                                                                // close the file
  delay(500);
}









//################################################################################################################
void loop() {

  currentMillis = millis();

  startbutton.update();
  stopbutton.update();
  encoderbutton.update();

  if (triggered == false) { //-------------------------------------------------------------------------------------  Waiting for start trigger, so setup menu available

    if (currentMillis > (startMillis + 1000)) {
      startMillis = currentMillis;
      waiting();
    }

    //----- Check Address rotary encoder-----

    newencoderposition = encoderknob.read();

    if (newencoderposition != encoderposition) {
      Serial.print("Encoder = ");
      Serial.println(newencoderposition);
      encoderposition = newencoderposition;

    }

    //-------------- Buttons ----------------

    if (startbutton.changed() ) {                                              // Start button
      int deboucedInput = startbutton.read();
      if (deboucedInput == LOW ) {
        Serial.println("SYSTEM TRIGGERED");
        triggered = true;
        mainlogo();
        approaching();

        //mixer1.gain(0, 0);                            // Left mixer 1 channel.     gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
        //mixer2.gain(0, 1);                            // Right mixer 2 channel.    gain(channel,level).  Level 0 = off.  1 = direct passthrough.  >1 to 32767 amplifies the signal
      }
    }

    if (encoderbutton.changed() ) {                                            // Encoder button (setup menu)
      int deboucedInput = encoderbutton.read();
      if (deboucedInput == LOW ) {
        Serial.println("encoder button");
        setupmenu();
      }
    }
  }
  else
  { // Start button has been pressed---------------------------------------------------------------------------

    if (currentMillis > (startMillis + 1000)) {                                // Flash plane approaching
      startMillis = currentMillis;
      approaching();
    }

    if (stopbutton.changed() ) {                                               // Stop button
      int deboucedInput = stopbutton.read();
      if (deboucedInput == LOW ) {
        Serial.println("Stop button operated");
        triggered = false;
        mainlogo();
      }
    }

  }

}
//##############################################################################################################



// -------------- Setup ---------------

void setupmenu() {

  clearscreen();

  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(0);
  tft.setCursor(5, 5);
  tft.println("SETUP MENU");

}
 
It needs AudioNoInterrupts() and AudioInterrupts() either side of the BMP drawing routine.

Anyone now how these commands are used?

playSdWav1.lengthMillis() or playSdWav1.length()

I need to determine the length of a WAV file before I play it.
 
All kinda working.

Is there any decent way of stopping the horrific speaker popping when you turn off the supply to the Teensy?
Running the 4.1 + audio board off a Meanwell 5v regulator. Turning the power off to it makes a horrible popping crackly sound
 
About the first rule of audio amplifiers - fade the volume, mute, or turn the amp off _before_ powering the sources on or off. Amplifiers just amplify what they are given.

Having said that some amps have 12V enable inputs to automate this, but they are usually fairly specialized. Mute buttons are great to have, but not that common. If an amp has a source selector you can switch to a source that's absent as a way to mute.
 
Back
Top