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 
45  void resizeReadBuffer(int size) {
46  buffer.resize(size);
47  }
49  void resizeResultQueue(int size) {
50  result_queue_buffer.resize(size);
51  result_queue.begin();
52  }
53 
54 
55  size_t readBytes(uint8_t *data, size_t len) {
56  LOGD("TransformationReader::readBytes: %d", (int)len);
57  if (!active) {
58  LOGE("inactive");
59  return 0;
60  }
61  if (p_stream == nullptr) {
62  LOGE("p_stream is NULL");
63  return 0;
64  }
65 
66  // we read half the necessary bytes
67  if (buffer.size() == 0) {
68  int size = (0.5f / p_transform->getByteFactor() * len);
69  // process full samples/frames
70  size = size / 4 * 4;
71  LOGI("read size: %d", size);
72  buffer.resize(size);
73  }
74 
75  if (result_queue_buffer.size() == 0) {
76  // make sure that the ring buffer is big enough
77  int rb_size = len * result_queue_factor;
78  LOGI("buffer size: %d", rb_size);
79  result_queue_buffer.resize(rb_size);
80  result_queue.begin();
81  }
82 
83  if (result_queue.available() < len) {
84  Print *tmp = setupOutput();
85  int zero_count = 0;
86  while (result_queue.available() < len) {
87  int read_eff = p_stream->readBytes(buffer.data(), buffer.size());
88  if (read_eff > 0) {
89  zero_count = 0; // reset 0 count
90  if (read_eff != buffer.size())
91  LOGD("readBytes %d -> %d", buffer.size(), read_eff);
92  int write_eff = p_transform->write(buffer.data(), read_eff);
93  if (write_eff != read_eff)
94  LOGE("write %d -> %d", read_eff, write_eff);
95  } else {
96  // limit the number of reads which provide 0;
97  if (++zero_count > MAX_ZERO_READ_COUNT){
98  break;
99  }
100  // wait for some more data
101  delay(5);
102  }
103  }
104  restoreOutput(tmp);
105  }
106 
107  int result_len = min((int)len, result_queue.available());
108  result_len = result_queue.readBytes(data, result_len);
109  LOGD("TransformationReader::readBytes: %d -> %d", (int)len,
110  result_len);
111 
112  return result_len;
113  }
114 
115  void end() {
116  result_queue_buffer.resize(0);
117  buffer.resize(0);
118  }
119 
121  void setResultQueueFactor(int factor) { result_queue_factor = factor; }
122 
123  protected:
124  RingBuffer<uint8_t> result_queue_buffer{0};
125  QueueStream<uint8_t> result_queue{result_queue_buffer}; //
126  Stream *p_stream = nullptr;
127  Vector<uint8_t> buffer{0}; // we allocate memory only when needed
128  T *p_transform = nullptr;
129  bool active = false;
130  int result_queue_factor = 5;
131 
136  Print *result = p_transform->getPrint();
137  p_transform->setOutput((Print &)result_queue);
138 
139  return result;
140  }
143  void restoreOutput(Print *out) {
144  if (out) p_transform->setOutput(*out);
145  }
146 };
147 
155  public:
156  virtual void setStream(Stream &stream) override {
157  TRACED();
158  p_stream = &stream;
159  p_print = &stream;
160  }
161 
162  virtual void setStream(AudioStream &stream) {
163  TRACED();
164  p_stream = &stream;
165  p_print = &stream;
166  //setNotifyOnOutput(stream);
167  addNotifyAudioChange(stream);
168  }
169 
170  virtual void setOutput(AudioOutput &print) {
171  TRACED();
172  p_print = &print;
173  addNotifyAudioChange(print);
174  }
175 
176  virtual void setOutput(Print &print) override {
177  TRACED();
178  p_print = &print;
179  }
180 
181  virtual Print *getPrint() { return p_print; }
182 
183  virtual Stream *getStream() { return p_stream; }
184 
185  size_t readBytes(uint8_t *data, size_t len) override {
186  LOGD("ReformatBaseStream::readBytes: %d", (int)len);
187  return reader.readBytes(data, len);
188  }
189 
190  int available() override {
191  return DEFAULT_BUFFER_SIZE; // reader.availableForWrite();
192  }
193 
194  int availableForWrite() override {
195  return DEFAULT_BUFFER_SIZE; // reader.availableForWrite();
196  }
197 
198  virtual float getByteFactor() = 0;
199 
200  void end() override {
201  TRACED();
202  AudioStream::end();
203  reader.end();
204  }
205 
208 
209  protected:
211  Stream *p_stream = nullptr;
212  Print *p_print = nullptr;
213 
214  void setupReader() {
215  if (getStream() != nullptr) {
216  reader.begin(this, getStream());
217  }
218  }
219 };
220 
225 class AudioOutputAdapter : public AudioOutput {};
226 
232  public:
233  AdapterPrintToAudioOutput(Print &print) { p_print = &print; }
234  void setAudioInfo(AudioInfo info) {}
235  size_t write(const uint8_t *data, size_t len) {
236  return p_print->write(data, len);
237  }
239  virtual bool isDeletable() { return true; }
240 
241  protected:
242  Print *p_print = nullptr;
243 };
244 
250  public:
252 
253  AdapterAudioStreamToAudioOutput(AudioStream &stream) { setStream(stream); }
254 
255  void setStream(AudioStream &stream) { p_stream = &stream; }
256 
257  void setAudioInfo(AudioInfo info) override { p_stream->setAudioInfo(info); }
258 
259  AudioInfo audioInfo() override { return p_stream->audioInfo(); }
260 
261  size_t write(const uint8_t *data, size_t len) override {
262  return p_stream->write(data, len);
263  }
264 
265  int availableForWrite() override { return p_stream->availableForWrite(); }
266 
267  bool begin() override { return p_stream->begin(); }
268 
269  void end() override { p_stream->end(); }
270 
272  virtual bool isDeletable() { return true; }
273 
274  operator bool() override { return *p_stream; }
275 
276  protected:
277  AudioStream *p_stream = nullptr;
278 };
279 
285  public:
287 
288  AdapterAudioOutputToAudioStream(AudioOutput &stream) { setOutput(stream); }
289 
290  void setOutput(AudioOutput &stream) { p_stream = &stream; }
291 
292  void setAudioInfo(AudioInfo info) override { p_stream->setAudioInfo(info); }
293 
294  AudioInfo audioInfo() override { return p_stream->audioInfo(); }
295 
296  size_t write(const uint8_t *data, size_t len) override {
297  return p_stream->write(data, len);
298  }
299 
300  bool begin() override { return p_stream->begin(); }
301 
302  void end() override { p_stream->end(); }
303 
305  virtual bool isDeletable() { return true; }
306 
307  operator bool() override { return *p_stream; }
308 
309  protected:
310  AudioOutput *p_stream = nullptr;
311 };
312 
319 class MultiOutput : public ModifyingOutput {
320  public:
322  MultiOutput() = default;
323 
324  MultiOutput(Print &out) { add(out); }
325 
327  MultiOutput(AudioOutput &out) { add(out); }
328 
329  MultiOutput(AudioStream &out) { add(out); }
330 
333  add(out1);
334  add(out2);
335  }
336 
339  add(out1);
340  add(out2);
341  }
342 
345  MultiOutput(Print &out1, Print &out2) {
346  add(out1);
347  add(out2);
348  }
349 
350  virtual ~MultiOutput() {
351  for (int j = 0; j < vector.size(); j++) {
352  if (vector[j]->isDeletable()) {
353  delete vector[j];
354  }
355  }
356  }
357 
359  void add(AudioOutput &out) { vector.push_back(&out); }
360 
362  void add(AudioStream &stream) {
365  vector.push_back(out);
366  }
367 
368  void add(Print &print) {
370  vector.push_back(out);
371  }
372 
373  void flush() {
374  for (int j = 0; j < vector.size(); j++) {
375  vector[j]->flush();
376  }
377  }
378 
379  void setAudioInfo(AudioInfo info) {
380  for (int j = 0; j < vector.size(); j++) {
381  vector[j]->setAudioInfo(info);
382  }
383  }
384 
385  size_t write(const uint8_t *data, size_t len) {
386  for (int j = 0; j < vector.size(); j++) {
387  int open = len;
388  int start = 0;
389  while (open > 0) {
390  int written = vector[j]->write(data + start, open);
391  open -= written;
392  start += written;
393  }
394  }
395  return len;
396  }
397 
398  size_t write(uint8_t ch) {
399  for (int j = 0; j < vector.size(); j++) {
400  int open = 1;
401  while (open > 0) {
402  open -= vector[j]->write(ch);
403  }
404  }
405  return 1;
406  }
407 
408  protected:
409  Vector<AudioOutput *> vector;
411  void setOutput(Print &out) { add(out); }
412 };
413 
423 class TimedStream : public ModifyingStream {
424  public:
425  TimedStream() = default;
426 
427  TimedStream(AudioStream &io, long startSeconds = 0, long endSeconds = -1) {
428  p_stream = &io;
429  p_print = &io;
430  p_info = &io;
431  setStartSec(startSeconds);
432  setEndSec(endSeconds);
433  }
434 
435  TimedStream(AudioOutput &o, long startSeconds = 0, long endSeconds = -1) {
436  p_print = &o;
437  p_info = &o;
438  setStartSec(startSeconds);
439  setEndSec(endSeconds);
440  }
441 
444  void setStartSec(uint32_t startSeconds) {
445  start_ms = startSeconds * 1000;
446  calculateByteLimits();
447  }
448 
450  void setStartMs(uint32_t ms) {
451  start_ms = ms;
452  calculateByteLimits();
453  }
454 
457  void setEndSec(uint32_t endSeconds) {
458  end_ms = endSeconds * 1000;
459  calculateByteLimits();
460  }
461 
463  void setEndMs(uint32_t ms) {
464  end_ms = ms;
465  calculateByteLimits();
466  }
467 
469  bool isPlaying() {
470  if (current_bytes < start_bytes) return false;
471  if (end_bytes > 0 && current_bytes > end_bytes) return false;
472  return true;
473  }
474 
476  bool isActive() {
477  return (current_bytes < end_bytes && current_bytes >= start_bytes);
478  }
479 
480  bool begin(AudioInfo info) {
481  setAudioInfo(info);
482  return begin();
483  }
484 
485  bool begin() override {
486  calculateByteLimits();
487  current_bytes = 0;
488  LOGI("byte range %u - %u",(unsigned) start_bytes,(unsigned) end_bytes);
489  return true;
490  }
491 
492  operator bool() { return isActive(); }
493 
497  size_t readBytes(uint8_t *data, size_t len) override {
498  // if reading is not supported we stop
499  if (p_stream == nullptr) return 0;
500  // Positioin to start
501  if (start_bytes > current_bytes){
502  consumeBytes(start_bytes - current_bytes);
503  }
504  // if we are past the end we stop
505  if (!isActive()) return 0;
506  // read the data now
507  size_t result = 0;
508  do {
509  result = p_stream->readBytes(data, len);
510  current_bytes += len;
511  // ignore data before start time
512  } while (result > 0 && current_bytes < start_bytes);
513  return isPlaying() ? result : 0;
514  }
515 
517  size_t write(const uint8_t *data, size_t len) override {
518  if (current_bytes >= end_bytes) return 0;
519  current_bytes += len;
520  if (current_bytes < start_bytes) return len;
521  return p_print->write(data, len);
522  }
523 
525  int available() override {
526  if (p_stream == nullptr) return 0;
527  return current_bytes < end_bytes ? p_stream->available() : 0;
528  }
529 
531  void setAudioInfo(AudioInfo info) override {
533  if (p_info) p_info->setAudioInfo(info);
534  calculateByteLimits();
535  }
536 
537  int availableForWrite() override {
538  return current_bytes < end_bytes ? p_print->availableForWrite() : 0;
539  }
540 
543  void setCompressionRatio(float ratio) { compression_ratio = ratio; }
544 
547  return info.sample_rate * info.channels * info.bits_per_sample / 8;
548  }
549 
550  void setOutput(Print &out) { p_print = &out; }
551 
552  void setStream(Stream &stream) {
553  p_print = &stream;
554  p_stream = &stream;
555  }
556 
557  void setOutput(AudioOutput &out) {
558  p_print = &out;
559  p_info = &out;
560  }
561 
562  void setStream(AudioOutput &out) {
563  p_print = &out;
564  p_info = &out;
565  }
566 
567  void setStream(AudioStream &stream) {
568  p_print = &stream;
569  p_stream = &stream;
570  p_info = &stream;
571  }
572 
573  size_t size() {
574  return end_bytes - start_bytes;
575  }
576 
577  protected:
578  Stream *p_stream = nullptr;
579  Print *p_print = nullptr;
580  AudioInfoSupport *p_info = nullptr;
581  uint32_t start_ms = 0;
582  uint32_t end_ms = UINT32_MAX;
583  uint32_t start_bytes = 0;
584  uint32_t end_bytes = UINT32_MAX;
585  uint32_t current_bytes = 0;
586  float compression_ratio = 1.0;
587 
588  void consumeBytes(uint32_t len){
589  int open = len;
590  uint8_t buffer[1024];
591  while (open > 0){
592  int toread = min(1024, open);
593  p_stream->readBytes(buffer, toread);
594  open -= toread;
595  }
596  current_bytes += len;
597  LOGD("consumed %u -> %u",(unsigned) len, (unsigned)current_bytes);
598  }
599 
600  void calculateByteLimits() {
601  float bytes_per_second = bytesPerSecond();
602  if (bytes_per_second > 0) {
603  start_bytes = bytes_per_second * start_ms / compression_ratio / 1000;
604  end_bytes = bytes_per_second * end_ms / compression_ratio / 1000;
605  } else {
606  LOGE("AudioInfo not defined");
607  }
608  }
609 };
610 
621  public:
622  ChannelsSelectOutput() = default;
623 
624  bool begin(AudioInfo info) {
625  setAudioInfo(info);
626  return begin();
627  }
628 
629  bool begin() {
630  AudioOutput::begin();
631  // make sure that selected channels are valid
632  for (auto &out : out_channels) {
633  for (auto &ch : out.channels) {
634  if (ch > cfg.channels - 1) {
635  LOGE("Channel '%d' not valid for max %d channels", ch, cfg.channels);
636  return false;
637  }
638  }
639  }
640  return true;
641  }
642 
645  void addOutput(AudioOutput &out, uint16_t channel) {
646  Vector<uint16_t> channels;
647  channels.push_back(channel);
649  def.channels = channels;
650  def.p_out = &out;
651  def.p_audio_info = &out;
652  out_channels.push_back(def);
653  }
654 
657  void addOutput(AudioStream &out, uint16_t channel) {
658  Vector<uint16_t> channels;
659  channels.push_back(channel);
661  def.channels = channels;
662  def.p_out = &out;
663  def.p_audio_info = &out;
664  out_channels.push_back(def);
665  }
666 
669  void addOutput(Print &out, uint16_t channel) {
670  Vector<uint16_t> channels;
671  channels.push_back(channel);
673  def.channels = channels;
674  def.p_out = &out;
675  out_channels.push_back(def);
676  }
677 
680  void addOutput(Print &out, uint16_t left, uint16_t right) {
681  Vector<uint16_t> channels;
682  channels.push_back(left);
683  channels.push_back(right);
685  def.channels = channels;
686  def.p_out = &out;
687  out_channels.push_back(def);
688  }
689 
692  void addOutput(AudioOutput &out, uint16_t left, uint16_t right) {
693  Vector<uint16_t> channels;
694  channels.push_back(left);
695  channels.push_back(right);
697  def.channels = channels;
698  def.p_out = &out;
699  def.p_audio_info = &out;
700  out_channels.push_back(def);
701  }
702 
705  void addOutput(AudioStream &out, uint16_t left, uint16_t right) {
706  Vector<uint16_t> channels;
707  channels.push_back(left);
708  channels.push_back(right);
710  def.channels = channels;
711  def.p_out = &out;
712  def.p_audio_info = &out;
713  out_channels.push_back(def);
714  }
715 
716  size_t write(const uint8_t *data, size_t len) override {
717  if (!is_active) return false;
718  LOGD("write %d", (int)len);
719  switch (cfg.bits_per_sample) {
720  case 16:
721  return writeT<int16_t>(data, len);
722  case 24:
723  return writeT<int24_t>(data, len);
724  case 32:
725  return writeT<int32_t>(data, len);
726  default:
727  return 0;
728  }
729  }
730 
731  void setAudioInfo(AudioInfo ai) override {
732  this->cfg = ai;
733  //notifyAudioChange(ai);
734  for (auto &info : out_channels) {
735  auto p_notify = info.p_audio_info;
736  if (p_notify != nullptr) {
737  AudioInfo result{ai};
738  result.channels = info.channels.size();
739  p_notify->setAudioInfo(result);
740  }
741  }
742  }
743 
744  protected:
746  Print *p_out = nullptr;
747  AudioInfoSupport *p_audio_info = nullptr;
748  SingleBuffer<uint8_t> buffer{CHANNEL_SELECT_BUFFER_SIZE};
749  Vector<uint16_t> channels{0};
750  };
751  Vector<ChannelSelectionOutputDef> out_channels{0};
752 
753  template <typename T>
754  size_t writeT(const uint8_t *buffer, size_t size) {
755  if (!is_active) return 0;
756  int sample_count = size / sizeof(T);
757  //int result_size = sample_count / cfg.channels;
758  T *data = (T *)buffer;
759 
760  for (int i = 0; i < sample_count; i += cfg.channels) {
761  T *frame = data + i;
762  for (auto &out : out_channels) {
763  T out_frame[out.channels.size()] = {0};
764  int ch_out = 0;
765  for (auto &ch : out.channels) {
766  // make sure we have a valid channel
767  int channel = (ch < cfg.channels) ? ch : cfg.channels - 1;
768  out_frame[ch_out++] = frame[channel];
769  }
770  // write to buffer
771  size_t written = out.buffer.writeArray((const uint8_t *)&out_frame, sizeof(out_frame));
772  // write buffer to final output
773  if (out.buffer.availableForWrite()<sizeof(out_frame)){
774  out.p_out->write(out.buffer.data(), out.buffer.available());
775  out.buffer.reset();
776  }
777  // if (written != sizeof(out_frame)) {
778  // LOGW("Could not write all samples %d -> %d", sizeof(out_frame), written);
779  // }
780  }
781  }
782  return size;
783  }
784 
786  int getChannels(Print *out, int defaultChannels) {
787  for (auto &channels_select : out_channels) {
788  if (channels_select.p_out == out) return channels_select.channels.size();
789  }
790  return defaultChannels;
791  }
792 };
793 
794 } // namespace audio_tools
Wrapper which converts a AudioStream to a AudioOutput.
Definition: AudioIO.h:284
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioIO.h:305
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioIO.h:292
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioIO.h:294
Wrapper which converts a AudioStream to a AudioOutput.
Definition: AudioIO.h:249
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioIO.h:272
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioIO.h:257
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioIO.h:259
Wrapper which converts a Print to a AudioOutput.
Definition: AudioIO.h:231
virtual bool isDeletable()
If true we need to release the related memory in the destructor.
Definition: AudioIO.h:239
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioIO.h:234
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:225
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:620
void addOutput(Print &out, uint16_t left, uint16_t right)
Definition: AudioIO.h:680
void setAudioInfo(AudioInfo ai) override
Defines the input AudioInfo.
Definition: AudioIO.h:731
void addOutput(Print &out, uint16_t channel)
Definition: AudioIO.h:669
void addOutput(AudioOutput &out, uint16_t channel)
Definition: AudioIO.h:645
int getChannels(Print *out, int defaultChannels)
Determine number of channels for destination.
Definition: AudioIO.h:786
void addOutput(AudioStream &out, uint16_t channel)
Definition: AudioIO.h:657
void addOutput(AudioStream &out, uint16_t left, uint16_t right)
Definition: AudioIO.h:705
void addOutput(AudioOutput &out, uint16_t left, uint16_t right)
Definition: AudioIO.h:692
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:319
void add(AudioOutput &out)
Add an additional AudioOutput output.
Definition: AudioIO.h:359
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioIO.h:379
void add(AudioStream &stream)
Add an AudioStream to the output.
Definition: AudioIO.h:362
MultiOutput(AudioStream &out1, AudioStream &out2)
Defines a MultiOutput with 2 final outputs.
Definition: AudioIO.h:338
MultiOutput(AudioOutput &out1, AudioOutput &out2)
Defines a MultiOutput with 2 final outputs.
Definition: AudioIO.h:332
MultiOutput(AudioOutput &out)
Defines a MultiOutput with a single final outputs,.
Definition: AudioIO.h:327
void setOutput(Print &out)
support for Pipleline
Definition: AudioIO.h:411
MultiOutput(Print &out1, Print &out2)
Definition: AudioIO.h:345
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:154
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition: AudioIO.h:156
virtual void setOutput(Print &print) override
Defines/Changes the output target.
Definition: AudioIO.h:176
virtual TransformationReader< ReformatBaseStream > & transformationReader()
Provides access to the TransformationReader.
Definition: AudioIO.h:207
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:423
void setEndSec(uint32_t endSeconds)
Definition: AudioIO.h:457
void setEndMs(uint32_t ms)
Defines the (optional) end time in milliseconds.
Definition: AudioIO.h:463
void setCompressionRatio(float ratio)
Definition: AudioIO.h:543
size_t readBytes(uint8_t *data, size_t len) override
Definition: AudioIO.h:497
void setStream(Stream &stream)
Defines/Changes the input & output.
Definition: AudioIO.h:552
void setStartSec(uint32_t startSeconds)
Definition: AudioIO.h:444
int available() override
Provides the available bytes until the end time has reached.
Definition: AudioIO.h:525
size_t write(const uint8_t *data, size_t len) override
Plays only data for the indiated start and end time.
Definition: AudioIO.h:517
void setStartMs(uint32_t ms)
Defines the start time in milliseconds.
Definition: AudioIO.h:450
bool isPlaying()
Returns true if we are in a valid time range and are still playing sound.
Definition: AudioIO.h:469
bool isActive()
Returns true if we are not past the end time;.
Definition: AudioIO.h:476
void setAudioInfo(AudioInfo info) override
Updates the AudioInfo in the current object and in the source or target.
Definition: AudioIO.h:531
void setOutput(Print &out)
Defines/Changes the output target.
Definition: AudioIO.h:550
int bytesPerSecond()
Calculates the bytes per second from the AudioInfo.
Definition: AudioIO.h:546
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 resizeReadBuffer(int size)
Defines the read buffer size for individual reads.
Definition: AudioIO.h:45
void restoreOutput(Print *out)
restores the original output in the converter class
Definition: AudioIO.h:143
Print * setupOutput()
Definition: AudioIO.h:135
void resizeResultQueue(int size)
Defines the queue size for result.
Definition: AudioIO.h:49
void setResultQueueFactor(int factor)
Defines the queue size dependent on the read size.
Definition: AudioIO.h:121
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