snapshot
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# A Simple Streaming Audio Player
|
||||
|
||||
It was pretty simple to build a simple audio player with the help of the Stream API.
|
||||
|
||||
The AudioPlayer supports
|
||||
|
||||
- __multiple processor architectures__
|
||||
- __multiple audio data sources__ (SD, URL, callbacks)
|
||||
- __different Output__ Scenarios (I2S, PWM, A2DP etc). Just pass the desired output stream object to the constructor.
|
||||
- __different Decoders__ for MP3, AAC, WAV. Just pass the desired decoder object to the constructor.
|
||||
- __Volume Control__ (by calling player.setVolume())
|
||||
- __Stopping and Resuming__ the processing (by calling player.stop() and player.play())
|
||||
- You can __move to the next file__ by calling player.next();
|
||||
- support for __Metadata__
|
||||
|
||||
|
||||
The example demonstrates how to implement an __MP3 Player__ which provides the data via the Internet (with the help of the AudioSourceURL class) and sends the audio via I2S to an external DAC using an ESP32.
|
||||
|
||||
### The External DAC
|
||||
|
||||
For my tests I am using the 24-bit PCM5102 PCM5102A Stereo DAC Digital-to-analog Converter PLL Voice Module pHAT
|
||||
|
||||

|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
|
||||
|
||||
DAC | ESP32
|
||||
-----|----------------
|
||||
VCC | 5V
|
||||
GND | GND
|
||||
BCK | BCK (GPIO14)
|
||||
DIN | OUT (GPIO22)
|
||||
LCK | BCK (GPIO15)
|
||||
FMT | GND
|
||||
XMT | 3V (or another GPIO PIN which is set to high)
|
||||
|
||||
- DMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCL - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
|
||||
|
||||
### Wiring the Volume Potentiometer
|
||||
|
||||

