Skip to content

Commit 7ad0a41

Browse files
committed
AudioServerEx DRAFT
1 parent cf71463 commit 7ad0a41

File tree

9 files changed

+226
-13
lines changed

9 files changed

+226
-13
lines changed

examples/examples-webserver/streams-effect-webserver_wav/streams-effect-webserver_wav.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ void setup() {
5555

5656
// copy the data
5757
void loop() {
58-
server.doLoop();
58+
server.copy();
5959
}

examples/examples-webserver/streams-flite-webserver_wav/streams-flite-webserver_wav.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ void setup(){
3232
// Arduino loop
3333
void loop() {
3434
// Handle new connections
35-
server.doLoop();
35+
server.copy();
3636
}

examples/examples-webserver/streams-generator-webserver_wav/streams-generator-webserver_wav.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ void setup() {
3939

4040
// copy the data
4141
void loop() {
42-
server.doLoop();
42+
server.copy();
4343
}

examples/examples-webserver/streams-i2s-webserver_wav/streams-i2s-webserver_wav.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ void setup(){
3636
// Arduino loop
3737
void loop() {
3838
// Handle new connections
39-
server.doLoop();
39+
server.copy();
4040
}

examples/examples-webserver/streams-sam-webserver_wav/streams-sam-webserver_wav.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ void setup(){
2828
// Arduino loop
2929
void loop() {
3030
// Handle new connections
31-
server.doLoop();
31+
server.copy();
3232
}

examples/examples-webserver/streams-tts-webserver_wav/streams-tts-webserver_wav.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ void setup(){
2929
// Arduino loop
3030
void loop() {
3131
// Handle new connections
32-
server.doLoop();
32+
server.copy();
3333
}

src/AudioCodecs/CodecWAV.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -478,9 +478,7 @@ class WAVEncoder : public AudioEncoder {
478478
}
479479
if (!header_written){
480480
LOGI("Writing Header");
481-
writeRiffHeader();
482-
writeFMT();
483-
writeDataHeader();
481+
writeHeader(stream_ptr);
484482
header_written = true;
485483
}
486484

@@ -514,6 +512,12 @@ class WAVEncoder : public AudioEncoder {
514512
this->offset = offset;
515513
}
516514

515+
void writeHeader(Print *out) {
516+
writeRiffHeader(out);
517+
writeFMT(out);
518+
writeDataHeader(out);
519+
}
520+
517521
protected:
518522
Print* stream_ptr;
519523
WAVAudioInfo audioInfo = defaultConfig();
@@ -522,13 +526,14 @@ class WAVEncoder : public AudioEncoder {
522526
volatile bool is_open;
523527
uint32_t offset=0; //adds n empty bytes at the beginning of the data
524528

525-
void writeRiffHeader(){
529+
530+
void writeRiffHeader(Print *stream_ptr){
526531
stream_ptr->write("RIFF",4);
527532
write32(*stream_ptr, audioInfo.file_size-8);
528533
stream_ptr->write("WAVE",4);
529534
}
530535

531-
void writeFMT(){
536+
void writeFMT(Print *stream_ptr){
532537
uint16_t fmt_len = 16;
533538
uint32_t byteRate = audioInfo.sample_rate * audioInfo.bits_per_sample * audioInfo.channels / 8;
534539
uint32_t frame_size = audioInfo.channels * audioInfo.bits_per_sample / 8;
@@ -550,7 +555,7 @@ class WAVEncoder : public AudioEncoder {
550555
stream.write((uint8_t *) &value, 2);
551556
}
552557

553-
void writeDataHeader() {
558+
void writeDataHeader(Print *stream_ptr) {
554559
stream_ptr->write("data",4);
555560
audioInfo.file_size -=44;
556561
write32(*stream_ptr, audioInfo.file_size);
@@ -559,7 +564,6 @@ class WAVEncoder : public AudioEncoder {
559564
memset(empty,0, offset);
560565
stream_ptr->write(empty,offset); // resolve issue with wrong aligment
561566
}
562-
563567
}
564568

565569
};

src/AudioLibs/AudioServerEx.h

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#pragma once
2+
3+
#include "AudioConfig.h"
4+
#include "AudioTools/AudioOutput.h"
5+
#include "AudioCodecs/CodecWAV.h"
6+
#include "HttpServer.h"
7+
#include "HttpExtensions.h"
8+
9+
namespace audio_tools {
10+
11+
/**
12+
* @brief Config information for AudioServerEx
13+
* @author Phil Schatzmann
14+
* @copyright GPLv3
15+
*/
16+
17+
struct AudioServerExConfig : public AudioBaseInfo {
18+
const char* mime = nullptr;
19+
const char* ssid = nullptr;
20+
const char* password = nullptr;
21+
const char* path = "/";
22+
// optional input; if not used use write methods to push data
23+
Stream *input=nullptr;
24+
int port = 80;
25+
};
26+
27+
/**
28+
* @brief A powerfull Web server which is based on
29+
* https://github.com/pschatzmann/TinyHttp.
30+
* It supports multiple concurrent clients. You can e.g. use it to write mp3 data and make
31+
* it available in multiple clients.
32+
* @author Phil Schatzmann
33+
* @copyright GPLv3
34+
*/
35+
36+
class AudioServerEx : public AudioPrint {
37+
public:
38+
// Default Constructor
39+
AudioServerEx() = default;
40+
41+
/// To be compatible with legacy API
42+
AudioServerEx(const char *ssid, const char* pwd){
43+
info.ssid = ssid;
44+
info.password = pwd;
45+
}
46+
47+
AudioServerExConfig defaultConfig() {
48+
AudioServerExConfig cfg;
49+
return cfg;
50+
}
51+
52+
bool begin(AudioServerExConfig cfg) {
53+
info = cfg;
54+
return begin();
55+
}
56+
57+
bool begin(Stream &in, const char* contentType) {
58+
info.input = ∈
59+
info.mime = contentType;
60+
return begin();
61+
}
62+
63+
bool begin() {
64+
end(); // we (re) start with a clean state
65+
if (info.input==nullptr){
66+
p_stream = new ExtensionStream(info.path,tinyhttp::GET, info.mime );
67+
} else {
68+
p_stream = new ExtensionStream(info.path, info.mime, *info.input);
69+
}
70+
p_stream->setReplyHeader(*getReplyHeader());
71+
p_server = new HttpServer(wifi);
72+
p_server->addExtension(*p_stream);
73+
return p_server->begin(info.port, info.ssid, info.password);
74+
}
75+
76+
void end() {
77+
if (p_stream!=nullptr) {
78+
delete p_stream;
79+
p_stream = nullptr;
80+
}
81+
if (p_server!=nullptr) {
82+
delete p_server;
83+
p_server = nullptr;
84+
}
85+
}
86+
87+
/// Web server supports write so that we can e.g. use is as destination for the audio player.
88+
size_t write(const uint8_t* data, size_t len) override {
89+
if (p_stream==nullptr) return 0;
90+
return p_stream->write((uint8_t*)data, len);
91+
}
92+
93+
int availableForWrite() override {
94+
if (p_stream==nullptr) return 0;
95+
return p_stream->availableForWrite();
96+
}
97+
98+
/// Needs to be called if the data was provided as input Stream in the AudioServerExConfig
99+
void copy() {
100+
if (p_server!=nullptr){
101+
p_server->copy();
102+
}
103+
}
104+
105+
protected:
106+
AudioServerExConfig info;
107+
WiFiServer wifi;
108+
HttpServer *p_server;
109+
ExtensionStream *p_stream=nullptr;
110+
111+
virtual tinyhttp::Str* getReplyHeader() {
112+
return nullptr;
113+
}
114+
115+
};
116+
117+
/**
118+
* @brief A powerfull WAV Web server which is based on
119+
* https://github.com/pschatzmann/TinyHttp.
120+
* It supports multiple concurrent clients
121+
* @author Phil Schatzmann
122+
* @copyright GPLv3
123+
*
124+
*/
125+
class AudioWAVServerEx : public AudioServerEx {
126+
public:
127+
// Default Constructor
128+
AudioWAVServerEx() = default;
129+
130+
/// To be compatible with legacy API
131+
AudioWAVServerEx(const char *ssid, const char* pwd):AudioServerEx(ssid, pwd){}
132+
133+
/// Legacy API support
134+
bool begin(Stream &in, int sample_rate, int channels, int bits_per_sample=16) {
135+
info.input = ∈
136+
info.sample_rate = sample_rate;
137+
info.channels = channels;
138+
info. bits_per_sample = bits_per_sample;
139+
info.mime = "audio/wav";
140+
return AudioServerEx::begin();
141+
}
142+
143+
AudioServerExConfig defaultConfig() {
144+
AudioServerExConfig cfg;
145+
cfg.mime = "audio/wav";
146+
return cfg;
147+
}
148+
149+
protected:
150+
// wav files start with a 44 bytes header
151+
virtual tinyhttp::Str* getReplyHeader() {
152+
MemoryPrint mp{(uint8_t*)header.c_str(), header.length()};
153+
WAVEncoder enc;
154+
WAVAudioInfo wi;
155+
wi.sample_rate = info.sample_rate;
156+
wi.bits_per_sample = info.bits_per_sample;
157+
wi.channels = info.channels;
158+
enc.setAudioInfo(wi);
159+
// fill header with data
160+
enc.writeHeader(&mp);
161+
162+
return &header;
163+
}
164+
165+
// Allocate memory for 44 bytes header
166+
tinyhttp::StrExt header{44};
167+
168+
};
169+
170+
}

src/AudioTools/AudioOutput.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class AudioPrint : public Print, public AudioBaseInfoDependent, public AudioBase
2828
return 1;
2929
}
3030

31+
virtual int availableForWrtie() {
32+
return 0;
33+
}
34+
3135
void flush() FLUSH_OVERRIDE {
3236
write((const uint8_t*)tmp, tmpPos-1);
3337
tmpPos=0;
@@ -659,5 +663,40 @@ class VolumePrint : public AudioPrint {
659663
}
660664
};
661665

666+
/**
667+
* @brief Prints to a preallocated memory
668+
*/
669+
class MemoryPrint : public AudioPrint {
670+
public:
671+
MemoryPrint(uint8_t*start, int len){
672+
p_start = start;
673+
p_next = start;
674+
size = len;
675+
}
676+
677+
size_t write(const uint8_t *buffer, size_t len) override {
678+
if (pos+len<=size){
679+
memcpy(p_next, buffer,len);
680+
pos+=len;
681+
p_next+=len;
682+
return len;
683+
} else {
684+
LOGE("Buffer too small");
685+
return 0;
686+
}
687+
}
688+
689+
int availableForWrite() {
690+
return size-pos;
691+
}
692+
693+
protected:
694+
int pos;
695+
uint8_t* p_start;
696+
uint8_t *p_next;
697+
size_t size;
698+
699+
};
700+
662701

663702
} //n namespace

0 commit comments

Comments
 (0)