arduino-audio-tools
AudioEncoded.h
1 #pragma once
2 
3 #include "AudioConfig.h"
4 #include "AudioLogger.h"
5 #include "AudioTools/AudioIO.h"
6 #include "AudioTools/AudioOutput.h"
7 #include "AudioTools/AudioStreams.h"
8 #include "AudioTools/AudioTypes.h"
9 
10 namespace audio_tools {
11 
18 class AudioDecoder : public AudioWriter, public AudioInfoSource {
19  public:
20  AudioDecoder() = default;
21  virtual ~AudioDecoder() = default;
22  AudioDecoder(AudioDecoder const &) = delete;
23  AudioDecoder &operator=(AudioDecoder const &) = delete;
24 
25  virtual AudioInfo audioInfo() { return info; };
26 
28  virtual void setAudioInfo(AudioInfo from) override {
29  TRACED();
30  if (info != from) {
31  notifyAudioChange(from);
32  }
33  info = from;
34  }
36  virtual void setOutput(AudioStream &out_stream) {
37  Print *p_print = &out_stream;
38  setOutput(*p_print);
39  addNotifyAudioChange(out_stream);
40  }
41 
43  virtual void setOutput(AudioOutput &out_stream) {
44  Print *p_print = &out_stream;
45  setOutput(*p_print);
46  addNotifyAudioChange(out_stream);
47  }
48 
50  virtual void setOutput(Print &out_stream) override { p_print = &out_stream; }
52  virtual bool isResultPCM() {
53  setAudioInfo(info);
54  return begin();
55  }
56  virtual bool begin(AudioInfo info) override {
57  setAudioInfo(info);
58  return begin();
59  }
60  bool begin() override { return true; }
61  void end() override {}
62 
64  int id;
65 
66  protected:
67  Print *p_print = nullptr;
68  AudioInfo info;
69 };
70 
79  bool isResultPCM() override { return true; }
80 };
81 
88 class AudioEncoder : public AudioWriter {
89  public:
90  AudioEncoder() = default;
91  virtual ~AudioEncoder() = default;
92  AudioEncoder(AudioEncoder const &) = delete;
93  AudioEncoder &operator=(AudioEncoder const &) = delete;
95  virtual const char *mime() = 0;
97  void setAudioInfo(AudioInfo from) override { info = from; }
98  AudioInfo audioInfo() { return info; }
99 
100  protected:
101  AudioInfo info;
102 };
103 
105  public:
106  virtual void setBlockSize(int blockSize) = 0;
107 };
108 
110  public:
111  virtual int blockSize() = 0;
112 };
113 
122 class CodecNOP : public AudioDecoder, public AudioEncoder {
123  public:
124  static CodecNOP *instance() {
125  static CodecNOP self;
126  return &self;
127  }
128 
129  virtual bool begin() { return true; }
130  virtual void end() {}
131  virtual void setOutput(Print &out_stream) {}
133  virtual void setAudioInfo(AudioInfo info) {}
134 
135  virtual AudioInfo audioInfo() {
136  AudioInfo info;
137  return info;
138  }
139  virtual operator bool() { return false; }
140  virtual int readStream(Stream &in) { return 0; };
141 
142  // just output silence
143  virtual size_t write(const void *in_ptr, size_t in_size) {
144  memset((void *)in_ptr, 0, in_size);
145  return in_size;
146  }
147 
148  virtual const char *mime() { return nullptr; }
149 };
150 
159  public:
161  virtual bool begin() = 0;
162 
164  virtual void end() = 0;
165 
167  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
168 
170  virtual void setOutput(AudioStream &out_stream) {
171  Print *p_print = &out_stream;
172  setOutput(*p_print);
173  addNotifyAudioChange(out_stream);
174  }
175 
177  virtual void setOutput(AudioOutput &out_stream) {
178  Print *p_print = &out_stream;
179  setOutput(*p_print);
180  addNotifyAudioChange(out_stream);
181  }
182 
186  void setInput(Stream &inStream) { this->p_input = &inStream; }
187 
188 #if USE_OBSOLETE
190  void setInputStream(Stream &inStream) { setInput(inStream); }
191 #endif
192 
194  virtual AudioInfo audioInfo() = 0;
195 
197  virtual operator bool() = 0;
198 
200  virtual bool copy() = 0;
201 
202  protected:
203  virtual size_t readBytes(uint8_t *buffer, size_t len) = 0;
204  Print *p_print = nullptr;
205  Stream *p_input = nullptr;
206 };
207 
215  public:
217  int copySize = DEFAULT_BUFFER_SIZE) {
218  p_decoder = &decoder;
219  if (copySize > 0) resize(copySize);
220  }
222  bool begin() override { return p_input != nullptr && p_decoder->begin(); }
223 
225  void end() override { p_decoder->end(); }
226 
228  void setOutput(Print &out_stream) override {
229  p_decoder->setOutput(out_stream);
230  }
231 
233  AudioInfo audioInfo() override { return p_decoder->audioInfo(); }
234 
236  virtual operator bool() { return *p_decoder; }
237 
239  virtual bool copy() {
240  int read = readBytes(&buffer[0], buffer.size());
241  int written = 0;
242  if (read > 0) written = p_decoder->write(&buffer[0], read);
243  return written > 0;
244  }
245 
247  void resize(int bufferSize) { buffer.resize(bufferSize); }
248 
249  protected:
250  AudioDecoder *p_decoder = nullptr;
251  Vector<uint8_t> buffer{0};
252 
253  size_t readBytes(uint8_t *buffer, size_t len) override {
254  if (p_input == nullptr) return 0;
255  return p_input->readBytes(buffer, len);
256  }
257 };
258 
268  public:
270  active = false;
271  }
272 
274  setDecoder(decoder);
275  active = false;
276  }
277 
279  setEncoder(encoder);
280  active = false;
281  }
282 
284  setDecoder(decoder);
285  setOutput(outputStream);
286  active = false;
287  }
288 
290  setDecoder(decoder);
291  setOutput(outputStream);
292  active = false;
293  }
294 
295  EncodedAudioOutput(Print *outputStream, AudioDecoder *decoder) {
296  setDecoder(decoder);
297  setOutput(outputStream);
298  active = false;
299  }
300 
301  EncodedAudioOutput(Print *outputStream, AudioEncoder *encoder) {
302  setEncoder(encoder);
303  setOutput(outputStream);
304  active = false;
305  }
306 
308  setEncoder(encoder);
309  setOutput(outputStream);
310  active = false;
311  }
312 
314  setEncoder(encoder);
315  setOutput(outputStream);
316  active = false;
317  }
318 
321  TRACEI();
322  static int count = 0;
323  count++;
324  assert(count<10);
325  decoder_ptr->addNotifyAudioChange(bi);
326  }
327 
328  AudioInfo defaultConfig() {
329  AudioInfo cfg;
330  cfg.channels = 2;
331  cfg.sample_rate = 44100;
332  cfg.bits_per_sample = 16;
333  return cfg;
334  }
335 
336  virtual void setAudioInfo(AudioInfo newInfo) override {
337  TRACED();
338  if (this->cfg != newInfo && newInfo.channels != 0 && newInfo.sample_rate != 0) {
339  this->cfg = newInfo;
340  decoder_ptr->setAudioInfo(cfg);
341  encoder_ptr->setAudioInfo(cfg);
342  }
343  }
344 
345  void setOutput(Print &outputStream) { setOutput(&outputStream); }
346 
348  void setOutput(Print *outputStream) {
349  ptr_out = outputStream;
350  if (decoder_ptr != nullptr) {
351  decoder_ptr->setOutput(*ptr_out);
352  }
353  if (encoder_ptr != nullptr) {
354  encoder_ptr->setOutput(*ptr_out);
355  }
356  }
357 
358  void setEncoder(AudioEncoder *encoder) {
359  if (encoder == nullptr) {
360  encoder = CodecNOP::instance();
361  }
362  encoder_ptr = encoder;
363  writer_ptr = encoder;
364  if (ptr_out != nullptr) {
365  encoder_ptr->setOutput(*ptr_out);
366  }
367  }
368 
369  AudioEncoder *getEncoder() { return encoder_ptr; }
370 
371  void setDecoder(AudioDecoder *decoder) {
372  if (decoder == nullptr) {
373  decoder = CodecNOP::instance();
374  }
375  decoder_ptr = decoder;
376  writer_ptr = decoder;
377  if (ptr_out != nullptr) {
378  decoder_ptr->setOutput(*ptr_out);
379  }
380  }
381 
382  AudioDecoder *getDecoder() { return decoder_ptr; }
383 
385  bool begin() override {
386  custom_log_level.set();
387  TRACED();
388  if (!active) {
389  TRACED();
390  const CodecNOP *nop = CodecNOP::instance();
391  if (decoder_ptr != nop || encoder_ptr != nop) {
392  active = true;
393  if (!decoder_ptr->begin(cfg)) active = false;
394  if (!encoder_ptr->begin(cfg)) active = false;
395  } else {
396  LOGW("no decoder or encoder defined");
397  }
398  }
399  custom_log_level.reset();
400  return active;
401  }
402 
404  virtual bool begin(AudioInfo newInfo) {
405  cfg = newInfo;
406  return begin();
407  }
408 
410  void end() override {
411  custom_log_level.set();
412  TRACEI();
413  decoder_ptr->end();
414  encoder_ptr->end();
415  active = false;
416  custom_log_level.reset();
417  }
418 
420  virtual size_t write(const uint8_t *data, size_t len) override {
421  if (len == 0) {
422  //LOGI("write: %d", 0);
423  return 0;
424  }
425  custom_log_level.set();
426  LOGD("EncodedAudioOutput::write: %d", (int)len);
427 
428  if (writer_ptr == nullptr || data == nullptr) {
429  LOGE("NPE");
430  return 0;
431  }
432 
433  if (check_available_for_write && availableForWrite() == 0) {
434  return 0;
435  }
436 
437  size_t result = writer_ptr->write(data, len);
438  LOGD("EncodedAudioOutput::write: %d -> %d", (int)len, (int)result);
439  custom_log_level.reset();
440 
441  return result;
442  }
443 
444  int availableForWrite() override {
445  if (!check_available_for_write) return frame_size;
446  return min(ptr_out->availableForWrite(), frame_size);
447  }
448 
450  operator bool() { return active; }
451 
453  AudioDecoder &decoder() { return *decoder_ptr; }
454 
456  AudioEncoder &encoder() { return *encoder_ptr; }
457 
459  void setLogLevel(AudioLogger::LogLevel level) { custom_log_level.set(level); }
461  bool isCheckAvailableForWrite() { return check_available_for_write; }
462 
464  void setFrameSize(int size) { frame_size = size; }
465 
466  protected:
467  // AudioInfo info;
468  AudioDecoder *decoder_ptr = CodecNOP::instance(); // decoder
469  AudioEncoder *encoder_ptr = CodecNOP::instance(); // decoder
470  AudioWriter *writer_ptr = nullptr;
471  Print *ptr_out = nullptr;
472  bool active = false;
473  bool check_available_for_write = false;
474  CustomLogLevel custom_log_level;
475  int frame_size = DEFAULT_BUFFER_SIZE;
476 };
477 
478 // legacy name
479 using EncodedAudioPrint = EncodedAudioOutput;
480 
489  public:
490  EncodedAudioStream() = default;
491 
493  setDecoder(decoder);
494  setStream(*ioStream);
495  }
496 
498  setDecoder(decoder);
499  setStream(*ioStream);
500  }
501 
503  setOutput(*outputStream);
504  setDecoder(decoder);
505  }
506 
507  EncodedAudioStream(Print *outputStream, AudioDecoder *decoder) {
508  setOutput(*outputStream);
509  setDecoder(decoder);
510  }
511 
512  EncodedAudioStream(Print *outputStream, AudioEncoder *encoder) {
513  setOutput(*outputStream);
514  setEncoder(encoder);
515  }
516 
518 
520 
521  void setEncoder(AudioEncoder *encoder) { enc_out.setEncoder(encoder); }
522 
523  void setDecoder(AudioDecoder *decoder) { enc_out.setDecoder(decoder); }
524 
525  AudioEncoder *getEncoder() { return enc_out.getEncoder(); }
526 
527  AudioDecoder *getDecoder() { return enc_out.getDecoder(); }
528 
530  AudioDecoder &decoder() { return *getDecoder(); }
531 
533  AudioEncoder &encoder() { return *getEncoder(); }
534 
535  void setStream(Stream *stream) {
536  setStream(*stream);
537  }
538 
539  void setStream(AudioStream *stream) {
540  setStream(*stream);
541  }
542 
543  void setOutput(AudioOutput *stream) {
544  setOutput(*stream);
545  }
546 
547  void setOutput(Print *stream) {
548  setOutput(*stream);
549  }
550 
551  void setStream(AudioStream &stream) {
553  enc_out.setOutput(&stream);
554  }
555 
556  void setStream(Stream &stream) {
558  enc_out.setOutput(&stream);
559  }
560 
561  void setOutput(AudioOutput &stream) {
562  ReformatBaseStream::setOutput(stream);
563  enc_out.setOutput(&stream);
564  }
565 
566  void setOutput(Print &out) {
567  ReformatBaseStream::setOutput(out);
568  enc_out.setOutput(&out);
569  }
570 
571  AudioInfo defaultConfig() {
572  AudioInfo ai;
573  return ai;
574  }
575 
576  bool begin(AudioInfo info) {
577  setAudioInfo(info);
578  return begin();
579  }
580 
581  bool begin() {
582  is_output_notify = false;
583  reader.setByteCountFactor(10);
584  setupReader();
585  ReformatBaseStream::begin();
586  return enc_out.begin(audioInfo());
587  }
588 
589  void end() {
590  enc_out.end();
591  reader.end();
592  }
593 
594  int availableForWrite() { return enc_out.availableForWrite(); }
595 
596  size_t write(const uint8_t *data, size_t len) {
598  return enc_out.write(data, len);
599  }
600 
601  size_t readBytes(uint8_t *data, size_t size) {
602  return reader.readBytes(data, size);
603  }
604 
606  enc_out.addNotifyAudioChange(bi);
607  }
608 
609  float getByteFactor() { return 1.0f; }
610 
612  void setLogLevel(AudioLogger::LogLevel level) { enc_out.setLogLevel(level); }
613 
614  protected:
615  EncodedAudioOutput enc_out;
616 
617 };
618 
627  public:
628  void setWriter(AudioWriter *writer) { p_writer = writer; }
629  size_t write(const uint8_t *in_ptr, size_t in_size) {
630  return p_writer->write(in_ptr, in_size);
631  };
632 
633  protected:
634  AudioWriter *p_writer = nullptr;
635 };
636 
645  public:
646  virtual bool begin() = 0;
647  virtual void end() = 0;
648  virtual void setAudioInfo(AudioInfo info) {
649  if (this->info != info && info.channels != 0 && info.sample_rate != 0) {
650  this->info = info;
651  if (p_writer1 != nullptr) p_writer1->setAudioInfo(info);
652  if (p_writer2 != nullptr) p_writer2->setAudioInfo(info);
653  }
654  }
655  virtual size_t write(uint8_t *data, size_t size) = 0;
656 
657  protected:
658  AudioInfo info;
659  AudioWriter *p_writer1 = nullptr;
660  AudioWriter *p_writer2 = nullptr;
662  bool active = false;
663 };
664 
666  public:
667  void setupOutput(AudioWriter *writer1, AudioWriter *writer2, Print &print) {
668  p_print = &print;
669  p_writer1 = writer1;
670  p_writer2 = writer2;
671  print2.setWriter(p_writer2);
672  }
673 
674  void setupOutput(AudioWriter *writer1, Print &print) {
675  p_print = &print;
676  p_writer1 = writer1;
677  }
678 
679  virtual bool begin() {
680  if (!active) {
681  active = true;
682  if (p_writer2 != nullptr) {
683  p_writer1->setOutput(print2);
684  p_writer2->setOutput(*p_print);
685  p_writer1->begin();
686  p_writer2->begin();
687  } else {
688  p_writer1->setOutput(*p_print);
689  p_writer1->begin();
690  }
691  }
692  return true;
693  }
694  virtual void end() {
695  if (active) {
696  if (p_writer1 != nullptr) p_writer1->end();
697  if (p_writer2 != nullptr) p_writer2->end();
698  }
699  active = false;
700  }
701  virtual size_t write(uint8_t *data, size_t size) {
702  TRACED();
703  return p_writer1->write(data, size);
704  }
705 
706  protected:
707  Print *p_print = nullptr;
709 };
710 
711 } // namespace audio_tools
Definition: AudioEncoded.h:104
Docoding of encoded audio into PCM data.
Definition: AudioEncoded.h:18
virtual bool isResultPCM()
If true, the decoding result is PCM data.
Definition: AudioEncoded.h:52
int id
custom id to be used by application
Definition: AudioEncoded.h:64
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition: AudioEncoded.h:36
virtual void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition: AudioEncoded.h:50
virtual void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition: AudioEncoded.h:28
virtual void setOutput(AudioOutput &out_stream)
Defines where the decoded result is written to.
Definition: AudioEncoded.h:43
virtual AudioInfo audioInfo()
provides the actual input AudioInfo
Definition: AudioEncoded.h:25
Definition: AudioEncoded.h:109
Encoding of PCM data.
Definition: AudioEncoded.h:88
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition: AudioEncoded.h:97
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition: AudioEncoded.h:98
virtual const char * mime()=0
Provides the mime type of the encoded result.
Supports the subscription to audio change notifications.
Definition: AudioTypes.h:155
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition: AudioTypes.h:158
Supports changes to the sampling rate, bits and channels.
Definition: AudioTypes.h:136
Base class for Output Adpapters.
Definition: AudioIO.h:219
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:24
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreams.h:32
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioStreams.h:55
E.g. used by Encoders and Decoders.
Definition: AudioTypes.h:227
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
Adapter class which lets an AudioWriter behave like a Print.
Definition: AudioEncoded.h:626
Dummy no implmentation Codec. This is used so that we can initialize some pointers to decoders and en...
Definition: AudioEncoded.h:122
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition: AudioEncoded.h:131
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition: AudioEncoded.h:132
virtual void setAudioInfo(AudioInfo info)
for most decoders this is not needed
Definition: AudioEncoded.h:133
virtual AudioInfo audioInfo()
provides the actual input AudioInfo
Definition: AudioEncoded.h:135
virtual const char * mime()
Provides the mime type of the encoded result.
Definition: AudioEncoded.h:148
Parent class for all container formats.
Definition: AudioEncoded.h:78
ContainerTarget: forwards requests to both the output and the encoder/decoder and sets up the output ...
Definition: AudioEncoded.h:644
Definition: AudioEncoded.h:665
A more natural Print class to process encoded data (aac, wav, mp3...). Just define the output and the...
Definition: AudioEncoded.h:267
virtual size_t write(const uint8_t *data, size_t len) override
encoder decode the data
Definition: AudioEncoded.h:420
AudioDecoder & decoder()
Provides the initialized decoder.
Definition: AudioEncoded.h:453
void setLogLevel(AudioLogger::LogLevel level)
Defines the class specific custom log level.
Definition: AudioEncoded.h:459
AudioEncoder & encoder()
Provides the initialized encoder.
Definition: AudioEncoded.h:456
void addNotifyAudioChange(AudioInfoSupport &bi) override
Define object which need to be notified if the basinfo is changing.
Definition: AudioEncoded.h:320
virtual bool begin(AudioInfo newInfo)
Starts the processing - sets the status to active.
Definition: AudioEncoded.h:404
void end() override
Ends the processing.
Definition: AudioEncoded.h:410
void setFrameSize(int size)
defines the size of the decoded frame in bytes
Definition: AudioEncoded.h:464
bool begin() override
Starts the processing - sets the status to active.
Definition: AudioEncoded.h:385
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioEncoded.h:336
bool isCheckAvailableForWrite()
Is Available for Write check activated ?
Definition: AudioEncoded.h:461
void setOutput(Print &outputStream)
Defines/Changes the output target.
Definition: AudioEncoded.h:345
void setOutput(Print *outputStream)
Defines the output.
Definition: AudioEncoded.h:348
A more natural Stream class to process encoded data (aac, wav, mp3...) which also supports the decodi...
Definition: AudioEncoded.h:488
AudioDecoder & decoder()
Provides the initialized decoder.
Definition: AudioEncoded.h:530
void setLogLevel(AudioLogger::LogLevel level)
Defines the class specific custom log level.
Definition: AudioEncoded.h:612
AudioEncoder & encoder()
Provides the initialized encoder.
Definition: AudioEncoded.h:533
void addNotifyAudioChange(AudioInfoSupport &bi) override
Adds target to be notified about audio changes.
Definition: AudioEncoded.h:605
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioEncoded.h:556
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioEncoded.h:566
Abstract class: Objects can be put into a pipleline.
Definition: AudioOutput.h:96
Definition: NoArduino.h:58
Base class for chained converting streams.
Definition: AudioIO.h:138
void addNotifyOnFirstWrite()
Add notification on first call of write.
Definition: AudioIO.h:200
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition: AudioIO.h:140
Definition: NoArduino.h:125
Converts any AudioDecoder to a StreamingDecoder.
Definition: AudioEncoded.h:214
void setOutput(Print &out_stream) override
Defines the output Stream.
Definition: AudioEncoded.h:228
virtual bool copy()
Process a single read operation - to be called in the loop.
Definition: AudioEncoded.h:239
void end() override
Releases the reserved memory.
Definition: AudioEncoded.h:225
void resize(int bufferSize)
Adjust the buffer size: the existing content of the buffer is lost!
Definition: AudioEncoded.h:247
bool begin() override
Starts the processing.
Definition: AudioEncoded.h:222
AudioInfo audioInfo() override
Provides the last available MP3FrameInfo.
Definition: AudioEncoded.h:233
A Streaming Decoder where we provide both the input and output as streams.
Definition: AudioEncoded.h:158
virtual bool copy()=0
Process a single read operation - to be called in the loop.
virtual void setOutput(Print &out_stream)
Defines the output Stream.
Definition: AudioEncoded.h:167
void setInput(Stream &inStream)
Definition: AudioEncoded.h:186
virtual void setOutput(AudioStream &out_stream)
Defines the output streams and register to be notified.
Definition: AudioEncoded.h:170
virtual void end()=0
Releases the reserved memory.
virtual void setOutput(AudioOutput &out_stream)
Defines the output streams and register to be notified.
Definition: AudioEncoded.h:177
virtual AudioInfo audioInfo()=0
Provides the last available MP3FrameInfo.
virtual bool begin()=0
Starts the processing.
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57