mirror of
https://github.com/pschatzmann/arduino-audio-tools.git
synced 2024-09-21 10:27:27 +00:00
USE_TASK
This commit is contained in:
parent
e87406e61b
commit
822c827585
@ -13,7 +13,7 @@ namespace audio_tools {
|
||||
#endif
|
||||
|
||||
#ifndef MTS_UNDERFLOW_LIMIT
|
||||
# define MTS_UNDERFLOW_LIMIT 200
|
||||
# define MTS_UNDERFLOW_LIMIT 188
|
||||
#endif
|
||||
|
||||
#ifndef MTS_WRITE_BUFFER_SIZE
|
||||
@ -177,13 +177,13 @@ class MTSDecoder : public AudioDecoder {
|
||||
TRACED();
|
||||
TSDCode res = TSD_OK;
|
||||
int count = 0;
|
||||
while (res == TSD_OK && buffer.available() > limit) {
|
||||
while (res == TSD_OK && buffer.available() >= limit) {
|
||||
// Unfortunatly we need to reset the demux after each file
|
||||
if (is_new_file(buffer.data())){
|
||||
LOGD("parsing new file");
|
||||
begin();
|
||||
}
|
||||
size_t len;
|
||||
size_t len = 0;
|
||||
res = tsd_demux(&ctx, (void *)buffer.data(), buffer.available(), &len);
|
||||
// remove processed bytes
|
||||
buffer.clearArray(len);
|
@ -226,7 +226,7 @@
|
||||
#define USE_EXT_BUTTON_LOGIC
|
||||
//#define USE_ALLOCATOR true
|
||||
#define HAS_IOSTRAM
|
||||
#define USE_TASK true
|
||||
#define USE_TASK false
|
||||
|
||||
#define PWM_FREQENCY 30000
|
||||
#define PIN_PWM_START 12
|
||||
@ -741,6 +741,10 @@ typedef WiFiClient WiFiClientSecure;
|
||||
# define URL_HANDSHAKE_TIMEOUT 120000
|
||||
#endif
|
||||
|
||||
#ifndef USE_TASK
|
||||
# define USE_TASK false
|
||||
#endif
|
||||
|
||||
#ifndef USE_SERVER_ACCEPT
|
||||
# define USE_SERVER_ACCEPT false
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#if defined(ESP32) && defined(USE_URL_ARDUINO)
|
||||
#include "AudioConfig.h"
|
||||
#include "AudioConfig.h"
|
||||
#if USE_TASK && defined(USE_URL_ARDUINO)
|
||||
#include "AudioHttp/ICYStream.h"
|
||||
|
||||
namespace audio_tools {
|
||||
@ -105,4 +105,4 @@ class ICYStreamBuffered : public AbstractURLStream {
|
||||
|
||||
} // namespace audio_tools
|
||||
|
||||
#endif // ESP32
|
||||
#endif // USE_TASK
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#if defined(ESP32) && defined(USE_URL_ARDUINO)
|
||||
#include "AudioConfig.h"
|
||||
#if USE_TASK && defined(USE_URL_ARDUINO)
|
||||
#include "AudioHttp/URLStream.h"
|
||||
#include "AudioTools/AudioStreams.h"
|
||||
#include "Concurrency/SynchronizedBuffers.h"
|
||||
|
@ -8,38 +8,83 @@
|
||||
#include "Concurrency/Concurrency.h"
|
||||
|
||||
#define MAX_HLS_LINE 512
|
||||
#define START_URLS_LIMIT 4
|
||||
#define HLS_BUFFER_COUNT 10
|
||||
|
||||
namespace audio_tools {
|
||||
|
||||
/// @brief Abstract API for URLLoaderHLS
|
||||
class URLLoaderHLSBase {
|
||||
public:
|
||||
virtual bool begin() = 0;
|
||||
virtual void end() = 0;
|
||||
virtual void addUrl(const char *url) = 0;
|
||||
virtual int urlCount() = 0;
|
||||
virtual int available() { return 0; }
|
||||
virtual size_t readBytes(uint8_t *data, size_t len) { return 0; }
|
||||
const char *contentType() { return nullptr; }
|
||||
int contentLength() { return 0; }
|
||||
|
||||
virtual void setBuffer(int size, int count) {}
|
||||
};
|
||||
|
||||
/// URLLoader which saves the HLS segments to the indicated output
|
||||
class URLLoaderHLSOutput {
|
||||
public:
|
||||
URLLoaderHLSOutput(Print &out, int maxUrls = 20) {
|
||||
max = maxUrls;
|
||||
p_print = &out;
|
||||
}
|
||||
virtual bool begin() { return true; };
|
||||
virtual void end(){};
|
||||
virtual void addUrl(const char *url) {
|
||||
LOGI("saving data for %s", url);
|
||||
url_stream.begin(url);
|
||||
url_stream.waitForData(500);
|
||||
copier.begin(*p_print, url_stream);
|
||||
int bytes_copied = copier.copyAll();
|
||||
LOGI("Copied %d of %d", bytes_copied, url_stream.contentLength());
|
||||
assert(bytes_copied == url_stream.contentLength());
|
||||
url_stream.end();
|
||||
}
|
||||
virtual int urlCount() { return 0; }
|
||||
|
||||
protected:
|
||||
int count = 0;
|
||||
int max = 20;
|
||||
Print *p_print;
|
||||
URLStream url_stream;
|
||||
StreamCopy copier;
|
||||
};
|
||||
|
||||
/***
|
||||
* @brief We feed the URLLoader with some url strings. At each readBytes or
|
||||
* available() call we refill the buffer. The buffer must be big enough to
|
||||
* bridge the delays caused by the reloading of the segments
|
||||
* @brief We feed the URLLoaderHLS with some url strings. The data of the
|
||||
* related segments are provided via the readBytes() method.
|
||||
* @author Phil Schatzmann
|
||||
* @copyright GPLv3
|
||||
*/
|
||||
|
||||
class URLLoader {
|
||||
class URLLoaderHLS : public URLLoaderHLSBase {
|
||||
public:
|
||||
URLLoader(URLStream &stream) { p_stream = &stream; };
|
||||
URLLoader() { p_stream = &default_stream; };
|
||||
// URLLoaderHLS(URLStream &stream) { p_stream = &stream; };
|
||||
URLLoaderHLS() = default;
|
||||
|
||||
~URLLoader() { end(); }
|
||||
~URLLoaderHLS() { end(); }
|
||||
|
||||
bool begin() {
|
||||
bool begin() override {
|
||||
TRACED();
|
||||
#if USE_TASK
|
||||
buffer.resize(buffer_size * buffer_count);
|
||||
task.begin(std::bind(&URLLoader::bufferRefill, this));
|
||||
task.begin(std::bind(&URLLoaderHLS::bufferRefill, this));
|
||||
#else
|
||||
buffer.resize(buffer_size, buffer_count);
|
||||
buffer.resize(buffer_size * buffer_count);
|
||||
#endif
|
||||
|
||||
active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void end() {
|
||||
void end() override {
|
||||
TRACED();
|
||||
#if USE_TASK
|
||||
task.end();
|
||||
@ -51,7 +96,7 @@ class URLLoader {
|
||||
}
|
||||
|
||||
/// Adds the next url to be played in sequence
|
||||
void addUrl(const char *url) {
|
||||
void addUrl(const char *url) override {
|
||||
LOGI("Adding %s", url);
|
||||
Str url_str(url);
|
||||
char *str = new char[url_str.length() + 1];
|
||||
@ -64,10 +109,10 @@ class URLLoader {
|
||||
|
||||
/// Provides the number of open urls which can be played. Refills them, when
|
||||
/// min limit is reached.
|
||||
int urlCount() { return urls.size(); }
|
||||
int urlCount() override { return urls.size(); }
|
||||
|
||||
/// Available bytes of the audio stream
|
||||
int available() {
|
||||
int available() override {
|
||||
if (!active) return 0;
|
||||
TRACED();
|
||||
#if !USE_TASK
|
||||
@ -77,7 +122,7 @@ class URLLoader {
|
||||
}
|
||||
|
||||
/// Provides data from the audio stream
|
||||
size_t readBytes(uint8_t *data, size_t len) {
|
||||
size_t readBytes(uint8_t *data, size_t len) override {
|
||||
if (!active) return 0;
|
||||
TRACED();
|
||||
#if !USE_TASK
|
||||
@ -97,25 +142,25 @@ class URLLoader {
|
||||
return p_stream->contentLength();
|
||||
}
|
||||
|
||||
void setBuffer(int size, int count) {
|
||||
void setBuffer(int size, int count) override {
|
||||
buffer_size = size;
|
||||
buffer_count = count;
|
||||
}
|
||||
|
||||
protected:
|
||||
URLStream default_stream;
|
||||
Vector<const char *> urls{10};
|
||||
#if USE_TASK
|
||||
BufferRTOS<uint8_t> buffer{0};
|
||||
Task task{"Refill", 1024 * 5, 1, 1};
|
||||
Mutex mutex;
|
||||
#else
|
||||
NBuffer<uint8_t> buffer{0, 0};
|
||||
RingBuffer<uint8_t> buffer{0};
|
||||
#endif
|
||||
bool active = false;
|
||||
int buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
int buffer_count = 10;
|
||||
URLStream *p_stream = nullptr;
|
||||
int buffer_count = HLS_BUFFER_COUNT;
|
||||
URLStream default_stream;
|
||||
URLStream *p_stream = &default_stream;
|
||||
const char *url_to_play = nullptr;
|
||||
|
||||
/// try to keep the buffer filled
|
||||
@ -134,15 +179,14 @@ class URLLoader {
|
||||
}
|
||||
|
||||
// switch current stream if we have no more data
|
||||
if ((!*p_stream || p_stream->totalRead() == p_stream->contentLength()) &&
|
||||
!urls.empty()) {
|
||||
if (!*p_stream && !urls.empty()) {
|
||||
LOGD("Refilling");
|
||||
if (url_to_play != nullptr) {
|
||||
delete url_to_play;
|
||||
}
|
||||
url_to_play = urls[0];
|
||||
LOGI("playing %s", url_to_play);
|
||||
if (p_stream->httpRequest().connected()) p_stream->end();
|
||||
p_stream->setTimeout(5000);
|
||||
p_stream->begin(url_to_play);
|
||||
p_stream->waitForData(500);
|
||||
#if USE_TASK
|
||||
@ -157,25 +201,36 @@ class URLLoader {
|
||||
LOGI("Playing %s of %d", p_stream->urlStr(), (int)urls.size());
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
int failed = 0;
|
||||
int to_write = min(buffer.availableForWrite(), DEFAULT_BUFFER_SIZE);
|
||||
if (to_write > 0) {
|
||||
int total = 0;
|
||||
int failed = 0;
|
||||
while (to_write > 0) {
|
||||
if (p_stream->totalRead() == p_stream->contentLength()) break;
|
||||
uint8_t tmp[to_write] = {0};
|
||||
int read = p_stream->readBytes(tmp, to_write);
|
||||
total += read;
|
||||
if (read > 0) {
|
||||
buffer.writeArray(tmp, read);
|
||||
to_write = min(buffer.availableForWrite(), DEFAULT_BUFFER_SIZE);
|
||||
} else {
|
||||
delay(5);
|
||||
// this should not really happen
|
||||
failed++;
|
||||
if (failed >= 3) break;
|
||||
// try to keep the buffer filled
|
||||
while (to_write > 0) {
|
||||
uint8_t tmp[to_write] = {0};
|
||||
int read = p_stream->readBytes(tmp, to_write);
|
||||
total += read;
|
||||
if (read > 0) {
|
||||
failed = 0;
|
||||
buffer.writeArray(tmp, read);
|
||||
LOGI("buffer add %d -> %d:", read, buffer.available());
|
||||
|
||||
to_write = min(buffer.availableForWrite(), DEFAULT_BUFFER_SIZE);
|
||||
} else {
|
||||
delay(10);
|
||||
// this should not really happen
|
||||
failed++;
|
||||
LOGW("No data idx %d: available: %d", failed, p_stream->available());
|
||||
if (failed >= 5) {
|
||||
LOGE("No data idx %d: available: %d", failed, p_stream->available());
|
||||
if (p_stream->available() == 0) p_stream->end();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// After we processed all data we close the stream to get a new url
|
||||
if (p_stream->totalRead() == p_stream->contentLength()) {
|
||||
p_stream->end();
|
||||
break;
|
||||
}
|
||||
LOGD("Refilled with %d now %d available to write", total,
|
||||
buffer.availableForWrite());
|
||||
}
|
||||
@ -244,7 +299,7 @@ class HLSParser {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!url_loader.begin()) {
|
||||
if (!p_url_loader->begin()) {
|
||||
TRACEE();
|
||||
return false;
|
||||
}
|
||||
@ -261,10 +316,10 @@ class HLSParser {
|
||||
TRACED();
|
||||
int result = 0;
|
||||
custom_log_level.set();
|
||||
#if USE_TASK
|
||||
#if !USE_TASK
|
||||
reloadSegments();
|
||||
#endif
|
||||
if (active) result = url_loader.available();
|
||||
if (active) result = p_url_loader->available();
|
||||
custom_log_level.reset();
|
||||
return result;
|
||||
}
|
||||
@ -273,10 +328,10 @@ class HLSParser {
|
||||
TRACED();
|
||||
size_t result = 0;
|
||||
custom_log_level.set();
|
||||
#if USE_TASK
|
||||
#if !USE_TASK
|
||||
reloadSegments();
|
||||
#endif
|
||||
if (active) result = url_loader.readBytes(buffer, len);
|
||||
if (active) result = p_url_loader->readBytes(buffer, len);
|
||||
custom_log_level.reset();
|
||||
return result;
|
||||
}
|
||||
@ -292,9 +347,9 @@ class HLSParser {
|
||||
const char *getCodec() { return codec.c_str(); }
|
||||
|
||||
/// Provides the content type of the audio data
|
||||
const char *contentType() { return url_loader.contentType(); }
|
||||
const char *contentType() { return p_url_loader->contentType(); }
|
||||
|
||||
int contentLength() { return url_loader.contentLength(); }
|
||||
int contentLength() { return p_url_loader->contentLength(); }
|
||||
|
||||
/// Closes the processing
|
||||
void end() {
|
||||
@ -305,18 +360,20 @@ class HLSParser {
|
||||
codec.clear();
|
||||
segments_url_str.clear();
|
||||
url_stream.end();
|
||||
url_loader.end();
|
||||
p_url_loader->end();
|
||||
url_history.clear();
|
||||
active = false;
|
||||
}
|
||||
|
||||
/// Defines the number of urls that are preloaded in the URLLoader
|
||||
/// Defines the number of urls that are preloaded in the URLLoaderHLS
|
||||
void setUrlCount(int count) { url_count = count; }
|
||||
|
||||
/// Defines the class specific custom log level
|
||||
void setLogLevel(AudioLogger::LogLevel level) { custom_log_level.set(level); }
|
||||
|
||||
void setBuffer(int size, int count) { url_loader.setBuffer(size, count); }
|
||||
void setBuffer(int size, int count) { p_url_loader->setBuffer(size, count); }
|
||||
|
||||
void setUrlLoader(URLLoaderHLSBase &loader) { p_url_loader = &loader; }
|
||||
|
||||
protected:
|
||||
CustomLogLevel custom_log_level;
|
||||
@ -329,7 +386,8 @@ class HLSParser {
|
||||
StrExt url_str;
|
||||
const char *index_url_str = nullptr;
|
||||
URLStream url_stream;
|
||||
URLLoader url_loader;
|
||||
URLLoaderHLS default_url_loader;
|
||||
URLLoaderHLSBase *p_url_loader = &default_url_loader;
|
||||
URLHistory url_history;
|
||||
#if USE_TASK
|
||||
Task segment_load_task{"Refill", 1024 * 5, 1, 1};
|
||||
@ -353,7 +411,7 @@ class HLSParser {
|
||||
// parse the index file and the segments
|
||||
bool parseIndex() {
|
||||
TRACED();
|
||||
url_stream.setTimeout(1000);
|
||||
url_stream.setTimeout(5000);
|
||||
// url_stream.setConnectionClose(true);
|
||||
|
||||
// we only update the content length
|
||||
@ -364,54 +422,7 @@ class HLSParser {
|
||||
return rc;
|
||||
}
|
||||
|
||||
// parse the segment url provided by the index
|
||||
bool parseSegments() {
|
||||
TRACED();
|
||||
if (parse_segments_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure that we load at relevant schedule
|
||||
if (millis() < next_sement_load_time && url_loader.urlCount() > 0) {
|
||||
return false;
|
||||
}
|
||||
parse_segments_active = true;
|
||||
|
||||
LOGI("Available urls: %d", url_loader.urlCount());
|
||||
|
||||
if (url_stream) url_stream.clear();
|
||||
LOGI("parsing %s", segments_url_str.c_str());
|
||||
|
||||
if (segments_url_str.isEmpty()) {
|
||||
TRACEE();
|
||||
parse_segments_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!url_stream.begin(segments_url_str.c_str())) {
|
||||
TRACEE();
|
||||
parse_segments_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
segment_count = 0;
|
||||
if (!parseSegmentLines()) {
|
||||
TRACEE();
|
||||
parse_segments_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
next_sement_load_time = millis() + (segment_count * tartget_duration_ms);
|
||||
// assert(segment_count > 0);
|
||||
|
||||
// we request a minimum of collected urls to play before we start
|
||||
if (url_history.size() > 8) active = true;
|
||||
parse_segments_active = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse the index file and the segments
|
||||
// parse the index file
|
||||
bool parseIndexLines() {
|
||||
TRACEI();
|
||||
char tmp[MAX_HLS_LINE];
|
||||
@ -441,7 +452,57 @@ class HLSParser {
|
||||
return result;
|
||||
}
|
||||
|
||||
// parse the index file and the segments
|
||||
|
||||
// parse the segment url provided by the index
|
||||
bool parseSegments() {
|
||||
TRACED();
|
||||
if (parse_segments_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure that we load at relevant schedule
|
||||
if (millis() < next_sement_load_time && p_url_loader->urlCount() > 1) {
|
||||
delay(1);
|
||||
return false;
|
||||
}
|
||||
parse_segments_active = true;
|
||||
|
||||
LOGI("Available urls: %d", p_url_loader->urlCount());
|
||||
|
||||
if (url_stream) url_stream.clear();
|
||||
LOGI("parsing %s", segments_url_str.c_str());
|
||||
|
||||
if (segments_url_str.isEmpty()) {
|
||||
TRACEE();
|
||||
parse_segments_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!url_stream.begin(segments_url_str.c_str())) {
|
||||
TRACEE();
|
||||
parse_segments_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
segment_count = 0;
|
||||
if (!parseSegmentLines()) {
|
||||
TRACEE();
|
||||
parse_segments_active = false;
|
||||
// do not display as erro
|
||||
return true;
|
||||
}
|
||||
|
||||
next_sement_load_time = millis() + (segment_count * tartget_duration_ms);
|
||||
// assert(segment_count > 0);
|
||||
|
||||
// we request a minimum of collected urls to play before we start
|
||||
if (url_history.size() > START_URLS_LIMIT) active = true;
|
||||
parse_segments_active = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse the segments
|
||||
bool parseSegmentLines() {
|
||||
TRACEI();
|
||||
char tmp[MAX_HLS_LINE];
|
||||
@ -509,9 +570,9 @@ class HLSParser {
|
||||
url_str.add("/");
|
||||
url_str.add(str.c_str());
|
||||
}
|
||||
url_loader.addUrl(url_str.c_str());
|
||||
p_url_loader->addUrl(url_str.c_str());
|
||||
} else {
|
||||
LOGD("Douplicate ignored: %s", str.c_str());
|
||||
LOGD("Duplicate ignored: %s", str.c_str());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -259,6 +259,11 @@ public:
|
||||
/// same as setOutput
|
||||
void setStream(Print &out) { p_out = &out; }
|
||||
|
||||
bool begin(AudioInfo info){
|
||||
setAudioInfo(info);
|
||||
return AudioStream::begin();
|
||||
}
|
||||
|
||||
void setAudioInfo(AudioInfo info) override {
|
||||
AudioStream::setAudioInfo(info);
|
||||
fade_last.setAudioInfo(info);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "AudioTools/AudioLogger.h"
|
||||
#include "AudioBasic/Collections/Allocator.h"
|
||||
|
||||
#if USE_TASK
|
||||
#ifdef ESP32
|
||||
# include <freertos/stream_buffer.h>
|
||||
# include "freertos/FreeRTOS.h"
|
||||
@ -195,4 +196,6 @@ class BufferRTOS : public BaseBuffer<T> {
|
||||
template <class T>
|
||||
using SynchronizedBufferRTOS = BufferRTOS<T>;
|
||||
|
||||
} // namespace audio_tools
|
||||
} // namespace audio_tools
|
||||
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
# include <mutex>
|
||||
#endif
|
||||
|
||||
#if USE_TASK
|
||||
#ifdef ESP32
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "freertos/semphr.h"
|
||||
@ -84,6 +85,7 @@ protected:
|
||||
SemaphoreHandle_t xSemaphore = NULL;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief RAII implementaion using a Mutex: Only a few microcontrollers provide
|
||||
* lock guards, so I decided to roll my own solution where we can just use a
|
||||
@ -114,4 +116,6 @@ protected:
|
||||
Mutex *p_mutex = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "AudioBasic/Collections/Allocator.h"
|
||||
#include "AudioConfig.h"
|
||||
|
||||
#if USE_TASK
|
||||
#ifdef ESP32
|
||||
# include <freertos/queue.h>
|
||||
# include "freertos/FreeRTOS.h"
|
||||
@ -109,4 +110,6 @@ class QueueRTOS {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace audio_tools
|
||||
} // namespace audio_tools
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "AudioTools/Buffers.h"
|
||||
#include "AudioTools/AudioLogger.h"
|
||||
|
||||
#if USE_TASK
|
||||
#ifdef ESP32
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "Concurrency/QueueRTOS.h"
|
||||
@ -205,3 +206,4 @@ protected:
|
||||
} // namespace audio_tools
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#if USE_TASK
|
||||
#ifdef ESP32
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "freertos/task.h"
|
||||
@ -64,4 +65,6 @@ class Task {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -26,7 +26,7 @@ if(NOT tsdemux_POPULATED)
|
||||
endif()
|
||||
|
||||
# Build with libhelix
|
||||
FetchContent_Declare(arduino_helix GIT_REPOSITORY "https://github.com/pschatzmann/arduino-libhelix.git" GIT_TAG main )
|
||||
FetchContent_Declare(arduino_helix GIT_REPOSITORY "https://github.com/pschatzmann/arduino-libhelix.git" GIT_TAG development )
|
||||
FetchContent_GetProperties(arduino_helix)
|
||||
if(NOT arduino_helix_POPULATED)
|
||||
FetchContent_Populate(arduino_helix)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "AudioTools.h"
|
||||
#include "AudioCodecs/CodecMTS.h"
|
||||
#include "AudioCodecs/CodecTSDemux.h"
|
||||
#include "AudioCodecs/CodecADTS.h"
|
||||
#include "AudioCodecs/CodecAACHelix.h"
|
||||
//#include "AudioLibs/PortAudioStream.h"
|
||||
@ -29,7 +29,7 @@ void setup(void) {
|
||||
//adts_stream.setLogLevel(AudioLogger::Debug);
|
||||
//mts_stream.setLogLevel(AudioLogger::Debug);
|
||||
|
||||
//aac.setAudioInfoNotifications(false);
|
||||
aac.setAudioInfoNotifications(false);
|
||||
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
cfg.copyFrom(info);
|
||||
|
55
tests-cmake/codec/hls1/CMakeLists.txt
Normal file
55
tests-cmake/codec/hls1/CMakeLists.txt
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# set the project name
|
||||
project(hls)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
set (DCMAKE_CXX_FLAGS "-Werror")
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Activate Emulator and Portaudio
|
||||
set(ADD_ARDUINO_EMULATOR ON CACHE BOOL "Add Arduino Emulator Library")
|
||||
set(ADD_PORTAUDIO OFF CACHE BOOL "Add Portaudio Library")
|
||||
|
||||
# Build with arduino-audio-tools
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../.. ${CMAKE_CURRENT_BINARY_DIR}/arduino-audio-tools )
|
||||
endif()
|
||||
|
||||
# Build with tms
|
||||
FetchContent_Declare(tsdemux GIT_REPOSITORY "https://github.com/pschatzmann/arduino-tsdemux" )
|
||||
FetchContent_GetProperties(tsdemux)
|
||||
if(NOT tsdemux_POPULATED)
|
||||
FetchContent_Populate(tsdemux)
|
||||
add_subdirectory(${tsdemux_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Build with libhelix
|
||||
FetchContent_Declare(arduino_helix GIT_REPOSITORY "https://github.com/pschatzmann/arduino-libhelix.git" GIT_TAG main )
|
||||
FetchContent_GetProperties(arduino_helix)
|
||||
if(NOT arduino_helix_POPULATED)
|
||||
FetchContent_Populate(arduino_helix)
|
||||
add_subdirectory(${arduino_helix_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# Download miniaudio.h
|
||||
file(DOWNLOAD https://raw.githubusercontent.com/mackron/miniaudio/master/miniaudio.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/miniaudio.h)
|
||||
|
||||
# build sketch as executable
|
||||
set_source_files_properties(hls.ino PROPERTIES LANGUAGE CXX)
|
||||
add_executable (hls hls.cpp ../../main.cpp )
|
||||
|
||||
# set preprocessor defines
|
||||
target_compile_definitions(hls PUBLIC -DARDUINO -DIS_DESKTOP -DEXIT_ON_STOP -DHELIX_PRINT)
|
||||
|
||||
# access to miniaudio in sketch directory
|
||||
target_include_directories(hls PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# specify libraries
|
||||
target_link_libraries(hls arduino-audio-tools arduino_emulator tsdemux arduino_helix)
|
||||
|
||||
|
||||
|
||||
|
50
tests-cmake/codec/hls1/hls.cpp
Normal file
50
tests-cmake/codec/hls1/hls.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "AudioTools.h"
|
||||
#include "AudioCodecs/CodecMTS.h"
|
||||
#include "AudioCodecs/CodecADTS.h"
|
||||
#include "AudioCodecs/CodecAACHelix.h"
|
||||
//#include "AudioLibs/PortAudioStream.h"
|
||||
#include "AudioLibs/MiniAudioStream.h"
|
||||
#include "AudioLibs/HLSStream.h"
|
||||
|
||||
AudioInfo info(48000,2,16);
|
||||
HLSStream hls_stream("NA", "NA");
|
||||
// HexDumpOutput hex(Serial);
|
||||
// NullStream null;
|
||||
//CsvOutput<int16_t> out(Serial, 2); // Or use StdOuput
|
||||
//PortAudioStream out;
|
||||
MiniAudioStream out;
|
||||
AACDecoderHelix aac;
|
||||
CodecMTS mts{aac};
|
||||
// ADTSDecoder adts;
|
||||
// AACDecoderHelix aac;
|
||||
// EncodedAudioStream aac_stream(&out, &aac);
|
||||
// EncodedAudioStream adts_stream(&aac_stream, &adts);
|
||||
EncodedAudioStream mts_stream(&out, &mts);
|
||||
StreamCopy copier(mts_stream, hls_stream);
|
||||
|
||||
// Arduino Setup
|
||||
void setup(void) {
|
||||
//Serial.begin(115200);
|
||||
AudioLogger::instance().begin(Serial, AudioLogger::Info);
|
||||
//hls_stream.setLogLevel(AudioLogger::Debug); // hls_stream is quite chatty at Info
|
||||
//adts_stream.setLogLevel(AudioLogger::Debug);
|
||||
//mts_stream.setLogLevel(AudioLogger::Debug);
|
||||
|
||||
//aac.setAudioInfoNotifications(false);
|
||||
|
||||
auto cfg = out.defaultConfig(TX_MODE);
|
||||
cfg.copyFrom(info);
|
||||
out.begin();
|
||||
|
||||
mts_stream.begin();
|
||||
// aac_stream.begin();
|
||||
// adts_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");
|
||||
Serial.println("playing...");
|
||||
}
|
||||
|
||||
// Arduino loop
|
||||
void loop() {
|
||||
copier.copy();
|
||||
}
|
Loading…
Reference in New Issue
Block a user