Can I play multiple mp3s at once with a teensy 3.6 and serialflash?

Status
Not open for further replies.

odinndagur

New member
Tl;dr
Can I play multiple (at most 6) audio files at once, encoded as mp3 or aac on a teensy 3.6 with serialflash and the audioboard?

I'm working on an audio project for an art installation.

The idea: You get a battery powered unit that hangs around your neck. It tracks your location within the installation (two rooms and a bridge that joins them). There are 47 different audio loops that fade in and out depending on where you are (some are talking pieces about artwork on the walls in specific places, some are musical loops that mesh with each other).

I'm using Decawave DWM-1001 development kit units for the tracking, that's fine for getting the x,y coordinates within the installation. It uses UART and sends a packet to the teensy in the form POS,25.0,48.2,3.0,95. POS for position, then x,y,z and finally how accurate the location data is as a percentage. It sends its data at 10hz which is fast enough for our purposes.

I haven't written all the code I need so far but this is how I'm thinking about this:

1)Get position data
2)use strtok to split it into different variables so I have a tagPosX and tagPosY float with x and y coordinates (this works fine)
3)compare x,y coordinates with x,y coordinates of each of the loops and get a linear distance to it
3a) if its coming into range of loop play loop
3b) if its going out of range of loop stop playing
4) adjust volume of all loops from min to max over a certain range (so first it plays at 0, then start fading in at a certain point, then have it at max volume maybe from like 50cm to the loop, then fade out again

We really want to have at most 6 loops playing at once. We bought 6 teensy 3.6 and 6 audioboards. We have 256mbit serialflash cards for the audio (one room on each teensy, basic mixer to mix the audio together, three units all in all - each with 2 teensies) which is enough space for all the loops as long as they're mp3 encoded. I had googled it a bit and saw that 1) the teensy 3.6 should handle playing a bunch of files at once and 2) that it should handle playing mp3s but didn't realise that it might not work together.

If I can’t I’m thinking about maybe using one voice per teensy, have them communicate between themselves and use 6 teensies at once, one per track.. it just sounds really overkill and complicated. Do y’all have any ideas?

Thanks so much!
 
As far as I am aware, there hasn't been an AAC or MP3 decoder written for the teensy audio library, so you would probably need to first find an open source decoder and get it working with the teensy audio library.

The bigger problem is the computing horsepower required to do MP3 decoding. I doubt very much you're going to be able to do more than 1 or 2 MP3 decoders simultaneously with a teensy 3.6.

A teensy 4 on the other hand, now that would be interesting to see. It's on another level, computing-wise.
 
Yeah, I had looked at the library but wasn't sure if it could or couldn't play multiple mp3s at once. I feel like I saw a post from him mentioning playing multiple mp3s with it but I'm not sure, guess I'll just have to try it once I get the teensies and flash chips. Thanks for the help!
 
Are you locked into using MP3 files? If not, use WAV and and serial flash chip. Depending on the length of your samples, it may be enough.
 
You might want to also read this thread:

However, I don't think there is a version to play MP3 files from flash memory. There is a class (AudioPlaySerialflashRaw) to play sounds with the RAW format from flash memory.

Note however, in the case of the 3.6, it is probably faster to use the built-in micro SD card, rather than the normal serial flash. This is because the built-in micro SD card uses SDIO 4-bit transfers while the standard serial flash only uses single bit SPI transfers. If you use a micro SD card, you want to use a higher end card, such as the SanDisk Extreme or ExtremePro cards, and you want to freshly format the card.
 
My understanding is that SD card only support 3 to 4 simultaneous streams, but SPI flash can support many more. It's a limitation of the SD card, not the interface to it. I'm not yet using either; my current project uses AudioPlayMemory (but is quickly running out of room, hence the study of SPI flash alternative).
 
My understanding is that SD card only support 3 to 4 simultaneous streams, but SPI flash can support many more. It's a limitation of the SD card, not the interface to it. I'm not yet using either; my current project uses AudioPlayMemory (but is quickly running out of room, hence the study of SPI flash alternative).

I suspect it isn't the card per-se, but whether the whole infrastructure can handle it. At the end of the day, a micro-SD card is essentially just serial flash memory, and you are limited to the underlying speed of the flash memory and how the bits are delivered to the Teensy.

I don't know where the 3-4 simultaneous streams comes from, but I suspect it probably comes from the announcement of the Audio Shield with the Teensy 3.2. The Audio Shield only has a single bit SPI interface for both the SD card and for the flash memory chip soldered onto the Audio Shield. So assuming you have a fast micro-SD card and fast flash memory, I would both would be of similar speeds. The micro-SD card on the Teensy 3.6/3.5 uses a 4 bit interface, so it should read data much faster. And of course the 3.6 has more memory and a faster clock speed than the 3.2.

Similarly using flash memory using the same 4 bit SDIO mode, should be faster than using the flash memory in 1-bit SPI mode. However, we don't have that in the standard library. FrankB did write this library 4 years ago. I don't know if it was abandoned because it didn't work, it got incorporated in a new library, or Frank just changed interests.

In theory, the Teensy 3.6 has 3 separate SPI buses available for use, plus the SPI bus used by the micro-SD card. But somebody would need to make sure all of the drivers work with multiple SPI buses, and do so in parallel.
 
I'm just going by what the AudioPlaySerialflashRaw documentation says:

Play a RAW data file, stored on a Serial Flash chip. These chips are far more efficient than SD cards, allowing many files to be played simultaneously by copies of this object.

And also posts by Frank B from earlier in 2019:

https://forum.pjrc.com/threads/42401-Instructions-or-tutorials-for-using-wav2sketch?p=202250&viewfull=1#post202250

However I'm new in these parts and I don't have personal experience with it myself and looking at other threads, you have seemed to have studied it quite a bit. I did just order a serial flash chip to try in a project -- I hope it works!
 
I'm just going by what the AudioPlaySerialflashRaw documentation says:

Note, don't read into my posts more knowledge than I have. I haven't done much in terms of playing multiple songs, etc. But it is more from a theory of how things work. Unless you have multiple SPI buses, one of the bottlenecks is just reading the data from the SD card or serial flash. You can't do separate I/O in parallel, since everything has to go through that one device. And at its core, a SD card is just serial flash. It isn't like a rotating disk drive where you have the latency of positioning the read head and the position of the track being read where you might be able to optimize somethings by having the data in just the right place.

Now, different SD cards and serial flash cards can operate at different speeds. And using the FAT32 filesystem can add extra slowdowns. If you have a slow micro SD card or you've been using the card for several years without reformatting the card, that might slow things down. Similarly, I can imagine some flash memory to be pretty slow as well. It is where you sometimes have to do a deep dive into the datasheet, and/or wire it up to see what your results are. And there might be other roadblocks other than just getting the data from the card.

But it stands to reason that if you have one device that reads a single bit every SPI clock cycle (SerialFlash with the current setup, or micro SD card one the audio shield) and another device that can transfer 4 bits every SPI clock cycle (built-in SD micro card on the 3.5, 3.6, or using the 4.0 pins to attach a micro SD card reader), that the second device should be 3-4 times faster than the first. You can get micro SD card readers that can do SDIO 4-bit mode and SerialFlash also, but right now, it isn't being used. Of course if somebody rolls up their sleeves and adds the support, Paul might decide to include it in future Teensyduino releases.

One problem unfortunately with all documentation is that it is not always updated when things change. I suspect (but do not know) that the SerialFlash documentation dates to the original release of the audio libraries with the Teensy 3.2. Perhaps it is now different using faster processors with built-in micro SD card support that uses 4-bit SDIO and faster micro-SD cards (SanDisk Extreme or faster). Perhaps it isn't.
 
Measured SD/flash memory timings

Ok, mea culpa. I decided to actually measure the times (rather than speculating on how I thought things should work). I ran the SD card tests from the audio library, measuring the speed of reading .WAV files, and I ran a modified version on flash memory. I had to use much smaller .WAV files that I used for the normal SD tests, since the flash memory I have soldered on the audio shield is only 16 megabytes (128 megabits).

Code:
Here is the overall speed measured over 4 files (single files, sequential files, and staggering the files):
 
1.73 - 1.76 MBytes/second: Teensy 4.0, built-in SD card (using breakout board), Samsung EVO select, 32GB
1.19 - 1.19 MBytes/second: Teensy 4.0, audio shield SD card, Samsung EVO select, 32GB
5.24 - 5.25 MBytes/second: Teensy 4.0, W25Q128JVSIQ flash memory soldered to audio shield, 16MB
1.73 - 1.75 Mbytes/second: Teensy 3.5, built-in SD card, Samsung EVO select, 32GB

I do wonder why a micro-SD card is so much slower than than a flash memory chip, unless it has to do with the much larger space on the micro-SD card.

I also would have expected more of a speed-up going from SPI 1 bit (audio shield SD) to SDIO 4 bit (built-in SD card).

At some point I want to solder a flash memory chip to use the built-in SD card pins and see what the difference in speed is.

BTW, here is the test for using the built-in SD card:
Code:
// SD Card Test
//
// Check if the SD card on the Audio Shield is working,
// and perform some simple speed measurements to gauge
// its ability to play 1, 2, 3 and 4 WAV files at a time.
//
// Requires the audio shield:
//   http://www.pjrc.com/store/teensy3_audio.html
//
// Data files to put on your SD card can be downloaded here:
//   http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html
//
// This example code is in the public domain.

#include <SD.h>
#include <SPI.h>

// Use these with the Teensy Audio Shield on the Teensy 3.2, 3.5, or 3.6
// #define SDCARD_CS_PIN    10
// #define SDCARD_MOSI_PIN  7
// #define SDCARD_SCK_PIN   14

// Use these with the Teensy Audio shield on the Teensy 4.0
// #define SDCARD_CS_PIN    10
// #define SDCARD_MOSI_PIN  11
// #define SDCARD_SCK_PIN   13

// Use these with the Teensy 3.5 & 3.6 SD card (or)
// Use with the Teensy 4.0 SD solder pads connected to a micro-SD card reader
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

void setup() {
  Sd2Card card;
  SdVolume volume;
  File f1, f2, f3, f4;
  char buffer[512];
  boolean status;
  unsigned long usec, usecMax;
  elapsedMicros usecTotal, usecSingle;
  int i, type;
  float size;

  // wait for the Arduino Serial Monitor to open
  while (!Serial) ;
  delay(50);

  // Configure SPI
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);

  Serial.begin(9600);
  Serial.println("SD Card Test");
  Serial.println("------------");

  // First, detect the card
  status = card.init(SPI_FULL_SPEED, SDCARD_CS_PIN);
  if (status) {
    Serial.println("SD card is connected :-)");
  } else {
    Serial.println("SD card is not connected or unusable :-(");
    return;
  }

  type = card.type();
  if (type == SD_CARD_TYPE_SD1 || type == SD_CARD_TYPE_SD2) {
    Serial.println("Card type is SD");
  } else if (type == SD_CARD_TYPE_SDHC) {
    Serial.println("Card type is SDHC");
  } else {
    Serial.println("Card is an unknown type (maybe SDXC?)");
  }

  // Then look at the file system and print its capacity
  status = volume.init(card);
  if (!status) {
    Serial.println("Unable to access the filesystem on this card. :-(");
    return;
  }

  size = volume.blocksPerCluster() * volume.clusterCount();
  size = size * (512.0 / 1e6); // convert blocks to millions of bytes
  Serial.print("File system space is ");
  Serial.print(size);
  Serial.println(" Mbytes.");

  // Now open the SD card normally
  status = SD.begin(SDCARD_CS_PIN);
  if (status) {
    Serial.println("SD library is able to access the filesystem");
  } else {
    Serial.println("SD library can not access the filesystem!");
    Serial.println("Please report this problem, with the make & model of your SD card.");
    Serial.println("  http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports");
  }


  // Open the 4 sample files.  Hopefully they're on the card
  f1 = SD.open("SDTEST1.WAV");
  f2 = SD.open("SDTEST2.WAV");
  f3 = SD.open("SDTEST3.WAV");
  f4 = SD.open("SDTEST4.WAV");

  // Speed test reading a single file
  if (f1) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV:");
    if (f1.size() >= 514048) {
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(1, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST1.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST1.WAV on this card");
    return;
  }

  // Speed test reading two files
  if (f2) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV & SDTEST2.WAV:");
    if (f2.size() >= 514048) {
      f1.seek(0);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(2, 1000, usecTotal, usecMax);

      Serial.println();
      Serial.println("Reading SDTEST1.WAV & SDTEST2.WAV staggered:");
      f1.seek(0);
      f2.seek(0);
      f1.read(buffer, 512);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(2, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST2.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST2.WAV on this card");
    return;
  }


  // Speed test reading three files
  if (f3) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV:");
    if (f3.size() >= 514048) {
      f1.seek(0);
      f2.seek(0);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(3, 1000, usecTotal, usecMax);

      Serial.println();
      Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV staggered:");
      f1.seek(0);
      f2.seek(0);
      f3.seek(0);
      f1.read(buffer, 512);
      f1.read(buffer, 512);
      f2.read(buffer, 512);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(3, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST3.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST3.WAV on this card");
    return;
  }


  // Speed test reading four files
  if (f4) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV:");
    if (f4.size() >= 514048) {
      f1.seek(0);
      f2.seek(0);
      f3.seek(0);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        f4.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(4, 1000, usecTotal, usecMax);

      Serial.println();
      Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV staggered:");
      f1.seek(0);
      f2.seek(0);
      f3.seek(0);
      f4.seek(0);
      f1.read(buffer, 512);
      f1.read(buffer, 512);
      f1.read(buffer, 512);
      f2.read(buffer, 512);
      f2.read(buffer, 512);
      f3.read(buffer, 512);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        f4.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(4, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST4.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST4.WAV on this card");
    return;
  }

}


unsigned long maximum(unsigned long a, unsigned long b,
  unsigned long c, unsigned long d)
{
  if (b > a) a = b;
  if (c > a) a = c;
  if (d > a) a = d;
  return a;
}


void reportSpeed(unsigned int numFiles, unsigned long blockCount, unsigned long usecTotal, unsigned long usecMax)
{
  float bytesPerSecond = (float)(blockCount * 512 * numFiles) / usecTotal;
  Serial.print("  Overall speed = ");
  Serial.print(bytesPerSecond);
  Serial.println(" Mbyte/sec");
  Serial.print("  Worst block time = ");
  Serial.print((float)usecMax / 1000.0);
  Serial.println(" ms");
  Serial.print("    ");
  Serial.print( (float)usecMax / 29.01333);
  Serial.println("% of audio frame time");
}


void loop(void) {
  // do nothing after the test
}

And here is the test modified for using flash memory:
Code:
// SD Card Test
//
// Check if the SD card on the Audio Shield is working,
// and perform some simple speed measurements to gauge
// its ability to play 1, 2, 3 and 4 WAV files at a time.
//
// Requires the audio shield:
//   http://www.pjrc.com/store/teensy3_audio.html
//
// Data files to put on your SD card can be downloaded here:
//   http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html
//
// This example code is in the public domain.

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

// Use these with the Teensy Audio Shield.  Teensy 4.0 uses a different
// pinout than Teensy 3.x
#if defined(__IMXRT1062__)
#define FLASH_CS_PIN     6		// Teensy 4.0
#define FLASH_MOSI_PIN  11
#define FLASH_SCK_PIN   13
#else

#define FLASH_CS_PIN     6		// Teensy 3.2/3.5/3.6
#define FLASH_MOSI_PIN   7
#define FLASH_SCK_PIN   14
#endif

#define SDCARD_CS_PIN	10

// Use these with the Teensy 3.5 & 3.6 SD card
//#define SDCARD_MOSI_PIN  11  // not actually used
//#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

void setup() {
  SerialFlashFile f1, f2, f3, f4;
  char buffer[512];
  boolean status;
  unsigned long usec, usecMax;
  elapsedMicros usecTotal, usecSingle;
  int i;

  // wait for the Arduino Serial Monitor to open
  while (!Serial) ;
  delay(50);

  //uncomment these if you have other SPI chips connected
  //to keep them disabled while using only SerialFlash
  pinMode (SDCARD_CS_PIN, INPUT_PULLUP);

  // Configure SPI
  SPI.setMOSI(FLASH_MOSI_PIN);
  SPI.setSCK(FLASH_SCK_PIN);

  Serial.begin(9600);
  Serial.println("Flash memory Test");
  Serial.println("-----------------");

  // First, detect the card
  status = SerialFlash.begin (FLASH_CS_PIN);
  if (status) {
    Serial.println("Flash memory is connected :-)");
  } else {
    Serial.println("Flash memory is not connected or unusable :-(");
    return;
  }

  // Now open the flash memory normally
  status = SerialFlash.begin(FLASH_CS_PIN);
  if (status) {
    Serial.println("SerialFlash library is able to access the filesystem");
  } else {
    Serial.println("SerialFlash library can not access the filesystem!");
  }


  // Open the 4 sample files.  Hopefully they're on the card
  f1 = SerialFlash.open("SDTEST1.WAV");
  f2 = SerialFlash.open("SDTEST2.WAV");
  f3 = SerialFlash.open("SDTEST3.WAV");
  f4 = SerialFlash.open("SDTEST4.WAV");

  // Speed test reading a single file
  if (f1) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV:");
    if (f1.size() >= 514048) {
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(1, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST1.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST1.WAV on this card");
    return;
  }

  // Speed test reading two files
  if (f2) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV & SDTEST2.WAV:");
    if (f2.size() >= 514048) {
      f1.seek(0);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(2, 1000, usecTotal, usecMax);

      Serial.println();
      Serial.println("Reading SDTEST1.WAV & SDTEST2.WAV staggered:");
      f1.seek(0);
      f2.seek(0);
      f1.read(buffer, 512);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(2, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST2.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST2.WAV on this card");
    return;
  }


  // Speed test reading three files
  if (f3) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV:");
    if (f3.size() >= 514048) {
      f1.seek(0);
      f2.seek(0);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(3, 1000, usecTotal, usecMax);

      Serial.println();
      Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV staggered:");
      f1.seek(0);
      f2.seek(0);
      f3.seek(0);
      f1.read(buffer, 512);
      f1.read(buffer, 512);
      f2.read(buffer, 512);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(3, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST3.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST3.WAV on this card");
    return;
  }


  // Speed test reading four files
  if (f4) {
    Serial.println();
    Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV:");
    if (f4.size() >= 514048) {
      f1.seek(0);
      f2.seek(0);
      f3.seek(0);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        f4.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(4, 1000, usecTotal, usecMax);

      Serial.println();
      Serial.println("Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV staggered:");
      f1.seek(0);
      f2.seek(0);
      f3.seek(0);
      f4.seek(0);
      f1.read(buffer, 512);
      f1.read(buffer, 512);
      f1.read(buffer, 512);
      f2.read(buffer, 512);
      f2.read(buffer, 512);
      f3.read(buffer, 512);
      usecMax = 0;
      usecTotal = 0;
      for (i=0; i < 1000; i++) {
        usecSingle = 0;
        f1.read(buffer, 512);
        f2.read(buffer, 512);
        f3.read(buffer, 512);
        f4.read(buffer, 512);
        usec = usecSingle;
        if (usec > usecMax) usecMax = usec;
      }
      reportSpeed(4, 1000, usecTotal, usecMax);
    } else {
      Serial.println("SDTEST4.WAV is too small for speed testing");
    }
  } else {
    Serial.println("Unable to find SDTEST4.WAV on this card");
    return;
  }

}


unsigned long maximum(unsigned long a, unsigned long b,
  unsigned long c, unsigned long d)
{
  if (b > a) a = b;
  if (c > a) a = c;
  if (d > a) a = d;
  return a;
}


void reportSpeed(unsigned int numFiles, unsigned long blockCount, unsigned long usecTotal, unsigned long usecMax)
{
  float bytesPerSecond = (float)(blockCount * 512 * numFiles) / usecTotal;
  Serial.print("  Overall speed = ");
  Serial.print(bytesPerSecond);
  Serial.println(" Mbyte/sec");
  Serial.print("  Worst block time = ");
  Serial.print((float)usecMax / 1000.0);
  Serial.println(" ms");
  Serial.print("    ");
  Serial.print( (float)usecMax / 29.01333);
  Serial.println("% of audio frame time");
}


void loop(void) {
  // do nothing after the test
}
 
Last edited:
Science!

I recall a post from Frank or Paul that it had to do with how the SD cards work internally; something about them doesn't like lots of random reads (which is what reading from multiple audio streams ends up looking like). It depended a lot on who made them and what type they were.

So if in your tests serial flash is ~3x faster than SD, and people were getting 3 to 4 simultaneous voices with SD cards, I should expect 9 to 12 from serial flash, which is quite acceptable to me (I only have 12 buttons on my device). I can put some of mine on internal memory too. Or, mathing it differently, 5.24 MBytes/second divided by 88.200 KBytes/second per stream = 60 streams absolute max. 50% of that is 30, so between 9 and 30 streams -- still plenty for my usage. I ordered some serial flash chips but they won't arrive for a while.
 
Note, the only Teensy Player for Serial Flash uses the RAW format, which in turn is like a mono WAV format without the extra headers. So you need to make sure all of your sounds fit in the serial flash (i.e. 16 megabytes) using the RAW format, and if you need stereo, you need to have two streams, one for the left and the other for the right channel.

The Serial Flash that I bought was in SOIC-8 format, which meant surface mount soldering. I did a quick check on ebay, and I didn't see any chips with > 64 M-bit (i.e. 8 megabyte) that used DIP or through hole soldering.

According to the SerialFlash documents on PJRC, 128 M-bit was the largest supported. I don't know if that means only 128 M-bit chips were tested, or if 256/512 M-bit chips use a different method to address the memory. When I looked at digikey, there were only two 256 M-bit chips, and neither where in the SOIC-8 package used by the audio shield.
 
Understood, and thanks. I'll be going from 230-ish KB to 16 MB, but also from 8-bit u-law at 11,025 Hz to 16-bit PCM at 44,100 Hz so I'll only have about ~8x the storage (~190 seconds vs. ~21 seconds) which gets me from "concerned it might not be enough" to "I know I can fit". I haven't built my full sample list yet, so if for some unexpected reason I'm able to fit in on-chip memory, I can just not populate the serial flash on my PCB. For prototyping I also ordered a SOIC breakout board (that same one!), and I'm familiar with the differences in storage format (but haven't have made samples for either; my prototype is still using the example sample include files). Fortunately, I've got audio tools and know how to use them, so sample generation is not expected to be a hurdle.
 
Understood, and thanks. I'll be going from 230-ish KB to 16 MB, but also from 8-bit u-law at 11,025 Hz to 16-bit PCM at 44,100 Hz so I'll only have about ~8x the storage (~190 seconds vs. ~21 seconds) which gets me from "concerned it might not be enough" to "I know I can fit". I haven't built my full sample list yet, so if for some unexpected reason I'm able to fit in on-chip memory, I can just not populate the serial flash on my PCB. For prototyping I also ordered a SOIC breakout board (that same one!), and I'm familiar with the differences in storage format (but haven't have made samples for either; my prototype is still using the example sample include files). Fortunately, I've got audio tools and know how to use them, so sample generation is not expected to be a hurdle.

Fair enough. I never know in writing replies what skill level the people are at.
 
I'm working on mp3/aac/flac.
On my experimental version it plays just now 4 MP3s concurrently (on T4)
So, more is possible, I think - but have not tried it so far.
It will depend on speed of SD, bitrate, free memory, number of unused "reserved" interrupts and so on..

This version works for T4 / mp3 only (T3.x and aac/flac in WIP), tested only SD so far.
https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib/tree/experimental-multi-instances
 
Last edited:
I'm working on mp3/aac/flac.
On my experimental version it plays just now 4 MP3s concurrently (on T4)
So, more is possible, I think - but have not tried it so far.
It will depend on speed of SD, bitrate, free memory, number of unused "reserved" interrupts and so on..

This version works for T4 / mp3 only (T3.x and aac/flac in WIP), tested only SD so far.
https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib/tree/experimental-multi-instances


Hello Frank! I'm trying to play several mp3s on Teensy 4.0 from builtin SD (for the beginning trying 2 files to play) with the last version of your library mentioned here, but the only last triggered to play file is actually playing. Also by printing out playing position it seems like the first file is stacked on the same position because the numbers don't change, but for the second file everything works fine.

Here is my code may be someone could help me to find the problem...

Code:
#include <Arduino.h>

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

#include "Arduino-Teensy-Codec-lib-master/play_sd_mp3.h"

// GUItool: begin automatically generated code
AudioPlaySdMp3 playSdWav1;  //xy=174,103
AudioPlaySdMp3 playSdWav2;  //xy=174,136
AudioPlaySdMp3 playSdWav3;  //xy=174,169
AudioPlaySdMp3 playSdWav5;  //xy=173.75000381469727,232.50000381469727
AudioPlaySdMp3 playSdWav4;  //xy=175,201
AudioPlaySdMp3 playSdWav6;  //xy=175.00000381469727,263.75000381469727
AudioPlaySdMp3 playSdWav7;  //xy=175.00000381469727,297.5000057220459
AudioPlaySdMp3 playSdWav8;  //xy=176.25,331.2500066757202
AudioPlaySdMp3 playSdWav9;  //xy=176.25,365.00000762939453
AudioPlaySdMp3 playSdWav10; //xy=178.75,398.75000858306885
AudioPlaySdMp3 playSdWav11; //xy=178.75000381469727,431.25000953674316
AudioPlaySdMp3 playSdWav12; //xy=178.75,463.75000953674316
AudioPlaySdMp3 playSdWav13; //xy=177.5,495.00000762939453
AudioPlaySdMp3 playSdWav14; //xy=177.5,526.2500085830688
AudioPlaySdMp3 playSdWav15; //xy=177.50000381469727,556.2500095367432
AudioPlaySdMp3 playSdWav16; //xy=177.50000381469727,587.5000095367432
AudioPlaySdMp3 playSdWav17; //xy=177.50000381469727,618.7500095367432
AudioPlaySdMp3 playSdWav18; //xy=177.50000381469727,650.0000095367432
AudioPlaySdMp3 playSdWav19; //xy=177.5,681.2500104904175
AudioPlaySdMp3 playSdWav20; //xy=177.5,712.5000114440918
AudioPlaySdMp3 playSdWav21; //xy=177.5,743.7500123977661
AudioPlaySdMp3 playSdWav22; //xy=177.50000381469727,775.0000114440918
AudioPlaySdMp3 playSdWav23; //xy=177.5,806.2500123977661
AudioPlaySdMp3 playSdWav24; //xy=177.50000381469727,837.5000133514404
AudioPlaySdMp3 playSdWav25; //xy=175.00000381469727,870.0000133514404
AudioMixer4 mixer1;         //xy=386,119
AudioMixer4 mixer2;         //xy=387,182
AudioMixer4 mixer3;         //xy=387,245
AudioMixer4 mixer4;         //xy=388,307
AudioMixer4 mixer9;         //xy=388,619
AudioMixer4 mixer5;         //xy=389,370
AudioMixer4 mixer6;         //xy=389,433
AudioMixer4 mixer7;         //xy=389,495
AudioMixer4 mixer8;         //xy=389,557
AudioMixer4 mixer10;        //xy=389,680
AudioMixer4 mixer12;        //xy=388.75000762939453,805.0000114440918
AudioMixer4 mixer11;        //xy=389.50000381469727,742.0000114440918
AudioMixer4 mixer13;        //xy=580.0000076293945,138.75000381469727
AudioMixer4 mixer14;        //xy=580.0000076293945,201.25001907348633
AudioMixer4 mixer15;        //xy=585.0000038146973,701.2500152587891
AudioMixer4 mixer16;        //xy=587.5000076293945,637.5000076293945
AudioMixer4 mixer17;        //xy=386,119
AudioMixer4 mixer18;        //xy=387,182
AudioMixer4 mixer19;        //xy=387,245
AudioMixer4 mixer20;        //xy=388,307
AudioMixer4 mixer21;        //xy=388,619
AudioMixer4 mixer22;        //xy=389,370
AudioMixer4 mixer23;        //xy=389,433
AudioMixer4 mixer24;        //xy=389,495
AudioMixer4 mixer25;        //xy=389,557
AudioMixer4 mixer26;        //xy=389,680
AudioMixer4 mixer27;        //xy=388.75000762939453,805.0000114440918
AudioMixer4 mixer28;        //xy=389.50000381469727,742.0000114440918
AudioMixer4 mixer29;        //xy=580.0000076293945,138.75000381469727
AudioMixer4 mixer30;        //xy=580.0000076293945,201.25001907348633
AudioMixer4 mixer31;        //xy=585.0000038146973,701.2500152587891
AudioMixer4 mixer32;
AudioAmplifier amp2;   //xy=872.2500152587891,550
AudioAmplifier amp1;   //xy=873.2500152587891,515
AudioOutputI2S i2s2_1; //xy=1002.2500152587891,531
AudioOutputTDM2 tdm1;  //xy=1003.2500152587891,309
AudioConnection patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord2(playSdWav1, 1, mixer2, 0);
AudioConnection patchCord3(playSdWav2, 0, mixer1, 1);
AudioConnection patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection patchCord5(playSdWav3, 0, mixer1, 2);
AudioConnection patchCord6(playSdWav3, 1, mixer2, 2);
AudioConnection patchCord7(playSdWav5, 0, mixer3, 0);
AudioConnection patchCord8(playSdWav5, 1, mixer4, 0);
AudioConnection patchCord9(playSdWav4, 0, mixer1, 3);
AudioConnection patchCord10(playSdWav4, 1, mixer2, 3);
AudioConnection patchCord11(playSdWav6, 0, mixer3, 1);
AudioConnection patchCord12(playSdWav6, 1, mixer4, 1);
AudioConnection patchCord13(playSdWav7, 0, mixer3, 2);
AudioConnection patchCord14(playSdWav7, 1, mixer4, 2);
AudioConnection patchCord15(playSdWav8, 0, mixer3, 3);
AudioConnection patchCord16(playSdWav8, 1, mixer4, 3);
AudioConnection patchCord17(playSdWav9, 0, mixer5, 0);
AudioConnection patchCord18(playSdWav9, 1, mixer6, 0);
AudioConnection patchCord35(playSdWav10, 0, mixer5, 1);
AudioConnection patchCord36(playSdWav10, 1, mixer6, 1);
AudioConnection patchCord41(playSdWav11, 0, mixer5, 2);
AudioConnection patchCord42(playSdWav11, 1, mixer6, 2);
AudioConnection patchCord45(playSdWav12, 0, mixer5, 3);
AudioConnection patchCord46(playSdWav12, 1, mixer6, 3);
AudioConnection patchCord21(playSdWav13, 0, mixer7, 0);
AudioConnection patchCord22(playSdWav13, 1, mixer8, 0);
AudioConnection patchCord23(playSdWav14, 0, mixer7, 1);
AudioConnection patchCord24(playSdWav14, 1, mixer8, 1);
AudioConnection patchCord25(playSdWav15, 0, mixer7, 2);
AudioConnection patchCord26(playSdWav15, 1, mixer8, 2);
AudioConnection patchCord27(playSdWav16, 0, mixer7, 3);
AudioConnection patchCord28(playSdWav16, 1, mixer8, 3);
AudioConnection patchCord29(playSdWav17, 0, mixer9, 0);
AudioConnection patchCord30(playSdWav17, 1, mixer10, 0);
AudioConnection patchCord31(playSdWav18, 0, mixer9, 1);
AudioConnection patchCord32(playSdWav18, 1, mixer10, 1);
AudioConnection patchCord33(playSdWav19, 0, mixer9, 2);
AudioConnection patchCord34(playSdWav19, 1, mixer10, 2);
AudioConnection patchCord37(playSdWav20, 0, mixer9, 3);
AudioConnection patchCord38(playSdWav20, 1, mixer10, 3);
AudioConnection patchCord39(playSdWav21, 0, mixer11, 0);
AudioConnection patchCord40(playSdWav21, 1, mixer12, 0);
AudioConnection patchCord43(playSdWav22, 0, mixer11, 1);
AudioConnection patchCord44(playSdWav22, 1, mixer12, 1);
AudioConnection patchCord47(playSdWav23, 0, mixer11, 2);
AudioConnection patchCord48(playSdWav23, 1, mixer12, 2);
AudioConnection patchCord49(playSdWav24, 0, mixer11, 3);
AudioConnection patchCord50(playSdWav24, 1, mixer12, 3);
AudioConnection patchCord19(playSdWav25, 0, mixer16, 3);
AudioConnection patchCord20(playSdWav25, 1, mixer15, 3);
AudioConnection patchCord51(mixer1, 0, mixer13, 0);
AudioConnection patchCord52(mixer2, 0, mixer14, 0);
AudioConnection patchCord53(mixer3, 0, mixer13, 1);
AudioConnection patchCord54(mixer4, 0, mixer14, 1);
AudioConnection patchCord55(mixer9, 0, mixer16, 0);
AudioConnection patchCord56(mixer5, 0, mixer13, 2);
AudioConnection patchCord57(mixer6, 0, mixer14, 2);
AudioConnection patchCord58(mixer7, 0, mixer13, 3);
AudioConnection patchCord59(mixer8, 0, mixer14, 3);
AudioConnection patchCord60(mixer10, 0, mixer15, 0);
AudioConnection patchCord61(mixer12, 0, mixer15, 1);
AudioConnection patchCord62(mixer11, 0, mixer16, 1);
AudioConnection patchCord63(mixer13, 0, mixer16, 2);
AudioConnection patchCord64(mixer14, 0, mixer15, 2);
AudioConnection patchCord65(playSdWav1, 0, mixer17, 0);
AudioConnection patchCord66(playSdWav1, 1, mixer18, 0);
AudioConnection patchCord67(playSdWav2, 0, mixer17, 1);
AudioConnection patchCord68(playSdWav2, 1, mixer18, 1);
AudioConnection patchCord69(playSdWav3, 0, mixer17, 2);
AudioConnection patchCord70(playSdWav3, 1, mixer18, 2);
AudioConnection patchCord71(playSdWav5, 0, mixer19, 0);
AudioConnection patchCord72(playSdWav5, 1, mixer20, 0);
AudioConnection patchCord73(playSdWav4, 0, mixer17, 3);
AudioConnection patchCord74(playSdWav4, 1, mixer18, 3);
AudioConnection patchCord75(playSdWav6, 0, mixer19, 1);
AudioConnection patchCord76(playSdWav6, 1, mixer20, 1);
AudioConnection patchCord77(playSdWav7, 0, mixer19, 2);
AudioConnection patchCord78(playSdWav7, 1, mixer20, 2);
AudioConnection patchCord79(playSdWav8, 0, mixer19, 3);
AudioConnection patchCord80(playSdWav8, 1, mixer20, 3);
AudioConnection patchCord81(playSdWav9, 0, mixer21, 0);
AudioConnection patchCord82(playSdWav9, 1, mixer22, 0);
AudioConnection patchCord83(playSdWav10, 0, mixer21, 1);
AudioConnection patchCord84(playSdWav10, 1, mixer22, 1);
AudioConnection patchCord85(playSdWav11, 0, mixer21, 2);
AudioConnection patchCord86(playSdWav11, 1, mixer22, 2);
AudioConnection patchCord87(playSdWav12, 0, mixer21, 3);
AudioConnection patchCord88(playSdWav12, 1, mixer22, 3);
AudioConnection patchCord89(playSdWav13, 0, mixer23, 0);
AudioConnection patchCord90(playSdWav13, 1, mixer24, 0);
AudioConnection patchCord91(playSdWav14, 0, mixer23, 1);
AudioConnection patchCord92(playSdWav14, 1, mixer24, 1);
AudioConnection patchCord93(playSdWav15, 0, mixer23, 2);
AudioConnection patchCord94(playSdWav15, 1, mixer24, 2);
AudioConnection patchCord95(playSdWav16, 0, mixer23, 3);
AudioConnection patchCord96(playSdWav16, 1, mixer24, 3);
AudioConnection patchCord97(playSdWav17, 0, mixer25, 0);
AudioConnection patchCord98(playSdWav17, 1, mixer26, 0);
AudioConnection patchCord99(playSdWav18, 0, mixer25, 1);
AudioConnection patchCord100(playSdWav18, 1, mixer26, 1);
AudioConnection patchCord101(playSdWav19, 0, mixer25, 2);
AudioConnection patchCord102(playSdWav19, 1, mixer26, 2);
AudioConnection patchCord103(playSdWav20, 0, mixer25, 3);
AudioConnection patchCord104(playSdWav20, 1, mixer26, 3);
AudioConnection patchCord105(playSdWav21, 0, mixer27, 0);
AudioConnection patchCord106(playSdWav21, 1, mixer28, 0);
AudioConnection patchCord107(playSdWav22, 0, mixer27, 1);
AudioConnection patchCord108(playSdWav22, 1, mixer28, 1);
AudioConnection patchCord109(playSdWav23, 0, mixer27, 2);
AudioConnection patchCord110(playSdWav23, 1, mixer28, 2);
AudioConnection patchCord111(playSdWav24, 0, mixer27, 3);
AudioConnection patchCord112(playSdWav24, 1, mixer28, 3);
AudioConnection patchCord113(playSdWav25, 0, mixer32, 3);
AudioConnection patchCord114(playSdWav25, 1, mixer31, 3);
AudioConnection patchCord115(mixer17, 0, mixer29, 0);
AudioConnection patchCord116(mixer18, 0, mixer30, 0);
AudioConnection patchCord117(mixer19, 0, mixer29, 1);
AudioConnection patchCord118(mixer20, 0, mixer30, 1);
AudioConnection patchCord119(mixer25, 0, mixer32, 0);
AudioConnection patchCord120(mixer21, 0, mixer29, 2);
AudioConnection patchCord121(mixer22, 0, mixer30, 2);
AudioConnection patchCord122(mixer23, 0, mixer29, 3);
AudioConnection patchCord123(mixer24, 0, mixer30, 3);
AudioConnection patchCord124(mixer26, 0, mixer31, 0);
AudioConnection patchCord6125(mixer28, 0, mixer31, 1);
AudioConnection patchCord126(mixer27, 0, mixer32, 1);
AudioConnection patchCord127(mixer29, 0, mixer32, 2);
AudioConnection patchCord6128(mixer30, 0, mixer31, 2);
AudioConnection patchCord129(mixer15, 0, tdm1, 0);
AudioConnection patchCord130(mixer16, 0, tdm1, 1);
AudioConnection patchCord131(mixer31, 0, amp1, 0);
AudioConnection patchCord132(mixer32, 0, amp2, 0);
AudioConnection patchCord133(amp2, 0, i2s2_1, 1);
AudioConnection patchCord134(amp1, 0, i2s2_1, 0);
// GUItool: end automatically generated code

void playing()
{
  if (!playSdWav1.isPlaying())
  {
    playSdWav1.play("01.mp3");
    // playSdWav1.("01.mp3");
    delayMicroseconds(10);
  }
  if (!playSdWav2.isPlaying())
  {
    playSdWav2.play("02.mp3");
    delayMicroseconds(1);
  }
}

void muteAll()
{
  mixer17.gain(0, 0.0);
  mixer17.gain(1, 0.0);
  mixer17.gain(2, 0.0);
  mixer17.gain(3, 0.0);
  mixer18.gain(0, 0.0);
  mixer18.gain(1, 0.0);
  mixer18.gain(2, 0.0);
  mixer18.gain(3, 0.0);
  mixer19.gain(0, 0.0);
  mixer19.gain(1, 0.0);
  mixer19.gain(2, 0.0);
  mixer19.gain(3, 0.0);
  mixer20.gain(0, 0.0);
  mixer20.gain(1, 0.0);
  mixer20.gain(2, 0.0);
  mixer20.gain(3, 0.0);
  mixer21.gain(0, 0.0);
  mixer21.gain(1, 0.0);
  mixer21.gain(2, 0.0);
  mixer21.gain(3, 0.0);
  mixer22.gain(0, 0.0);
  mixer22.gain(1, 0.0);
  mixer22.gain(2, 0.0);
  mixer22.gain(3, 0.0);
  mixer23.gain(0, 0.0);
  mixer23.gain(1, 0.0);
  mixer23.gain(2, 0.0);
  mixer23.gain(3, 0.0);
  mixer24.gain(0, 0.0);
  mixer24.gain(1, 0.0);
  mixer24.gain(2, 0.0);
  mixer24.gain(3, 0.0);
  mixer25.gain(0, 0.0);
  mixer25.gain(1, 0.0);
  mixer25.gain(2, 0.0);
  mixer25.gain(3, 0.0);
  mixer26.gain(0, 0.0);
  mixer26.gain(1, 0.0);
  mixer26.gain(2, 0.0);
  mixer26.gain(3, 0.0);
  mixer27.gain(0, 0.0);
  mixer27.gain(1, 0.0);
  mixer27.gain(2, 0.0);
  mixer27.gain(3, 0.0);
  mixer28.gain(0, 0.0);
  mixer28.gain(1, 0.0);
  mixer28.gain(2, 0.0);
  mixer28.gain(3, 0.0);

  mixer31.gain(3, 0.0);
  mixer32.gain(3, 0.0);
}

void switching()
{
  static byte count = 0;
  static unsigned long timer = millis();

  if ((millis() - timer) > 10000)
  {
    muteAll();

    switch (count)
    {
    case 0:
      mixer17.gain(0, 1.0);
      mixer18.gain(0, 1.0);
      break;

    case 1:
      mixer17.gain(1, 1.0);
      mixer18.gain(1, 1.0);
      break;

    default:
      break;
    }

    count++;
    if (count >= 2)
      count = 0;
    timer = millis();
  }
}

void setup()
{
  AudioMemory(1000);
  Serial.begin(9600);

again:
  if (!(SD.begin(BUILTIN_SDCARD)))
  {
    // stop here, but print a message repetitively
    while (1)
    {
      Serial.println("Unable to access the SD card");
      delay(500);
      goto again;
    }
  }
  amp1.gain(0.3);
  amp2.gain(0.3);
  muteAll();
  Serial.println("\n\n MemUse \t MaxMemUse \t CPUuse \t MaxCPUuse");
}

void loop()
{
  static unsigned long timer = millis();
  playing();
  switching();
  if ((millis() - timer) > 500)
  {
    Serial.print("\n MemUse " + String(AudioMemoryUsage()));
    Serial.print("\t MaxMemUse " + String(AudioMemoryUsageMax()));
    Serial.print("\t CPUuse " + String(AudioProcessorUsage()));
    Serial.print("\t MaxCPUuse " + String(AudioProcessorUsageMax()));
    Serial.print("\t Time_1 " + String(playSdWav1.positionMillis()));
    Serial.println("\t Time_2 " + String(playSdWav2.positionMillis()));
    AudioMemoryUsageMaxReset();
    AudioProcessorUsageMaxReset();

    timer = millis();
  }
}
 
Last edited:
That was an experiment.
Havn't tried since then. But you're using way too much player objects. Try a low number, perhaps 4.
Sorry, I can't help if that does not work, too, and I do not intend to work on this anymore.
 
Status
Not open for further replies.
Back
Top