Cannot read mp3 after navigate to the next mp3 track

headquaker
Posts: 20
Joined: Thu Sep 21, 2023 6:28 am

Cannot read mp3 after navigate to the next mp3 track

Postby headquaker » Wed Nov 15, 2023 8:35 am

Hi, I've made a mp3 player for my child.
I have an issue that I cannot resolved.
The setup :
- ESP32S3
- SDCard

On loading; the ESP32 load a content.json in the first folder.
It reads, based on the json, a preview track mp3 (it is a Text To Speech mp3 generated by a script that says the Title of the track because my child is too young too read for now).
Then, if pushing the play button, it plays the mp3 that is corresponding of the selection (always based on the json).
The issue starts here : I don't know why but it seems that if I next to the next track, it cannot read mp3 anymore.
I can see in console that the path is good but there is not sound while the first mp3 has no issue.

Any idea ?

EDIT : I know that when the ESP32 is loading for the first time, it will not play the preview track, I don't have made that cade for now.
  1. #include "Arduino.h"
  2. #include "Audio.h"
  3. #include "FS.h"
  4. #include "SPI.h"
  5. #include "SD.h"
  6. #include <Wire.h>
  7. #include <vector>
  8. #include <lvgl.h>
  9. #include <ui.h>
  10. #include <Arduino_GFX_Library.h>
  11. #include <esp_wifi.h>
  12. #include "esp_bt.h"
  13. #include <ArduinoJson.h>
  14.  
  15. #define TFT_BL 2
  16.  
  17. #define SD_SCK 12 // CLK
  18. #define SD_MISO 13 // D0
  19. #define SD_MOSI 11 // CMD
  20. #define SD_CS 10   // CLK
  21.  
  22. #define I2S_DOUT 17
  23. #define I2S_BCLK 0
  24. #define I2S_LRC 18
  25.  
  26. #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
  27.  
  28. #if defined(DISPLAY_DEV_KIT)
  29. Arduino_GFX *gfx = create_default_Arduino_GFX();
  30. #else /* !defined(DISPLAY_DEV_KIT) */
  31.  
  32. Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
  33.     GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
  34.     40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
  35.     45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
  36.     5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
  37.     8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
  38. );
  39. // option 1:
  40. // ST7262 IPS LCD 800x480
  41.  Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
  42.    bus,
  43.    800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
  44.    480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
  45.    1 /* pclk_active_neg */, 13000000 /* prefer_speed */, true /* auto_flush */);
  46. #endif /* !defined(DISPLAY_DEV_KIT) */
  47. // End of Arduino_GFX setting
  48.  
  49. // screen configuration
  50. static uint32_t screenWidth;
  51. static uint32_t screenHeight;
  52. static lv_disp_draw_buf_t draw_buf;
  53. static lv_color_t *disp_draw_buf;
  54. static lv_disp_drv_t disp_drv;
  55.  
  56. // Touch Configuration
  57. #include "touch.h"
  58.  
  59. Audio audio;
  60.  
  61. // Variables for navigation
  62. int currentFolderIndex = 0;
  63. int currentTrackIndex = 0;
  64. std::vector<String> folders;
  65.  
  66. // Adjust function declarations
  67. void playCurrentTrack(_lv_event_t *event = NULL);
  68. void playPreviewTrack(_lv_event_t *event = NULL);
  69. void playNextTrack(_lv_event_t *event = NULL);
  70. void playPreviousTrack(_lv_event_t *event = NULL);
  71.  
  72. // ESP32 pins initialization
  73. void pin_init()
  74. {
  75.     pinMode(TFT_BL, OUTPUT);
  76.     digitalWrite(TFT_BL, HIGH);
  77. }
  78.  
  79. // SD Card initialization
  80. void sd_init()
  81. {
  82.     pinMode(SD_CS, OUTPUT);
  83.     digitalWrite(SD_CS, HIGH);
  84.     SPI.begin(SD_SCK, SD_MISO, SD_MOSI);
  85.     SPI.setFrequency(400000);
  86.     if (!SD.begin(SD_CS, SPI))
  87.     {
  88.         Serial.println("Card Mount Failed");
  89.         while (1)
  90.             ;
  91.     }
  92.     else
  93.     {
  94.         Serial.println("SD OK");
  95.     }
  96. }
  97.  
  98. /* Display flushing */
  99. void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
  100. {
  101.     uint32_t w = (area->x2 - area->x1 + 1);
  102.     uint32_t h = (area->y2 - area->y1 + 1);
  103.  
  104. #if (LV_COLOR_16_SWAP != 0)
  105.     gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
  106. #else
  107.     gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
  108. #endif
  109.  
  110.     lv_disp_flush_ready(disp);
  111. }
  112.  
  113. // Touchpad
  114. void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
  115. {
  116.     if (touch_has_signal())
  117.     {
  118.         if (touch_touched())
  119.         {
  120.             data->state = LV_INDEV_STATE_PR;
  121.  
  122.             /*Set the coordinates*/
  123.             data->point.x = touch_last_x;
  124.             data->point.y = touch_last_y;
  125.         }
  126.         else if (touch_released())
  127.         {
  128.             data->state = LV_INDEV_STATE_REL;
  129.         }
  130.     }
  131.     else
  132.     {
  133.         data->state = LV_INDEV_STATE_REL;
  134.     }
  135. }
  136.  
  137.  
  138.  
  139. // Functions with Files & Folders
  140. void goToPreviousFolder(lv_event_t *event)
  141. {
  142.     navigateFolder(-1);
  143. }
  144.  
  145. void goToNextFolder(lv_event_t *event)
  146. {
  147.     navigateFolder(1);
  148. }
  149.  
  150. void loadFolders()
  151. {
  152.     folders.clear(); // Clear existing folders
  153.     File root = SD.open("/");
  154.     while (File entry = root.openNextFile())
  155.     {
  156.         if (entry.isDirectory())
  157.         {
  158.             String folderName = entry.name();
  159.             if (folderName != "System Volume Information")
  160.             {
  161.                 folders.push_back(folderName);
  162.             }
  163.         }
  164.         entry.close();
  165.     }
  166.     root.close();
  167.     // Sort folders alphabetically
  168.     std::sort(folders.begin(), folders.end());
  169. }
  170.  
  171. void navigateFolder(int direction)
  172. {
  173.     if (folders.empty())
  174.     {
  175.         Serial.println("No valid folders found");
  176.         return;
  177.     }
  178.  
  179.     currentFolderIndex = (currentFolderIndex + direction + folders.size()) % folders.size();
  180.     currentTrackIndex = 0; // Reset track index when changing folders
  181.     //playCurrentTrack();
  182.     playPreviewTrack();
  183. }
  184.  
  185. void playNextTrack(_lv_event_t *event)
  186. {
  187.     // Stop the current audio playback
  188.     audio.stopSong();
  189.     currentTrackIndex++;
  190.     //playCurrentTrack();
  191.     playPreviewTrack();
  192. }
  193.  
  194. void playPreviousTrack(_lv_event_t *event)
  195. {
  196.   // Stop the current audio playback
  197.     audio.stopSong();
  198.     currentTrackIndex--;
  199.     if (currentTrackIndex < 0)
  200.     {
  201.         currentTrackIndex = 0;
  202.     }
  203.     //playCurrentTrack();
  204.     playPreviewTrack();
  205. }
  206.  
  207. void playCurrentTrack(_lv_event_t *event)
  208. {
  209.     if (folders.empty())
  210.     {
  211.         Serial.println("No valid folders found");
  212.         return;
  213.     }
  214.  
  215.     String selectedFolder = folders[currentFolderIndex];
  216.     Serial.println(selectedFolder);
  217.  
  218.     File jsonFile = SD.open("/" + selectedFolder + "/content.json");
  219.     if (jsonFile)
  220.     {
  221.         DynamicJsonDocument doc(1024);
  222.         DeserializationError error = deserializeJson(doc, jsonFile);
  223.         if (error)
  224.         {
  225.             Serial.print("Failed to parse content.json. Error: ");
  226.             Serial.println(error.c_str());
  227.  
  228.             // Print the raw JSON content for debugging
  229.             jsonFile.seek(0);
  230.             while (jsonFile.available())
  231.             {
  232.                 Serial.write(jsonFile.read());
  233.             }
  234.  
  235.             jsonFile.close();
  236.             return;
  237.         }
  238.  
  239.         JsonArray tracks = doc["AlbumTracks"];
  240.         int totalTracks = tracks.size();
  241.  
  242.         if (currentTrackIndex >= totalTracks)
  243.         {
  244.             currentTrackIndex = 0; // Wrap around to the first track
  245.         }
  246.         else if (currentTrackIndex < 0)
  247.         {
  248.             currentTrackIndex = totalTracks - 1; // Wrap around to the last track
  249.         }
  250.  
  251.         const char *trackPath = tracks[currentTrackIndex]["TrackFullPath"];
  252.         const char *artist = tracks[currentTrackIndex]["TrackArtist"];
  253.         const char *title = tracks[currentTrackIndex]["TrackName"];
  254.         playMP3(trackPath);
  255.         updateLabels(artist, title);
  256.         jsonFile.close();
  257.     }
  258.     else
  259.     {
  260.         Serial.println("Failed to open content.json");
  261.     }
  262. }
  263.  
  264. void playPreviewTrack(_lv_event_t *event)
  265. {
  266.     if (folders.empty())
  267.     {
  268.         Serial.println("No valid folders found");
  269.         return;
  270.     }
  271.  
  272.     String selectedFolder = folders[currentFolderIndex];
  273.     Serial.println(selectedFolder);
  274.  
  275.     File jsonFile = SD.open("/" + selectedFolder + "/content.json");
  276.     if (jsonFile)
  277.     {
  278.         DynamicJsonDocument doc(1024);
  279.         DeserializationError error = deserializeJson(doc, jsonFile);
  280.         if (error)
  281.         {
  282.             Serial.print("Failed to parse content.json. Error: ");
  283.             Serial.println(error.c_str());
  284.  
  285.             // Print the raw JSON content for debugging
  286.             jsonFile.seek(0);
  287.             while (jsonFile.available())
  288.             {
  289.                 Serial.write(jsonFile.read());
  290.             }
  291.  
  292.             jsonFile.close();
  293.             return;
  294.         }
  295.  
  296.         JsonArray tracks = doc["AlbumTracks"];
  297.         int totalTracks = tracks.size();
  298.  
  299.         if (currentTrackIndex >= totalTracks)
  300.         {
  301.             currentTrackIndex = 0; // Wrap around to the first track
  302.         }
  303.         else if (currentTrackIndex < 0)
  304.         {
  305.             currentTrackIndex = totalTracks - 1; // Wrap around to the last track
  306.         }
  307.  
  308.         const char *trackPath = tracks[currentTrackIndex]["TrackPreview"];
  309.         const char *artist = tracks[currentTrackIndex]["TrackArtist"];
  310.         const char *title = tracks[currentTrackIndex]["TrackName"];
  311.         playMP3(trackPath);
  312.         updateLabels(artist, title);
  313.         jsonFile.close();
  314.     }
  315.     else
  316.     {
  317.         Serial.println("Failed to open content.json");
  318.     }
  319. }
  320.  
  321.  
  322. // Playing audio
  323. void playMP3(const String &mp3FilePath)
  324. {
  325.     const char *mp3Path = mp3FilePath.c_str();
  326.     audio.connecttoSD(mp3Path);
  327. }
  328.  
  329. void changeVolume(lv_event_t *event) {
  330.     lv_event_code_t code = lv_event_get_code(event);
  331.    
  332.     if (code == LV_EVENT_VALUE_CHANGED) {
  333.         int arcValue = lv_arc_get_value(ui_arcVolume);
  334.         int maxArcValue = 100;
  335.         int maxSound = 10;
  336.        
  337.         // Map arc value (0-100) to sound volume (0-14)
  338.         int volume = (arcValue * maxSound) / maxArcValue;
  339.        
  340.         audio.setVolume(volume);
  341.     }
  342. }
  343.  
  344. void stopSong(lv_event_t *event) {
  345.   audio.stopSong();
  346. }
  347.  
  348. void tooglePlayPause(lv_event_t *event) {
  349.     audio.pauseResume();
  350. }
  351.  
  352. void updateLabels(const char *artist, const char *title)
  353. {
  354.     lv_label_set_text(ui_labelAlbum, artist);
  355.     lv_label_set_text(ui_labelTitle, title);
  356. }
  357.  
  358. // Setup
  359. void setup()
  360. {
  361.     // Disable Wi-Fi
  362.     esp_err_t results = esp_wifi_stop();
  363.  
  364.     // Disable Bluetooth
  365.     esp_bt_controller_disable();
  366.     esp_bt_controller_deinit();
  367.  
  368.     // Serial console for debug
  369.     Serial.begin(115200);
  370.     Serial.println("Starting...");
  371.  
  372.     // Hardware initialization
  373.     pin_init();
  374.     sd_init();
  375.     lv_init();
  376.  
  377.     // Init Display
  378.     gfx->begin();
  379.     gfx->fillScreen(RED);
  380.     delay(500);
  381.     gfx->fillScreen(GREEN);
  382.     delay(500);
  383.     gfx->fillScreen(BLUE);
  384.     delay(500);
  385.     gfx->fillScreen(BLACK);
  386.     delay(500);
  387.     lv_init();
  388.     delay(10);
  389.  
  390.     // Touch screen initialization
  391.     touch_init();
  392.     screenWidth = gfx->width();
  393.     screenHeight = gfx->height();
  394. #ifdef ESP32
  395.     disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  396. #else
  397.     disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4);
  398. #endif
  399.     if (!disp_draw_buf)
  400.     {
  401.         Serial.println("LVGL disp_draw_buf allocate failed!");
  402.     }
  403.     else
  404.     {
  405.         lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 4);
  406.  
  407.         /* Initialize the display */
  408.         lv_disp_drv_init(&disp_drv);
  409.         /* Change the following line to your display resolution */
  410.         disp_drv.hor_res = screenWidth;
  411.         disp_drv.ver_res = screenHeight;
  412.         disp_drv.flush_cb = my_disp_flush;
  413.         disp_drv.draw_buf = &draw_buf;
  414.         lv_disp_drv_register(&disp_drv);
  415.  
  416.         /* Initialize the (dummy) input device driver */
  417.         static lv_indev_drv_t indev_drv;
  418.         lv_indev_drv_init(&indev_drv);
  419.         indev_drv.type = LV_INDEV_TYPE_POINTER;
  420.         indev_drv.read_cb = my_touchpad_read;
  421.         lv_indev_drv_register(&indev_drv);
  422.  
  423.         // Loading interface
  424.         ui_init();
  425.  
  426.         // Setup functions on LVGL items
  427.         lv_obj_add_event_cb(ui_btUp, goToPreviousFolder, LV_EVENT_PRESSED, NULL);
  428.         lv_obj_add_event_cb(ui_btDown, goToNextFolder, LV_EVENT_PRESSED, NULL);
  429.         lv_obj_add_event_cb(ui_btPlay, playCurrentTrack, LV_EVENT_PRESSED, NULL);
  430.         lv_obj_add_event_cb(ui_btPause, tooglePlayPause, LV_EVENT_PRESSED, NULL);
  431.         lv_obj_add_event_cb(ui_btStop, stopSong, LV_EVENT_PRESSED, NULL);
  432.         lv_obj_add_event_cb(ui_btNext, playNextTrack, LV_EVENT_PRESSED, NULL);
  433.         lv_obj_add_event_cb(ui_btPrevious, playPreviousTrack, LV_EVENT_PRESSED, NULL);
  434.         lv_obj_add_event_cb(ui_arcVolume, changeVolume, LV_EVENT_VALUE_CHANGED, NULL);
  435.         // Setup audio
  436.         audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  437.         audio.setVolume(5);
  438.  
  439.         // Initialize folders during setup
  440.         loadFolders();
  441.     }
  442. }
  443.  
  444. // Loop
  445. void loop()
  446. {
  447.     // Audio loop
  448.     audio.loop();
  449.  
  450.     lv_event_t lv_event;
  451.  
  452.     // LVGL GUI processing
  453.     lv_timer_handler();
  454.     delay(2);
  455. }

