snapshot
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
|
||||
/**
|
||||
* @file receive-mp3.ino
|
||||
* @brief Example of receiving an mp3 stream over serial and playing it over I2S
|
||||
* using the AudioTools library.
|
||||
* The processing implements a flow control using a custom digital pin. We process
|
||||
* the data receiving in a separate task and the playback in the main loop.
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
#include "AudioTools/Concurrency/RTOS.h"
|
||||
|
||||
const int flowControlPin = 17; // flow control pin acitive low
|
||||
const int min_percent = 10;
|
||||
const int max_percent = 90;
|
||||
|
||||
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
|
||||
MP3DecoderHelix helix;
|
||||
EncodedAudioStream dec(&i2s, &helix); // Decoding stream
|
||||
// queue
|
||||
BufferRTOS<uint8_t> buffer(0);
|
||||
QueueStream<uint8_t> queue(buffer);
|
||||
// copy
|
||||
StreamCopy copierFill(queue, Serial1);
|
||||
StreamCopy copierPlay(dec, queue);
|
||||
|
||||
Task task("mp3-copy", 10000, 1, 0);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
Serial1.begin(115200);
|
||||
pinMode(flowControlPin, OUTPUT); // flow control pin
|
||||
|
||||
// set up buffer here to allow PSRAM usage
|
||||
buffer.resize(1024 * 10); // 10kB buffer
|
||||
queue.begin(50); // start when half full
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(config);
|
||||
|
||||
// setup decoder
|
||||
dec.begin();
|
||||
|
||||
// start fill buffer copy task
|
||||
task.begin([]() {
|
||||
copierFill.copy();
|
||||
// data synchronization to prevent buffer overflow
|
||||
if (buffer.levelPercent() >= max_percent) {
|
||||
digitalWrite(flowControlPin, HIGH); // stop receiving
|
||||
} else if (buffer.levelPercent() <= min_percent) {
|
||||
digitalWrite(flowControlPin, LOW); // start receiving
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void loop() { copierPlay.copy(); }
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
/**
|
||||
* @file send-mp3.ino
|
||||
* @brief Example of sending an mp3 stream over Serial the AudioTools library.
|
||||
* We use a custom pin to control the flow of the data. If we are ready to
|
||||
* receive data, we set the pin to LOW.
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
URLStream url("ssid", "password"); // or replace with ICYStream to get metadata
|
||||
StreamCopy copier(Serial1, url); // copy url to decoder
|
||||
// pins
|
||||
const int flowControlPin = 17;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Error);
|
||||
|
||||
// setup flow control pin
|
||||
pinMode(flowControlPin, INPUT_PULLUP); // flow control pin
|
||||
|
||||
// setup serial data sink
|
||||
Serial1.begin(115200);
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128", "audio/mp3");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (digitalRead(flowControlPin) == LOW) {
|
||||
copier.copy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
/**
|
||||
* @file receive-mp3.ino
|
||||
* @brief Example of receiving an mp3 stream over serial and playing it over I2S
|
||||
* using the AudioTools library.
|
||||
* The processing implements a xon-xoff flow control over Serial. We
|
||||
* process the data receiving in a separate task and the playback in the main
|
||||
* loop.
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
#include "AudioTools/Concurrency/RTOS.h"
|
||||
|
||||
// xon/xoff flow control
|
||||
const char xon = 17;
|
||||
const char xoff = 19;
|
||||
const int min_percent = 10;
|
||||
const int max_percent = 90;
|
||||
|
||||
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
|
||||
MP3DecoderHelix helix;
|
||||
EncodedAudioStream dec(&i2s, &helix); // Decoding stream
|
||||
// queue
|
||||
BufferRTOS<uint8_t> buffer(0);
|
||||
QueueStream<uint8_t> queue(buffer);
|
||||
// copy
|
||||
StreamCopy copierFill(queue, Serial1);
|
||||
StreamCopy copierPlay(dec, queue);
|
||||
|
||||
Task task("mp3-copy", 10000, 1, 0);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
|
||||
Serial0.begin(115200);
|
||||
|
||||
// set up buffer here to allow PSRAM usage
|
||||
buffer.resize(1024 * 10); // 10kB buffer
|
||||
queue.begin(50); // start when half full
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(config);
|
||||
|
||||
// setup decoder
|
||||
dec.begin();
|
||||
|
||||
// start fill buffer copy task
|
||||
task.begin([]() {
|
||||
copierFill.copy();
|
||||
// data synchronization to prevent buffer overflow
|
||||
if (buffer.levelPercent() >= max_percent) {
|
||||
Serial1.write(xoff); // stop receiving
|
||||
Serial1.flush();
|
||||
} else if (buffer.levelPercent() <= min_percent) {
|
||||
Serial1.write(xon); // start receiving
|
||||
Serial1.flush();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void loop() { copierPlay.copy(); }
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
/**
|
||||
* @file send-mp3.ino
|
||||
* @brief Example of sending an mp3 stream over Serial the AudioTools library.
|
||||
* We use xon/xoff to control the flow of the data.
|
||||
* I am using an ESP32 Dev Module for the test with the pins TX=17 and RX=16.
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
URLStream url("ssid", "password"); // or replace with ICYStream to get metadata
|
||||
StreamCopy copier(Serial1, url); // copy url to decoder
|
||||
// xon/xoff flow control
|
||||
const char xon = 17;
|
||||
const char xoff = 19;
|
||||
bool is_active = false;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Error);
|
||||
|
||||
// setup serial data sink
|
||||
Serial2.begin(115200);
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128", "audio/mp3");
|
||||
}
|
||||
|
||||
// Determine if we can send data from the flow control sent by the receiver
|
||||
bool isActive() {
|
||||
char c = Serial2.read();
|
||||
switch (c) {
|
||||
case xon:
|
||||
is_active = true;
|
||||
break;
|
||||
case xoff:
|
||||
is_active = false;
|
||||
break;
|
||||
}
|
||||
return is_active;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (isActive()) {
|
||||
copier.copy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
/**
|
||||
* @file receive-mp3.ino
|
||||
* @brief Example of receiving an mp3 stream over serial and playing it over I2S
|
||||
* using the AudioTools library.
|
||||
* The processing must be synchronized with RTS/CTS flow control to prevent a
|
||||
* buffer overflow and lost data.
|
||||
*/
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
|
||||
|
||||
AudioBoardStream i2s(AudioKitEs8388V1); // final output of decoded stream
|
||||
EncodedAudioStream dec(&i2s, new MP3DecoderHelix()); // Decoding stream
|
||||
HardwareSerial MP3Serial(1); // define a Serial for UART1
|
||||
StreamCopy copier(dec, MP3Serial); // copy url to decoder
|
||||
// pins
|
||||
const int MySerialTX = -1;
|
||||
const int MySerialRX = 18;
|
||||
const int MySerialRTS = -1;
|
||||
const int MySerialCTS = 20;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// setup serial data source with flow control
|
||||
MP3Serial.begin(115200, SERIAL_8N1);
|
||||
MP3Serial.setPins(MySerialRX, MySerialTX, MySerialCTS, MySerialRTS);
|
||||
MP3Serial.setHwFlowCtrlMode(UART_HW_FLOWCTRL_CTS_RTS);
|
||||
|
||||
// setup i2s
|
||||
auto config = i2s.defaultConfig(TX_MODE);
|
||||
i2s.begin(config);
|
||||
|
||||
// setup I2S based on sampling rate provided by decoder
|
||||
dec.begin();
|
||||
|
||||
}
|
||||
|
||||
void loop() { copier.copy(); }
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/**
|
||||
* @file send-mp3.ino
|
||||
* @brief ESP32 Example of sending an mp3 stream over Serial the AudioTools library.
|
||||
* The processing must be synchronized with RTS/CTS flow control to prevent a
|
||||
* buffer overflow and lost data. We get the mp3 from an URLStream.
|
||||
* We used a ESP32 Dev Module for the test.
|
||||
*/
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
|
||||
#include "AudioTools/Communication/AudioHttp.h"
|
||||
|
||||
URLStream url("ssid", "password"); // or replace with ICYStream to get metadata
|
||||
HardwareSerial MP3Serial(1); // define a Serial for UART1
|
||||
StreamCopy copier(MP3Serial, url); // copy url to decoder
|
||||
// pins
|
||||
const int MySerialTX = 17; // TX2
|
||||
const int MySerialRX = -1; // not used
|
||||
const int MySerialRTS = 4; // GPIO 4
|
||||
const int MySerialCTS = -1; // not useed
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
|
||||
|
||||
// improve performance
|
||||
MP3Serial.setTxBufferSize(1024); // must be called before begin
|
||||
|
||||
// setup serial data sink with flow control
|
||||
MP3Serial.begin(115200, SERIAL_8N1);
|
||||
MP3Serial.setPins(MySerialRX, MySerialTX, MySerialCTS, MySerialRTS);
|
||||
MP3Serial.setHwFlowCtrlMode(UART_HW_FLOWCTRL_CTS_RTS);
|
||||
|
||||
// mp3 radio
|
||||
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128", "audio/mp3");
|
||||
}
|
||||
|
||||
void loop() { copier.copy(); }
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file send-8bit-receive.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief Sending and receiving audio via Serial. You need to connect the RX pin
|
||||
* with the TX pin!
|
||||
*
|
||||
* We send 8bit data over the wire, so any (small) data loss will not be audible
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2023-11-25
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
// #include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
|
||||
AudioInfo info(44100, 2, 16);
|
||||
I2SStream out; // or AnalogAudioStream, AudioBoardStream etc
|
||||
SineWaveGenerator<int16_t> sineWave(32000);
|
||||
GeneratedSoundStream<int16_t> sound(sineWave);
|
||||
auto &serial = Serial2;
|
||||
EncoderL8 enc;
|
||||
DecoderL8 dec;
|
||||
EncodedAudioStream enc_stream(&serial, &enc);
|
||||
EncodedAudioStream dec_stream(&out, &dec);
|
||||
Throttle throttle(enc_stream);
|
||||
StreamCopy copierOut(throttle, sound, 256); // copies sound into Serial
|
||||
StreamCopy copierIn(dec_stream, serial, 256); // copies sound from Serial
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
|
||||
// Note the format for setting a serial port is as follows:
|
||||
// Serial.begin(baud-rate, protocol, RX pin, TX pin);
|
||||
Serial2.begin(3000000, SERIAL_8N1);
|
||||
|
||||
sineWave.begin(info, N_B4);
|
||||
throttle.begin(info);
|
||||
enc_stream.begin(info);
|
||||
dec_stream.begin(info);
|
||||
|
||||
// start I2S
|
||||
auto config = out.defaultConfig(TX_MODE);
|
||||
config.copyFrom(info);
|
||||
out.begin(config);
|
||||
|
||||
// better visibility in logging
|
||||
copierOut.setLogName("out");
|
||||
copierIn.setLogName("in");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// copy to serial
|
||||
copierOut.copy();
|
||||
// copy from serial
|
||||
copierIn.copy();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file send-adpcm-receive.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief Sending and receiving audio via Serial. You need to connect the RX pin
|
||||
* with the TX pin!
|
||||
*
|
||||
* We send encoded ADPCM audio over the serial wire: The higher the transmission rate
|
||||
* the higher the risk of data loss!
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2023-11-25
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecADPCM.h" // https://github.com/pschatzmann/adpcm
|
||||
//#include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
|
||||
AudioInfo info(22000, 1, 16);
|
||||
I2SStream out; // or AnalogAudioStream, AudioBoardStream etc
|
||||
SineWaveGenerator<int16_t> sineWave(32000);
|
||||
GeneratedSoundStream<int16_t> sound(sineWave);
|
||||
|
||||
auto &serial = Serial2;
|
||||
ADPCMEncoder enc(AV_CODEC_ID_ADPCM_IMA_WAV);
|
||||
ADPCMDecoder dec(AV_CODEC_ID_ADPCM_IMA_WAV);
|
||||
EncodedAudioStream enc_stream(&serial, &enc);
|
||||
EncodedAudioStream dec_stream(&out, &dec);
|
||||
Throttle throttle(enc_stream);
|
||||
static int frame_size = 498;
|
||||
StreamCopy copierOut(throttle, sound, frame_size); // copies sound into Serial
|
||||
StreamCopy copierIn(dec_stream, serial, frame_size); // copies sound from Serial
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
|
||||
// Note the format for setting a serial port is as follows:
|
||||
// Serial.begin(baud-rate, protocol, RX pin, TX pin);
|
||||
Serial2.begin(115200, SERIAL_8N1);
|
||||
|
||||
sineWave.begin(info, N_B4);
|
||||
throttle.begin(info);
|
||||
enc_stream.begin(info);
|
||||
dec_stream.begin(info);
|
||||
|
||||
// start I2S
|
||||
auto config = out.defaultConfig(TX_MODE);
|
||||
config.copyFrom(info);
|
||||
out.begin(config);
|
||||
|
||||
// better visibility in logging
|
||||
copierOut.setLogName("out");
|
||||
copierIn.setLogName("in");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// copy to serial
|
||||
copierOut.copy();
|
||||
// copy from serial
|
||||
copierIn.copy();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file send-adpcm-receive.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief Sending and receiving audio via Serial. You need to connect the RX pin
|
||||
* with the TX pin!
|
||||
*
|
||||
* We send encoded ADPCM audio over the serial wire. In order to be able to recover
|
||||
* from data loss in the encoded frames we use a Container
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2023-11-25
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
#include "AudioTools/AudioCodecs/CodecADPCM.h" // https://github.com/pschatzmann/adpcm
|
||||
#include "AudioTools/AudioCodecs/ContainerBinary.h"
|
||||
// #include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
|
||||
AudioInfo info(44100, 2, 16);
|
||||
I2SStream out; // or AnalogAudioStream, AudioBoardStream etc
|
||||
SineWaveGenerator<int16_t> sineWave(32000);
|
||||
GeneratedSoundStream<int16_t> sound(sineWave);
|
||||
|
||||
auto &serial = Serial2;
|
||||
ADPCMEncoder enc(AV_CODEC_ID_ADPCM_IMA_WAV);
|
||||
ADPCMDecoder dec(AV_CODEC_ID_ADPCM_IMA_WAV);
|
||||
BinaryContainerEncoder bin_enc(&enc);
|
||||
BinaryContainerDecoder bin_dec(&dec);
|
||||
EncodedAudioOutput enc_stream(&serial, &bin_enc);
|
||||
EncodedAudioOutput dec_stream(&out, &bin_dec);
|
||||
Throttle throttle(enc_stream);
|
||||
static int frame_size = 498;
|
||||
StreamCopy copierOut(throttle, sound, frame_size); // copies sound into Serial
|
||||
StreamCopy copierIn(dec_stream, serial, frame_size); // copies sound from Serial
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
|
||||
// Note the format for setting a serial port is as follows:
|
||||
// Serial.begin(baud-rate, protocol, RX pin, TX pin);
|
||||
Serial2.begin(1100000, SERIAL_8N1);
|
||||
|
||||
sineWave.begin(info, N_B4);
|
||||
throttle.begin(info);
|
||||
|
||||
// increase the reliability
|
||||
dec_stream.setFrameSize(frame_size);
|
||||
enc_stream.setFrameSize(frame_size);
|
||||
|
||||
enc_stream.begin(info);
|
||||
dec_stream.begin(info);
|
||||
|
||||
|
||||
// start I2S
|
||||
auto config = out.defaultConfig(TX_MODE);
|
||||
config.copyFrom(info);
|
||||
out.begin(config);
|
||||
|
||||
// better visibility in logging
|
||||
copierOut.setLogName("out");
|
||||
copierIn.setLogName("in");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// copy to serial
|
||||
copierOut.copy();
|
||||
// copy from serial
|
||||
copierIn.copy();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file send-receive.ino
|
||||
* @author Phil Schatzmann
|
||||
* @brief Sending and receiving audio via Serial. You need to connect the RX pin
|
||||
* with the TX pin!
|
||||
* The sine wave generator is providing the data as fast as possible, therefore we
|
||||
* throttle on the sending side to prevent that the receiver is getting the data
|
||||
* too fast.
|
||||
*
|
||||
* @version 0.1
|
||||
* @date 2022-03-09
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*/
|
||||
|
||||
#include "AudioTools.h"
|
||||
// #include "AudioTools/AudioLibs/AudioBoardStream.h"
|
||||
|
||||
AudioInfo info(22000, 1, 16);
|
||||
SineWaveGenerator<int16_t> sineWave(32000);
|
||||
GeneratedSoundStream<int16_t> sound(sineWave);
|
||||
I2SStream out; // or AnalogAudioStream, AudioBoardStream etc
|
||||
auto &serial = Serial2;
|
||||
Throttle throttle(serial);
|
||||
StreamCopy copierOut(throttle, sound, 256); // copies sound into Serial
|
||||
StreamCopy copierIn(out, serial, 256); // copies sound from Serial
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
|
||||
|
||||
// Note the format for setting a serial port is as follows:
|
||||
// Serial.begin(baud-rate, protocol, RX pin, TX pin);
|
||||
Serial2.begin(3000000, SERIAL_8N1 );
|
||||
|
||||
// Setup sine wave
|
||||
sineWave.begin(info, N_B4);
|
||||
throttle.begin(info);
|
||||
|
||||
// start I2S
|
||||
auto config = out.defaultConfig(TX_MODE);
|
||||
config.copyFrom(info);
|
||||
out.begin(config);
|
||||
|
||||
// better visibility in logging
|
||||
copierOut.setLogName("out");
|
||||
copierIn.setLogName("in");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// copy to serial
|
||||
copierOut.copy();
|
||||
// copy from serial
|
||||
copierIn.copy();
|
||||
}
|
||||
Reference in New Issue
Block a user