arduino-audio-tools
AudioIO.h
1 #pragma once
2 #include "AudioTools/CoreAudio/AudioOutput.h"
3 #include "AudioTools/CoreAudio/AudioStreams.h"
4 
5 #ifndef MAX_ZERO_READ_COUNT
6 # define MAX_ZERO_READ_COUNT 3
7 #endif
8 
9 #ifndef CHANNEL_SELECT_BUFFER_SIZE
10 # define CHANNEL_SELECT_BUFFER_SIZE 256
11 #endif
12 
13 
14 namespace audio_tools {
22 template <class T>
24  public:
29  void begin(T *transform, Stream *source) {
30  TRACED();
31  active = true;
32  p_stream = source;
33  p_transform = transform;
34  if (transform == nullptr) {
35  LOGE("transform is NULL");
36  active = false;
37  }
38  if (p_stream == nullptr) {
39  LOGE("p_stream is NULL");
40  active = false;
41  }
42  }
43 
44  size_t readBytes(uint8_t *data, size_t len) {
45  LOGD("TransformationReader::readBytes: %d", (int)len);
46  if (!active) {
47  LOGE("inactive");
48  return 0;
49  }
50  if (p_stream == nullptr) {
51  LOGE("p_stream is NULL");
52  return 0;
53  }
54 
55  // we read half the necessary bytes
56  if (buffer.size() == 0) {
57  int size = (0.5 / p_transform->getByteFactor() * len);
58  // process full samples/frames
59  size = size / 4 * 4;
60  LOGI("read size: %d", size);
61  buffer.resize(size);
62  }
63 
64  if (rb.size() == 0) {
65  // make sure that the ring buffer is big enough
66  int rb_size = len * byte_count_factor;
67  LOGI("buffer size: %d", rb_size);
68  rb.resize(rb_size);
69  result_queue.begin();
70  }
71 
72  if (result_queue.available() < len) {
73  Print *tmp = setupOutput();
74  int zero_count = 0;
75  while (result_queue.available() < len) {
76  int read_eff = p_stream->readBytes(buffer.data(), buffer.size());
77  if (read_eff > 0) {
78  zero_count = 0; // reset 0 count
79  if (read_eff != buffer.size())
80  LOGD("readBytes %d -> %d", buffer.size(), read_eff);
81  int write_eff = p_transform->write(buffer.data(), read_eff);
82  if (write_eff != read_eff)
83  LOGE("write %d -> %d", read_eff, write_eff);
84  } else {
85  // limit the number of reads which provide 0;
86  if (++zero_count > MAX_ZERO_READ_COUNT){
87  break;
88  }
89  // wait for some more data
90  delay(5);
91  }
92  }
93  restoreOutput(tmp);
94  }
95 
96  int result_len = min((int)len, result_queue.available());
97  result_len = result_queue.readBytes(data, result_len);
98  LOGD("TransformationReader::readBytes: %d -> %d", (int)len,
99  result_len);
100 
101  return result_len;
102  }
103 
104  void end() {
105  rb.resize(0);
106  buffer.resize(0);
107  }
108 
109  void setByteCountFactor(int f) { byte_count_factor = f; }
110 
111  protected:
112  RingBuffer<uint8_t> rb{0};
113  QueueStream<uint8_t> result_queue{rb}; //
114  Stream *p_stream = nullptr;
115  Vector<uint8_t> buffer{0}; // we allocate memory only when needed
116  T *p_transform = nullptr;
117  bool active = false;
118  int byte_count_factor = 3;
119 
124  Print *result = p_transform->getPrint();
125  p_transform->setOutput((Print &)result_queue);
126 
127  return result;
128  }
131  void restoreOutput(Print *out) {
132  if (out) p_transform->setOutput(*out);
133  }
134 };
135 
143  public:
144  virtual void setStream(Stream &stream) override {
145  TRACED();
146  p_stream = &stream;
147  p_print = &stream;
148  }
149 
150  virtual void setStream(AudioStream &stream) {
151  TRACED();
152  p_stream = &stream;
153  p_print = &stream;
154  //setNotifyOnOutput(stream);
155  addNotifyAudioChange(stream);
156  }
157 
158  virtual void setOutput(AudioOutput &print) {
159  TRACED();
160  p_print = &print;
161  addNotifyAudioChange(print);
162  }
163 
164  virtual void setOutput(Print &print) override {
165  TRACED();
166  p_print = &print;
167  }
168 
169  virtual Print *getPrint() { return p_print; }
170 
171  virtual Stream *getStream() { return p_stream; }
172 
173  size_t readBytes(uint8_t *data, size_t len) override {
174  LOGD("ReformatBaseStream::readBytes: %d", (int)len);
175  return reader.readBytes(data, len);
176  }
177 
178  int available() override {
179  return DEFAULT_BUFFER_SIZE; // reader.availableForWrite();
180  }
181 
182  int availableForWrite() override {
183  return DEFAULT_BUFFER_SIZE; // reader.availableForWrite();
184  }
185 
186  virtual float getByteFactor() = 0;
187 
188  void end() override {
189  TRACED();
190  AudioStream::end();
191  reader.end();
192  }
193 
194  protected:
195  TransformationReader<ReformatBaseStream> reader;
196  Stream *p_stream = nullptr;
197  Print *p_print = nullptr;
198 // bool is_output_notify = false;
199 // AudioInfoSupport *p_notify_on_output = nullptr;
200 
201  // /// Define potential notification
202  // void setNotifyOnOutput(AudioInfoSupport &info) { p_notify_on_output = &info; }
203 
204  // /// Add notification on first call of write
205  // void addNotifyOnFirstWrite() {
206  // if (!is_output_notify) {
207  // if (p_notify_on_output != nullptr)
208  // addNotifyAudioChange(*p_notify_on_output);
209  // is_output_notify = true;
210  // }
211  // }
212 
213  void setupReader() {
214  if (getStream() != nullptr) {
215  reader.begin(this, getStream());
216  }
217  }
218 };
219 
224 class AudioOutputAdapter : public AudioOutput {};
225 
231  public:
232  AdapterPrintToAudioOutput(Print &print) { p_print = &print; }
233  void setAudioInfo(AudioInfo info) {}
234  size_t write(const uint8_t *data, size_t len) {
235  return p_print->write(data, len);
236  }
238  virtual bool isDeletable() { return true; }
239 
240  protected:
241  Print *p_print = nullptr;
242 };
243 
249  public:
251 
252  AdapterAudioStreamToAudioOutput(AudioStream &stream) { setStream(stream); }
253 
254  void setStream(AudioStream &stream) { p_stream = &stream; }
255 
256  void setAudioInfo(AudioInfo info) override { p_stream->setAudioInfo(info); }
257 
258  AudioInfo audioInfo() override { return p_stream->audioInfo(); }
259 
260  size_t write(const uint8_t *data, size_t len) override {
261  return p_stream->write(data, len);
262  }
263 
264  int availableForWrite() override { return p_stream->availableForWrite(); }
265 
266  bool begin() override { return p_stream->begin(); }
267 
268  void end() override { p_stream->end(); }
269 
271  virtual bool isDeletable() { return true; }
272 
273  operator bool() override { return *p_stream; }
274 
275  protected:
276  AudioStream *p_stream = nullptr;
277 };
278 
284  public:
286 
287  AdapterAudioOutputToAudioStream(AudioOutput &stream) { setOutput(stream); }
288 
289  void setOutput(AudioOutput &stream) { p_stream = &stream; }
290 
291  void setAudioInfo(AudioInfo info) override { p_stream->setAudioInfo(info); }
292 
293  AudioInfo audioInfo() override { return p_stream->audioInfo(); }
294 
295  size_t write(const uint8_t *data, size_t len) override {
296  return p_stream->write(data, len);
297  }
298 
299  bool begin() override { return p_stream->begin(); }
300 
301  void end() override { p_stream->end(); }
302 
304  virtual bool isDeletable() { return true; }
305 
306  operator bool() override { return *p_stream; }
307 
308  protected:
309  AudioOutput *p_stream = nullptr;
310 };
311 
318 class MultiOutput : public ModifyingOutput {
319  public:
321  MultiOutput() = default;
322 
323  MultiOutput(Print &out) { add(out); }
324 
326  MultiOutput(AudioOutput &out) { add(out); }
327 
328  MultiOutput(AudioStream &out) { add(out); }
329 
332  add(out1);
333  add(out2);
334  }
335 
338  add(out1);
339  add(out2);
340  }
341 
344  MultiOutput(Print &out1, Print &out2) {
345  add(out1);
346  add(out2);
347  }
348 
349  virtual ~MultiOutput() {
350  for (int j = 0; j < vector.size(); j++) {
351  if (vector[j]->isDeletable()) {
352  delete vector[j];
353  }
354  }
355  }
356 
358  void add(AudioOutput &out) { vector.push_back(&out); }
359 
361  void add(AudioStream &stream) {
364  vector.push_back(out);
365  }
366 
367  void add(Print &print) {
369  vector.push_back(out);
370  }
371 
372  void flush() {
373  for (int j = 0; j < vector.size(); j++) {
374  vector[j]->flush();
375  }
376  }
377 
378  void setAudioInfo(AudioInfo info) {
379  for (int j = 0; j < vector.size(); j++) {
380  vector[j]->setAudioInfo(info);
381  }
382  }
383 
384  size_t write(const uint8_t *data, size_t len) {
385  for (int j = 0; j < vector.size(); j++) {
386  int open = len;
387  int start = 0;
388  while (open > 0) {
389  int written = vector[j]->write(data + start, open);
390  open -= written;
391  start += written;
392  }
393  }
394  return len;
395  }
396 
397  size_t write(uint8_t ch) {
398  for (int j = 0; j < vector.size(); j++) {
399  int open = 1;
400  while (open > 0) {
401  open -= vector[j]->write(ch);
402  }
403  }
404  return 1;
405  }
406 
407  protected:
408  Vector<AudioOutput *> vector;
410  void setOutput(Print &out) { add(out); }
411 };
412 
422 class TimedStream : public ModifyingStream {
423  public:
424  TimedStream() = default;
425 
426  TimedStream(AudioStream &io, long startSeconds = 0, long endSeconds = -1) {
427  p_stream = &io;
428  p_print = &io;
429  p_info = &io;
430  setStartSec(startSeconds);
431  setEndSec(endSeconds);
432  }
433 
434  TimedStream(AudioOutput &o, long startSeconds = 0, long endSeconds = -1) {
435  p_print = &o;
436  p_info = &o;
437  setStartSec(startSeconds);
438  setEndSec(endSeconds);
439  }
440 
443  void setStartSec(uint32_t startSeconds) {
444  start_ms = startSeconds * 1000;
445  calculateByteLimits();
446  }
447 
449  void setStartMs(uint32_t ms) {
450  start_ms = ms;
451  calculateByteLimits();
452  }
453 
456  void setEndSec(uint32_t endSeconds) {
457  end_ms = endSeconds * 1000;
458  calculateByteLimits();
459  }
460 
462  void setEndMs(uint32_t ms) {
463  end_ms = ms;
464  calculateByteLimits();
465  }
466 
468  bool isPlaying() {
469  if (current_bytes < start_bytes) return false;
470  if (end_bytes > 0 && current_bytes > end_bytes) return false;
471  return true;
472  }
473 
475  bool isActive() {
476  return (current_bytes < end_bytes && current_bytes >= start_bytes);
477  }
478 
479  bool begin(AudioInfo info) {
480  setAudioInfo(info);
481  return begin();
482  }
483 
484  bool begin() override {
485  calculateByteLimits();
486  current_bytes = 0;
487  LOGI("byte range %u - %u",(unsigned) start_bytes,(unsigned) end_bytes);
488  return true;
489  }
490 
491  operator bool() { return isActive(); }
492 
496  size_t readBytes(uint8_t *data, size_t len) override {
497  // if reading is not supported we stop
498  if (p_stream == nullptr) return 0;
499  // Positioin to start
500  if (start_bytes > current_bytes){
501  consumeBytes(start_bytes - current_bytes);
502  }
503  // if we are past the end we stop
504  if (!isActive()) return 0;
505  // read the data now
506  size_t result = 0;
507  do {
508  result = p_stream->readBytes(data, len);
509  current_bytes += len;
510  // ignore data before start time
511  } while (result > 0 && current_bytes < start_bytes);
512  return isPlaying() ? result : 0;
513  }
514 
516  size_t write(const uint8_t *data, size_t len) override {
517  if (current_bytes >= end_bytes) return 0;
518  current_bytes += len;
519  if (current_bytes < start_bytes) return len;
520  return p_print->write(data, len);
521  }
522 
524  int available() override {
525  if (p_stream == nullptr) return 0;
526  return current_bytes < end_bytes ? p_stream->available() : 0;
527  }
528 
530  void setAudioInfo(AudioInfo info) override {
532  if (p_info) p_info->setAudioInfo(info);
533  calculateByteLimits();
534  }
535 
536  int availableForWrite() override {
537  return current_bytes < end_bytes ? p_print->availableForWrite() : 0;
538  }
539 
542  void setCompressionRatio(float ratio) { compression_ratio = ratio; }
543 
546  return info.sample_rate * info.channels * info.bits_per_sample / 8;
547  }
548 
549  void setOutput(Print &out) { p_print = &out; }
550 
551  void setStream(Stream &stream) {
552  p_print = &stream;
553  p_stream = &stream;
554  }
555 
556  void setOutput(AudioOutput &out) {
557  p_print = &out;
558  p_info = &out;
559  }
560 
561  void setStream(AudioOutput &out) {
562  p_print = &out;
563  p_info = &out;
564  }
565 
566  void setStream(AudioStream &stream) {
567  p_print = &stream;
568  p_stream = &stream;
569  p_info = &stream;
570  }
571 
572  size_t size() {
573  return end_bytes - start_bytes;
574  }
575 
576  protected:
577  Stream *p_stream = nullptr;
578  Print *p_print = nullptr;
579  AudioInfoSupport *p_info = nullptr;
580  uint32_t start_ms = 0;
581  uint32_t end_ms = UINT32_MAX;
582  uint32_t start_bytes = 0;
583  uint32_t end_bytes = UINT32_MAX;
584  uint32_t current_bytes = 0;
585  float compression_ratio = 1.0;
586 
587  void consumeBytes(uint32_t len){
588  int open = len;
589  uint8_t buffer[1024];
590  while (open > 0){
591  int toread = min(1024, open);
592  p_stream->readBytes(buffer, toread);
593  open -= toread;
594  }
595  current_bytes += len;
596  LOGD("consumed %u -> %u",(unsigned) len, (unsigned)current_bytes);
597  }
598 
599  void calculateByteLimits() {
600  float bytes_per_second = bytesPerSecond();
601  if (bytes_per_second > 0) {
602  start_bytes = bytes_per_second * start_ms / compression_ratio / 1000;
603  end_bytes = bytes_per_second * end_ms / compression_ratio / 1000;
604  } else {
605  LOGE("AudioInfo not defined");
606  }
607  }
608 };
609 
620  public:
621  ChannelsSelectOutput() = default;
622 
623  bool begin(AudioInfo info) {
624  setAudioInfo(info);
625  return begin();
626  }
627 
628  bool begin() {
629  AudioOutput::begin();
630  // make sure that selected channels are valid
631  for (auto &out : out_channels) {
632  for (auto &ch : out.channels) {
633  if (ch > cfg.channels - 1) {
634  LOGE("Channel '%d' not valid for max %d channels", ch, cfg.channels);
635  return false;
636  }
637  }
638  }
639  return true;
640  }
641 
644  void addOutput(AudioOutput &out, uint16_t channel) {
645  Vector<uint16_t> channels;
646  channels.push_back(channel);
648  def.channels = channels;
649  def.p_out = &out;
650  def.p_audio_info = &out;
651  out_channels.push_back(def);
652  }
653 
656  void addOutput(AudioStream &out, uint16_t channel) {
657  Vector<uint16_t> channels;
658  channels.push_back(channel);
660  def.channels = channels;
661  def.p_out = &out;
662  def.p_audio_info = &out;
663  out_channels.push_back(def);
664  }
665 
668  void addOutput(Print &out, uint16_t channel) {
669  Vector<uint16_t> channels;
670  channels.push_back(channel);
672  def.channels = channels;
673  def.p_out = &out;
674  out_channels.push_back(def);
675  }
676 
679  void addOutput(Print &out, uint16_t left, uint16_t right) {
680  Vector<uint16_t> channels;
681  channels.push_back(left);
682  channels.push_back(right);
684  def.channels = channels;
685  def.p_out = &out;
686  out_channels.push_back(def);
687  }
688 
691  void addOutput(AudioOutput &out, uint16_t left, uint16_t right) {
692  Vector<uint16_t> channels;
693  channels.push_back(left);
694  channels.push_back(right);
696  def.channels = channels;
697  def.p_out = &out;
698  def.p_audio_info = &out;
699  out_channels.push_back(def);
700  }
701 
704  void addOutput(AudioStream &out, uint16_t left, uint16_t right) {
705  Vector<uint16_t> channels;
706  channels.push_back(left);
707  channels.push_back(right);
709  def.channels = channels;
710  def.p_out = &out;
711  def.p_audio_info = &out;
712  out_channels.push_back(def);
713  }
714 
715  size_t write(const uint8_t *data, size_t len) override {
716  if (!is_active) return false;
717  LOGD("write %d", (int)len);
718  switch (cfg.bits_per_sample) {
719  case 16:
720  return writeT<int16_t>(data, len);
721  case 24:
722  return writeT<int24_t>(data, len);
723  case 32:
724  return writeT<int32_t>(data, len);
725  default:
726  return 0;
727  }
728  }
729 
730  void setAudioInfo(AudioInfo ai) override {
731  this->cfg = ai;
732  //notifyAudioChange(ai);
733  for (auto &info : out_channels) {
734  auto p_notify = info.p_audio_info;
735  if (p_notify != nullptr) {
736  AudioInfo result{ai};
737  result.channels = info.channels.size();
738  p_notify->setAudioInfo(result);
739  }
740  }
741  }
742 
743  protected:
745  Print *p_out = nullptr;
746  AudioInfoSupport *p_audio_info = nullptr;
747  SingleBuffer<uint8_t> buffer{CHANNEL_SELECT_BUFFER_SIZE};
748  Vector<uint16_t> channels{0};
749  };
750  Vector<ChannelSelectionOutputDef> out_channels{0};
751 
752  template <typename T>
753  size_t writeT(const uint8_t *buffer, size_t size) {
754  if (!is_active) return 0;
755  int sample_count = size / sizeof(T);
756  //int result_size = sample_count / cfg.channels;
757  T *data = (T *)buffer;
758 
759  for (int i = 0; i < sample_count; i += cfg.channels) {
760  T *frame = data + i;
761  for (auto &out : out_channels) {
762  T out_frame[out.channels.size()] = {0};
763  int ch_out = 0;
764  for (auto &ch : out.channels) {
765  // make sure we have a valid channel
766  int channel = (ch < cfg.channels) ? ch : cfg.channels - 1;
767  out_frame[ch_out++] = frame[channel];
768  }
769  // write to buffer
770  size_t written = out.buffer.writeArray((const uint8_t *)&out_frame, sizeof(out_frame));
771  // write buffer to final output
772  if (out.buffer.availableForWrite()<sizeof(out_frame)){
773  out.p_out->write(out.buffer.data(), out.buffer.available());
774  out.buffer.reset();
775  }
776  // if (written != sizeof(out_frame)) {
777  // LOGW("Could not write all samples %d -> %d", sizeof(out_frame), written);
778  // }
779  }
780  }
781  return size;
782  }
783 
785  int getChannels(Print *out, int defaultChannels) {
786  for (auto &channels_select : out_channels) {
787  if (channels_select.p_out == out) return channels_select.channels.size();
788  }
789  return defaultChannels;
790  }
791 };
792 
793 } // namespace audio_tools
Wrapper which converts a AudioStream to a AudioOutput.
Definition: AudioIO.h:283
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioIO.h:304
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioIO.h:291
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioIO.h:293
Wrapper which converts a AudioStream to a AudioOutput.
Definition: AudioIO.h:248
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioIO.h:271
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioIO.h:256
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioIO.h:258
Wrapper which converts a Print to a AudioOutput.
Definition: AudioIO.h:230
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioIO.h:238
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioIO.h:233
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
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
Base class for Output Adpapters.
Definition: AudioIO.h:224
Abstract Audio Ouptut class.
Definition: AudioOutput.h:22
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioOutput.h:57
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
Flexible functionality to extract one or more channels from a multichannel signal....
Definition: AudioIO.h:619
void addOutput(Print &out, uint16_t left, uint16_t right)
Definition: AudioIO.h:679
void setAudioInfo(AudioInfo ai) override
Defines the input AudioInfo.
Definition: AudioIO.h:730
void addOutput(Print &out, uint16_t channel)
Definition: AudioIO.h:668
void addOutput(AudioOutput &out, uint16_t channel)
Definition: AudioIO.h:644
int getChannels(Print *out, int defaultChannels)
Determine number of channels for destination.
Definition: AudioIO.h:785
void addOutput(AudioStream &out, uint16_t channel)
Definition: AudioIO.h:656
void addOutput(AudioStream &out, uint16_t left, uint16_t right)
Definition: AudioIO.h:704
void addOutput(AudioOutput &out, uint16_t left, uint16_t right)
Definition: AudioIO.h:691
Abstract class: Objects can be put into a pipleline.
Definition: AudioOutput.h:97
Abstract class: Objects can be put into a pipleline.
Definition: AudioStreams.h:69
Replicates the output to multiple destinations.
Definition: AudioIO.h:318
void add(AudioOutput &out)
Add an additional AudioOutput output.
Definition: AudioIO.h:358
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioIO.h:378
void add(AudioStream &stream)
Add an AudioStream to the output.
Definition: AudioIO.h:361
MultiOutput(AudioStream &out1, AudioStream &out2)
Defines a MultiOutput with 2 final outputs.
Definition: AudioIO.h:337
MultiOutput(AudioOutput &out1, AudioOutput &out2)
Defines a MultiOutput with 2 final outputs.
Definition: AudioIO.h:331
MultiOutput(AudioOutput &out)
Defines a MultiOutput with a single final outputs,.
Definition: AudioIO.h:326
void setOutput(Print &out)
support for Pipleline
Definition: AudioIO.h:410
MultiOutput(Print &out1, Print &out2)
Definition: AudioIO.h:344
MultiOutput()=default
Defines a MultiOutput with no final output: Define your outputs with add()
Definition: NoArduino.h:58
virtual bool begin()
Activates the output.
Definition: BaseStream.h:318
Base class for chained converting streams.
Definition: AudioIO.h:142
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition: AudioIO.h:144
virtual void setOutput(Print &print) override
Defines/Changes the output target.
Definition: AudioIO.h:164
virtual size_t size()
Returns the maximum capacity of the buffer.
Definition: Buffers.h:383
Definition: NoArduino.h:125
AudioStream class that can define a start and (an optional) stop time Usually it is used to wrap an A...
Definition: AudioIO.h:422
void setEndSec(uint32_t endSeconds)
Definition: AudioIO.h:456
void setEndMs(uint32_t ms)
Defines the (optional) end time in milliseconds.
Definition: AudioIO.h:462
void setCompressionRatio(float ratio)
Definition: AudioIO.h:542
size_t readBytes(uint8_t *data, size_t len) override
Definition: AudioIO.h:496
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioIO.h:551
void setStartSec(uint32_t startSeconds)
Definition: AudioIO.h:443
int available() override
Provides the available bytes until the end time has reached.
Definition: AudioIO.h:524
size_t write(const uint8_t *data, size_t len) override
Plays only data for the indiated start and end time.
Definition: AudioIO.h:516
void setStartMs(uint32_t ms)
Defines the start time in milliseconds.
Definition: AudioIO.h:449
bool isPlaying()
Returns true if we are in a valid time range and are still playing sound.
Definition: AudioIO.h:468
bool isActive()
Returns true if we are not past the end time;.
Definition: AudioIO.h:475
void setAudioInfo(AudioInfo info) override
Updates the AudioInfo in the current object and in the source or target.
Definition: AudioIO.h:530
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioIO.h:549
int bytesPerSecond()
Calculates the bytes per second from the AudioInfo.
Definition: AudioIO.h:545
ConverterStream Helper class which implements the readBytes with the help of write.
Definition: AudioIO.h:23
void begin(T *transform, Stream *source)
setup of the TransformationReader class
Definition: AudioIO.h:29
void restoreOutput(Print *out)
restores the original output in the converter class
Definition: AudioIO.h:131
Print * setupOutput()
Definition: AudioIO.h:123
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823
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