headquaker
Posts: 20
Joined: Thu Sep 21, 2023 6:28 am

Re: Cannot read mp3 after navigate to the next mp3 track

Postby headquaker » Wed Nov 15, 2023 10:39 pm

please I really need help to finish my project.

Here is the log when using :

/Album1/Track1-2.mp3
info buffers freed, free Heap: 41756 bytes
info Reading file: "/Album1/Track1-2.mp3"
info MP3Decoder has been initialized, free Heap: 37376 bytes
info Content-Length: 14079205
info ID3 framesSize: 4096
info ID3 version: 2.3
info ID3 normal frames
id3data Title: Les étoiles récit d'un berger provençal
id3data Album: Livres audio gratuits
id3data ContentType: Other
id3data Band: www.livresaudio.e-monsite.com
id3data Artist: www.livresaudio.e-monsite.com
info Audio-Length: 14075109
info stream ready
info syncword found at pos 0
info Channels: 2
info SampleRate: 44100
info BitsPerSample: 16
info BitRate: 128000
info Closing audio file
Album1
/Album1/previewTrack1-3.mp3
info buffers freed, free Heap: 41756 bytes
info Reading file: "/Album1/previewTrack1-3.mp3"
info MP3Decoder has been initialized, free Heap: 37372 bytes
info Closing audio file
info End of file "previewTrack1-3.mp3"
Album1
/Album1/Track1-3.mp3
info buffers freed, free Heap: 41756 bytes
info Reading file: "/Album1/Track1-3.mp3"
info MP3Decoder has been initialized, free Heap: 37376 bytes
info Closing audio file
info End of file "Track1-3.mp3"

headquaker
Posts: 20
Joined: Thu Sep 21, 2023 6:28 am

Re: Cannot read mp3 after navigate to the next mp3 track

Postby headquaker » Thu Nov 16, 2023 3:21 pm

it's because it's impossible to open more then 2 files in same time.
Closing it before playing the mp3 and it works

Who is online

Users browsing this forum: No registered users and 73 guests