Cannot read mp3 after navigate to the next mp3 track
Posted: 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.
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.
- #include "Arduino.h"
- #include "Audio.h"
- #include "FS.h"
- #include "SPI.h"
- #include "SD.h"
- #include <Wire.h>
- #include <vector>
- #include <lvgl.h>
- #include <ui.h>
- #include <Arduino_GFX_Library.h>
- #include <esp_wifi.h>
- #include "esp_bt.h"
- #include <ArduinoJson.h>
- #define TFT_BL 2
- #define SD_SCK 12 // CLK
- #define SD_MISO 13 // D0
- #define SD_MOSI 11 // CMD
- #define SD_CS 10 // CLK
- #define I2S_DOUT 17
- #define I2S_BCLK 0
- #define I2S_LRC 18
- #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
- #if defined(DISPLAY_DEV_KIT)
- Arduino_GFX *gfx = create_default_Arduino_GFX();
- #else /* !defined(DISPLAY_DEV_KIT) */
- Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
- GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
- 40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
- 45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
- 5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
- 8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
- );
- // option 1:
- // ST7262 IPS LCD 800x480
- Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
- bus,
- 800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
- 480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
- 1 /* pclk_active_neg */, 13000000 /* prefer_speed */, true /* auto_flush */);
- #endif /* !defined(DISPLAY_DEV_KIT) */
- // End of Arduino_GFX setting
- // screen configuration
- static uint32_t screenWidth;
- static uint32_t screenHeight;
- static lv_disp_draw_buf_t draw_buf;
- static lv_color_t *disp_draw_buf;
- static lv_disp_drv_t disp_drv;
- // Touch Configuration
- #include "touch.h"
- Audio audio;
- // Variables for navigation
- int currentFolderIndex = 0;
- int currentTrackIndex = 0;
- std::vector<String> folders;
- // Adjust function declarations
- void playCurrentTrack(_lv_event_t *event = NULL);
- void playPreviewTrack(_lv_event_t *event = NULL);
- void playNextTrack(_lv_event_t *event = NULL);
- void playPreviousTrack(_lv_event_t *event = NULL);
- // ESP32 pins initialization
- void pin_init()
- {
- pinMode(TFT_BL, OUTPUT);
- digitalWrite(TFT_BL, HIGH);
- }
- // SD Card initialization
- void sd_init()
- {
- pinMode(SD_CS, OUTPUT);
- digitalWrite(SD_CS, HIGH);
- SPI.begin(SD_SCK, SD_MISO, SD_MOSI);
- SPI.setFrequency(400000);
- if (!SD.begin(SD_CS, SPI))
- {
- Serial.println("Card Mount Failed");
- while (1)
- ;
- }
- else
- {
- Serial.println("SD OK");
- }
- }
- /* Display flushing */
- void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
- {
- uint32_t w = (area->x2 - area->x1 + 1);
- uint32_t h = (area->y2 - area->y1 + 1);
- #if (LV_COLOR_16_SWAP != 0)
- gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
- #else
- gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
- #endif
- lv_disp_flush_ready(disp);
- }
- // Touchpad
- void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
- {
- if (touch_has_signal())
- {
- if (touch_touched())
- {
- data->state = LV_INDEV_STATE_PR;
- /*Set the coordinates*/
- data->point.x = touch_last_x;
- data->point.y = touch_last_y;
- }
- else if (touch_released())
- {
- data->state = LV_INDEV_STATE_REL;
- }
- }
- else
- {
- data->state = LV_INDEV_STATE_REL;
- }
- }
- // Functions with Files & Folders
- void goToPreviousFolder(lv_event_t *event)
- {
- navigateFolder(-1);
- }
- void goToNextFolder(lv_event_t *event)
- {
- navigateFolder(1);
- }
- void loadFolders()
- {
- folders.clear(); // Clear existing folders
- File root = SD.open("/");
- while (File entry = root.openNextFile())
- {
- if (entry.isDirectory())
- {
- String folderName = entry.name();
- if (folderName != "System Volume Information")
- {
- folders.push_back(folderName);
- }
- }
- entry.close();
- }
- root.close();
- // Sort folders alphabetically
- std::sort(folders.begin(), folders.end());
- }
- void navigateFolder(int direction)
- {
- if (folders.empty())
- {
- Serial.println("No valid folders found");
- return;
- }
- currentFolderIndex = (currentFolderIndex + direction + folders.size()) % folders.size();
- currentTrackIndex = 0; // Reset track index when changing folders
- //playCurrentTrack();
- playPreviewTrack();
- }
- void playNextTrack(_lv_event_t *event)
- {
- // Stop the current audio playback
- audio.stopSong();
- currentTrackIndex++;
- //playCurrentTrack();
- playPreviewTrack();
- }
- void playPreviousTrack(_lv_event_t *event)
- {
- // Stop the current audio playback
- audio.stopSong();
- currentTrackIndex--;
- if (currentTrackIndex < 0)
- {
- currentTrackIndex = 0;
- }
- //playCurrentTrack();
- playPreviewTrack();
- }
- void playCurrentTrack(_lv_event_t *event)
- {
- if (folders.empty())
- {
- Serial.println("No valid folders found");
- return;
- }
- String selectedFolder = folders[currentFolderIndex];
- Serial.println(selectedFolder);
- File jsonFile = SD.open("/" + selectedFolder + "/content.json");
- if (jsonFile)
- {
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, jsonFile);
- if (error)
- {
- Serial.print("Failed to parse content.json. Error: ");
- Serial.println(error.c_str());
- // Print the raw JSON content for debugging
- jsonFile.seek(0);
- while (jsonFile.available())
- {
- Serial.write(jsonFile.read());
- }
- jsonFile.close();
- return;
- }
- JsonArray tracks = doc["AlbumTracks"];
- int totalTracks = tracks.size();
- if (currentTrackIndex >= totalTracks)
- {
- currentTrackIndex = 0; // Wrap around to the first track
- }
- else if (currentTrackIndex < 0)
- {
- currentTrackIndex = totalTracks - 1; // Wrap around to the last track
- }
- const char *trackPath = tracks[currentTrackIndex]["TrackFullPath"];
- const char *artist = tracks[currentTrackIndex]["TrackArtist"];
- const char *title = tracks[currentTrackIndex]["TrackName"];
- playMP3(trackPath);
- updateLabels(artist, title);
- jsonFile.close();
- }
- else
- {
- Serial.println("Failed to open content.json");
- }
- }
- void playPreviewTrack(_lv_event_t *event)
- {
- if (folders.empty())
- {
- Serial.println("No valid folders found");
- return;
- }
- String selectedFolder = folders[currentFolderIndex];
- Serial.println(selectedFolder);
- File jsonFile = SD.open("/" + selectedFolder + "/content.json");
- if (jsonFile)
- {
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, jsonFile);
- if (error)
- {
- Serial.print("Failed to parse content.json. Error: ");
- Serial.println(error.c_str());
- // Print the raw JSON content for debugging
- jsonFile.seek(0);
- while (jsonFile.available())
- {
- Serial.write(jsonFile.read());
- }
- jsonFile.close();
- return;
- }
- JsonArray tracks = doc["AlbumTracks"];
- int totalTracks = tracks.size();
- if (currentTrackIndex >= totalTracks)
- {
- currentTrackIndex = 0; // Wrap around to the first track
- }
- else if (currentTrackIndex < 0)
- {
- currentTrackIndex = totalTracks - 1; // Wrap around to the last track
- }
- const char *trackPath = tracks[currentTrackIndex]["TrackPreview"];
- const char *artist = tracks[currentTrackIndex]["TrackArtist"];
- const char *title = tracks[currentTrackIndex]["TrackName"];
- playMP3(trackPath);
- updateLabels(artist, title);
- jsonFile.close();
- }
- else
- {
- Serial.println("Failed to open content.json");
- }
- }
- // Playing audio
- void playMP3(const String &mp3FilePath)
- {
- const char *mp3Path = mp3FilePath.c_str();
- audio.connecttoSD(mp3Path);
- }
- void changeVolume(lv_event_t *event) {
- lv_event_code_t code = lv_event_get_code(event);
- if (code == LV_EVENT_VALUE_CHANGED) {
- int arcValue = lv_arc_get_value(ui_arcVolume);
- int maxArcValue = 100;
- int maxSound = 10;
- // Map arc value (0-100) to sound volume (0-14)
- int volume = (arcValue * maxSound) / maxArcValue;
- audio.setVolume(volume);
- }
- }
- void stopSong(lv_event_t *event) {
- audio.stopSong();
- }
- void tooglePlayPause(lv_event_t *event) {
- audio.pauseResume();
- }
- void updateLabels(const char *artist, const char *title)
- {
- lv_label_set_text(ui_labelAlbum, artist);
- lv_label_set_text(ui_labelTitle, title);
- }
- // Setup
- void setup()
- {
- // Disable Wi-Fi
- esp_err_t results = esp_wifi_stop();
- // Disable Bluetooth
- esp_bt_controller_disable();
- esp_bt_controller_deinit();
- // Serial console for debug
- Serial.begin(115200);
- Serial.println("Starting...");
- // Hardware initialization
- pin_init();
- sd_init();
- lv_init();
- // Init Display
- gfx->begin();
- gfx->fillScreen(RED);
- delay(500);
- gfx->fillScreen(GREEN);
- delay(500);
- gfx->fillScreen(BLUE);
- delay(500);
- gfx->fillScreen(BLACK);
- delay(500);
- lv_init();
- delay(10);
- // Touch screen initialization
- touch_init();
- screenWidth = gfx->width();
- screenHeight = gfx->height();
- #ifdef ESP32
- disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
- #else
- disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4);
- #endif
- if (!disp_draw_buf)
- {
- Serial.println("LVGL disp_draw_buf allocate failed!");
- }
- else
- {
- lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 4);
- /* Initialize the display */
- lv_disp_drv_init(&disp_drv);
- /* Change the following line to your display resolution */
- disp_drv.hor_res = screenWidth;
- disp_drv.ver_res = screenHeight;
- disp_drv.flush_cb = my_disp_flush;
- disp_drv.draw_buf = &draw_buf;
- lv_disp_drv_register(&disp_drv);
- /* Initialize the (dummy) input device driver */
- static lv_indev_drv_t indev_drv;
- lv_indev_drv_init(&indev_drv);
- indev_drv.type = LV_INDEV_TYPE_POINTER;
- indev_drv.read_cb = my_touchpad_read;
- lv_indev_drv_register(&indev_drv);
- // Loading interface
- ui_init();
- // Setup functions on LVGL items
- lv_obj_add_event_cb(ui_btUp, goToPreviousFolder, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_btDown, goToNextFolder, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_btPlay, playCurrentTrack, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_btPause, tooglePlayPause, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_btStop, stopSong, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_btNext, playNextTrack, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_btPrevious, playPreviousTrack, LV_EVENT_PRESSED, NULL);
- lv_obj_add_event_cb(ui_arcVolume, changeVolume, LV_EVENT_VALUE_CHANGED, NULL);
- // Setup audio
- audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
- audio.setVolume(5);
- // Initialize folders during setup
- loadFolders();
- }
- }
- // Loop
- void loop()
- {
- // Audio loop
- audio.loop();
- lv_event_t lv_event;
- // LVGL GUI processing
- lv_timer_handler();
- delay(2);
- }