Skip to content

Commit 4e50204

Browse files
committed
mp3 support
1 parent b3fcef0 commit 4e50204

File tree

8 files changed

+153
-17
lines changed

8 files changed

+153
-17
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ We also provide plenty of examples that demonstrate how to implement the differe
1717

1818
## Optional Libraries
1919

20-
- SD Library
21-
- A2DP Library
22-
- arduino-fdk-aac
23-
- ESP8266Audio
20+
- [ESP32-A2DP Library](https://github.com/pschatzmann/ESP32-A2DP)
21+
- [arduino-fdk-aac](https://github.com/pschatzmann/arduino-fdk-aac)
22+
- [ESP8266Audio](https://github.com/earlephilhower/ESP8266Audio)
23+
- [SD Library](https://www.arduino.cc/en/reference/SD)
2424

2525
## Examples
2626

@@ -49,7 +49,7 @@ This is currently work in progress:
4949
|------------------------|---------|
5050
| Analog input - ADC | tested |
5151
| I2S | tested |
52-
| Files | tested |
52+
| Files (RAW, MP3...) | tested |
5353
| Streams | open |
5454
| WAV encoding/deconding | open |
5555
| AAC encoding/deconding | open |

examples/file_mp3-a2dp/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Using ESP8266Audio to Read Files
2+
3+
The processing of files with the help of the [ESP8266Audio](https://github.com/earlephilhower/ESP8266Audio) is a little bit more involved. Howver it allows to process different file types from different sources. Please consult the project for further details.
4+
5+
In this Sketch we use the ESP8266Audio library to read the [audio.mp3](https://pschatzmann.github.io/arduino-sound-tools/resources/audio.mp3) file from a SD drive. The output is pushed into a temporary buffer. The A2DP Callback then just consumes this buffered data...
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include <SPI.h>
2+
#include <SD.h>
3+
#include "AudioFileSourceSPIFFS.h"
4+
#include "AudioFileSourceID3.h"
5+
#include "AudioGeneratorMP3.h"
6+
#include "AudioOutputWithCallback.h"
7+
#include "BluetoothA2DPSource.h"
8+
#include "SoundTools.h"
9+
10+
using namespace sound_tools;
11+
12+
const int sd_ss_pin = 5;
13+
String fileName = "";
14+
BluetoothA2DPSource a2dp_source;
15+
AudioFileSourceSPIFFS *file;
16+
AudioFileSourceID3 *id3;
17+
AudioGeneratorMP3 *mp3;
18+
AudioOutputWithCallback *out;
19+
20+
// callback used by A2DP to provide the sound data
21+
int32_t get_sound_data(Channels* data, int32_t len) {
22+
return out.read(data, len);
23+
}
24+
25+
// finds a mp3 file
26+
bool findMp3File() {
27+
File dir, root = SPIFFS.open("/");
28+
while ((dir = root.openNextFile())) {
29+
if (String(dir.name()).endsWith(".mp3")) {
30+
if (file->open(dir.name())) {
31+
fileName = String(dir.name());
32+
break;
33+
}
34+
}
35+
dir = root.openNextFile();
36+
}
37+
return fileName.length() > 0;
38+
}
39+
40+
// Arduino Setup
41+
void setup(void) {
42+
Serial.begin(115200);
43+
audioLogger = &Serial;
44+
45+
// start the bluetooth
46+
Serial.println("starting A2DP...");
47+
a2dp_source.start("MyMusic", get_sound_data);
48+
49+
// Setup Audio
50+
SPIFFS.begin(sd_ss_pin);
51+
file = new AudioFileSourceSPIFFS();
52+
mp3 = new AudioGeneratorMP3();
53+
out = new AudioOutputWithCallback(1024,5);
54+
55+
// Find first MP3 file in SPIFF and play it
56+
if (findMp3File()) {
57+
id3 = new AudioFileSourceID3(file);
58+
mp3->begin(id3, out);
59+
Serial.printf("Playback of '%s' begins...\n", fileName.c_str());
60+
} else {
61+
Serial.println("Can't find .mp3 file in SPIFFS");
62+
}
63+
}
64+
65+
// Arduino loop - repeated processing
66+
void loop() {
67+
if (mp3->isRunning()) {
68+
if (!mp3->loop()) mp3->stop();
69+
} else {
70+
Serial.println("MP3 done");
71+
delay(1000);
72+
}
73+
}

src/AudioOutputWithCallback.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
#pragma once
3+
4+
#include "AudioOutput.h"
5+
#include "SoundData.h"
6+
#include "SoundTools.h"
7+
8+
namespace sound_tools {
9+
10+
/**
11+
* @brief ESP8266Audio AudioOutput class which stores the data in a temporary buffer.
12+
* The buffer can be consumed e.g. by a callback function by calling read();
13+
*/
14+
class AudioOutputWithCallback : public AudioOutput
15+
{
16+
public:
17+
AudioOutputWithCallback(int bufferSize, int bufferCount ){
18+
buffer_ptr = new NBuffer<Channels>(bufferSize, bufferCount);
19+
}
20+
21+
virtual ~AudioOutputWithCallback() {
22+
delete buffer_ptr;
23+
}
24+
25+
virtual bool begin() {
26+
active = true;
27+
return true;
28+
}
29+
30+
/// puts the sample into a buffer
31+
virtual bool ConsumeSample(int16_t sample[2]) {
32+
Channels c;
33+
c.channel1 = sample[0];
34+
c.channel2 = sample[1];
35+
return buffer_ptr->write(c);
36+
};
37+
38+
/// stops the processing
39+
virtual bool stop() {
40+
active = false;
41+
return true;
42+
};
43+
44+
/// Provides the data from the internal buffer to the callback
45+
size_t read(Channels *src, size_t len){
46+
return active ? this->buffer_ptr->readArray(src, len) : 0;
47+
}
48+
49+
protected:
50+
NBuffer<Channels> *buffer_ptr;
51+
bool active;
52+
};
53+
54+
}

src/SoundTools.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
#include "SoundTools/SoundGenerator.h"
1515
#include "SoundTools/I2S.h"
1616
#include "SoundTools/ADC.h"
17+
#include "SoundTools/AudioLogger.h"
1718
#include "SoundTools/Buffers.h"

src/SoundTools/AudioLogger.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
#define SOUND_LOG_LEVEL Error
77
#endif
88

9-
namespace pico_arduino {
9+
#ifndef PRINTF_BUFFER_SIZE
10+
#define PRINTF_BUFFER_SIZE 160
11+
#endif
12+
13+
namespace sound_tools {
1014

1115
/**
1216
* @brief A simple Logger that writes messages dependent on the log level
@@ -101,6 +105,6 @@ class SoundLogger {
101105

102106
};
103107

104-
inline SoundLogger Logger;
108+
SoundLogger Logger;
105109

106110
}

src/SoundTools/Buffers.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class NBuffer : public BaseBuffer<T> {
221221
actual_write_buffer = getNextAvailableBuffer();
222222
}
223223
} else {
224-
Serial.println("actual_write_buffer is full");
224+
//Logger.debug("actual_write_buffer is full");
225225
}
226226

227227
if (start_time==0l){
@@ -290,14 +290,14 @@ class NBuffer : public BaseBuffer<T> {
290290

291291

292292
protected:
293-
uint16_t buffer_count;
294-
uint16_t write_buffer_count;
295-
BaseBuffer<T> *actual_read_buffer;
296-
BaseBuffer<T> *actual_write_buffer;
297-
BaseBuffer<T> **avaliable_buffers;
298-
BaseBuffer<T> **filled_buffers;
299-
unsigned long start_time;
300-
unsigned long sample_count;
293+
uint16_t buffer_count = 0;
294+
uint16_t write_buffer_count = 0;
295+
BaseBuffer<T> *actual_read_buffer = nullptr;
296+
BaseBuffer<T> *actual_write_buffer = nullptr;
297+
BaseBuffer<T> **avaliable_buffers = nullptr;
298+
BaseBuffer<T> **filled_buffers = nullptr;
299+
unsigned long start_time = 0;
300+
unsigned long sample_count = 0;
301301

302302

303303
BaseBuffer<T> *getNextAvailableBuffer() {

src/SoundTools/SoundTypes.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#pragma once
2-
#include <bits/stdc++.h>
32

43
namespace sound_tools {
54

0 commit comments

Comments
 (0)