I read a post in 2023 about the RandomAll() function only randomizing the first 255 tracks, no matter how many folders & MP3s are stored on the SD card.
Since the DFPlayer canât scan or report the SD card contents, the microcontroller cannot discover the file structure automatically.
To handle this, you need to know or predefine the file organization in your code and then your code can randomly choose a folder and track from that list and command the DFPlayer to play it.
Without this, you cannot randomize beyond the first 255 tracks using built-in commands - itâs a firmware limitation.
This likely relates to the file management system integrated into the chip firmware, where the file system structure is defined by the firmware as:
01 Folder/001xxx.mp3, 01 Folder/002xxx.mp3, 02 Folder/001xxx.mp3, etc. Therefore, you should use a command for random playback from a specified folder, such as:
Iâm reluctant to contradict you while Iâm unable to physically double check; away from PC on hols. But the DFR inbuilt randomAll command ignores folder structure. It plays a track chosen randomly between the first and last tracks chronologically added to the mSD card.
My JukeBox has nearly 3,000 files within 26 folders. Switched to its random mode before power up, it will sometimes play tracks from any of those 26. So if I said otherwise a couple of years ago I was mistaken.
Itâs possible that Tom was referring to the more challenging issue of playing a folder randomly without repetition?
Could still be my mistake, so Iâll look into it again next week. That is assuming I can still understand what was a complicated and messily coded project!
EDIT:
And having read through that old thread of mine Iâm thinking maybe I abandoned the use of randomAll() and used the same âshuffling, no repetitionâ method entirely?
Testing could be done by having 99 directorys each with ten files and have the sound say âdirectory xxx file yyâ and fill in the DF player by writing directories one after the other in ascending order.
If the function is limited to the first 255 written files, youâll never hear a directory above 26 and as you have 990 files, chances of getting one from the far end should be (990-255)/990=0,742
â almost 3/4 chances to get something from the far end if the random algorithm is good so we shouldnât have to wait for too long to confirm if it works or not.
Generating the folder architecture and sound files can easily be done on a Mac at least with a small shell script using say and afconvert
Yes, I had a similar plan in mind, probably using my existing recordings of âzeroâ to âsixtyâ , or even simply my full file listing. However, before any such tests, I can at least now confirm my earlier growing suspicion. Using my Dropbox account I was able to downoad the likely sketch used in JukeBox to my iPhone. A methodical search found no use of randomAll(). Instead, basically, I selected a random folder and then used a shuffle & no repeat function to randomly play from it.
Doesnât prove that randomAll() is constrained to 255 tracks, of course. It might have been my need to avoid repetition and ensure exhaustive coverage that motivated me against using it, despite its tempting simplicity.
Anyway, a simple sketch should resolve that question definitively.
So I wrote the script on my Mac to generate the sounds. I had to use lame instead of afconvert to generate the mp3, so lame needs to be installed first. (brew install lame)
here is the code
#!/bin/bash
# Make sure LAME is installed: brew install lame
# create a TEST directory and save this file as generate.sh inside
# open a terminal and change directory to TEST
# change file to be executable: chmod +x generate.sh
# execute the script: ./generate.sh
OUTDIR="./DFPLAYER"
mkdir -p "$OUTDIR"
for d in $(seq -w 1 99); do
FOLDER="$OUTDIR/$d"
mkdir -p "$FOLDER"
for f in $(seq -w 1 9); do
FILEPATH="$FOLDER/00$f.mp3"
TEXT="directory $d file $f"
# Generate AIFF from TTS in English
say -v Alex "$TEXT" -o "$FOLDER/tmp.aiff"
# Convert AIFF to MP3 using LAME (mono, low bitrate for speech)
lame --preset voice -m m --quiet "$FOLDER/tmp.aiff" "$FILEPATH"
rm "$FOLDER/tmp.aiff"
done
done
echo "Done: files created in $OUTDIR"
if your Mac does not have English as its main default language, you have to switch temporarily the language (don't even reboot) and launch terminal after that so that the say command does speak in "proper" English (and not with the French accent or saying "UN" instead of "ONE" when trying to read out "1".
The arduino sketch could be something like that (typed here, totally untested)
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
const byte rxPin = 10; // Arduino RX â DFPlayer TX
const byte txPin = 11; // Arduino TX â DFPlayer RX
const byte busyPin = 9; // DFPlayer BUSY pin
SoftwareSerial mySerial(rxPin, txPin);
DFRobotDFPlayerMini myDFPlayer;
void setup() {
pinMode(busyPin, INPUT);
mySerial.begin(9600);
Serial.begin(115200);
if (!myDFPlayer.begin(mySerial)) {
Serial.println("Unable to begin:");
while (true) yield();
}
myDFPlayer.volume(20);
}
void loop() {
// play a random file from the SD
myDFPlayer.randomAll();
// allow DFPlayer to start playback
delay(50);
// synchronous wait until file is done playing
while (digitalRead(busyPin) == LOW) delay(10);
// small pause before next random play
delay(100);
}
The file generation takes a bit of a long time and is over 10 Megs so I can't attach it here but here is what it sounds like from directory 96, file 5
Not at PC until next week, but my approach was basically as follows. Instead of randomAll() I used random() to first select a folder and then used code to shuffle its entire contents and index those in an array , which was itself then randomised.
See how far you can get. If others havenât already got that working how you need, Iâll get back to you next week.
â I assume you have a fixed list of your files or that they are organized in a way that lets you generate the right info to select the folder and then a specific file in that folder and if you change the content of your SD card, you'll have to modify the code and upload again?
a simple approach could be
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
const byte rxPin = 10;
const byte txPin = 11;
const byte busyPin = 9;
SoftwareSerial mySerial(rxPin, txPin);
DFRobotDFPlayerMini myDFPlayer;
struct Directory {
byte numberOfFiles;
};
const Directory directories[] = {
{3}, // folder 1 has 3 files
{5}, // folder 2 has 5 files
{2} // folder 3 has 2 files
};
const byte numDirectories = sizeof directories / sizeof *directories;
byte shuffledDirs[numDirectories];
void shuffleArray(byte *array, byte n) {
for (byte i = n - 1; i > 0; i--) {
byte j = random(i + 1);
byte tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
void playDirectory(byte dirIndex) {
byte numFiles = directories[dirIndex].numberOfFiles;
byte fileOrder[numFiles];
for (byte i = 0; i < numFiles; i++) fileOrder[i] = i + 1;
shuffleArray(fileOrder, numFiles);
for (byte i = 0; i < numFiles; i++) {
myDFPlayer.playFolder(dirIndex + 1, fileOrder[i]);
delay(50);
while (digitalRead(busyPin) == LOW) delay(10);
}
}
void setup() {
pinMode(busyPin, INPUT);
mySerial.begin(9600);
Serial.begin(115200);
if (!myDFPlayer.begin(mySerial)) {
Serial.println("Unable to begin:");
while (true) yield();
}
myDFPlayer.volume(20);
for (byte i = 0; i < numDirectories; i++) shuffledDirs[i] = i;
shuffleArray(shuffledDirs, numDirectories);
}
void loop() {
for (byte i = 0; i < numDirectories; i++) {
playDirectory(shuffledDirs[i]);
}
shuffleArray(shuffledDirs, numDirectories);
}
where we shuffle the directories (fisher Yates algorithm) and then for each directory selected we shuffle the entries.
This way we play each song only once until all songs are played, all "randomly" (a randomSeeed() call in setup() might be useful)
Thanks much for your help Jackson, Terry, and Jim. I feel more confident getting this randomize stuff figured out.
If I understand, I can divide up my MP3 files into groups of 255 into individual folders. Then I can use Jackson's sample code to randomize the folders to select one, then randomize the files in that folder to select a file.
Another technique could be to randomize the folders to select one, then use the RandomAll command to randomize the files in the selected folder.
I appreciate the help!
May I ask one more question, I realize are clones of DP Player, some are inferior to others. Here are the ones that I ordered:
Back at PC now but looks like JML has it all squared away. Let me know if there's any further help you need from me.
@J-M-L
I too confirm that randomAll() does operate across all tracks. Regardless of their number or structure.
I already had useful resources at hand so first added my 'Big Band' folder of 253 individual MP3 tracks to a new mSD card. Followed by an arbitrary five copies of my 1-60 spoken numbers folder 'msd4 60Numbers-1to60\ â (made for earlier projects). Then played a simple sketch like yours until I heard one of those. The first was "two" (which could be the 255th chronologically indexed track), but another couple of minutes got me a "twenty three" QED.
OK so the file saying "23" was names like 0023-.mp3
it's likely indeed that it has been copied over to the SD way later than 0002-two.mp3 as modern file systems tend to copy files in alphabetical order and the DF player does not care about the name but really just in which order the file was copied over.
The files were in chronological order. I added them to ensure that. And if File Explorer wasnât limited to a precision of one second it would show that, when sorted by Date Created. So hearing 23 played proved beyond any doubt that randomAll() is not limited to 255 files.