Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 5 1 2 3 ... LastLast
Results 1 to 25 of 114

Thread: Now for MP3 with FS...

  1. #1
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619

    Now for MP3 with FS...

    @FrankB - Your Teensy-WavePlayer works absolutely great with all SD, MSC and LFS devices I have used it with. That is all of them

    I have not delved into MP3 yet but I want to. What is the status of this with all of the different filesystems to date. Is it something possible?

    Thanks...

  2. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    9,619
    Quote Originally Posted by wwatson View Post
    @FrankB - Your Teensy-WavePlayer works absolutely great with all SD, MSC and LFS devices I have used it with. That is all of them

    I have not delved into MP3 yet but I want to. What is the status of this with all of the different filesystems to date. Is it something possible?

    Thanks...
    It can play from SD, from serial flash (uses the serial flash library) and from Teensy-Memory (give it a pointer).
    No work has been done to add LittlFS so far.

    I currently only use the ESP32.
    The codecs run fantastic on it too (a ported version), currently I'm at ~10% CPU load for a radio MP3 stream (128kbps Edit: 12% for 320kbps..) for everything (so incl. wifi connection, buffering, and a basic audiomixer. It uses floats, not short).
    Plenty left for additional goodies.. Edit Also, it is (better: will be) much easier to play several mp3 simultanously. And perhaps I'll port some of chip`s float-audio-lib parts and use the esp dsp lib/features...
    Last edited by Frank B; 11-26-2021 at 09:18 AM.

  3. #3
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Quote Originally Posted by Frank B View Post
    It can play from SD, from serial flash (uses the serial flash library) and from Teensy-Memory (give it a pointer).
    No work has been done to add LittlFS so far.

    I currently only use the ESP32.
    The codecs run fantastic on it too (a ported version), currently I'm at ~10% CPU load for a radio MP3 stream (128kbps Edit: 12% for 320kbps..) for everything (so incl. wifi connection, buffering, and a basic audiomixer. It uses floats, not short).
    Plenty left for additional goodies.. Edit Also, it is (better: will be) much easier to play several mp3 simultanously. And perhaps I'll port some of chip`s float-audio-lib parts and use the esp dsp lib/features...
    With a little tweaking to codec.h and Mp3FilePlayer.ino I can play MP3 files from LittleFS devices. I was able to play them from the QPINand, SPINand (CS 5 and 6), SPIFlash (CS 3 and 4). I do not have QSPIFlash on the T4.1 I was using so have not tested that one yet but I'm sure it will. It was a chop job on codec.h for now. Once I test MSC devices I can figure out a better way to implement it.

    Works well

  4. #4
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Quote Originally Posted by wwatson View Post
    With a little tweaking to codec.h and Mp3FilePlayer.ino I can play MP3 files from LittleFS devices. I was able to play them from the QPINand, SPINand (CS 5 and 6), SPIFlash (CS 3 and 4). I do not have QSPIFlash on the T4.1 I was using so have not tested that one yet but I'm sure it will. It was a chop job on codec.h for now. Once I test MSC devices I can figure out a better way to implement it.

    Works well
    @wwatson - you should post your changes for LittleFS and/or issue a PR when you get done should be fun to play with. I have used the Library in the past and it works great.

  5. #5
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Quote Originally Posted by mjs513 View Post
    @wwatson - you should post your changes for LittleFS and/or issue a PR when you get done should be fun to play with. I have used the Library in the past and it works great.
    Mike I just now got MSC working with it Everything is now working are all working through FS. I now can setup a sketch(s) to demonstrate all of the filesystems using MP3 files. I will put my version on GitHub. I still am having issues with msFilesystem and myusb.task(). Will figure that out. It will not repeat the play in loop();

    At least it is playing MP3 files...

  6. #6
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    @all who want to try this out - I have setup a repo for playing MP3 files with LittleFS using @FrankB's Arduino-Teensy-Codec-lib. In this I have added a sketch to play MP3 files from LittleFS devices. Five files were modified to do this. This is using Arduino 1.8.16 and TD1.56B3. LittleFS devices that I have tested are listed in the sketch Mp3FilePlayerLFS.ino. There are devices not tested but should work as main ones do work.

    REPO here:
    https://github.com/wwatson4506/Ardui.../tree/FS_Usage

    Modified files are:
    - play_sd_mp3.h
    Code:
    public:
    	void stop(void);
    	int play(FS *fs, const char *filename) {stop();if (!fopen(fs,filename)) return ERR_CODEC_FILE_NOT_FOUND; return play();}
    	int play(const char *filename) {stop();if (!fopen(filename)) return ERR_CODEC_FILE_NOT_FOUND; return play();}
    	int play(const size_t p, const size_t size) {stop();if (!fopen(p,size)) return ERR_CODEC_FILE_NOT_FOUND; return play();}
    	int play(const uint8_t*p, const size_t size) {stop();if (!fopen(p,size))  return ERR_CODEC_FILE_NOT_FOUND; return play();}
    - codecs.h
    Code:
    public:
    	bool fopen(FS *fs,const char *filename) {ftype=codec_file; AudioStartUsingSPI(); fptr=NULL;	file=fs->open(filename); _fsize=file.size(); _fposition=0;return file != 0;} //FILE
    	bool fopen(const char *filename) {ftype=codec_file; AudioStartUsingSPI(); fptr=NULL; file=SD.open(filename); _fsize=file.size(); _fposition=0; return file != 0;} //FILE
    	bool fopen(const uint8_t*p, const size_t size) {ftype=codec_flash; fptr=(uint8_t*)p; _fsize=size; _fposition=0; return true;} //FLASH
    	bool fopen(const size_t p, const size_t size) {ftype=codec_serflash; offset=p; _fsize=size; _fposition=0; AudioStartUsingSPI(); serflashinit(); return true;} //SERIAL FLASH
    	void fclose(void)
    This is just a new overload for using an FS pointer for opening any FS file type.SD, LFS and MSC.

    You will have to modify Mp3FilePlayerLFS.ino manually to select the LFS device you want to use.
    Code:
    // Simple MP3 player example for LittleFS
    //
    // Requires the audio shield:
    //   http://www.pjrc.com/store/teensy3_audio.html
    //
    // This example code is in the public domain.
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    
    #if defined(ARDUINO_TEENSY41)
    #include "LittleFS.h" // T4.1 only
    #endif
    
    #include <play_sd_mp3.h>
    
    LittleFS_QPINAND   lfsFS;
    //LittleFS_QSPIFlash lfsFS;
    //LittleFS_SPIFlash  lfsFS;
    //LittleFS_SPINAND   lfsFS;
    SDClass sd;
    
    // GUItool: begin automatically generated code
    AudioPlaySdMp3           playMp31;       //xy=154,78
    AudioOutputI2S           i2s1;           //xy=334,89
    AudioConnection          patchCord1(playMp31, 0, i2s1, 0);
    AudioConnection          patchCord2(playMp31, 1, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=240,153
    // GUItool: end automatically generated code
    
    void setup() {
      Serial.begin(9600);
    
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(5);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
    
      SPI.setMOSI(7);
      SPI.setSCK(14);
      
    //  if (!(SD.begin(10))) { // For external SD card.
    //  if (!(sd.begin(BUILTIN_SDCARD))) { // For BUILTIN_SDCARD.
      if (!lfsFS.begin()) { // For LittleFS
    //  pinMode(6,OUTPUT); Change these for SPIFlash and SPINAND.
    //  digitalWriteFast(6,HIGH); // Ditto
    //  if(!lfsFS.begin(6,SPI)) { // Again ditto
      // stop here, but print a message repetitively
        while (1) {
          Serial.println("Unable to access the drive...");
    //      Serial.println("Unable to access the SD card");
          delay(500);
        }
      }
    }
    
    void playFile(const char *filename)
    {
      Serial.print("Playing file: ");
      Serial.println(filename);
      // Start playing the file.  This sketch continues to
      // run while the file plays.
      playMp31.play(&lfsFS, filename);
    //  playMp31.play(&sd, filename);
        // Simply wait for the file to finish playing.
        while (playMp31.isPlaying()) {
        // uncomment these lines if your audio shield
        // has the optional volume pot soldered
        float vol = analogRead(15);
        vol = vol / 1024;
        sgtl5000_1.volume(vol);
    #if 0	
    	 Serial.print("Max Usage: ");
    	 Serial.print(playMp31.processorUsageMax());
    	 Serial.print("% Audio, ");
    	 Serial.print(playMp31.processorUsageMaxDecoder());	 	 
    	 Serial.print("% Decoding max, ");
    	 
    	 Serial.print(playMp31.processorUsageMaxSD());	 
    	 Serial.print("% SD max, ");
    	 	 
    	 Serial.print(AudioProcessorUsageMax());	 
    	 Serial.println("% All");
    	 
    	 AudioProcessorUsageMaxReset();
    	 playMp31.processorUsageMaxReset();
    	 playMp31.processorUsageMaxResetDecoder();
    #endif 
    	 
    	 delay(250);
      }
    }
    
    
    void loop() {
    //  playFile("ForTag.mp3");	
    //  playFile("Tom.mp3");
    //  playFile("Foreverm.mp3");
      //Play a Def Lepard MP3.
      playFile("armaged.mp3"); // Install your own MP3 file on your selected device.
      delay(500);
    }
    This is a simple proof of functionality of using FrankB's library.
    Now for testing MSC

  7. #7
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Quote Originally Posted by wwatson
    @all who want to try this out - I have setup a repo for playing MP3 files with LittleFS using @FrankB's Arduino-Teensy-Codec-lib. In this I have added a sketch to play MP3 files from LittleFS devices. Five files were modified to do this. This is using Arduino 1.8.16 and TD1.56B3. LittleFS devices that I have tested are listed in the sketch Mp3FilePlayerLFS.ino. There are devices not tested but should work as main ones do work.
    Thank you - definitely will try it later today.

  8. #8
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    @All - Quick update. Now have MSC working properly with MP3. Will update Arduino-Teensy-Codec-lib and create a sketch specifically for playing MP3 files with MSC.

  9. #9
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Another update. Not out off the woods yet with MP3 and MSC After further testing I am still not able to repeat playing an MP3 file intermittently. With the T4.1 breakout board I see it hitting stop() three times and then getting a decode_res of -6 or -9 when it fails. This is here marked in red:
    Code:
    //decoding-interrupt
    //__attribute__ ((optimize("O2"))) <- does not work here, bug in g++
    void decodeMp3(void)
    {
    	AudioPlaySdMp3 *o = mp3objptr;
    	int db = o->decoding_block;
    
    	if ( o->decoded_length[db] > 0 ) return; //this block is playing, do NOT fill it
    
    	uint32_t cycles = ARM_DWT_CYCCNT;
    	int eof = false;
    
    	switch (o->decoding_state) {
    
    	case 0:
    		{
    
    			o->sd_left = o->fillReadBuffer( o->file, o->sd_buf, o->sd_p, o->sd_left, MP3_SD_BUF_SIZE);
    			if (!o->sd_left) { eof = true; 
    				goto mp3end; }
    			o->sd_p = o->sd_buf;
    
    			uint32_t cycles_rd = (ARM_DWT_CYCCNT - cycles);
    			if (cycles_rd > o->decode_cycles_max_read )o-> decode_cycles_max_read = cycles_rd;
    			break;
    		}
    
    	case 1:
    		{
    			// find start of next MP3 frame - assume EOF if no sync found
    			int offset = MP3FindSyncWord(o->sd_p, o->sd_left);
    
    			if (offset < 0) {
    				//Serial.println("No sync"); //no error at end of file
    				eof = true;
    				goto mp3end;
    			}
    
    			o->sd_p += offset;
    			o->sd_left -= offset;
    
    			int decode_res = MP3Decode(o->hMP3Decoder, &o->sd_p, (int*)&o->sd_left,o->buf[db], 0);
    
    			switch(decode_res)
    			{
    				case ERR_MP3_NONE:
    				{
    					MP3GetLastFrameInfo(o->hMP3Decoder, &o->mp3FrameInfo);
    					o->decoded_length[db] = o->mp3FrameInfo.outputSamps;
    					break;
    				}
    
    				case ERR_MP3_MAINDATA_UNDERFLOW:
    				{
    					break;
    				}
    
    				default :
    				{
    					AudioPlaySdMp3::lastError = decode_res;
    					eof = true;
    					break;
    				}
    			}
    
    			cycles = (ARM_DWT_CYCCNT - cycles);
    			if (cycles > o->decode_cycles_max ) o->decode_cycles_max = cycles;
    			break;
    		}
    	}//switch
    
    mp3end:
    
    	o->decoding_state++;
    	if (o->decoding_state >= DECODE_NUM_STATES) o->decoding_state = 0;
    	if (eof) o->stop();
    }
    These are the error code defs:
    Code:
    	ERR_MP3_INVALID_FRAMEHEADER =  -6,
    	ERR_MP3_INVALID_HUFFCODES =    -9,
    On the T4.1 breakout board -9 is seen the most with occasional -6 as it loops. On the T4.0 breakout board -6 is seen the most.
    On both boards if you do an upload or power off or disconnect/connect it will always play the MP3 once but fail most of the time with a repeat play in loop().

    It's like the reads to the buffer of the second play are corrupted. Not sure...

    Here is the sketch for MSC:
    Code:
    // Simple MP3 player example for USB drives.
    //
    // Requires the audio shield:
    //   http://www.pjrc.com/store/teensy3_audio.html
    //
    // This example code is in the public domain.
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <USBHost_t36.h>
    #include <USBHost_ms.h>
    
    #include <play_sd_mp3.h>
    // Setup USBHost_t36 and as many HUB ports as needed.
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    USBHub hub3(myusb);
    USBHub hub4(myusb);
    
    msFilesystem msFS1(myusb);
    msController drive1(myusb);
    USBMSCDevice mscDrive;
    
    // GUItool: begin automatically generated code
    AudioPlaySdMp3           playMp31;       //xy=154,78
    AudioOutputI2S           i2s1;           //xy=334,89
    AudioConnection          patchCord1(playMp31, 0, i2s1, 0);
    AudioConnection          patchCord2(playMp31, 1, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=240,153
    // GUItool: end automatically generated code
    
    void setup() {
      Serial.begin(9600);
    
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(5);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
    
      // Initialize USBHost_t36
      myusb.begin();
      delay(100);
      
      if (!mscDrive.begin(&drive1)) {
      // stop here, but print a message repetitively
        while (1) {
          Serial.println("Unable to access the drive...");
          delay(500);
        }
      }
      myusb.Task();
    }
    
    void playFile(const char *filename)
    {
    int error = 0;
      Serial.print("Playing file: ");
      Serial.println(filename);
      // Start playing the file.  This sketch continues to
      // run while the file plays.
      if(msFS1 == 0)
        Serial.printf("mscFS no longer valid...\r\n");
        error = playMp31.play(&msFS1, filename);
    	Serial.printf("play() error = %d\r\n",error);
      // Simply wait for the file to finish playing.
        while (playMp31.isPlaying()) {
      // uncomment these lines if your audio shield
      // has the optional volume pot soldered
        float vol = analogRead(15);
        vol = vol / 1024;
        sgtl5000_1.volume(vol);
    //   delay(250);
      }
    }
    
    
    void loop() {
    //  playFile("ForTag.mp3");	
    //  playFile("Tom.mp3");
    //  playFile("Foreverm.mp3");
      playFile("armaged.mp3");
      delay(100);
    }
    This is using USBHost_t36-FS_Integration_MSC found here:
    https://github.com/KurtE/USBHost_t36...ntegration_MSC

    Will keep testing to find out what's going wrong. Dang so close yet not there
    Last edited by wwatson; 11-27-2021 at 11:43 PM. Reason: Can't talk right...

  10. #10
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    9,619
    Since I'm currently back on topic (ESP), and I also briefly struggled with the -6 and -.9, I can say that this is almost 100% an offset issue. The decoder reads wrong data.
    Whenever it is called, the frame header should be in byte 1 and 2. If this is not the case, such errors often occur.
    It looks like something is not synchronized. Since the rest of the code works fine (for other file types) it must be the reading somehow.
    (Or you found a bug.. this first after many years!)

    I hope this helps...

    When you get it running, i'll be happy to merge it.

  11. #11
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Quote Originally Posted by Frank B View Post
    Since I'm currently back on topic (ESP), and I also briefly struggled with the -6 and -.9, I can say that this is almost 100% an offset issue. The decoder reads wrong data.
    Whenever it is called, the frame header should be in byte 1 and 2. If this is not the case, such errors often occur.
    It looks like something is not synchronized. Since the rest of the code works fine (for other file types) it must be the reading somehow.
    (Or you found a bug.. this first after many years!)

    I hope this helps...

    When you get it running, i'll be happy to merge it.
    Thanks Frank. That gives me something to work with. Like you said it is working consistently with SD (BUILTIN and External) and LFS. So suspect is MSC implementation. Maybe hexdump the frame header upon initial play and next play then compare to find a clue. Might also go back and use UsbMSCFat to check it's response. Things are still in development with MSC so it all might change.

    Again thanks for the clues

  12. #12
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,519
    @wwatson - have you seen KurtE's github.com/KurtE/MemoryHexDump
    > coolest thing is it hides dupe lines - that won't help much on an mpg.

  13. #13
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    @wwatson
    Downloaded your lib this morning to give it a try and I am not seeing any errors:
    Code:
    Playing file: SDTEST1.mp3
    play() error = 0
    but the problem is nothing is playing. This is using a USB Drive.

  14. #14
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Quote Originally Posted by mjs513 View Post
    @wwatson
    Downloaded your lib this morning to give it a try and I am not seeing any errors:
    Code:
    Playing file: SDTEST1.mp3
    play() error = 0
    but the problem is nothing is playing. This is using a USB Drive.
    I just tried SDTEST(1-4).mp3 and I could not get them to play either. I have been using regular MP3 music file I have. More to go on for testing. Did you ever have a chance test with LittleFS? I never did try SDTEST*.mp3 files on that either.

    @defragster - Downloaded KurtE's MemHexDump library. Will use that for testing.

    Edit: Just tried SDTEST*.mp3 with LittleFS devices and they do work. Back to testing MSC and MP3...
    Last edited by wwatson; 11-28-2021 at 02:55 PM.

  15. #15
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Quote Originally Posted by wwatson View Post
    I just tried SDTEST(1-4).mp3 and I could not get them to play either. I have been using regular MP3 music file I have. More to go on for testing. Did you ever have a chance test with LittleFS? I never did try SDTEST*.mp3 files on that either.

    @defragster - Downloaded KurtE's MemHexDump library. Will use that for testing.

    Edit: Just tried SDTEST*.mp3 with LittleFS devices and they do work. Back to testing MSC and MP3...
    Going to see if I can modify the sketch to use it in conjunction with MTP and see what happens at some point today.

  16. #16
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Going to see if I can modify the sketch to use it in conjunction with MTP and see what happens at some point today.
    That should be an interesting adventure

  17. #17
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Quote Originally Posted by wwatson View Post
    That should be an interesting adventure
    yeah it was but still didn't work

  18. #18
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    yeah it was but still didn't work
    I am gaining some debug info using MemoryHexDump and sprinkling in some Serial.prints. Going through both LFS and MSC use of the MP3 player with SDTEST1.mp3 step by step comparing the debug info. MCS gets about 4 frames in before it fails with error -9. So now into the next function that is setting the errror.

  19. #19
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    @mjs513 @FrankB @All - I Got it
    I did a lot of debugging and testing but nothing was working. If the MP3 file had a MP3 ID3 info header it would not play it would fail after reading 4 frames of data and if it did not have an MP3 ID3 info header it would play once but would not replay -9 error. As it turned out I was getting incomplete reads into sb_buf. So I was thinking this is going to be one of those MSC is to slow things But then I started to remember back in the day's of uSDFS when I was testing different types of buffering to speed MSC up. Then I remembered using malloc() was causing grief and was really slow. To make a long 4 days of debugging and testing short I changed sd_buf from being calloced() to a global uint8_t sd_buf[]. That took care of the failures. Tested SD, SDIO, LFS and MSC they all work.

    Have an errand to run but will zip up Arduino-Teensy-Codec-lib and post it for testing when I get back.
    I really love success

  20. #20
    Senior Member wwatson's Avatar
    Join Date
    Aug 2017
    Posts
    619
    Ok - Here is the attached zip of Arduino-Teensy-Codec-lib. Apparently the zip is to big so I updated my REPO:
    https://github.com/wwatson4506/Ardui.../tree/FS_Usage

    This is only for testing not going to submit a PR until there is something more than a workaround for the issue. I know using a global array for a buffer is bad. That's why I hope you guy's might be able to come up with a better way of doing it. Also wondering if MTP_Teensy is using calloc/malloc for buffering MSC drives. That could be an issue

    So far I cannot get any MP3 files to fail that does not fail on my one PC.
    Ran out of time to play...
    Last edited by wwatson; 11-29-2021 at 01:39 AM. Reason: Correct Spelling...

  21. #21
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Quote Originally Posted by wwatson View Post
    Ok - Here is the attached zip of Arduino-Teensy-Codec-lib. Apparently the zip is to big so I updated my REPO:
    https://github.com/wwatson4506/Ardui.../tree/FS_Usage

    This is only for testing not going to submit a PR until there is something more than a workaround for the issue. I know using a global array for a buffer is bad. That's why I hope you guy's might be able to come up with a better way of doing it. Also wondering if MTP_Teensy is using calloc/malloc for buffering MSC drives. That could be an issue

    So far I cannot get any MP3 files to fail that does not fail on my one PC.
    Ran out of time to play...
    Just downloaded your updates and gave it a try and looks like you got it solved. Played on first try. Now to have some fun

  22. #22
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    @wwatson and all interested parties.

    You got me inspired this morning so I did a modification to the MTP_test sketch so instead of logging data it will play mp3 files on the device or a single hardcoded file in the sketch. PS. I also did a hack to play_sd_wav.h and .cpp so the sketch will also play wav files as well. Did test it from USB Drive. There are improvements that you can do to the sketch-error checking and maybe a next key for when playing all files but again this is a test So I am attaching a copy of the hacked up play_sd_wav files for the audio library and the mtp_test_audio sketch Have fun.

    Audio.zip

    Code:
    #include <SD.h>
    #include <MTP_Teensy.h>
    #include <Audio.h>
    #include <play_sd_mp3.h>
    
    // GUItool: begin automatically generated code
    AudioPlaySdMp3           playMp31;       //xy=154,78
    AudioPlaySdWav           playWav; //xy=154,422
    AudioOutputI2S           i2s1;           //xy=334,89
    AudioMixer4              mixer1;         //xy=323,326
    AudioConnection          patchCord1(playMp31, 0, mixer1, 0);
    AudioConnection          patchCord2(playMp31, 1, mixer1, 1);
    AudioConnection          patchCord3(playWav, 0, mixer1, 2);
    AudioConnection          patchCord4(playWav, 1, mixer1, 3);
    AudioConnection          patchCord5(mixer1, i2s1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=240,153
    // GUItool: end automatically generated code
    float volume = 0.5f;
    char filename[] = "SDTEST1.mp3";
    
    //---------------------------------------------------
    // Select drives you want to create
    //---------------------------------------------------
    #define USE_SD  1         // SDFAT based SDIO and SPI
    #ifdef ARDUINO_TEENSY41
    #define USE_LFS_RAM 1     // T4.1 PSRAM (or RAM)
    #else
    #define USE_LFS_RAM 0     // T4.1 PSRAM (or RAM)
    #endif
    #ifdef ARDUINO_TEENSY_MICROMOD
    #define USE_LFS_QSPI 0    // T4.1 QSPI
    #define USE_LFS_PROGM 1   // T4.4 Progam Flash
    #define USE_LFS_SPI 0     // SPI Flash
    #define USE_LFS_NAND 0
    #define USE_LFS_QSPI_NAND 0
    #define USE_LFS_FRAM 0
    #else
    #define USE_LFS_QSPI 1    // T4.1 QSPI
    #define USE_LFS_PROGM 1   // T4.4 Progam Flash
    #define USE_LFS_SPI 1     // SPI Flash
    #define USE_LFS_NAND 1
    #define USE_LFS_QSPI_NAND 0
    #define USE_LFS_FRAM 0
    #endif
    #define USE_MSC 1    // set to > 0 experiment with MTP (USBHost.t36 + mscFS)
    #define USE_SW_PU  1 //set to 1 if SPI devices does not have PUs,
                         // https://www.pjrc.com/better-spi-bus-design-in-3-steps/
    
    
    #define DBGSerial Serial
    FS *myfs;
    File dataFile, myFile;  // Specifes that dataFile is of File type
    int record_count = 0;
    bool write_data = false;
    uint8_t current_store = 0;
    
    #define BUFFER_SIZE_INDEX 128
    uint8_t write_buffer[BUFFER_SIZE_INDEX];
    #define buffer_mult 4
    uint8_t buffer_temp[buffer_mult*BUFFER_SIZE_INDEX];
    
    int bytesRead;
    uint32_t drive_index = 0;
    
    
    //=============================================================================
    // Global defines
    //=============================================================================
    
    MTPStorage storage;
    MTPD    mtpd(&storage);
    
    //=============================================================================
    // MSC & SD classes
    //=============================================================================
    #if USE_SD==1
    #define USE_BUILTIN_SDCARD
    #if defined(USE_BUILTIN_SDCARD) && defined(BUILTIN_SDCARD)
    #define CS_SD  BUILTIN_SDCARD
    #else
    #define CS_SD 10
    #endif
    #endif
    
    
    // SDClasses 
    #if USE_SD==1
      // edit SPI to reflect your configuration (following is for T4.1)
      #define SD_MOSI 11
      #define SD_MISO 12
      #define SD_SCK  13
    
      #define SPI_SPEED SD_SCK_MHZ(16)  // adjust to sd card 
    
      #if defined (BUILTIN_SDCARD)
        const char *sd_str[]={"sdio","sd1"}; // edit to reflect your configuration
        const int cs[] = {BUILTIN_SDCARD,10}; // edit to reflect your configuration
      #else
        const char *sd_str[]={"sd1"}; // edit to reflect your configuration
        const int cs[] = {10}; // edit to reflect your configuration
      #endif
      const int nsd = sizeof(sd_str)/sizeof(const char *);
      
    SDClass sdx[nsd];
    #endif
    
    // =======================================================================
    // Set up MSC Drive file systems on different storage media
    // =======================================================================
    #if USE_MSC == 1
    #include <USBHost_t36.h>
    #include <USBHost_ms.h>
    
    // Add USBHost objectsUsbFs
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    USBHub hub(myusb);
    
    // MSC objects.
    msController drive1(myusb);
    msController drive2(myusb);
    msController drive3(myusb);
    msController drive4(myusb);
    
    msFilesystem msFS1(myusb);
    msFilesystem msFS2(myusb);
    msFilesystem msFS3(myusb);
    msFilesystem msFS4(myusb);
    msFilesystem msFS5(myusb);
    
    // Quick and dirty
    msFilesystem *pmsFS[] = {&msFS1, &msFS2, &msFS3, &msFS4, &msFS5};
    #define CNT_MSC  (sizeof(pmsFS)/sizeof(pmsFS[0]))
    uint32_t pmsfs_store_ids[CNT_MSC] = {0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL};
    char  pmsFS_display_name[CNT_MSC][20];
    
    msController *pdrives[] {&drive1, &drive2, &drive3, &drive4};
    #define CNT_DRIVES  (sizeof(pdrives)/sizeof(pdrives[0]))
    bool drive_previous_connected[CNT_DRIVES] = {false, false, false, false};
    #endif
    
    
    // =======================================================================
    // Set up LittleFS file systems on different storage media
    // =======================================================================
    
    #if USE_LFS_FRAM == 1 || USE_LFS_NAND == 1 || USE_LFS_PROGM == 1 || USE_LFS_QSPI == 1 || USE_LFS_QSPI_NAND == 1 || \
      USE_LFS_RAM == 1 || USE_LFS_SPI == 1
    #include <LittleFS.h>
    #endif
    
    #if USE_LFS_RAM==1
    const char *lfs_ram_str[] = {"RAM1"};  // edit to reflect your configuration
    const int lfs_ram_size[] = {4'000'000}; // edit to reflect your configuration
    const int nfs_ram = sizeof(lfs_ram_str)/sizeof(const char *);
    LittleFS_RAM ramfs[nfs_ram];
    #endif
    
    #if USE_LFS_QSPI==1
    const char *lfs_qspi_str[]={"QSPI"};     // edit to reflect your configuration
    const int nfs_qspi = sizeof(lfs_qspi_str)/sizeof(const char *);
    LittleFS_QSPIFlash qspifs[nfs_qspi];
    #endif
    
    #if USE_LFS_PROGM==1
    const char *lfs_progm_str[]={"PROGM"};     // edit to reflect your configuration
    const int lfs_progm_size[] = {1'000'000}; // edit to reflect your configuration
    const int nfs_progm = sizeof(lfs_progm_str)/sizeof(const char *);
    LittleFS_Program progmfs[nfs_progm];
    #endif
    
    #if USE_LFS_SPI==1
    const char *lfs_spi_str[]={"sflash5", "sflash6"}; // edit to reflect your configuration
    const int lfs_cs[] = {5, 6}; // edit to reflect your configuration
    const int nfs_spi = sizeof(lfs_spi_str)/sizeof(const char *);
    LittleFS_SPIFlash spifs[nfs_spi];
    #endif
    
    #if USE_LFS_NAND == 1
    const char *nspi_str[]={"WINBOND1G", "WINBOND2G"};     // edit to reflect your configuration
    const int nspi_cs[] = {3, 4}; // edit to reflect your configuration
    const int nspi_nsd = sizeof(nspi_cs)/sizeof(int);
    LittleFS_SPINAND nspifs[nspi_nsd]; // needs to be declared if LittleFS is used in storage.h
    #endif
    
    #if USE_LFS_QSPI_NAND == 1
    const char *qnspi_str[]={"WIN-M02"};     // edit to reflect your configuration
    const int qnspi_nsd = sizeof(qnspi_str)/sizeof(const char *);
    LittleFS_QPINAND qnspifs[qnspi_nsd]; // needs to be declared if LittleFS is used in storage.h
    #endif
    
    void storage_configure()
    {
      DateTimeFields date;
      breakTime(Teensy3Clock.get(), date);
      const char *monthname[12]={
        "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
      DBGSerial.printf("Date: %u %s %u %u:%u:%u\n",
        date.mday, monthname[date.mon], date.year+1900, date.hour, date.min, date.sec);
    
        
      #if USE_SD==1
        #if defined SD_SCK
          SPI.setMOSI(SD_MOSI);
          SPI.setMISO(SD_MISO);
          SPI.setSCK(SD_SCK);
        #endif
    
        for(int ii=0; ii<nsd; ii++)
        { 
          #if defined(BUILTIN_SDCARD)
            if(cs[ii] == BUILTIN_SDCARD)
            {
              DBGSerial.printf("!! Try installing BUILTIN SD Card");
              if(!sdx[ii].begin(BUILTIN_SDCARD))
              { 
                Serial.printf("SDIO Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]);  Serial.println();
              }
              else
              {
                storage.addFilesystem(sdx[ii], sd_str[ii]);
                uint64_t totalSize = sdx[ii].totalSize();
                uint64_t usedSize  = sdx[ii].usedSize();
                Serial.printf("SDIO Storage %d %d %s ",ii,cs[ii],sd_str[ii]); 
                Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
              }
            }
            else if(cs[ii]<BUILTIN_SDCARD)
          #endif
          {
            pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
            if(!sdx[ii].begin(cs[ii])) 
            { Serial.printf("SD Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]);  Serial.println();
            }
            else
            {
              storage.addFilesystem(sdx[ii], sd_str[ii]);
              uint64_t totalSize = sdx[ii].totalSize();
              uint64_t usedSize  = sdx[ii].usedSize();
              Serial.printf("SD Storage %d %d %s ",ii,cs[ii],sd_str[ii]); 
              Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
            }
          }
        
        }
        #endif
    
    #if USE_LFS_RAM==1
      for (int ii=0; ii<nfs_ram;ii++) {
        if (!ramfs[ii].begin(lfs_ram_size[ii])) {
          DBGSerial.printf("Ram Storage %d %s failed or missing",ii,lfs_ram_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(ramfs[ii], lfs_ram_str[ii]);
          uint64_t totalSize = ramfs[ii].totalSize();
          uint64_t usedSize  = ramfs[ii].usedSize();
          DBGSerial.printf("RAM Storage %d %s %llu %llu\n", ii, lfs_ram_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_PROGM==1
      for (int ii=0; ii<nfs_progm;ii++) {
        if (!progmfs[ii].begin(lfs_progm_size[ii])) {
          DBGSerial.printf("Program Storage %d %s failed or missing",ii,lfs_progm_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(progmfs[ii], lfs_progm_str[ii]);
          uint64_t totalSize = progmfs[ii].totalSize();
          uint64_t usedSize  = progmfs[ii].usedSize();
          DBGSerial.printf("Program Storage %d %s %llu %llu\n", ii, lfs_progm_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_QSPI==1
      for(int ii=0; ii<nfs_qspi;ii++) {
        if(!qspifs[ii].begin()) {
          DBGSerial.printf("QSPI Storage %d %s failed or missing",ii,lfs_qspi_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(qspifs[ii], lfs_qspi_str[ii]);
          uint64_t totalSize = qspifs[ii].totalSize();
          uint64_t usedSize  = qspifs[ii].usedSize();
          DBGSerial.printf("QSPI Storage %d %s %llu %llu\n", ii, lfs_qspi_str[ii], totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_SPI==1
      for (int ii=0; ii<nfs_spi;ii++) {
        if (USE_SW_PU == 1) {
          pinMode(lfs_cs[ii],OUTPUT);
          digitalWriteFast(lfs_cs[ii],HIGH);
        }
        if (!spifs[ii].begin(lfs_cs[ii], SPI)) {
          DBGSerial.printf("SPIFlash Storage %d %d %s failed or missing",ii,lfs_cs[ii],lfs_spi_str[ii]);      DBGSerial.println();
        } else {
          storage.addFilesystem(spifs[ii], lfs_spi_str[ii]);
          uint64_t totalSize = spifs[ii].totalSize();
          uint64_t usedSize  = spifs[ii].usedSize();
          DBGSerial.printf("SPIFlash Storage %d %d %s %llu %llu\n", ii, lfs_cs[ii], lfs_spi_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    #if USE_LFS_NAND == 1
      for(int ii=0; ii<nspi_nsd;ii++) {
        if (USE_SW_PU == 1) {
          pinMode(nspi_cs[ii],OUTPUT);
          digitalWriteFast(nspi_cs[ii],HIGH);
        }
        if(!nspifs[ii].begin(nspi_cs[ii], SPI)) {
          DBGSerial.printf("SPIFlash NAND Storage %d %d %s failed or missing",ii,nspi_cs[ii],nspi_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(nspifs[ii], nspi_str[ii]);
          uint64_t totalSize = nspifs[ii].totalSize();
          uint64_t usedSize  = nspifs[ii].usedSize();
          DBGSerial.printf("Storage %d %d %s %llu %llu\n", ii, nspi_cs[ii], nspi_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_QSPI_NAND == 1
      for(int ii=0; ii<qnspi_nsd;ii++) {
        if(!qnspifs[ii].begin()) {
           DBGSerial.printf("QSPI NAND Storage %d %s failed or missing",ii,qnspi_str[ii]); DBGSerial.println();
        } else {
          storage.addFilesystem(qnspifs[ii], qnspi_str[ii]);
          uint64_t totalSize = qnspifs[ii].totalSize();
          uint64_t usedSize  = qnspifs[ii].usedSize();
          DBGSerial.printf("Storage %d %s %llu %llu\n", ii, qnspi_str[ii], totalSize, usedSize);
        }
      }
    #endif
    
    }
    
    void setup()
    {
    
      // Open serial communications and wait for port to open
      while (!Serial && !DBGSerial.available() && millis() < 5000) 
    
      DBGSerial.print(CrashReport);
      DBGSerial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      delay(3000);
      
      //Setup Audio
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(40);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(volume);
    
    
      //This is mandatory to begin the mtpd session.
      mtpd.begin();
      
      storage_configure();
    
      #if USE_MSC == 1
      myusb.begin();
      DBGSerial.print("Initializing MSC Drives ...");
      DBGSerial.println("\nInitializing USB MSC drives...");
      DBGSerial.println("MSC and MTP initialized.");
      checkMSCChanges();
      #endif
      DBGSerial.println("\nSetup done");
      menu();
    }
    
    int ReadAndEchoSerialChar() {
      int ch = DBGSerial.read();
      if (ch >= ' ') DBGSerial.write(ch);
      return ch;
    }
    
    uint8_t storage_index = '0';
    void loop()
    {
      if ( DBGSerial.available() ) {
        uint8_t command = DBGSerial.read();
        int ch = DBGSerial.read();
        if ('2'==command) storage_index = CommandLineReadNextNumber(ch, 0);
        while (ch == ' ') ch = DBGSerial.read();
    
        uint32_t fsCount;
        switch (command) {
        case '1':
          // first dump list of storages:
          fsCount = storage.getFSCount();
          DBGSerial.printf("\nDump Storage list(%u)\n", fsCount);
          for (uint32_t ii = 0; ii < fsCount; ii++) {
            if ( ii == storage_index )
              DBGSerial.print("STORE");
            else
              DBGSerial.print("store");
            DBGSerial.printf(":%u storage:%x name:%s fs:%x\n", ii, mtpd.Store2Storage(ii),
              storage.getStoreName(ii), (uint32_t)storage.getStoreFS(ii));
          }
          //DBGSerial.println("\nDump Index List");
          //storage.dumpIndexList();
          break;
        case '2':
          if (storage_index < storage.getFSCount()) {
            DBGSerial.printf("Storage Index %u Name: %s Selected\n", storage_index,
              storage.getStoreName(storage_index));
            myfs = storage.getStoreFS(storage_index);
            current_store = storage_index;
          } else {
            DBGSerial.printf("Storage Index %u out of range\n", storage_index);
          }
          break;
    
        case 'l': listFiles(); break;
        case 'e': eraseFiles(); break;
        case 'p':
        {
          write_data = true;   // sets flag to continue to write data until new command is received
          int errorMp3 = 0;
          DBGSerial.print("Playing file: ");
          DBGSerial.println(filename);
          // Start playing the file.  This sketch continues to
          // run while the file plays.
          errorMp3 = playMp31.play(myfs, filename);
          DBGSerial.printf("play() error = %d\r\n",errorMp3);
          // Simply wait for the file to finish playing.
          if(errorMp3 != 0) write_data = false;
          break;
        }
        case 'P': 
          playDir(myfs);
          break;
        case'r':
          DBGSerial.println("Reset");
          mtpd.send_DeviceResetEvent();
          break;
        case 'R':
          DBGSerial.print(" RESTART Teensy ...");
          delay(100);
          SCB_AIRCR = 0x05FA0004;
          break;
        case '\r':
        case '\n':
        case 'h': menu(); break;
        }
        while (DBGSerial.read() != -1) ; // remove rest of characters.
      } else {
        #if USE_MSC == 1
        checkMSCChanges();
        #endif
        mtpd.loop();
      }
    
      if (write_data) {
        while (playMp31.isPlaying()) {
          // uncomment these lines if your audio shield
          // has the optional volume pot soldered
          //  float vol = analogRead(15);
          //  vol = vol / 1024;
          //  sgtl5000_1.volume(vol);
          //   delay(250);
        }
      }
    }
    
    #if USE_MSC == 1
    void checkMSCChanges() {
      myusb.Task();
    
      USBMSCDevice mscDrive;
      PFsLib pfsLIB;
      for (uint8_t i=0; i < CNT_DRIVES; i++) {
        if (*pdrives[i]) {
          if (!drive_previous_connected[i]) {
            if (mscDrive.begin(pdrives[i])) {
              Serial.printf("\nUSB Drive: %u connected\n", i);
              pfsLIB.mbrDmp(&mscDrive, (uint32_t)-1, Serial);
              Serial.printf("\nTry Partition list");
              pfsLIB.listPartitions(&mscDrive, Serial);
              drive_previous_connected[i] = true;
            }
          }
        } else {
          drive_previous_connected[i] = false;
        }
      }
      bool send_device_reset = false;
      for (uint8_t i = 0; i < CNT_MSC; i++) {
        if (*pmsFS[i] && (pmsfs_store_ids[i] == 0xFFFFFFFFUL)) {
          Serial.printf("Found new Volume:%u\n", i); Serial.flush();
          // Lets see if we can get the volume label:
          char volName[20];
          if (pmsFS[i]->mscfs.getVolumeLabel(volName, sizeof(volName)))
            snprintf(pmsFS_display_name[i], sizeof(pmsFS_display_name[i]), "MSC%d-%s", i, volName);
          else
            snprintf(pmsFS_display_name[i], sizeof(pmsFS_display_name[i]), "MSC%d", i);
          pmsfs_store_ids[i] = storage.addFilesystem(*pmsFS[i], pmsFS_display_name[i]);
    
          // Try to send store added. if > 0 it went through = 0 stores have not been enumerated
          if (mtpd.send_StoreAddedEvent(pmsfs_store_ids[i]) < 0) send_device_reset = true;
        }
        // Or did volume go away?
        else if ((pmsfs_store_ids[i] != 0xFFFFFFFFUL) && !*pmsFS[i] ) {
          if (mtpd.send_StoreRemovedEvent(pmsfs_store_ids[i]) < 0) send_device_reset = true;
          storage.removeFilesystem(pmsfs_store_ids[i]);
          // Try to send store added. if > 0 it went through = 0 stores have not been enumerated
          pmsfs_store_ids[i] = 0xFFFFFFFFUL;
        }
      }
      if (send_device_reset) mtpd.send_DeviceResetEvent();
    }
    #endif
    
    
    void menu()
    {
      DBGSerial.println();
      DBGSerial.println("Menu Options:");
      DBGSerial.println("\t1 - List Drives (Step 1)");
      DBGSerial.println("\t2# - Select Drive # for Logging (Step 2)");
      DBGSerial.println("\tl - List files on disk");
      DBGSerial.println("\te - Erase files on disk with Format");
      DBGSerial.println("\tp - Play Hardcoded test file");
      DBGSerial.println("\tP - Play all music on selected device");
      DBGSerial.println("\tr - Reset MTP");
      DBGSerial.printf("\t%s","R - Restart Teensy");
      DBGSerial.println("\th - Menu");
      DBGSerial.println();
    }
    
    void listFiles()
    {
      DBGSerial.print("\n Space Used = ");
      DBGSerial.println(myfs->usedSize());
      DBGSerial.print("Filesystem Size = ");
      DBGSerial.println(myfs->totalSize());
    
      printDirectory(myfs);
    }
    
    void eraseFiles()
    {
      //DBGSerial.println("Formating not supported at this time");
      DBGSerial.println("\n*** Erase/Format started ***");
      myfs->format(1, '.', DBGSerial);
      DBGSerial.println("Completed, sending device reset event");
      mtpd.send_DeviceResetEvent();
    }
    
    void printDirectory(FS *pfs) {
      DBGSerial.println("Directory\n---------");
      printDirectory(pfs->open("/"), 0);
      DBGSerial.println();
    }
    
    void printDirectory(File dir, int numSpaces) {
      while (true) {
        File entry = dir.openNextFile();
        if (! entry) {
          //DBGSerial.println("** no more files **");
          break;
        }
        printSpaces(numSpaces);
        DBGSerial.print(entry.name());
        if (entry.isDirectory()) {
          DBGSerial.println("/");
          printDirectory(entry, numSpaces + 2);
        } else {
          // files have sizes, directories do not
          printSpaces(36 - numSpaces - strlen(entry.name()));
          DBGSerial.print("  ");
          DBGSerial.println(entry.size(), DEC);
        }
        entry.close();
      }
    }
    
    void printSpaces(int num) {
      for (int i = 0; i < num; i++) {
        DBGSerial.print(" ");
      }
    }
    
    
    uint32_t CommandLineReadNextNumber(int &ch, uint32_t default_num) {
      while (ch == ' ') ch = DBGSerial.read();
      if ((ch < '0') || (ch > '9')) return default_num;
    
      uint32_t return_value = 0;
      while ((ch >= '0') && (ch <= '9')) {
        return_value = return_value * 10 + ch - '0';
        ch = DBGSerial.read();
      }
      return return_value;
    }
    
    void playFile(const char *filename)
    {
      int filetype;
    
      filetype = 0;
      if (strstr(filename, ".MP3") != NULL || strstr(filename, ".mp3") != NULL) {
          filetype = 1;
      } else if (strstr(filename, ".WAV") != NULL || strstr(filename, ".wav") != NULL ) {
          filetype = 2;
      } else {
          filetype = 0;
      }
      if (filetype > 0) {
        DBGSerial.print("Playing file: ");
        DBGSerial.println(filename);
        
        switch (filetype) {
          case 1 :
            mixer1.gain(0, volume);
            mixer1.gain(1, volume);
            mixer1.gain(2, 0.0f);
            mixer1.gain(3, 0.0f);
            playMp31.play(myfs, filename);
            delay(5);
            while (playMp31.isPlaying()) {
            }
            break;
          case 2 :
            mixer1.gain(0, 0.0f);
            mixer1.gain(1, 0.0f);
            mixer1.gain(2, volume);
            mixer1.gain(3, volume);
            playWav.play(myfs, filename);
            delay(5);
            while (playWav.isPlaying()) {
            }
            break;
        }
      }
    }
    
    void playDir(FS *pfs) {
      DBGSerial.println("Playing files on device");
      playAll(pfs->open("/"));
      DBGSerial.println();
    }
    
    void playAll(File dir){
      char filename[64];
      char filnam[64];
       while(true) {
         File entry =  dir.openNextFile();
         if (! entry) {
           // no more files
           // rewind to begining of directory and start over
           dir.rewindDirectory();
           break;
         }
         //DBGSerial.print(entry.name());
         if (entry.isDirectory()) {
           //DBGSerial.println("Directory/");
           //do nothing for now
           //DBGSerial.println(entry.name());
           playAll(entry);
         } else {
           // files have sizes, directories do not
           //DBGSerial.print("\t\t");
           //DBGSerial.println(entry.size(), DEC);
           // files have sizes, directories do not
           strcpy(filename, dir.name());
           if(strlen(dir.name()) > 0) strcat(filename, "/");
           strcat(filename, strcpy(filnam, entry.name()));
           playFile(filename);
         }
       entry.close();
     }
    }

  23. #23
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,018
    Sounds like you are having too much fun!

  24. #24
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Quote Originally Posted by KurtE View Post
    Sounds like you are having too much fun!
    Definitely especially when its something you can get working.

  25. #25
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    7,868
    Ok got carried away. I edited the rest of the codec library so you can play aac and flac files as well as editing raw in the audio library. Unfortunately not sure why FLAC files are not playing - not getting any errors and says its playing - maybe something with using audio buffers that its using from the audio library. Anyway here are all the changed files for the audio lib and the codec library:

    Audio.zip

    Arduino-Teensy-Codec-lib-FS_Usage.zip

    and the changed sketch:
    Code:
    #include <SD.h>
    #include <MTP_Teensy.h>
    #include <Audio.h>
    #include <play_sd_mp3.h>
    #include <play_sd_aac.h>
    #include <play_sd_flac.h>
    
    // GUItool: begin automatically generated code
    AudioPlaySdMp3           playMp31;       //xy=154,78
    AudioPlaySdWav           playWav; //xy=154,422
    AudioPlaySdRaw           playRaw; //xy=154,422
    AudioPlaySdAac           playAac; //xy=154,422
    AudioPlaySdFlac          playFlac;
    AudioOutputI2S           i2s1;           //xy=334,89
    AudioMixer4              mixer1;         //xy=323,326
    AudioMixer4              mixer2;         //xy=323,326
    AudioMixer4              mixer3;
    AudioConnection          patchCord1(playMp31, 0, mixer1, 0);
    AudioConnection          patchCord2(playMp31, 1, mixer1, 1);
    AudioConnection          patchCord3(playWav, 0, mixer1, 2);
    AudioConnection          patchCord5(playAac, 0, mixer2, 0);
    AudioConnection          patchCord6(playAac, 1, mixer2, 1);
    AudioConnection          patchCord7(playRaw, 0, mixer2, 2);
    AudioConnection          patchCord8(playFlac, 0, mixer3, 0);
    AudioConnection          patchCord9(playFlac, 1, mixer3, 1);
    AudioConnection          patchCord10(mixer1, i2s1);
    AudioConnection          patchCord11(mixer2, i2s1);
    AudioConnection          patchCord12(mixer3, i2s1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=240,153
    // GUItool: end automatically generated code
    float volume = 0.7f;
    char filename[] = "SDTEST1.mp3";
    
    //---------------------------------------------------
    // Select drives you want to create
    //---------------------------------------------------
    #define USE_SD  1         // SDFAT based SDIO and SPI
    #ifdef ARDUINO_TEENSY41
    #define USE_LFS_RAM 1     // T4.1 PSRAM (or RAM)
    #else
    #define USE_LFS_RAM 0     // T4.1 PSRAM (or RAM)
    #endif
    #ifdef ARDUINO_TEENSY_MICROMOD
    #define USE_LFS_QSPI 0    // T4.1 QSPI
    #define USE_LFS_PROGM 1   // T4.4 Progam Flash
    #define USE_LFS_SPI 0     // SPI Flash
    #define USE_LFS_NAND 0
    #define USE_LFS_QSPI_NAND 0
    #define USE_LFS_FRAM 0
    #else
    #define USE_LFS_QSPI 1    // T4.1 QSPI
    #define USE_LFS_PROGM 1   // T4.4 Progam Flash
    #define USE_LFS_SPI 1     // SPI Flash
    #define USE_LFS_NAND 1
    #define USE_LFS_QSPI_NAND 0
    #define USE_LFS_FRAM 0
    #endif
    #define USE_MSC 1    // set to > 0 experiment with MTP (USBHost.t36 + mscFS)
    #define USE_SW_PU  1 //set to 1 if SPI devices does not have PUs,
                         // https://www.pjrc.com/better-spi-bus-design-in-3-steps/
    
    
    #define DBGSerial Serial
    FS *myfs;
    File dataFile, myFile;  // Specifes that dataFile is of File type
    int record_count = 0;
    bool write_data = false;
    uint8_t current_store = 0;
    
    #define BUFFER_SIZE_INDEX 128
    uint8_t write_buffer[BUFFER_SIZE_INDEX];
    #define buffer_mult 4
    uint8_t buffer_temp[buffer_mult*BUFFER_SIZE_INDEX];
    
    int bytesRead;
    uint32_t drive_index = 0;
    
    
    //=============================================================================
    // Global defines
    //=============================================================================
    
    MTPStorage storage;
    MTPD    mtpd(&storage);
    
    //=============================================================================
    // MSC & SD classes
    //=============================================================================
    #if USE_SD==1
    #define USE_BUILTIN_SDCARD
    #if defined(USE_BUILTIN_SDCARD) && defined(BUILTIN_SDCARD)
    #define CS_SD  BUILTIN_SDCARD
    #else
    #define CS_SD 10
    #endif
    #endif
    
    
    // SDClasses 
    #if USE_SD==1
      // edit SPI to reflect your configuration (following is for T4.1)
      #define SD_MOSI 11
      #define SD_MISO 12
      #define SD_SCK  13
    
      #define SPI_SPEED SD_SCK_MHZ(16)  // adjust to sd card 
    
      #if defined (BUILTIN_SDCARD)
        const char *sd_str[]={"sdio","sd1"}; // edit to reflect your configuration
        const int cs[] = {BUILTIN_SDCARD,10}; // edit to reflect your configuration
      #else
        const char *sd_str[]={"sd1"}; // edit to reflect your configuration
        const int cs[] = {10}; // edit to reflect your configuration
      #endif
      const int nsd = sizeof(sd_str)/sizeof(const char *);
      
    SDClass sdx[nsd];
    #endif
    
    // =======================================================================
    // Set up MSC Drive file systems on different storage media
    // =======================================================================
    #if USE_MSC == 1
    #include <USBHost_t36.h>
    #include <USBHost_ms.h>
    
    // Add USBHost objectsUsbFs
    USBHost myusb;
    USBHub hub1(myusb);
    USBHub hub2(myusb);
    USBHub hub(myusb);
    
    // MSC objects.
    msController drive1(myusb);
    msController drive2(myusb);
    msController drive3(myusb);
    msController drive4(myusb);
    
    msFilesystem msFS1(myusb);
    msFilesystem msFS2(myusb);
    msFilesystem msFS3(myusb);
    msFilesystem msFS4(myusb);
    msFilesystem msFS5(myusb);
    
    // Quick and dirty
    msFilesystem *pmsFS[] = {&msFS1, &msFS2, &msFS3, &msFS4, &msFS5};
    #define CNT_MSC  (sizeof(pmsFS)/sizeof(pmsFS[0]))
    uint32_t pmsfs_store_ids[CNT_MSC] = {0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL};
    char  pmsFS_display_name[CNT_MSC][20];
    
    msController *pdrives[] {&drive1, &drive2, &drive3, &drive4};
    #define CNT_DRIVES  (sizeof(pdrives)/sizeof(pdrives[0]))
    bool drive_previous_connected[CNT_DRIVES] = {false, false, false, false};
    #endif
    
    
    // =======================================================================
    // Set up LittleFS file systems on different storage media
    // =======================================================================
    
    #if USE_LFS_FRAM == 1 || USE_LFS_NAND == 1 || USE_LFS_PROGM == 1 || USE_LFS_QSPI == 1 || USE_LFS_QSPI_NAND == 1 || \
      USE_LFS_RAM == 1 || USE_LFS_SPI == 1
    #include <LittleFS.h>
    #endif
    
    #if USE_LFS_RAM==1
    const char *lfs_ram_str[] = {"RAM1"};  // edit to reflect your configuration
    const int lfs_ram_size[] = {4'000'000}; // edit to reflect your configuration
    const int nfs_ram = sizeof(lfs_ram_str)/sizeof(const char *);
    LittleFS_RAM ramfs[nfs_ram];
    #endif
    
    #if USE_LFS_QSPI==1
    const char *lfs_qspi_str[]={"QSPI"};     // edit to reflect your configuration
    const int nfs_qspi = sizeof(lfs_qspi_str)/sizeof(const char *);
    LittleFS_QSPIFlash qspifs[nfs_qspi];
    #endif
    
    #if USE_LFS_PROGM==1
    const char *lfs_progm_str[]={"PROGM"};     // edit to reflect your configuration
    const int lfs_progm_size[] = {1'000'000}; // edit to reflect your configuration
    const int nfs_progm = sizeof(lfs_progm_str)/sizeof(const char *);
    LittleFS_Program progmfs[nfs_progm];
    #endif
    
    #if USE_LFS_SPI==1
    const char *lfs_spi_str[]={"sflash5", "sflash6"}; // edit to reflect your configuration
    const int lfs_cs[] = {5, 6}; // edit to reflect your configuration
    const int nfs_spi = sizeof(lfs_spi_str)/sizeof(const char *);
    LittleFS_SPIFlash spifs[nfs_spi];
    #endif
    
    #if USE_LFS_NAND == 1
    const char *nspi_str[]={"WINBOND1G", "WINBOND2G"};     // edit to reflect your configuration
    const int nspi_cs[] = {3, 4}; // edit to reflect your configuration
    const int nspi_nsd = sizeof(nspi_cs)/sizeof(int);
    LittleFS_SPINAND nspifs[nspi_nsd]; // needs to be declared if LittleFS is used in storage.h
    #endif
    
    #if USE_LFS_QSPI_NAND == 1
    const char *qnspi_str[]={"WIN-M02"};     // edit to reflect your configuration
    const int qnspi_nsd = sizeof(qnspi_str)/sizeof(const char *);
    LittleFS_QPINAND qnspifs[qnspi_nsd]; // needs to be declared if LittleFS is used in storage.h
    #endif
    
    void storage_configure()
    {
      DateTimeFields date;
      breakTime(Teensy3Clock.get(), date);
      const char *monthname[12]={
        "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
      DBGSerial.printf("Date: %u %s %u %u:%u:%u\n",
        date.mday, monthname[date.mon], date.year+1900, date.hour, date.min, date.sec);
    
        
      #if USE_SD==1
        #if defined SD_SCK
          SPI.setMOSI(SD_MOSI);
          SPI.setMISO(SD_MISO);
          SPI.setSCK(SD_SCK);
        #endif
    
        for(int ii=0; ii<nsd; ii++)
        { 
          #if defined(BUILTIN_SDCARD)
            if(cs[ii] == BUILTIN_SDCARD)
            {
              DBGSerial.printf("!! Try installing BUILTIN SD Card");
              if(!sdx[ii].begin(BUILTIN_SDCARD))
              { 
                Serial.printf("SDIO Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]);  Serial.println();
              }
              else
              {
                storage.addFilesystem(sdx[ii], sd_str[ii]);
                uint64_t totalSize = sdx[ii].totalSize();
                uint64_t usedSize  = sdx[ii].usedSize();
                Serial.printf("SDIO Storage %d %d %s ",ii,cs[ii],sd_str[ii]); 
                Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
              }
            }
            else if(cs[ii]<BUILTIN_SDCARD)
          #endif
          {
            pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
            if(!sdx[ii].begin(cs[ii])) 
            { Serial.printf("SD Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]);  Serial.println();
            }
            else
            {
              storage.addFilesystem(sdx[ii], sd_str[ii]);
              uint64_t totalSize = sdx[ii].totalSize();
              uint64_t usedSize  = sdx[ii].usedSize();
              Serial.printf("SD Storage %d %d %s ",ii,cs[ii],sd_str[ii]); 
              Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
            }
          }
        
        }
        #endif
    
    #if USE_LFS_RAM==1
      for (int ii=0; ii<nfs_ram;ii++) {
        if (!ramfs[ii].begin(lfs_ram_size[ii])) {
          DBGSerial.printf("Ram Storage %d %s failed or missing",ii,lfs_ram_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(ramfs[ii], lfs_ram_str[ii]);
          uint64_t totalSize = ramfs[ii].totalSize();
          uint64_t usedSize  = ramfs[ii].usedSize();
          DBGSerial.printf("RAM Storage %d %s %llu %llu\n", ii, lfs_ram_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_PROGM==1
      for (int ii=0; ii<nfs_progm;ii++) {
        if (!progmfs[ii].begin(lfs_progm_size[ii])) {
          DBGSerial.printf("Program Storage %d %s failed or missing",ii,lfs_progm_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(progmfs[ii], lfs_progm_str[ii]);
          uint64_t totalSize = progmfs[ii].totalSize();
          uint64_t usedSize  = progmfs[ii].usedSize();
          DBGSerial.printf("Program Storage %d %s %llu %llu\n", ii, lfs_progm_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_QSPI==1
      for(int ii=0; ii<nfs_qspi;ii++) {
        if(!qspifs[ii].begin()) {
          DBGSerial.printf("QSPI Storage %d %s failed or missing",ii,lfs_qspi_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(qspifs[ii], lfs_qspi_str[ii]);
          uint64_t totalSize = qspifs[ii].totalSize();
          uint64_t usedSize  = qspifs[ii].usedSize();
          DBGSerial.printf("QSPI Storage %d %s %llu %llu\n", ii, lfs_qspi_str[ii], totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_SPI==1
      for (int ii=0; ii<nfs_spi;ii++) {
        if (USE_SW_PU == 1) {
          pinMode(lfs_cs[ii],OUTPUT);
          digitalWriteFast(lfs_cs[ii],HIGH);
        }
        if (!spifs[ii].begin(lfs_cs[ii], SPI)) {
          DBGSerial.printf("SPIFlash Storage %d %d %s failed or missing",ii,lfs_cs[ii],lfs_spi_str[ii]);      DBGSerial.println();
        } else {
          storage.addFilesystem(spifs[ii], lfs_spi_str[ii]);
          uint64_t totalSize = spifs[ii].totalSize();
          uint64_t usedSize  = spifs[ii].usedSize();
          DBGSerial.printf("SPIFlash Storage %d %d %s %llu %llu\n", ii, lfs_cs[ii], lfs_spi_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    #if USE_LFS_NAND == 1
      for(int ii=0; ii<nspi_nsd;ii++) {
        if (USE_SW_PU == 1) {
          pinMode(nspi_cs[ii],OUTPUT);
          digitalWriteFast(nspi_cs[ii],HIGH);
        }
        if(!nspifs[ii].begin(nspi_cs[ii], SPI)) {
          DBGSerial.printf("SPIFlash NAND Storage %d %d %s failed or missing",ii,nspi_cs[ii],nspi_str[ii]);
          DBGSerial.println();
        } else {
          storage.addFilesystem(nspifs[ii], nspi_str[ii]);
          uint64_t totalSize = nspifs[ii].totalSize();
          uint64_t usedSize  = nspifs[ii].usedSize();
          DBGSerial.printf("Storage %d %d %s %llu %llu\n", ii, nspi_cs[ii], nspi_str[ii],
            totalSize, usedSize);
        }
      }
    #endif
    
    #if USE_LFS_QSPI_NAND == 1
      for(int ii=0; ii<qnspi_nsd;ii++) {
        if(!qnspifs[ii].begin()) {
           DBGSerial.printf("QSPI NAND Storage %d %s failed or missing",ii,qnspi_str[ii]); DBGSerial.println();
        } else {
          storage.addFilesystem(qnspifs[ii], qnspi_str[ii]);
          uint64_t totalSize = qnspifs[ii].totalSize();
          uint64_t usedSize  = qnspifs[ii].usedSize();
          DBGSerial.printf("Storage %d %s %llu %llu\n", ii, qnspi_str[ii], totalSize, usedSize);
        }
      }
    #endif
    
    }
    
    void setup()
    {
    
      // Open serial communications and wait for port to open
      while (!Serial && !DBGSerial.available() && millis() < 5000) 
    
      DBGSerial.print(CrashReport);
      DBGSerial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      delay(3000);
      
      //Setup Audio
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(50);
    
      sgtl5000_1.enable();
      sgtl5000_1.volume(volume);
    
    
      //This is mandatory to begin the mtpd session.
      mtpd.begin();
      
      storage_configure();
    
      #if USE_MSC == 1
      myusb.begin();
      DBGSerial.print("Initializing MSC Drives ...");
      DBGSerial.println("\nInitializing USB MSC drives...");
      DBGSerial.println("MSC and MTP initialized.");
      checkMSCChanges();
      #endif
      DBGSerial.println("\nSetup done");
      menu();
    }
    
    int ReadAndEchoSerialChar() {
      int ch = DBGSerial.read();
      if (ch >= ' ') DBGSerial.write(ch);
      return ch;
    }
    
    uint8_t storage_index = '0';
    void loop()
    {
      if ( DBGSerial.available() ) {
        uint8_t command = DBGSerial.read();
        int ch = DBGSerial.read();
        if ('2'==command) storage_index = CommandLineReadNextNumber(ch, 0);
        while (ch == ' ') ch = DBGSerial.read();
    
        uint32_t fsCount;
        switch (command) {
        case '1':
          // first dump list of storages:
          fsCount = storage.getFSCount();
          DBGSerial.printf("\nDump Storage list(%u)\n", fsCount);
          for (uint32_t ii = 0; ii < fsCount; ii++) {
            if ( ii == storage_index )
              DBGSerial.print("STORE");
            else
              DBGSerial.print("store");
            DBGSerial.printf(":%u storage:%x name:%s fs:%x\n", ii, mtpd.Store2Storage(ii),
              storage.getStoreName(ii), (uint32_t)storage.getStoreFS(ii));
          }
          //DBGSerial.println("\nDump Index List");
          //storage.dumpIndexList();
          break;
        case '2':
          if (storage_index < storage.getFSCount()) {
            DBGSerial.printf("Storage Index %u Name: %s Selected\n", storage_index,
              storage.getStoreName(storage_index));
            myfs = storage.getStoreFS(storage_index);
            current_store = storage_index;
          } else {
            DBGSerial.printf("Storage Index %u out of range\n", storage_index);
          }
          break;
    
        case 'l': listFiles(); break;
        case 'e': eraseFiles(); break;
        case 'p':
        {
          write_data = true;   // sets flag to continue to write data until new command is received
          int errorMp3 = 0;
          DBGSerial.print("Playing file: ");
          DBGSerial.println(filename);
          // Start playing the file.  This sketch continues to
          // run while the file plays.
          errorMp3 = playMp31.play(myfs, filename);
          DBGSerial.printf("play() error = %d\r\n",errorMp3);
          // Simply wait for the file to finish playing.
          if(errorMp3 != 0) write_data = false;
          break;
        }
        case 'P': 
          playDir(myfs);
          break;
        case'r':
          DBGSerial.println("Reset");
          mtpd.send_DeviceResetEvent();
          break;
        case 'R':
          DBGSerial.print(" RESTART Teensy ...");
          delay(100);
          SCB_AIRCR = 0x05FA0004;
          break;
        case '\r':
        case '\n':
        case 'h': menu(); break;
        }
        while (DBGSerial.read() != -1) ; // remove rest of characters.
      } else {
        #if USE_MSC == 1
        checkMSCChanges();
        #endif
        mtpd.loop();
      }
    
      if (write_data) {
        while (playMp31.isPlaying()) {
          // uncomment these lines if your audio shield
          // has the optional volume pot soldered
          //  float vol = analogRead(15);
          //  vol = vol / 1024;
          //  sgtl5000_1.volume(vol);
          //   delay(250);
        }
      }
    }
    
    #if USE_MSC == 1
    void checkMSCChanges() {
      myusb.Task();
    
      USBMSCDevice mscDrive;
      PFsLib pfsLIB;
      for (uint8_t i=0; i < CNT_DRIVES; i++) {
        if (*pdrives[i]) {
          if (!drive_previous_connected[i]) {
            if (mscDrive.begin(pdrives[i])) {
              Serial.printf("\nUSB Drive: %u connected\n", i);
              pfsLIB.mbrDmp(&mscDrive, (uint32_t)-1, Serial);
              Serial.printf("\nTry Partition list");
              pfsLIB.listPartitions(&mscDrive, Serial);
              drive_previous_connected[i] = true;
            }
          }
        } else {
          drive_previous_connected[i] = false;
        }
      }
      bool send_device_reset = false;
      for (uint8_t i = 0; i < CNT_MSC; i++) {
        if (*pmsFS[i] && (pmsfs_store_ids[i] == 0xFFFFFFFFUL)) {
          Serial.printf("Found new Volume:%u\n", i); Serial.flush();
          // Lets see if we can get the volume label:
          char volName[20];
          if (pmsFS[i]->mscfs.getVolumeLabel(volName, sizeof(volName)))
            snprintf(pmsFS_display_name[i], sizeof(pmsFS_display_name[i]), "MSC%d-%s", i, volName);
          else
            snprintf(pmsFS_display_name[i], sizeof(pmsFS_display_name[i]), "MSC%d", i);
          pmsfs_store_ids[i] = storage.addFilesystem(*pmsFS[i], pmsFS_display_name[i]);
    
          // Try to send store added. if > 0 it went through = 0 stores have not been enumerated
          if (mtpd.send_StoreAddedEvent(pmsfs_store_ids[i]) < 0) send_device_reset = true;
        }
        // Or did volume go away?
        else if ((pmsfs_store_ids[i] != 0xFFFFFFFFUL) && !*pmsFS[i] ) {
          if (mtpd.send_StoreRemovedEvent(pmsfs_store_ids[i]) < 0) send_device_reset = true;
          storage.removeFilesystem(pmsfs_store_ids[i]);
          // Try to send store added. if > 0 it went through = 0 stores have not been enumerated
          pmsfs_store_ids[i] = 0xFFFFFFFFUL;
        }
      }
      if (send_device_reset) mtpd.send_DeviceResetEvent();
    }
    #endif
    
    
    void menu()
    {
      DBGSerial.println();
      DBGSerial.println("Menu Options:");
      DBGSerial.println("\t1 - List Drives (Step 1)");
      DBGSerial.println("\t2# - Select Drive # for Logging (Step 2)");
      DBGSerial.println("\tl - List files on disk");
      DBGSerial.println("\te - Erase files on disk with Format");
      DBGSerial.println("\tp - Play Hardcoded test file");
      DBGSerial.println("\tP - Play all music on selected device");
      DBGSerial.println("\tr - Reset MTP");
      DBGSerial.printf("\t%s","R - Restart Teensy");
      DBGSerial.println("\n\th - Menu");
      DBGSerial.println();
    }
    
    void listFiles()
    {
      DBGSerial.print("\n Space Used = ");
      DBGSerial.println(myfs->usedSize());
      DBGSerial.print("Filesystem Size = ");
      DBGSerial.println(myfs->totalSize());
    
      printDirectory(myfs);
    }
    
    void eraseFiles()
    {
      //DBGSerial.println("Formating not supported at this time");
      DBGSerial.println("\n*** Erase/Format started ***");
      myfs->format(1, '.', DBGSerial);
      DBGSerial.println("Completed, sending device reset event");
      mtpd.send_DeviceResetEvent();
    }
    
    void printDirectory(FS *pfs) {
      DBGSerial.println("Directory\n---------");
      printDirectory(pfs->open("/"), 0);
      DBGSerial.println();
    }
    
    void printDirectory(File dir, int numSpaces) {
      while (true) {
        File entry = dir.openNextFile();
        if (! entry) {
          //DBGSerial.println("** no more files **");
          break;
        }
        printSpaces(numSpaces);
        DBGSerial.print(entry.name());
        if (entry.isDirectory()) {
          DBGSerial.println("/");
          printDirectory(entry, numSpaces + 2);
        } else {
          // files have sizes, directories do not
          printSpaces(36 - numSpaces - strlen(entry.name()));
          DBGSerial.print("  ");
          DBGSerial.println(entry.size(), DEC);
        }
        entry.close();
      }
    }
    
    void printSpaces(int num) {
      for (int i = 0; i < num; i++) {
        DBGSerial.print(" ");
      }
    }
    
    
    uint32_t CommandLineReadNextNumber(int &ch, uint32_t default_num) {
      while (ch == ' ') ch = DBGSerial.read();
      if ((ch < '0') || (ch > '9')) return default_num;
    
      uint32_t return_value = 0;
      while ((ch >= '0') && (ch <= '9')) {
        return_value = return_value * 10 + ch - '0';
        ch = DBGSerial.read();
      }
      return return_value;
    }
    
    
    void playFile(const char *filename)
    {
      int filetype;
      int errAudio = 0;
      
      filetype = 0;
      if (strstr(filename, ".MP3") != NULL || strstr(filename, ".mp3") != NULL) {
          filetype = 1;
      } else if (strstr(filename, ".WAV") != NULL || strstr(filename, ".wav") != NULL ) {
          filetype = 2;
      } else if (strstr(filename, ".AAC") != NULL || strstr(filename, ".aac") != NULL) {
          filetype = 3;
      } else if (strstr(filename, ".RAW") != NULL || strstr(filename, ".raw") != NULL) {
          filetype = 4;
      } else if (strstr(filename, ".FLA") != NULL || strstr(filename, ".fla") != NULL ) {
          filetype = 5;    
      } else {
          filetype = 0;
      }
      if (filetype > 0) {
        DBGSerial.print("Playing file: ");
        DBGSerial.println(filename);
        
        switch (filetype) {
          case 1 :
            mixer1.gain(0, volume);
            mixer1.gain(1, volume);
            mixer1.gain(2, 0.0f);
            mixer1.gain(3, 0.0f);
            errAudio = playMp31.play(myfs, filename);
            if(errAudio != 0) {
              Serial.printf("Audio Error: %d\n", errAudio);
              break;
            }
            delay(5);
            while (playMp31.isPlaying()) {
            }
            break;
          case 2 :
            mixer1.gain(0, 0.0f);
            mixer1.gain(1, 0.0f);
            mixer1.gain(2, volume);
            mixer1.gain(3, volume);
            errAudio = playWav.play(myfs, filename);
            if(errAudio == 0) {
              Serial.printf("Audio Error: %d\n", errAudio);
              break;
            }
            delay(5);
            while (playWav.isPlaying()) {
            }
            break;
          case 3 :
            mixer2.gain(0, volume);
            mixer2.gain(1, volume);
            mixer2.gain(2, 0.0f);
            errAudio = playAac.play(myfs, filename);
            if(errAudio != 0) {
              Serial.printf("Audio Error: %d\n", errAudio);
              break;
            }
            delay(5);
            while (playAac.isPlaying()) {
            }
            break;
          case 4 :
            mixer2.gain(0, 0.0f);
            mixer2.gain(1, 0.0f);
            mixer2.gain(2, volume);
            errAudio = playRaw.play(myfs, filename);
            if(errAudio == 0) {
              Serial.printf("Audio Error: %d\n", errAudio);
              break;
            }
            delay(5);
            while (playRaw.isPlaying()) {
            }
            break;
          case 5 :
            mixer3.gain(0, volume);
            mixer3.gain(1, volume);
            errAudio =playFlac.play(myfs, filename);
            if(errAudio != 0) {
              Serial.printf("Audio Error: %d\n", errAudio);
              break;
            }
            delay(5);
            while (playFlac.isPlaying()) {
            }
            break;
        }
      }
    }
    
    void playDir(FS *pfs) {
      DBGSerial.println("Playing files on device");
      playAll(pfs->open("/"));
      DBGSerial.println();
    }
    
    void playAll(File dir){
      char filename[64];
      char filnam[64];
       while(true) {
         File entry =  dir.openNextFile();
         if (! entry) {
           // no more files
           // rewind to begining of directory and start over
           dir.rewindDirectory();
           break;
         }
         //DBGSerial.print(entry.name());
         if (entry.isDirectory()) {
           //DBGSerial.println("Directory/");
           //do nothing for now
           //DBGSerial.println(entry.name());
           playAll(entry);
         } else {
           // files have sizes, directories do not
           //DBGSerial.print("\t\t");
           //DBGSerial.println(entry.size(), DEC);
           // files have sizes, directories do not
           strcpy(filename, dir.name());
           if(strlen(dir.name()) > 0) strcat(filename, "/");
           strcat(filename, strcpy(filnam, entry.name()));
           playFile(filename);
         }
       entry.close();
     }
    }

Posting Permissions

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