arduino-audio-tools
AudioEncoded.h
1 #pragma once
2 
3 #include "AudioConfig.h"
4 #include "AudioTools/AudioIO.h"
5 #include "AudioTools/AudioOutput.h"
6 #include "AudioTools/AudioStreams.h"
7 #include "AudioTools/AudioTypes.h"
8 
9 namespace audio_tools {
10 
17 class AudioDecoder : public AudioWriter, public AudioInfoSource {
18  public:
19  AudioDecoder() = default;
20  virtual ~AudioDecoder() = default;
21  AudioDecoder(AudioDecoder const &) = delete;
22  AudioDecoder &operator=(AudioDecoder const &) = delete;
23 
24  virtual AudioInfo audioInfo() { return info; };
25 
27  virtual void setAudioInfo(AudioInfo from) override {
28  TRACED();
29  if (info != from) {
30  if (p_notify != nullptr) {
31  p_notify->setAudioInfo(from);
32  }
33  }
34  info = from;
35  }
37  virtual void setOutput(AudioStream &out_stream) {
38  Print *p_print = &out_stream;
39  setOutput(*p_print);
40  setNotifyAudioChange(out_stream);
41  }
42 
44  virtual void setOutput(AudioOutput &out_stream) {
45  Print *p_print = &out_stream;
46  setOutput(*p_print);
47  setNotifyAudioChange(out_stream);
48  }
49 
51  virtual void setOutput(Print &out_stream) override {
52  p_print = &out_stream;
53  }
55  virtual bool isResultPCM() { return true; }
56 
58  void setNotifyAudioChange(AudioInfoSupport &notify) override {
59  p_notify = &notify;
60  }
61 
62  protected:
63  Print *p_print = nullptr;
64  AudioInfo info;
65  AudioInfoSupport *p_notify = nullptr;
66 };
67 
74 class AudioEncoder : public AudioWriter {
75  public:
76  AudioEncoder() = default;
77  virtual ~AudioEncoder() = default;
78  AudioEncoder(AudioEncoder const &) = delete;
79  AudioEncoder &operator=(AudioEncoder const &) = delete;
81  virtual const char *mime() = 0;
83  void setAudioInfo(AudioInfo from) override{};
84 };
85 
86 class AudioDecoderExt : public AudioDecoder {
87  public:
88  virtual void setBlockSize(int blockSize) = 0;
89 };
90 
91 class AudioEncoderExt : public AudioEncoder {
92  public:
93  virtual int blockSize() =0;
94 };
95 
96 
105 class CodecNOP : public AudioDecoder, public AudioEncoder {
106  public:
107  static CodecNOP *instance() {
108  static CodecNOP self;
109  return &self;
110  }
111 
112  virtual void begin() {}
113  virtual void end() {}
114  virtual void setOutput(Print &out_stream) {}
116  virtual void setAudioInfo(AudioInfo info) {}
117 
118  virtual AudioInfo audioInfo() {
119  AudioInfo info;
120  return info;
121  }
122  virtual operator bool() { return false; }
123  virtual int readStream(Stream &in) { return 0; };
124 
125  // just output silence
126  virtual size_t write(const void *in_ptr, size_t in_size) {
127  memset((void *)in_ptr, 0, in_size);
128  return in_size;
129  }
130 
131  virtual const char *mime() { return nullptr; }
132 };
133 
142  public:
144  virtual void begin() = 0;
145 
147  virtual void end() = 0;
148 
150  virtual void setOutput(Print &outStream) = 0;
151 
153  virtual void setNotifyAudioChange(AudioInfoSupport &bi) = 0;
154 
156  virtual void setOutput(AudioStream &out_stream) {
157  Print *p_print = &out_stream;
158  setOutput(*p_print);
159  setNotifyAudioChange(out_stream);
160  }
161 
163  virtual void setOutput(AudioOutput &out_stream) {
164  Print *p_print = &out_stream;
165  setOutput(*p_print);
166  setNotifyAudioChange(out_stream);
167  }
168 
170  virtual void setInputStream(Stream &inStream) = 0;
171 
173  virtual AudioInfo audioInfo() = 0;
174 
176  virtual operator bool() = 0;
177 
179  virtual bool copy() = 0;
180 
181  protected:
182  virtual size_t readBytes(uint8_t *buffer, size_t len) = 0;
183 };
184 
194  public:
195 
197  TRACED();
198  active = false;
199  }
200 
202  TRACED();
203  decoder_ptr = decoder;
204  writer_ptr = decoder_ptr;
205  active = false;
206  }
207 
209  TRACED();
210  ptr_out = outputStream;
211  decoder_ptr = decoder;
212  decoder_ptr->setOutput(*outputStream);
213  decoder_ptr->setNotifyAudioChange(*outputStream);
214  writer_ptr = decoder_ptr;
215  active = false;
216  }
217 
219  TRACED();
220  ptr_out = outputStream;
221  decoder_ptr = decoder;
222  decoder_ptr->setOutput(*outputStream);
223  decoder_ptr->setNotifyAudioChange(*outputStream);
224  writer_ptr = decoder_ptr;
225  active = false;
226  }
227 
228  EncodedAudioOutput(Print *outputStream, AudioDecoder *decoder) {
229  TRACED();
230  ptr_out = outputStream;
231  decoder_ptr = decoder;
232  decoder_ptr->setOutput(*outputStream);
233  writer_ptr = decoder_ptr;
234  active = false;
235  }
236 
237  EncodedAudioOutput(Print *outputStream, AudioEncoder *encoder) {
238  TRACED();
239  ptr_out = outputStream;
240  encoder_ptr = encoder;
241  encoder_ptr->setOutput(*outputStream);
242  writer_ptr = encoder_ptr;
243  active = false;
244  }
245 
247  TRACED();
248  ptr_out = outputStream;
249  encoder_ptr = encoder;
250  encoder_ptr->setOutput(*outputStream);
251  decoder_ptr->setNotifyAudioChange(*outputStream);
252  writer_ptr = encoder_ptr;
253  active = false;
254  }
255 
257  TRACED();
258  ptr_out = outputStream;
259  encoder_ptr = encoder;
260  encoder_ptr->setOutput(*outputStream);
261  decoder_ptr->setNotifyAudioChange(*outputStream);
262  writer_ptr = encoder_ptr;
263  active = false;
264  }
265 
266 
269  TRACEI();
270  decoder_ptr->setNotifyAudioChange(bi);
271  }
272 
273  AudioInfo defaultConfig() {
274  AudioInfo cfg;
275  cfg.channels = 2;
276  cfg.sample_rate = 44100;
277  cfg.bits_per_sample = 16;
278  return cfg;
279  }
280 
281  virtual void setAudioInfo(AudioInfo info) override {
282  TRACED();
283  if (this->info != info && info.channels!=0 && info.sample_rate!=0) {
284  this->info = info;
285  AudioStream::setAudioInfo(info);
286  decoder_ptr->setAudioInfo(info);
287  encoder_ptr->setAudioInfo(info);
288  }
289  }
290 
292  void setOutput(Print *outputStream) {
293  ptr_out = outputStream;
294  if (decoder_ptr != nullptr) {
295  decoder_ptr->setOutput(*ptr_out);
296  }
297  if (encoder_ptr != nullptr) {
298  encoder_ptr->setOutput(*ptr_out);
299  }
300  }
301 
303  void setStream(Print *outputStream) { setOutput(outputStream); }
304 
305  void setEncoder(AudioEncoder *encoder) {
306  if (encoder == nullptr) {
307  encoder = CodecNOP::instance();
308  }
309  encoder_ptr = encoder;
310  writer_ptr = encoder;
311  if (ptr_out != nullptr) {
312  encoder_ptr->setOutput(*ptr_out);
313  }
314  }
315 
316  void setDecoder(AudioDecoder *decoder) {
317  if (decoder == nullptr) {
318  decoder = CodecNOP::instance();
319  }
320  decoder_ptr = decoder;
321  writer_ptr = decoder;
322  if (ptr_out != nullptr) {
323  decoder_ptr->setOutput(*ptr_out);
324  }
325  }
326 
328  bool begin() override {
329  custom_log_level.set();
330  TRACED();
331  if (!active) {
332  TRACED();
333  const CodecNOP *nop = CodecNOP::instance();
334  if (decoder_ptr != nop || encoder_ptr != nop) {
335  active = true;
336  decoder_ptr->begin();
337  encoder_ptr->begin();
338  } else {
339  LOGW("no decoder or encoder defined");
340  }
341  }
342  custom_log_level.reset();
343  return active;
344  }
345 
347  virtual bool begin(AudioInfo cfg) {
348  info = cfg;
349  return begin();
350  }
351 
353  void end() override {
354  custom_log_level.set();
355  TRACEI();
356  decoder_ptr->end();
357  encoder_ptr->end();
358  active = false;
359  custom_log_level.reset();
360  }
361 
363  virtual size_t write(const uint8_t *data, size_t len) override {
364  custom_log_level.set();
365  LOGD("EncodedAudioOutput::write: %d", (int)len);
366  if (len == 0) {
367  LOGI("write: %d", 0);
368  return 0;
369  }
370 
371  if (writer_ptr == nullptr || data == nullptr) {
372  LOGE("NPE");
373  return 0;
374  }
375 
376  size_t result = writer_ptr->write(data, len);
377  LOGD("EncodedAudioOutput::write: %d -> %d", (int)len, (int)result);
378  custom_log_level.reset();
379 
380  return result;
381  }
382 
383  int availableForWrite() override { return min(ptr_out->availableForWrite(), DEFAULT_BUFFER_SIZE); }
384 
386  operator bool() { return active; }
387 
389  AudioDecoder &decoder() { return *decoder_ptr; }
390 
392  AudioEncoder &encoder() { return *encoder_ptr; }
393 
395  void setLogLevel(AudioLogger::LogLevel level){
396  custom_log_level.set(level);
397  }
398 
399  protected:
400  AudioInfo info;
401  AudioDecoder *decoder_ptr = CodecNOP::instance(); // decoder
402  AudioEncoder *encoder_ptr = CodecNOP::instance(); // decoder
403  AudioWriter *writer_ptr = nullptr;
404  Print *ptr_out = nullptr;
405  bool active;
406  CustomLogLevel custom_log_level;
407 };
408 
409 // legacy name
410 using EncodedAudioPrint = EncodedAudioOutput;
411 
420  public:
421 
423 
425  : EncodedAudioOutput(ioStream, decoder) {
426  // the indicated stream can be used as input
427  setStream(ioStream);
428  }
429 
431  : EncodedAudioOutput((Print *)ioStream, decoder) {
432  // the indicated stream can be used as input
433  setStream(ioStream);
434  }
435 
437  decoder_ptr = decoder;
438  writer_ptr = decoder_ptr;
439  active = false;
440  }
441 
443  : EncodedAudioOutput(outputStream, decoder) {}
444 
446  : EncodedAudioOutput(outputStream, decoder) {}
447 
448 
450  : EncodedAudioOutput(outputStream, encoder) {}
451 
452 
454  void setInput(Stream *ioStream) { setStream(ioStream); }
455 
457  void setStream(Stream *ioStream) {
458  TRACED();
460  p_stream = ioStream;
461  }
462 
463  void setEncoder(AudioEncoder *encoder) {
464  EncodedAudioOutput::setEncoder(encoder);
465  is_setup = false;
466  }
467 
468  void setDecoder(AudioDecoder *decoder) {
469  EncodedAudioOutput::setDecoder(decoder);
470  is_setup = false;
471  }
472 
474  void resize(int size) { decoded_buffer.resize(size); }
475 
477  void resize() { resize(1024 * 10); }
478 
479  int available() override {
480  if (p_stream == nullptr) return 0;
481  decode(reqested_bytes);
482  return decoded_buffer.available();
483  }
484 
485  size_t readBytes(uint8_t *buffer, size_t length) override {
486  custom_log_level.set();
487  LOGD("EncodedAudioStream::readBytes: %d", (int)length);
488  if (p_stream == nullptr) {
489  TRACEE();
490  return 0;
491  }
492  decode(reqested_bytes);
493  size_t result = decoded_buffer.readArray(buffer, length);
494  custom_log_level.reset();
495  return result;
496  }
497 
498  protected:
499  RingBuffer<uint8_t> decoded_buffer{0};
500  QueueStream<uint8_t> queue_stream{decoded_buffer};
501  Vector<uint8_t> copy_buffer{DEFAULT_BUFFER_SIZE};
502  Stream *p_stream = nullptr;
503  AudioWriter *p_write = nullptr;
504  int reqested_bytes = DEFAULT_BUFFER_SIZE;
505  bool is_setup = false;
506  int max_read_count = 5;
507 
508  // Fill the decoded_buffer so that we have data for readBytes call
509  void decode(int requestedBytes) {
510  TRACED();
511  // setup buffer once
512  setupOnce();
513 
514  // fill decoded_buffer if we do not have enough data
515  if (p_stream->available() > 0 &&
516  decoded_buffer.available() < reqested_bytes) {
517  for (int j = 0; j < max_read_count; j++) {
518  int bytes_read =
519  p_stream->readBytes(copy_buffer.data(), DEFAULT_BUFFER_SIZE);
520  LOGD("bytes_read: %d", bytes_read);
521  int result = writer_ptr->write(copy_buffer.data(), bytes_read);
522  if (p_stream->available() == 0 ||
523  decoded_buffer.available() >= reqested_bytes) {
524  break;
525  }
526  }
527  }
528  LOGD("available decoded data %d", decoded_buffer.available());
529  }
530 
531  void setupOnce() {
532  if (!is_setup) {
533  is_setup = true;
534  LOGI("Setup reading support");
535  resize();
536  // make sure the result goes to out_stream
537  writer_ptr->setOutput(queue_stream);
538  queue_stream.begin();
539  }
540  }
541 };
542 
551  public:
552  void setWriter(AudioWriter *writer) { p_writer = writer; }
553  size_t write(const uint8_t *in_ptr, size_t in_size) {
554  return p_writer->write(in_ptr, in_size);
555  };
556 
557  protected:
558  AudioWriter *p_writer = nullptr;
559 };
560 
569  public:
570  virtual bool begin() = 0;
571  virtual void end() = 0;
572  virtual void setAudioInfo(AudioInfo info) {
573  if (this->info != info && info.channels!=0 && info.sample_rate!=0) {
574  this->info = info;
575  if (p_writer1 != nullptr) p_writer1->setAudioInfo(info);
576  if (p_writer2 != nullptr) p_writer2->setAudioInfo(info);
577  }
578  }
579  virtual size_t write(uint8_t *data, size_t size) = 0;
580 
581  protected:
582  AudioInfo info;
583  AudioWriter *p_writer1 = nullptr;
584  AudioWriter *p_writer2 = nullptr;
586  bool active = false;
587 };
588 
590  public:
591  void setupOutput(AudioWriter *writer1, AudioWriter *writer2, Print &print) {
592  p_print = &print;
593  p_writer1 = writer1;
594  p_writer2 = writer2;
595  print2.setWriter(p_writer2);
596  }
597 
598  void setupOutput(AudioWriter *writer1, Print &print) {
599  p_print = &print;
600  p_writer1 = writer1;
601  }
602 
603  virtual bool begin() {
604  if (!active) {
605  active = true;
606  if (p_writer2 != nullptr) {
607  p_writer1->setOutput(print2);
608  p_writer2->setOutput(*p_print);
609  p_writer1->begin();
610  p_writer2->begin();
611  } else {
612  p_writer1->setOutput(*p_print);
613  p_writer1->begin();
614  }
615  }
616  return true;
617  }
618  virtual void end() {
619  if (active) {
620  if (p_writer1 != nullptr) p_writer1->end();
621  if (p_writer2 != nullptr) p_writer2->end();
622  }
623  active = false;
624  }
625  virtual size_t write(uint8_t *data, size_t size) {
626  TRACED();
627  return p_writer1->write(data, size);
628  }
629 
630  protected:
631  Print *p_print = nullptr;
633 };
634 
635 } // namespace audio_tools
Definition: AudioEncoded.h:86
Docoding of encoded audio into PCM data.
Definition: AudioEncoded.h:17
virtual bool isResultPCM()
If true, the decoding result is PCM data.
Definition: AudioEncoded.h:55
void setNotifyAudioChange(AudioInfoSupport &notify) override
Registers an object that is notified if the audio format is changing.
Definition: AudioEncoded.h:58
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition: AudioEncoded.h:37
virtual void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition: AudioEncoded.h:51
virtual void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition: AudioEncoded.h:27
virtual void setOutput(AudioOutput &out_stream)
Defines where the decoded result is written to.
Definition: AudioEncoded.h:44
Definition: AudioEncoded.h:91
Encoding of PCM data.
Definition: AudioEncoded.h:74
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition: AudioEncoded.h:83
virtual const char * mime()=0
Provides the mime type of the encoded result.
Supports the subscription to audio change notifications.
Definition: AudioTypes.h:128
Supports changes to the sampling rate, bits and channels.
Definition: AudioTypes.h:109
Base class for Output Adpapters.
Definition: AudioIO.h:11
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: AudioStreams.h:47
E.g. used by Encoders and Decoders.
Definition: AudioTypes.h:138
Adapter class which lets an AudioWriter behave like a Print.
Definition: AudioEncoded.h:550
virtual int readArray(T data[], int len)
reads multiple values
Definition: Buffers.h:41
Dummy no implmentation Codec. This is used so that we can initialize some pointers to decoders and en...
Definition: AudioEncoded.h:105
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition: AudioEncoded.h:114
virtual void setNotifyAudioChange(AudioInfoSupport &bi)
Registers an object that is notified if the audio format is changing.
Definition: AudioEncoded.h:115
virtual void setAudioInfo(AudioInfo info)
for most decoders this is not needed
Definition: AudioEncoded.h:116
virtual const char * mime()
Provides the mime type of the encoded result.
Definition: AudioEncoded.h:131
ContainerTarget: forwards requests to both the output and the encoder/decoder and sets up the output ...
Definition: AudioEncoded.h:568
Definition: AudioEncoded.h:589
A more natural Print class to process encoded data (aac, wav, mp3...). Just define the output and the...
Definition: AudioEncoded.h:193
virtual size_t write(const uint8_t *data, size_t len) override
encodeor decode the data
Definition: AudioEncoded.h:363
AudioDecoder & decoder()
Provides the initialized decoder.
Definition: AudioEncoded.h:389
void setLogLevel(AudioLogger::LogLevel level)
Defines the class specific custom log level.
Definition: AudioEncoded.h:395
AudioEncoder & encoder()
Provides the initialized encoder.
Definition: AudioEncoded.h:392
void setStream(Print *outputStream)
The same as setOutput.
Definition: AudioEncoded.h:303
void end() override
Ends the processing.
Definition: AudioEncoded.h:353
void setNotifyAudioChange(AudioInfoSupport &bi) override
Define object which need to be notified if the basinfo is changing.
Definition: AudioEncoded.h:268
bool begin() override
Starts the processing - sets the status to active.
Definition: AudioEncoded.h:328
void setOutput(Print *outputStream)
Defines the output.
Definition: AudioEncoded.h:292
virtual bool begin(AudioInfo cfg)
Starts the processing - sets the status to active.
Definition: AudioEncoded.h:347
A more natural Stream class to process encoded data (aac, wav, mp3...) which also supports the decodi...
Definition: AudioEncoded.h:419
void resize()
setup default size for buffer
Definition: AudioEncoded.h:477
void setStream(Stream *ioStream)
Defines the input/output stream for decoding.
Definition: AudioEncoded.h:457
void resize(int size)
Defines the buffer size.
Definition: AudioEncoded.h:474
void setInput(Stream *ioStream)
Same as setStream()
Definition: AudioEncoded.h:454
Definition: NoArduino.h:51
virtual bool begin() override
Activates the output.
Definition: AudioStreams.h:892
virtual int available()
provides the number of entries that are available to read
Definition: Buffers.h:356
Definition: NoArduino.h:114
A Streaming Decoder where we provide both the input and output as streams.
Definition: AudioEncoded.h:141
virtual bool copy()=0
Process a single read operation - to be called in the loop.
virtual void setOutput(AudioStream &out_stream)
Defines the output streams and register to be notified.
Definition: AudioEncoded.h:156
virtual void setNotifyAudioChange(AudioInfoSupport &bi)=0
Register Output Stream to be notified about changes.
virtual void setOutput(Print &outStream)=0
Defines the output Stream.
virtual void setInputStream(Stream &inStream)=0
Defines the input data stream.
virtual void end()=0
Releases the reserved memory.
virtual void begin()=0
Starts the processing.
virtual void setOutput(AudioOutput &out_stream)
Defines the output streams and register to be notified.
Definition: AudioEncoded.h:163
virtual AudioInfo audioInfo()=0
Provides the last available MP3FrameInfo.
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:9
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:43