|
||||
|
||||
| Pot | ESP32 | ESP8266
|
||||
| --------| ---------|---------
|
||||
| POW | 3V | 3V
|
||||
| GND | GND | GND
|
||||
| VOUT | A0 | A0
|
||||
|
||||
### Moving to the next song
|
||||
|
||||
We use a button to move to the next url.
|
||||
|
||||
| Button | ESP32 | ESP8266
|
||||
|------------|----------|---------
|
||||
| Button | GPIO13 | GPIO13
|
||||
| Out 3V
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-audio-tools
|
||||
- https://github.com/pschatzmann/arduino-libhelix
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file player-url-i2s.ino
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-player/player-url-i2s/README.md
|
||||
*
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Disk/AudioSourceURL.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
const char *urls[] = {
|
||||
"http://stream.srg-ssr.ch/m/rsj/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/drs3/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/rr/mp3_128",
|
||||
"http://sunshineradio.ice.infomaniak.ch/sunshineradio-128.mp3",
|
||||
"http://streaming.swisstxt.ch/m/drsvirus/mp3_128"
|
||||
};
|
||||
const char *wifi = "wifi";
|
||||
const char *password = "password";
|
||||
|
||||
URLStream urlStream(wifi, password);
|
||||
AudioSourceURL source(urlStream, urls, "audio/mp3");
|
||||
I2SStream i2s;
|
||||
MP3DecoderHelix decoder;
|
||||
AudioPlayer player(source, i2s, decoder);
|
||||
|
||||
// additional controls
|
||||
const int volumePin = A0;
|
||||
Debouncer nextButtonDebouncer(2000);
|
||||
const int nextButtonPin = 13;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup output
|
||||
auto cfg = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(cfg);
|
||||
|
||||
// setup player
|
||||
player.begin();
|
||||
}
|
||||
|
||||
// Sets the volume control from a linear potentiometer input
|
||||
void updateVolume() {
|
||||
// Reading potentiometer value (range is 0 - 4095)
|
||||
float vol = static_cast<float>(analogRead(volumePin));
|
||||
// min in 0 - max is 1.0
|
||||
player.setVolume(vol/4095.0);
|
||||
}
|
||||
|
||||
|
||||
// Moves to the next url when we touch the pin
|
||||
void updatePosition() {
|
||||
if (digitalRead(nextButtonPin)) {
|
||||
Serial.println("Moving to next url");
|
||||
if (nextButtonDebouncer.debounce()){
|
||||
player.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
//updateVolume(); // remove comments to activate volume control
|
||||
//updatePosition(); // remove comments to activate position control
|
||||
player.copy();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# A Simple Icecast Streaming Audio Player
|
||||
|
||||
Compared to the regular URLStream, and ICYStream provides audio Metadata.
|
||||
|
||||
<img src="https://pschatzmann.github.io/Resources/img/audio-toolkit.png" alt="Audio Kit" />
|
||||
|
||||
You dont need to bother about any wires because everything is on one nice board. Just just need to install the dependencies:
|
||||
|
||||
I also demonstrate how to assign your own actions to the buttons of the audio kit.
|
||||
|
||||
### Notes
|
||||
|
||||
- Do not forget to set the wifi name and password.
|
||||
- The log level has been set to Info to help you to identify any problems. Please change it to AudioLogger::Warning to get the best sound quality!
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-audio-tools
|
||||
- https://github.com/pschatzmann/arduino-libhelix
|
||||
- https://github.com/pschatzmann/arduino-audio-driver
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @file player-url-kit.ino
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-audiokit/player-url-audiokit/README.md
|
||||
*
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
#include "AudioTools/Disk/AudioSourceURL.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
const char *urls[] = {
|
||||
"http://stream.srg-ssr.ch/m/rsj/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/drs3/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/rr/mp3_128",
|
||||
"http://sunshineradio.ice.infomaniak.ch/sunshineradio-128.mp3",
|
||||
"http://streaming.swisstxt.ch/m/drsvirus/mp3_128"
|
||||
};
|
||||
const char *wifi = "wifi";
|
||||
const char *password = "password";
|
||||
|
||||
ICYStream urlStream(wifi, password);
|
||||
AudioSourceURL source(urlStream, urls, "audio/mp3");
|
||||
AudioBoardStream kit(AudioKitEs8388V1);
|
||||
MP3DecoderHelix decoder;
|
||||
AudioPlayer player(source, kit, decoder);
|
||||
|
||||
void next(bool, int, void*) {
|
||||
player.next();
|
||||
}
|
||||
|
||||
void previous(bool, int, void*) {
|
||||
player.previous();
|
||||
}
|
||||
|
||||
void stopResume(bool, int, void*){
|
||||
if (player.isActive()){
|
||||
player.stop();
|
||||
} else{
|
||||
player.play();
|
||||
}
|
||||
}
|
||||
|
||||
// Arduino setup
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup output
|
||||
auto cfg = kit.defaultConfig(TX_MODE);
|
||||
cfg.sd_active = false;
|
||||
kit.begin(cfg);
|
||||
|
||||
// setup navigation
|
||||
kit.addAction(kit.getKey(4), next);
|
||||
kit.addAction(kit.getKey(3), previous);
|
||||
|
||||
// setup player
|
||||
player.setVolume(0.7);
|
||||
player.begin();
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
player.copy();
|
||||
kit.processActions();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# A Simple Icecast Streaming Audio Player
|
||||
|
||||
Compared to the regular URLStream, and ICYStream provides audio Metadata.
|
||||
|
||||
### The External DAC
|
||||
|
||||
For my tests I am using the 24-bit PCM5102 PCM5102A Stereo DAC Digital-to-analog Converter PLL Voice Module pHAT
|
||||
|
||||

|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
|
||||
|
||||
DAC | ESP32
|
||||
-----|----------------
|
||||
VCC | 5V
|
||||
GND | GND
|
||||
BCK | BCK (GPIO14)
|
||||
DIN | OUT (GPIO22)
|
||||
LCK | BCK (GPIO15)
|
||||
FMT | GND
|
||||
XMT | 3V (or another GPIO PIN which is set to high)
|
||||
|
||||
- DMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCL - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
|
||||
|
||||
### Wiring the Volume Potentiometer
|
||||
|
||||

|
||||
|
||||
| Pot | ESP32 | ESP8266
|
||||
| --------| ---------|---------
|
||||
| POW | 3V | 3V
|
||||
| GND | GND | GND
|
||||
| VOUT | A0 | A0
|
||||
|
||||
### Moving to the next song
|
||||
|
||||
We use a button to move to the next url.
|
||||
|
||||
| Button | ESP32 | ESP8266
|
||||
|------------|----------|---------
|
||||
| Button | GPIO13 | GPIO13
|
||||
| Out 3V
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-audio-tools
|
||||
- https://github.com/pschatzmann/arduino-libhelix
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file player-url-i2s.ino
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-player/player-url-i2s/README.md
|
||||
*
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Disk/AudioSourceURL.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
const char *urls[] = {
|
||||
"http://stream.srg-ssr.ch/m/rsj/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/drs3/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/rr/mp3_128",
|
||||
"http://sunshineradio.ice.infomaniak.ch/sunshineradio-128.mp3",
|
||||
"http://streaming.swisstxt.ch/m/drsvirus/mp3_128"
|
||||
};
|
||||
const char *wifi = "wifi";
|
||||
const char *password = "password";
|
||||
|
||||
ICYStream urlStream(wifi, password);
|
||||
AudioSourceURL source(urlStream, urls, "audio/mp3");
|
||||
I2SStream i2s;
|
||||
MP3DecoderHelix decoder;
|
||||
AudioPlayer player(source, i2s, decoder);
|
||||
|
||||
// additional controls
|
||||
const int volumePin = A0;
|
||||
Debouncer nextButtonDebouncer(2000);
|
||||
const int nextButtonPin = 13;
|
||||
|
||||
// Print Audio Metadata
|
||||
void printMetaData(MetaDataType type, const char* str, int len){
|
||||
Serial.print("==> ");
|
||||
Serial.print(toStr(type));
|
||||
Serial.print(": ");
|
||||
Serial.println(str);
|
||||
}
|
||||
|
||||
|
||||
// Arduino setup
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup output
|
||||
auto cfg = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(cfg);
|
||||
|
||||
// setup player
|
||||
player.setMetadataCallback(printMetaData);
|
||||
player.begin();
|
||||
}
|
||||
|
||||
// Sets the volume control from a linear potentiometer input
|
||||
void updateVolume() {
|
||||
// Reading potentiometer value (range is 0 - 4095)
|
||||
float vol = static_cast<float>(analogRead(volumePin));
|
||||
// min in 0 - max is 1.0
|
||||
player.setVolume(vol/4095.0);
|
||||
}
|
||||
|
||||
|
||||
// Moves to the next url when we touch the pin
|
||||
void updatePosition() {
|
||||
if (digitalRead(nextButtonPin)) {
|
||||
Serial.println("Moving to next url");
|
||||
if (nextButtonDebouncer.debounce()){
|
||||
player.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
//updateVolume(); // remove comments to activate volume control
|
||||
//updatePosition(); // remove comments to activate position control
|
||||
player.copy();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/HTTP/URLStream.h"
|
||||
#include "AudioTools/Disk/AudioSourceURL.h"
|
||||
|
||||
namespace audio_tools {
|
||||
|
||||
/**
|
||||
* @brief URLStream which provides the ICY Http Parameters
|
||||
*
|
||||
*/
|
||||
class AudioSourceIcyUrl : public AudioSourceURL {
|
||||
public:
|
||||
template<typename T, size_t N>
|
||||
AudioSourceIcyUrl(URLStream& urlStream, T(&urlArray)[N], const char* mime, int start=0)
|
||||
: AudioSourceURL(urlStream, urlArray, mime,start) {
|
||||
}
|
||||
|
||||
const char *icyValue(const char* name) {
|
||||
return actual_stream->httpRequest().reply().get(name);
|
||||
}
|
||||
const char *icyName() {
|
||||
return icyValue("icy-name");
|
||||
}
|
||||
const char *icyDescription() {
|
||||
return icyValue("icy-description");
|
||||
}
|
||||
const char *icyGenre() {
|
||||
return icyValue("icy-genre");
|
||||
}
|
||||
|
||||
/// Returns the last section of a url: https://22323.live.streamtheworld.com/TOPRETRO.mp3 gives TOPRETRO.mp3
|
||||
const char *urlName(){
|
||||
const char* result = "";
|
||||
StrView tmpStr(toStr());
|
||||
int pos = tmpStr.lastIndexOf("/");
|
||||
if (pos>0){
|
||||
result = toStr()+pos+1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Returns the icy name if available otherwise we use our custom logic
|
||||
const char* name() {
|
||||
StrView result(icyName());
|
||||
if (result.isEmpty()){
|
||||
result.set(urlName());
|
||||
}
|
||||
return result.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# A Simple Streaming Audio Player
|
||||
|
||||
This is just a simple example which demonstrates how to use your own subclasses to add additional functionality.
|
||||
|
||||
We provide the URL ICY parameters in our own AudioSourceIcyUrl subclass!
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-audio-tools
|
||||
- https://github.com/pschatzmann/arduino-libhelix
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file player-url-i2s.ino
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-player/player-url_subclass-i2s/README.md
|
||||
*
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioSourceIcyUrl.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
const char *urls[] = {
|
||||
"http://stream.srg-ssr.ch/m/rsj/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/drs3/mp3_128",
|
||||
"http://stream.srg-ssr.ch/m/rr/mp3_128",
|
||||
"http://sunshineradio.ice.infomaniak.ch/sunshineradio-128.mp3",
|
||||
"http://streaming.swisstxt.ch/m/drsvirus/mp3_128"
|
||||
};
|
||||
const char *wifi = "wifi";
|
||||
const char *password = "password";
|
||||
|
||||
URLStream urlStream(wifi, password);
|
||||
AudioSourceIcyUrl source(urlStream, urls, "audio/mp3");
|
||||
I2SStream i2s;
|
||||
MP3DecoderHelix decoder;
|
||||
AudioPlayer player(source, i2s, decoder);
|
||||
|
||||
// additional controls
|
||||
const int volumePin = A0;
|
||||
Debouncer nextButtonDebouncer(2000);
|
||||
const int nextButtonPin = 13;
|
||||
|
||||
|
||||
void printName() {
|
||||
Serial.print("icy name: ");
|
||||
Serial.println(source.icyName());
|
||||
Serial.print("Url name: ");
|
||||
Serial.println(source.urlName());
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup output
|
||||
auto cfg = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(cfg);
|
||||
|
||||
// setup player
|
||||
player.begin();
|
||||
printName();
|
||||
}
|
||||
|
||||
// Sets the volume control from a linear potentiometer input
|
||||
void updateVolume() {
|
||||
// Reading potentiometer value (range is 0 - 4095)
|
||||
float vol = static_cast<float>(analogRead(volumePin));
|
||||
// min in 0 - max is 1.0
|
||||
player.setVolume(vol/4095.0);
|
||||
}
|
||||
|
||||
|
||||
// Moves to the next url when we touch the pin
|
||||
void updatePosition() {
|
||||
if (digitalRead(nextButtonPin)) {
|
||||
Serial.println("Moving to next url");
|
||||
if (nextButtonDebouncer.debounce()){
|
||||
player.next();
|
||||
printName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
//updateVolume(); // remove comments to activate volume control
|
||||
//updatePosition(); // remove comments to activate position control
|
||||
player.copy();
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file streams-url_mp3-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
|
||||
// Enter a MAC address for your controller below.
|
||||
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
|
||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
const int CS = SS;
|
||||
EthernetClient eth;
|
||||
URLStream url(eth);
|
||||
I2SStream i2s; // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
void setupEthernet() {
|
||||
// You can use Ethernet.init(pin) to configure the CS pin
|
||||
Ethernet.init(CS);
|
||||
|
||||
// start the Ethernet connection:
|
||||
Serial.println("Initialize Ethernet with DHCP:");
|
||||
if (Ethernet.begin(mac)) {
|
||||
Serial.print(" DHCP assigned IP ");
|
||||
Serial.println(Ethernet.localIP());
|
||||
} else {
|
||||
Serial.println("Failed to configure Ethernet using DHCP");
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
setupEthernet();
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
// you could define e.g your pins and change other settings
|
||||
//config.pin_ws = 10;
|
||||
//config.pin_bck = 11;
|
||||
//config.pin_data = 12;
|
||||
//config.mode = I2S_STD_FORMAT;
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
/**
|
||||
* @file streams-url-post.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief example how to http post data from an input stream using the
|
||||
* HttpRequest class.
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
const char *ssid = "your SSID";
|
||||
const char *password = "your PASSWORD";
|
||||
const char *url_str = "http://192.168.1.44:9988";
|
||||
AudioInfo info(44100, 2, 16);
|
||||
SineWaveGenerator<int16_t> sineWave(32000);
|
||||
GeneratedSoundStream<int16_t> sound(sineWave);
|
||||
TimedStream timed(sound);
|
||||
WiFiClient client;
|
||||
HttpRequest http(client);
|
||||
StreamCopy copier(http, timed);
|
||||
|
||||
void startWiFi() {
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.print("Connecting to WiFi ..");
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print('.');
|
||||
delay(1000);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
startWiFi();
|
||||
|
||||
// Setup sine wave
|
||||
sineWave.begin(info, N_B4);
|
||||
|
||||
// limit the size of the input stream to 60 seconds
|
||||
timed.setEndSec(60);
|
||||
timed.begin();
|
||||
|
||||
// start post
|
||||
Url url(url_str);
|
||||
http.header().put(TRANSFER_ENCODING, CHUNKED); // uncomment if chunked
|
||||
if (!http.processBegin(POST, url, "audio/pcm")){
|
||||
Serial.println("post failed");
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out
|
||||
void loop() {
|
||||
// posting the data
|
||||
if (copier.copy() == 0) {
|
||||
// closing the post
|
||||
http.processEnd();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file streams-url-file.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief Demo how to download a file from the internet and store it to a file. The test was done with an AudioKit which requires
|
||||
* some specific pin settings
|
||||
* @version 0.1
|
||||
* @date 2022-09-09
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#include "SD.h"
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
#define PIN_AUDIO_KIT_SD_CARD_CS 13
|
||||
#define PIN_AUDIO_KIT_SD_CARD_MISO 2
|
||||
#define PIN_AUDIO_KIT_SD_CARD_MOSI 15
|
||||
#define PIN_AUDIO_KIT_SD_CARD_CLK 14
|
||||
|
||||
|
||||
const char *ssid = "SSID";
|
||||
const char *password = "password";
|
||||
URLStream url(ssid, password); // Music Stream
|
||||
StreamCopy copier; //(i2s, music, 1024); // copy music to i2s
|
||||
File file; // final output stream
|
||||
int retryCount = 5;
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// define custom SPI pins
|
||||
SPI.begin(PIN_AUDIO_KIT_SD_CARD_CLK, PIN_AUDIO_KIT_SD_CARD_MISO, PIN_AUDIO_KIT_SD_CARD_MOSI, PIN_AUDIO_KIT_SD_CARD_CS);
|
||||
|
||||
// intialize SD
|
||||
if(!SD.begin(PIN_AUDIO_KIT_SD_CARD_CS)){
|
||||
LOGE("SD failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// open music stream
|
||||
url.begin("https://pschatzmann.github.io/Resources/audio/audio-8000.raw");
|
||||
|
||||
// copy file
|
||||
file = SD.open("/audio-8000.raw", FILE_WRITE);
|
||||
// overwirte from beginning
|
||||
file.seek(0);
|
||||
copier.begin(file, url);
|
||||
copier.copyAll();
|
||||
file.close();
|
||||
|
||||
file = SD.open("/audio-8000.raw");
|
||||
LOGI("file size: %d", file.size());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file streams-url_mp3-measuring.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and measure bytes per second of decoded data
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
URLStream url("ssid","password"); // or replace with ICYStream to get metadata
|
||||
MeasuringStream out(50, &Serial); // final output of decoded stream
|
||||
EncodedAudioStream dec(&out, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://direct.fipradio.fr/live/fip-midfi.mp3","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Streaming Radio Player
|
||||
|
||||
We just play a streamed radio station which provides the audio as aac and output the result via I2S to an external DAC
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file streams-url_aac-audiokit.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S on audiokit
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecAACHelix.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password"); // or replace with ICYStream to get metadata
|
||||
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new AACDecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// aac radio
|
||||
url.begin("http://peacefulpiano.stream.publicradio.org/peacefulpiano.aac","audio/aac");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# Streaming Radio Player
|
||||
|
||||
We just play a streamed radio station which provides the audio as mp3 and output the result via I2S to an external DAC
|
||||
|
||||
An ESP32 was used to test this sketch.
|
||||
|
||||
### External DAC:
|
||||
|
||||

|
||||
|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
DAC | ESP32
|
||||
-----|----------------
|
||||
VCC | 5V
|
||||
GND | GND
|
||||
BCK | BCK (GPIO14)
|
||||
DIN | OUT (GPIO22)
|
||||
LCK | BCK (GPIO15)
|
||||
FMT | GND
|
||||
XMT | 3V (or another GPIO PIN which is set to high)
|
||||
|
||||
- DMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCL - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file streams-url_aac-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecAACHelix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password");
|
||||
I2SStream i2s; // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new AACDecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
// you could define e.g your pins and change other settings
|
||||
//config.pin_ws = 10;
|
||||
//config.pin_bck = 11;
|
||||
//config.pin_data = 12;
|
||||
//config.mode = I2S_STD_FORMAT;
|
||||
i2s.begin(config);
|
||||
|
||||
// aac radio
|
||||
url.begin("http://peacefulpiano.stream.publicradio.org/peacefulpiano.aac","audio/aac");
|
||||
|
||||
// initialize decoder
|
||||
dec.begin();
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file streams-url_flac-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief The FLAC decoder supports a streaming interface where we can directly assign a source stream
|
||||
* @version 0.1
|
||||
* @date 2022-05-13
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecFLAC.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
const char* ssid = "ssid";
|
||||
const char* pwd = "password";
|
||||
URLStream url(ssid, pwd);
|
||||
FLACDecoder dec;
|
||||
I2SStream i2s;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
i2s.begin(i2s.defaultConfig(TX_MODE));
|
||||
|
||||
url.begin("http://www.lindberg.no/hires/test/2L-145_01_stereo_01.cd.flac");
|
||||
dec.setInput(url);
|
||||
dec.setOutput(i2s);
|
||||
dec.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
dec.copy();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @file streams-url_flac_foxen-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief Demo using the Foxen FLAC decoder
|
||||
* @version 0.1
|
||||
* @date 2025-01-09
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
* Warning: The WIFI speed is quite limited and the FLAC files are quite big. So there
|
||||
* is a big chance that the WIFI is just not fast enough. For my test I was downsampling
|
||||
* the file to 8000 samples per second!
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecFLACFoxen.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
const char* ssid = "ssid";
|
||||
const char* pwd = "password";
|
||||
URLStream url(ssid, pwd);
|
||||
AudioBoardStream i2s(AudioKitEs8388V1); // or replace with e.g. I2SStream i2s;
|
||||
|
||||
FLACDecoderFoxen flac(5*1024, 2);
|
||||
EncodedAudioStream dec(&i2s, &flac); // Decoding to i2s
|
||||
StreamCopy copier(dec, url, 1024); // copy url to decoder
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
while(!Serial);
|
||||
Serial.println("starting...");
|
||||
|
||||
// Open I2S: if the buffer is too slow audio is breaking up
|
||||
auto cfg =i2s.defaultConfig(TX_MODE);
|
||||
cfg.buffer_size= 1024;
|
||||
cfg.buffer_count = 20;
|
||||
if (!i2s.begin(cfg)){
|
||||
Serial.println("i2s error");
|
||||
stop();
|
||||
}
|
||||
|
||||
// Open url
|
||||
url.begin("https://pschatzmann.github.io/Resources/audio/audio.flac", "audio/flac");
|
||||
|
||||
// Start decoder
|
||||
if (!dec.begin()){
|
||||
Serial.println("Decoder failed");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Streaming Radio Player
|
||||
|
||||
We just play a streamed radio station which provides the audio as mp3 and output the result via I2S via the built in DAC
|
||||
|
||||
An ESP32 was used to test this sketch.
|
||||
|
||||
### Output Device: Piezo Electric Element
|
||||
|
||||
To test the output I am using a piezo electric element
|
||||
|
||||

|
||||
|
||||
It should also be possible to connect a headphone to the output pins...
|
||||
|
||||
|
||||
On the ESP32 the output is on the Pins GPIO26 and GPIO27
|
||||
|
||||
| PIEZO | ESP32
|
||||
| --------| ---------------
|
||||
| + | GPIO25 / GPIO26
|
||||
| - | GND
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file streams-url_mp3-out.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password");
|
||||
AnalogAudioStream out; // final output of decoded stream
|
||||
EncodedAudioStream dec(&out, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup out
|
||||
auto config = out.defaultConfig(TX_MODE);
|
||||
out.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Streaming Radio Player
|
||||
|
||||
We just play a streamed radio station which provides the audio as mp3 and output the result via I2S to an external DAC
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file streams-url_mp3-audiokit.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S on audiokit
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password"); // or replace with ICYStream to get metadata
|
||||
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file streams-url_mp3-out.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief read MP3 stream from url and output of metadata only: There is no audio output!
|
||||
* @date 2021-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
ICYStream url("ssid","password");
|
||||
MetaDataOutput out; // final output of decoded stream
|
||||
StreamCopy copier(out, url); // copy url to decoder
|
||||
|
||||
// callback for meta data
|
||||
void printMetaData(MetaDataType type, const char* str, int len){
|
||||
Serial.print("==> ");
|
||||
Serial.print(toStr(type));
|
||||
Serial.print(": ");
|
||||
Serial.println(str);
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// mp3 radio
|
||||
url.httpRequest().header().put("Icy-MetaData","1");
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
out.setCallback(printMetaData);
|
||||
out.begin(url.httpRequest());
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @file streams-url_mp3-metadata2.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief read MP3 stream from url and output metadata and audio!
|
||||
* The used mp3 file contains ID3 Metadata!
|
||||
* @date 2021-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
// -> EncodedAudioStream -> I2SStream
|
||||
// URLStream -> MultiOutput -|
|
||||
// -> MetaDataOutput
|
||||
|
||||
URLStream url("ssid","password");
|
||||
MetaDataOutput out1; // final output of metadata
|
||||
I2SStream i2s; // I2S output
|
||||
EncodedAudioStream out2dec(&i2s, new MP3DecoderHelix()); // Decoding stream
|
||||
MultiOutput out;
|
||||
StreamCopy copier(out, url); // copy url to decoder
|
||||
|
||||
// callback for meta data
|
||||
void printMetaData(MetaDataType type, const char* str, int len){
|
||||
Serial.print("==> ");
|
||||
Serial.print(toStr(type));
|
||||
Serial.print(": ");
|
||||
Serial.println(str);
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup multi output
|
||||
out.add(out1);
|
||||
out.add(out2dec);
|
||||
|
||||
// setup input
|
||||
url.begin("https://pschatzmann.github.io/Resources/audio/audio.mp3","audio/mp3");
|
||||
|
||||
// setup metadata
|
||||
out1.setCallback(printMetaData);
|
||||
out1.begin(url.httpRequest());
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
out2dec.begin();
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file streams-url_mp3-out.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it with the help of PWM
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password");
|
||||
PWMAudioOutput out; // final output of decoded stream
|
||||
EncodedAudioStream dec(&out, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup out
|
||||
auto config = out.defaultConfig(TX_MODE);
|
||||
//config.resolution = 8; // must be between 8 and 11 -> drives pwm frequency (8 is default)
|
||||
// alternative 1
|
||||
//config.start_pin = 3;
|
||||
// alternative 2
|
||||
int pins[] = {22, 23};
|
||||
// alternative 3
|
||||
//Pins pins = {3};
|
||||
//config.setPins(pins);
|
||||
out.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# Streaming Radio Player
|
||||
|
||||
We just play a streamed radio station which provides the audio as mp3 and output the result via I2S to an external DAC
|
||||
To decode the data we use the libhelix library.
|
||||
|
||||
An ESP32 was used to test this sketch.
|
||||
|
||||
### External DAC:
|
||||
|
||||

|
||||
|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
DAC | ESP32
|
||||
-----|----------------
|
||||
VCC | 5V
|
||||
GND | GND
|
||||
BCK | BCK (GPIO14)
|
||||
DIN | OUT (GPIO22)
|
||||
LCK | BCK (GPIO15)
|
||||
FMT | GND
|
||||
XMT | 3V (or another GPIO PIN which is set to high)
|
||||
|
||||
- DMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCL - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-libhelix
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file streams-url_mp3-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password");
|
||||
I2SStream i2s; // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
// you could define e.g your pins and change other settings
|
||||
//config.pin_ws = 10;
|
||||
//config.pin_bck = 11;
|
||||
//config.pin_data = 12;
|
||||
//config.mode = I2S_STD_FORMAT;
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @file streams-url_mp3-i2s_24bit.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S. The data is converted from
|
||||
* 16 to 32 bit
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libhelix.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password");
|
||||
I2SStream i2s; // final output of decoded stream
|
||||
NumberFormatConverterStream nfc(i2s);
|
||||
EncodedAudioStream dec(&nfc, new MP3DecoderHelix()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// convert 16 bits to 32, you could also change the gain
|
||||
nfc.begin(16, 32);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
// you could define e.g your pins and change other settings
|
||||
//config.pin_ws = 10;
|
||||
//config.pin_bck = 11;
|
||||
//config.pin_data = 12;
|
||||
//config.mode = I2S_STD_FORMAT;
|
||||
//config.bits_per_sample = 32; // we coult do this explicitly
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# Streaming Radio Player
|
||||
|
||||
We just play a streamed radio station which provides the audio as mp3 and output the result via I2S to an external DAC
|
||||
To decode the data we use the libmad library.
|
||||
|
||||
An ESP32 was used to test this sketch.
|
||||
|
||||
### External DAC:
|
||||
|
||||

|
||||
|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
DAC | ESP32
|
||||
-----|----------------
|
||||
VCC | 5V
|
||||
GND | GND
|
||||
BCK | BCK (GPIO14)
|
||||
DIN | OUT (GPIO22)
|
||||
LCK | BCK (GPIO15)
|
||||
FMT | GND
|
||||
XMT | 3V (or another GPIO PIN which is set to high)
|
||||
|
||||
- DMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCL - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
|
||||
### Dependencies
|
||||
|
||||
- https://github.com/pschatzmann/arduino-libmad
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file streams-url_mp3-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief decode MP3 stream from url and output it on I2S
|
||||
* @version 0.1
|
||||
* @date 2021-96-25
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*/
|
||||
|
||||
// install https://github.com/pschatzmann/arduino-libmad.git
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3MAD.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
URLStream url("ssid","password");
|
||||
I2SStream i2s; // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new MP3DecoderMAD()); // Decoding stream
|
||||
StreamCopy copier(dec, url); // copy url to decoder
|
||||
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
// you could define e.g your pins and change other settings
|
||||
//config.pin_ws = 10;
|
||||
//config.pin_bck = 11;
|
||||
//config.pin_data = 12;
|
||||
//config.mode = I2S_STD_FORMAT;
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file url_mts-hex.ino
|
||||
* @author Phil Schatzmann
|
||||
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMTS.h"
|
||||
#include "AudioTools/Communication/HLSStream.h"
|
||||
|
||||
HexDumpOutput out(Serial);
|
||||
HLSStream hls_stream("SSID", "password");
|
||||
MTSDecoder mts;
|
||||
EncodedAudioStream mts_stream(&out, &mts);
|
||||
StreamCopy copier(mts_stream, hls_stream);
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
mts_stream.begin();
|
||||
|
||||
hls_stream.begin("http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/nonuk/sbr_vlow/ak/bbc_world_service.m3u8");
|
||||
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
/**
|
||||
* @file streams-url-post.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief example how to http post data from an input stream
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
AudioInfo info(44100, 2, 16);
|
||||
SineWaveGenerator<int16_t> sineWave(32000);
|
||||
GeneratedSoundStream<int16_t> sound(sineWave);
|
||||
TimedStream timed(sound);
|
||||
URLStream url("ssid", "password");
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// Setup sine wave
|
||||
sineWave.begin(info, N_B4);
|
||||
|
||||
// limit the size of the input stream
|
||||
timed.setEndSec(60);
|
||||
timed.begin();
|
||||
|
||||
// post the data
|
||||
url.begin("http://192.168.1.35:8000", "audio/bin", POST, "text/html", timed);
|
||||
}
|
||||
|
||||
// Arduino loop - copy sound to out
|
||||
void loop() {}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Stream URL to I2S external DAC
|
||||
|
||||
We are reading a raw audio file from the Intenet and write the data to the I2S interface. The audio file must be available using 16 bit integers with 2 channels. I used a sampling rate of 8000.
|
||||
|
||||
[Audacity](https://www.audacityteam.org/) might help you out here: export with the file name audio.raw as RAW signed 16 bit PCM and copy it to the SD card. In my example I was using the file [audio.raw](https://pschatzmann.github.io/Resources/audio/audio.raw).
|
||||
|
||||
|
||||
### External DAC:
|
||||
|
||||

|
||||
|
||||
|
||||
I am just using the default pins defined by the framework. However I could change them with the help of the config object. The mute pin can be defined in the constructor of the I2SStream - by not defining anything we use the default which is GPIO23
|
||||
|
||||
DAC | ESP32
|
||||
-----|----------------
|
||||
VCC | 5V
|
||||
GND | GND
|
||||
BCK | BCK (GPIO14)
|
||||
DIN | OUT (GPIO22)
|
||||
LCK | BCK (GPIO15)
|
||||
FMT | GND
|
||||
XMT | 3V (or another GPIO PIN which is set to high)
|
||||
|
||||
- DMP - De-emphasis control for 44.1kHz sampling rate(1): Off (Low) / On (High)
|
||||
- FLT - Filter select : Normal latency (Low) / Low latency (High)
|
||||
- SCL - System clock input (probably SCL on your board).
|
||||
- FMT - Audio format selection : I2S (Low) / Left justified (High)
|
||||
- XMT - Soft mute control(1): Soft mute (Low) / soft un-mute (High)
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file url_raw-I2S_external_dac.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/url_raw-I2S_externel_dac/README.md
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
#include "WiFi.h"
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
URLStream music; // Music Stream
|
||||
I2SStream i2s;// I2S as Stream
|
||||
StreamCopy copier(i2s, music, 1024); // copy music to i2s
|
||||
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// connect to WIFI
|
||||
WiFi.begin("network", "pwd");
|
||||
while (WiFi.status() != WL_CONNECTED){
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
// open music stream
|
||||
music.begin("https://pschatzmann.github.io/Resources/audio/audio-8000.raw");
|
||||
|
||||
// start I2S with external DAC
|
||||
Serial.println("\nstarting I2S...");
|
||||
auto cfg = i2s.defaultConfig(TX_MODE);
|
||||
cfg.sample_rate = 8000;
|
||||
i2s.begin(cfg);
|
||||
}
|
||||
|
||||
// Arduino loop - repeated processing: copy input stream to output stream
|
||||
void loop() {
|
||||
int len = copier.copy();
|
||||
if (len){
|
||||
Serial.print(".");
|
||||
} else {
|
||||
delay(5000);
|
||||
i2s.end();
|
||||
Serial.println("\nCopy ended");
|
||||
stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Display RAW Stream
|
||||
|
||||
Sometimes it is handy to check out the data on the screen with the help of the Arduino Serial Monitor and Serial Plotter.
|
||||
We read the raw binary data from an URLStream.
|
||||
|
||||
As output stream we use a CsvOutput: this class transforms the data into CSV and prints the result to Serial. Finally we can use the Arduino Serial Plotter to view the result as chart:
|
||||
|
||||

|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file streams-url_raw-serial.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-stream/streams-url_raw-serial/README.md
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
#include "WiFi.h"
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
|
||||
|
||||
URLStream music; // Music Stream
|
||||
int channels = 2; // The stream has 2 channels
|
||||
CsvOutput<int16_t> printer(Serial, channels); // ASCII stream
|
||||
StreamCopy copier(printer, music); // copies music into printer
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
// Open Serial
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// connect to WIFI
|
||||
WiFi.begin("network-name", "password");
|
||||
while (WiFi.status() != WL_CONNECTED){
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
// open music stream - it contains 2 channels of int16_t data
|
||||
music.begin("https://pschatzmann.github.io/Resources/audio/audio.raw");
|
||||
}
|
||||
|
||||
|
||||
// Arduino loop - repeated processing
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file streams-url_flac-i2s.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief The FLAC decoder supports a streaming interface where we can directly assign a source stream
|
||||
* @version 0.1
|
||||
* @date 2022-05-13
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecVorbis.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
const char* ssid = "ssid";
|
||||
const char* pwd = "password";
|
||||
URLStream url(ssid, pwd);
|
||||
VorbisDecoder dec;
|
||||
I2SStream i2s;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
i2s.begin(i2s.defaultConfig(TX_MODE));
|
||||
|
||||
url.begin("http://marmalade.scenesat.com:8086/bitjam.ogg","application/ogg");
|
||||
dec.setInput(url);
|
||||
dec.setOutput(i2s);
|
||||
dec.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
dec.copy();
|
||||
}
|
||||
Reference in New Issue
Block a user