arduino-audio-tools
AudioEncoded.h
1 #pragma once
2 
3 #include "AudioConfig.h"
4 #include "AudioLogger.h"
5 #include "AudioTools/CoreAudio/AudioIO.h"
6 #include "AudioTools/CoreAudio/AudioOutput.h"
7 #include "AudioTools/CoreAudio/AudioStreams.h"
8 #include "AudioTools/CoreAudio/AudioTypes.h"
9 #include "AudioCodecsBase.h"
10 
11 namespace audio_tools {
12 
22  public:
24  active = false;
25  }
26 
28  setDecoder(decoder);
29  active = false;
30  }
31 
33  setEncoder(encoder);
34  active = false;
35  }
36 
38  setDecoder(decoder);
39  setOutput(outputStream);
40  active = false;
41  }
42 
44  setDecoder(decoder);
45  setOutput(outputStream);
46  active = false;
47  }
48 
49  EncodedAudioOutput(Print *outputStream, AudioDecoder *decoder) {
50  setDecoder(decoder);
51  setOutput(outputStream);
52  active = false;
53  }
54 
55  EncodedAudioOutput(Print *outputStream, AudioEncoder *encoder) {
56  setEncoder(encoder);
57  setOutput(outputStream);
58  active = false;
59  }
60 
62  setEncoder(encoder);
63  setOutput(outputStream);
64  active = false;
65  }
66 
68  setEncoder(encoder);
69  setOutput(outputStream);
70  active = false;
71  }
72 
75  TRACEI();
76  decoder_ptr->addNotifyAudioChange(bi);
77  }
78 
79  AudioInfo defaultConfig() {
80  AudioInfo cfg;
81  cfg.channels = 2;
82  cfg.sample_rate = 44100;
83  cfg.bits_per_sample = 16;
84  return cfg;
85  }
86 
87  virtual void setAudioInfo(AudioInfo newInfo) override {
88  TRACED();
89  if (this->cfg != newInfo && newInfo.channels != 0 && newInfo.sample_rate != 0) {
90  this->cfg = newInfo;
91  decoder_ptr->setAudioInfo(cfg);
92  encoder_ptr->setAudioInfo(cfg);
93  }
94  }
95 
96  void setOutput(Print &outputStream) { setOutput(&outputStream); }
97 
99  void setOutput(Print *outputStream) {
100  ptr_out = outputStream;
101  if (decoder_ptr != nullptr) {
102  decoder_ptr->setOutput(*ptr_out);
103  }
104  if (encoder_ptr != nullptr) {
105  encoder_ptr->setOutput(*ptr_out);
106  }
107  }
108 
109  void setEncoder(AudioEncoder *encoder) {
110  if (encoder == nullptr) {
111  encoder = CodecNOP::instance();
112  }
113  encoder_ptr = encoder;
114  writer_ptr = encoder;
115  if (ptr_out != nullptr) {
116  encoder_ptr->setOutput(*ptr_out);
117  }
118  }
119 
120  AudioEncoder *getEncoder() { return encoder_ptr; }
121 
122  void setDecoder(AudioDecoder *decoder) {
123  if (decoder == nullptr) {
124  decoder = CodecNOP::instance();
125  }
126  decoder_ptr = decoder;
127  writer_ptr = decoder;
128  if (ptr_out != nullptr) {
129  decoder_ptr->setOutput(*ptr_out);
130  }
131  }
132 
133  AudioDecoder *getDecoder() { return decoder_ptr; }
134 
136  bool begin() override {
137 #if USE_AUDIO_LOGGING
138  custom_log_level.set();
139 #endif
140  TRACED();
141  if (!active) {
142  TRACED();
143  const CodecNOP *nop = CodecNOP::instance();
144  if (decoder_ptr != nop || encoder_ptr != nop) {
145  active = true;
146  if (!decoder_ptr->begin(cfg)) active = false;
147  if (!encoder_ptr->begin(cfg)) active = false;
148  } else {
149  LOGW("no decoder or encoder defined");
150  }
151  }
152 #if USE_AUDIO_LOGGING
153  custom_log_level.reset();
154 #endif
155  return active;
156  }
157 
159  virtual bool begin(AudioInfo newInfo) {
160  cfg = newInfo;
161  return begin();
162  }
163 
165  void end() override {
166 #if USE_AUDIO_LOGGING
167  custom_log_level.set();
168 #endif
169  TRACEI();
170  decoder_ptr->end();
171  encoder_ptr->end();
172  active = false;
173 #if USE_AUDIO_LOGGING
174  custom_log_level.reset();
175 #endif
176  }
177 
179  virtual size_t write(const uint8_t *data, size_t len) override {
180  if (len == 0) {
181  //LOGI("write: %d", 0);
182  return 0;
183  }
184 #if USE_AUDIO_LOGGING
185  custom_log_level.set();
186 #endif
187  LOGD("EncodedAudioOutput::write: %d", (int)len);
188 
189  if (writer_ptr == nullptr || data == nullptr) {
190  LOGE("NPE");
191  return 0;
192  }
193 
194  if (check_available_for_write && availableForWrite() == 0) {
195  return 0;
196  }
197 
198  size_t result = writer_ptr->write(data, len);
199  LOGD("EncodedAudioOutput::write: %d -> %d", (int)len, (int)result);
200 #if USE_AUDIO_LOGGING
201  custom_log_level.reset();
202 #endif
203  return result;
204  }
205 
206  int availableForWrite() override {
207  if (!check_available_for_write) return frame_size;
208  return min(ptr_out->availableForWrite(), frame_size);
209  }
210 
212  operator bool() { return active; }
213 
215  AudioDecoder &decoder() { return *decoder_ptr; }
216 
218  AudioEncoder &encoder() { return *encoder_ptr; }
219 
220 #if USE_AUDIO_LOGGING
222  void setLogLevel(AudioLogger::LogLevel level) { custom_log_level.set(level); }
223 #endif
225  bool isCheckAvailableForWrite() { return check_available_for_write; }
226 
228  void setFrameSize(int size) { frame_size = size; }
229 
230  protected:
231  // AudioInfo info;
232  AudioDecoder *decoder_ptr = CodecNOP::instance(); // decoder
233  AudioEncoder *encoder_ptr = CodecNOP::instance(); // decoder
234  AudioWriter *writer_ptr = nullptr;
235  Print *ptr_out = nullptr;
236  bool active = false;
237  bool check_available_for_write = false;
238 #if USE_AUDIO_LOGGING
239  CustomLogLevel custom_log_level;
240 #endif
241  int frame_size = DEFAULT_BUFFER_SIZE;
242 };
243 
244 // legacy name
245 using EncodedAudioPrint = EncodedAudioOutput;
246 
255  public:
256  EncodedAudioStream() = default;
257 
259  setDecoder(decoder);
260  setStream(*ioStream);
261  }
262 
264  setDecoder(decoder);
265  setStream(*ioStream);
266  }
267 
269  setOutput(*outputStream);
270  setDecoder(decoder);
271  }
272 
273  EncodedAudioStream(Print *outputStream, AudioDecoder *decoder) {
274  setOutput(*outputStream);
275  setDecoder(decoder);
276  }
277 
278  EncodedAudioStream(Print *outputStream, AudioEncoder *encoder) {
279  setOutput(*outputStream);
280  setEncoder(encoder);
281  }
282 
284 
286 
287  void setEncoder(AudioEncoder *encoder) { enc_out.setEncoder(encoder); }
288 
289  void setDecoder(AudioDecoder *decoder) { enc_out.setDecoder(decoder); }
290 
291  AudioEncoder *getEncoder() { return enc_out.getEncoder(); }
292 
293  AudioDecoder *getDecoder() { return enc_out.getDecoder(); }
294 
296  AudioDecoder &decoder() { return *getDecoder(); }
297 
299  AudioEncoder &encoder() { return *getEncoder(); }
300 
301  void setStream(Stream *stream) {
302  setStream(*stream);
303  }
304 
305  void setStream(AudioStream *stream) {
306  setStream(*stream);
307  }
308 
309  void setOutput(AudioOutput *stream) {
310  setOutput(*stream);
311  }
312 
313  void setOutput(Print *stream) {
314  setOutput(*stream);
315  }
316 
317  void setStream(AudioStream &stream) {
319  enc_out.setOutput(&stream);
320  }
321 
322  void setStream(Stream &stream) {
324  enc_out.setOutput(&stream);
325  }
326 
327  void setOutput(AudioOutput &stream) {
328  ReformatBaseStream::setOutput(stream);
329  enc_out.setOutput(&stream);
330  }
331 
332  void setOutput(Print &out) {
333  ReformatBaseStream::setOutput(out);
334  enc_out.setOutput(&out);
335  }
336 
337  AudioInfo defaultConfig() {
338  AudioInfo ai;
339  return ai;
340  }
341 
342  bool begin(AudioInfo info) {
343  setAudioInfo(info);
344  return begin();
345  }
346 
347  bool begin() {
348  //is_output_notify = false;
349  setupReader();
350  ReformatBaseStream::begin();
351  return enc_out.begin(audioInfo());
352  }
353 
354  void end() {
355  enc_out.end();
356  reader.end();
357  }
358 
359  int availableForWrite() { return enc_out.availableForWrite(); }
360 
361  size_t write(const uint8_t *data, size_t len) {
362  //addNotifyOnFirstWrite();
363  return enc_out.write(data, len);
364  }
365 
366  size_t readBytes(uint8_t *data, size_t len) {
367  return reader.readBytes(data, len);
368  }
369 
371  enc_out.addNotifyAudioChange(bi);
372  }
373 
375  float getByteFactor() { return byte_factor; }
376  void setByteFactor(float factor) {byte_factor = factor;}
377 
378 #if USE_AUDIO_LOGGING
380  void setLogLevel(AudioLogger::LogLevel level) { enc_out.setLogLevel(level); }
381 #endif
382 
384  void setFrameSize(int size) { enc_out.setFrameSize(size); }
385 
386  protected:
387  EncodedAudioOutput enc_out;
388  float byte_factor = 2.0f;
389 
390 };
391 
400  public:
401  void setWriter(AudioWriter *writer) { p_writer = writer; }
402  size_t write(const uint8_t *data, size_t len) {
403  return p_writer->write(data, len);
404  };
405 
406  protected:
407  AudioWriter *p_writer = nullptr;
408 };
409 
418  public:
419  virtual bool begin() = 0;
420  virtual void end() = 0;
421  virtual void setAudioInfo(AudioInfo info) {
422  if (this->info != info && info.channels != 0 && info.sample_rate != 0) {
423  this->info = info;
424  if (p_writer1 != nullptr) p_writer1->setAudioInfo(info);
425  if (p_writer2 != nullptr) p_writer2->setAudioInfo(info);
426  }
427  }
428  virtual size_t write(uint8_t *data, size_t size) = 0;
429 
430  protected:
431  AudioInfo info;
432  AudioWriter *p_writer1 = nullptr;
433  AudioWriter *p_writer2 = nullptr;
435  bool active = false;
436 };
437 
439  public:
440  void setupOutput(AudioWriter *writer1, AudioWriter *writer2, Print &print) {
441  p_print = &print;
442  p_writer1 = writer1;
443  p_writer2 = writer2;
444  print2.setWriter(p_writer2);
445  }
446 
447  void setupOutput(AudioWriter *writer1, Print &print) {
448  p_print = &print;
449  p_writer1 = writer1;
450  }
451 
452  virtual bool begin() {
453  if (!active) {
454  active = true;
455  if (p_writer2 != nullptr) {
456  p_writer1->setOutput(print2);
457  p_writer2->setOutput(*p_print);
458  p_writer1->begin();
459  p_writer2->begin();
460  } else {
461  p_writer1->setOutput(*p_print);
462  p_writer1->begin();
463  }
464  }
465  return true;
466  }
467  virtual void end() {
468  if (active) {
469  if (p_writer1 != nullptr) p_writer1->end();
470  if (p_writer2 != nullptr) p_writer2->end();
471  }
472  active = false;
473  }
474  virtual size_t write(uint8_t *data, size_t size) {
475  TRACED();
476  return p_writer1->write(data, size);
477  }
478 
479  protected:
480  Print *p_print = nullptr;
482 };
483 
484 } // namespace audio_tools
Docoding of encoded audio into PCM data.
Definition: AudioCodecsBase.h:16
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition: AudioCodecsBase.h:34
virtual void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition: AudioCodecsBase.h:26
Encoding of PCM data.
Definition: AudioCodecsBase.h:84
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition: AudioCodecsBase.h:93
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition: AudioTypes.h:162
Supports changes to the sampling rate, bits and channels.
Definition: AudioTypes.h:139
Base class for Output Adpapters.
Definition: AudioIO.h:225
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:109
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: BaseStream.h:117
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: BaseStream.h:140
E.g. used by Encoders and Decoders.
Definition: AudioTypes.h:224
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
Adapter class which lets an AudioWriter behave like a Print.
Definition: AudioEncoded.h:399
Dummy no implmentation Codec. This is used so that we can initialize some pointers to decoders and en...
Definition: AudioCodecsBase.h:118
ContainerTarget: forwards requests to both the output and the encoder/decoder and sets up the output ...
Definition: AudioEncoded.h:417
Definition: AudioEncoded.h:438
A more natural Print class to process encoded data (aac, wav, mp3...). Just define the output and the...
Definition: AudioEncoded.h:21
virtual size_t write(const uint8_t *data, size_t len) override
encoder decode the data
Definition: AudioEncoded.h:179
AudioDecoder & decoder()
Provides the initialized decoder.
Definition: AudioEncoded.h:215
AudioEncoder & encoder()
Provides the initialized encoder.
Definition: AudioEncoded.h:218
void addNotifyAudioChange(AudioInfoSupport &bi) override
Define object which need to be notified if the basinfo is changing.
Definition: AudioEncoded.h:74
virtual bool begin(AudioInfo newInfo)
Starts the processing - sets the status to active.
Definition: AudioEncoded.h:159
void end() override
Ends the processing.
Definition: AudioEncoded.h:165
void setFrameSize(int size)
defines the size of the decoded frame in bytes
Definition: AudioEncoded.h:228
bool begin() override
Starts the processing - sets the status to active.
Definition: AudioEncoded.h:136
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioEncoded.h:87
bool isCheckAvailableForWrite()
Is Available for Write check activated ?
Definition: AudioEncoded.h:225
void setOutput(Print &outputStream)
Defines/Changes the output target.
Definition: AudioEncoded.h:96
void setOutput(Print *outputStream)
Defines the output.
Definition: AudioEncoded.h:99
A more natural Stream class to process encoded data (aac, wav, mp3...) which also supports the decodi...
Definition: AudioEncoded.h:254
AudioDecoder & decoder()
Provides the initialized decoder.
Definition: AudioEncoded.h:296
AudioEncoder & encoder()
Provides the initialized encoder.
Definition: AudioEncoded.h:299
void addNotifyAudioChange(AudioInfoSupport &bi) override
Adds target to be notified about audio changes.
Definition: AudioEncoded.h:370
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioEncoded.h:322
void setFrameSize(int size)
defines the size of the decoded frame in bytes
Definition: AudioEncoded.h:384
float getByteFactor()
approx compression factor: e.g. mp3 is around 4
Definition: AudioEncoded.h:375
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioEncoded.h:332
Abstract class: Objects can be put into a pipleline.
Definition: AudioOutput.h:97
Definition: NoArduino.h:58
Base class for chained converting streams.
Definition: AudioIO.h:154
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition: AudioIO.h:156
Definition: NoArduino.h:125
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:868
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:52
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:59