-
-
Notifications
You must be signed in to change notification settings - Fork 281
Playing Multiple Files in Sequence
Phil Schatzmann edited this page Feb 19, 2025
·
10 revisions
With this library you have usually many ways to provide the same functionality. This chapter gives a short overview of the alternatives how you can multiple files (or streams) in a defined sequence:
You can just store the file names in an array and play them one after the other:
#include <SPI.h>
#include <SD.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecAACHelix.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
// files from https://filesamples.com/formats/aac
const char* filesNames[] = {
"/aac/sample1.aac",
"/aac/sample2.aac",
"/aac/sample3.aac",
"/aac/sample4.aac",
nullptr,
};
int fileIdx = 0;
const int chipSelect = PIN_AUDIO_KIT_SD_CARD_CS;
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
EncodedAudioStream decoder(&i2s, new AACDecoderHelix()); // Decoding stream
File audioFile;
StreamCopy copier(decoder, audioFile);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// setup i2s
auto config = i2s.defaultConfig(TX_MODE);
config.sd_active = true;
i2s.begin(config);
// setup file
SD.begin(chipSelect);
audioFile = SD.open(filesNames[fileIdx++]);
if (!audioFile){
Serial.println("file does not exist");
stop();
}
// setup I2S based on sampling rate provided by decoder
decoder.begin();
}
void loop() {
if (!copier.copy()) {
// move to beginning on end
if (filesNames[fileIdx]==nullptr) fileIdx = 0;
// move to next file
audioFile = SD.open(filesNames[fileIdx++]);
}
}
We just manage the fileIdx variable to select the file to be played next.
If you use an audio format that can be concatenated (e.g. aac or mp3) you can use a CatStream to concatenate them.
#include <SPI.h>
#include <SD.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecAACHelix.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
const int chipSelect = PIN_AUDIO_KIT_SD_CARD_CS;
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
EncodedAudioStream decoder(&i2s, new AACDecoderHelix()); // Decoding stream
File file[4];
CatStream cat;
StreamCopy copier(decoder, cat);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// setup i2s
auto config = i2s.defaultConfig(TX_MODE);
config.sd_active = true;
i2s.begin(config);
// setup file
SD.begin(chipSelect);
// define concatenated files
file[0] = SD.open("/aac/sample1.aac");
file[1] = SD.open("/aac/sample2.aac");
file[2] = SD.open("/aac/sample3.aac");
file[3] = SD.open("/aac/sample4.aac");
for (int j=0;j < 4; j++){
cat.add(file[j]);
}
// start decoder
decoder.begin();
}
void loop() {
if (!copier.copy()) {
stop();
}
}
If you select an index based AudioSource, you can define (or edit) the index file to define the files that should be played in sequence
- AudioSourceIdxSD: SD Library with an index file
- AudioSourceIdxSDFAT: SDFAT library with index file
- AudioSourceIdxSDMMC: SDMMC library with index file
You can just implement an AudioSourceCallback that returns the files (or streams) in your desired sequence:
#include "Arduino.h"
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include <SPI.h>
#include <SD.h>
// files
const char* files[]{
"/file1.mp3",
"/file2.mp3"
};
int fileIndex = 0;
File actualFile;
// forward declarations
void callbackInit();
Stream* callbackNextStream(int offset);
// data
const int chipSelect=PIN_CS;
AudioSourceCallback source(callbackNextStream, callbackInit);
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);
void callbackInit() {
fileIndex = 0;
}
Stream* callbackNextStream(int offset) {
if (fileIndex >= sizeof(files)) return nullptr;
actualFile = SD.open(files[fileIndex]);
fileIndex += offset;
return &actualFile;
}
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// setup SD
SD.begin(chipSelect);
// setup output
auto cfg = i2s.defaultConfig(TX_MODE);
i2s.begin(cfg);
// setup player
player.begin();
}
void loop() {
player.copy();
}