arduino-audio-tools
Loading...
Searching...
No Matches
AudioSync.h
1
2#pragma once
3#include "AudioTools/CoreAudio/AudioStreams.h"
4#include "AudioTools/CoreAudio/AudioOutput.h"
5#include "AudioTools/CoreAudio/Buffers.h"
6#include "AudioTools/AudioCodecs/AudioEncoded.h"
7
8
9namespace audio_tools {
10
11
12enum class RecordType : uint8_t { Undefined, Begin, Send, Receive, End };
13enum class AudioType : uint8_t { PCM, MP3, AAC, WAV, ADPC };
14enum class TransmitRole : uint8_t { Sender, Receiver };
15
18 AudioHeader() = default;
19 uint8_t app = 123;
20 RecordType rec = RecordType::Undefined;
21 uint16_t seq = 0;
22 // record counter
23 void increment() {
24 static uint16_t static_count = 0;
25 seq = static_count++;
26 }
27};
28
30struct AudioDataBegin : public AudioHeader {
31 AudioDataBegin() { rec = RecordType::Begin; }
32 AudioInfo info;
33 AudioType type = AudioType::PCM;
34};
35
37struct AudioSendData : public AudioHeader {
39 rec = RecordType::Send;
40 }
41 uint16_t size = 0;
42};
43
46 AudioConfirmDataToReceive() { rec = RecordType::Receive; }
47 uint16_t size = 0;
48};
49
51struct AudioDataEnd : public AudioHeader {
52 AudioDataEnd() { rec = RecordType::End; }
53};
54
55
63 public:
64 AudioSyncWriter(Stream &dest) { p_dest = &dest; }
65
66 bool begin(AudioInfo &info, AudioType type) {
67 is_sync = true;
68 AudioDataBegin begin;
69 begin.info = info;
70 begin.type = type;
71 begin.increment();
72 int write_len = sizeof(begin);
73 int len = p_dest->write((const uint8_t *)&begin, write_len);
74 return len == write_len;
75 }
76
77 size_t write(const uint8_t *data, size_t len) override {
78 int written_len = 0;
79 int open_len = len;
80 AudioSendData send;
81 while (written_len < len) {
82 int available_to_write = waitForRequest();
83 size_t to_write_len = DEFAULT_BUFFER_SIZE;
84 to_write_len = min(open_len, available_to_write);
85 send.increment();
86 send.size = to_write_len;
87 p_dest->write((const uint8_t *)&send, sizeof(send));
88 int w = p_dest->write(data + written_len, to_write_len);
89 written_len += w;
90 open_len -= w;
91 }
92 return written_len;
93 }
94
95 int availableForWrite() override { return available_to_write; }
96
97 void end() {
98 AudioDataEnd end;
99 end.increment();
100 p_dest->write((const uint8_t *)&end, sizeof(end));
101 }
102
103 protected:
104 Stream *p_dest;
105 int available_to_write = 1024;
106 bool is_sync;
107
109 void waitFor(int size) {
110 while (p_dest->available() < size) {
111 delay(10);
112 }
113 }
114
115 int waitForRequest() {
117 size_t rcv_len = sizeof(rcv);
119 p_dest->readBytes((uint8_t *)&rcv, rcv_len);
120 return rcv.size;
121 }
122};
123
133 public:
135 bool isConfirmer = true) {
136 p_in = &in;
137 p_out = &out;
138 is_confirmer = isConfirmer;
139 }
140
141 size_t copy() {
142 int processed = 0;
143 int header_size = sizeof(header);
144 waitFor(header_size);
145 readBytes((uint8_t *)&header, header_size);
146
147 switch (header.rec) {
148 case RecordType::Begin:
150 break;
151 case RecordType::End:
152 audioDataEnd();
153 break;
154 case RecordType::Send:
155 processed = receiveData();
156 break;
157 }
158 return processed;
159 }
160
161 protected:
162 Stream *p_in;
163 EncodedAudioStream *p_out;
165 AudioHeader header;
166 AudioDataBegin begin;
167 size_t available = 0; // initial value
168 bool is_started = false;
169 bool is_confirmer;
170 int last_seq = 0;
171
174 readProtocol(&begin, sizeof(begin));
175 p_out->begin();
176 p_out->setAudioInfo(begin.info);
177 requestData();
178 }
179
182 AudioDataEnd end;
183 readProtocol(&end, sizeof(end));
184 p_out->end();
185 }
186
187 // Receives audio data
188 int receiveData() {
189 AudioSendData data;
190 readProtocol(&data, sizeof(data));
191 available = data.size;
192 // receive and process audio data
193 waitFor(available);
194 int max_gap = 10;
195 if (data.seq > last_seq ||
196 (data.seq < max_gap && last_seq >= (32767 - max_gap))) {
197 uint8_t buffer[available];
198 p_in->readBytes((uint8_t *)buffer, available);
199 p_out->write((const uint8_t *)buffer, available);
200 // only one reader should be used as confirmer
201 if (is_confirmer) {
202 requestData();
203 }
204 last_seq = data.seq;
205 }
206 return available;
207 }
208
210 void waitFor(int size) {
211 while (p_in->available() < size) {
212 delay(10);
213 }
214 }
215
217 void requestData() {
218 req.size = p_out->availableForWrite();
219 req.increment();
220 p_in->write((const uint8_t *)&req, sizeof(req));
221 p_in->flush();
222 }
223
225 void readProtocol(AudioHeader *data, int len) {
226 static const int header_size = sizeof(header);
227 memcpy(data, &header, header_size);
228 int read_size = len - header_size;
229 waitFor(read_size);
230 readBytes((uint8_t *)data + header_size, read_size);
231 }
232};
233
234} // namespace audio_tools
Abstract Audio Ouptut class.
Definition AudioOutput.h:22
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:115
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:123
Receving Audio Data over the wire and requesting for more data when done to synchronize the processin...
Definition AudioSync.h:132
void audioDataEnd()
Ends the processing.
Definition AudioSync.h:181
void audioDataBegin()
Starts the processing.
Definition AudioSync.h:173
void waitFor(int size)
Waits for the data to be available.
Definition AudioSync.h:210
void readProtocol(AudioHeader *data, int len)
Reads the protocol record.
Definition AudioSync.h:225
void requestData()
Request new data from writer.
Definition AudioSync.h:217
Audio Writer which is synchronizing the amount of data that can be processed with the AudioReceiver.
Definition AudioSync.h:62
void waitFor(int size)
Waits for the data to be available.
Definition AudioSync.h:109
A more natural Stream class to process encoded data (aac, wav, mp3...) which also supports the decodi...
Definition AudioEncoded.h:255
Definition NoArduino.h:142
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioConfig.h:885
Protocol Record for Request.
Definition AudioSync.h:45
Protocal Record To Start.
Definition AudioSync.h:30
Protocol Record for End.
Definition AudioSync.h:51
Common Header for all records.
Definition AudioSync.h:17
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:52
Protocol Record for Data.
Definition AudioSync.h:37