arduino-audio-tools
AudioStreamsConverter.h
1 #pragma once
2 #include "AudioIO.h"
3 #include "AudioTools/CoreAudio/AudioStreams.h"
4 #include "AudioTools/CoreAudio/ResampleStream.h"
5 
6 namespace audio_tools {
7 
14 template <typename T>
16  public:
17  ChannelFormatConverterStreamT(Stream &stream) { setStream(stream); }
18  ChannelFormatConverterStreamT(Print &print) { setOutput(print); }
21  ChannelFormatConverterStreamT const &) = delete;
22 
23  bool begin(int fromChannels, int toChannels) {
24  LOGI("begin %d -> %d channels", fromChannels, toChannels);
25  //is_output_notify = false;
26  from_channels = fromChannels;
27  to_channels = toChannels;
28  factor = static_cast<float>(toChannels) / static_cast<float>(fromChannels);
29 
30  converter.setSourceChannels(from_channels);
31  converter.setTargetChannels(to_channels);
32 
33  return true;
34  }
35 
36  bool begin() { return begin(from_channels, to_channels); }
37 
38  void setToChannels(uint16_t channels) { to_channels = channels; }
39 
40  virtual size_t write(const uint8_t *data, size_t len) override {
41  TRACED();
42  if (p_print == nullptr) return 0;
43  //addNotifyOnFirstWrite();
44  if (from_channels == to_channels) {
45  return p_print->write(data, len);
46  }
47  size_t resultBytes = convert(data, len);
48  //assert(resultBytes == factor * len);
49  p_print->write((uint8_t *)buffer.data(), resultBytes);
50  return len;
51  }
52 
53  size_t readBytes(uint8_t *data, size_t len) override {
54  TRACED();
55  if (p_stream == nullptr) return 0;
56  if (from_channels == to_channels) {
57  return p_stream->readBytes(data, len);
58  }
59  size_t in_bytes = 1.0f / factor * len;
60  bufferTmp.resize(in_bytes);
61  p_stream->readBytes(bufferTmp.data(), in_bytes);
62  size_t resultBytes = convert(bufferTmp.data(), in_bytes);
63  assert(len == resultBytes);
64  memcpy(data, (uint8_t *)buffer.data(), len);
65  return len;
66  }
67 
68  void setAudioInfo(AudioInfo cfg) override {
69  from_channels = cfg.channels;
71  }
72 
74  AudioInfo audioInfoOut() override {
75  AudioInfo out = audioInfo();
76  out.channels = to_channels;
77  return out;
78  }
79 
80  virtual int available() override {
81  return p_stream != nullptr ? p_stream->available() : 0;
82  }
83 
84  virtual int availableForWrite() override {
85  if (p_print == nullptr) return 0;
86  return 1.0f / factor * p_print->availableForWrite();
87  }
88 
89  float getByteFactor() {
90  return static_cast<float>(to_channels) / static_cast<float>(from_channels);
91  }
92 
93  protected:
94  int from_channels = 2;
95  int to_channels = 2;
96  float factor = 1;
97  Vector<T> buffer{0};
98  Vector<uint8_t> bufferTmp{0};
99  ChannelConverter<T> converter;
100 
101  size_t convert(const uint8_t *in_data, size_t size) {
102  size_t result;
103  size_t result_samples = size / sizeof(T) * factor;
104  buffer.resize(result_samples);
105  result =
106  converter.convert((uint8_t *)buffer.data(), (uint8_t *)in_data, size);
107  if (result != result_samples * sizeof(T)) {
108  LOGE("size %d -> result: %d - expeced: %d", (int)size, (int)result,
109  static_cast<int>(result_samples * sizeof(T)));
110  }
111  return result;
112  }
113 };
114 
122  public:
123  ChannelFormatConverterStream() = default;
124  ChannelFormatConverterStream(Stream &stream) { setStream(stream); }
125  ChannelFormatConverterStream(Print &print) { setOutput(print); }
127  ChannelFormatConverterStream &operator=(
128  ChannelFormatConverterStream const &) = delete;
129 
130  void setAudioInfo(AudioInfo cfg) override {
131  TRACED();
132  from_channels = cfg.channels;
133  LOGI("--> ChannelFormatConverterStream");
135  switch (bits_per_sample) {
136  case 8:
137  getConverter<int8_t>()->setAudioInfo(cfg);
138  break;
139  case 16:
140  getConverter<int16_t>()->setAudioInfo(cfg);
141  break;
142  case 24:
143  getConverter<int24_t>()->setAudioInfo(cfg);
144  break;
145  case 32:
146  getConverter<int32_t>()->setAudioInfo(cfg);
147  break;
148  }
149  }
150 
152  AudioInfo audioInfoOut() override {
153  AudioInfo out = audioInfo();
154  out.channels = to_channels;
155  return out;
156  }
157 
158  bool begin(AudioInfo from, AudioInfo to) {
159  if (from.sample_rate != to.sample_rate){
160  LOGE("invalid sample_rate: %d", (int)to.sample_rate);
161  return false;
162  }
163  if (from.bits_per_sample != to.bits_per_sample){
164  LOGE("invalid bits_per_sample: %d", (int)to.bits_per_sample);
165  return false;
166  }
167  return begin(from, to.channels);
168  }
169 
170  bool begin(AudioInfo cfg, int toChannels) {
171  assert(toChannels != 0);
172  //is_output_notify = false;
173  to_channels = toChannels;
174  from_channels = cfg.channels;
175  bits_per_sample = cfg.bits_per_sample;
176  LOGI("--> ChannelFormatConverterStream");
178  LOGI("begin %d -> %d channels", cfg.channels, toChannels);
179  bool result = setupConverter(cfg.channels, toChannels);
180  if (!result) {
181  TRACEE()
182  }
183  return result;
184  }
185 
186  bool begin() { return begin(audioInfo(), to_channels); }
187 
188  void setToChannels(uint16_t channels) { to_channels = channels; }
189 
190  virtual size_t write(const uint8_t *data, size_t len) override {
191  LOGD("ChannelFormatConverterStream::write: %d", (int)len);
192  if (p_print == nullptr) return 0;
193  //addNotifyOnFirstWrite();
194  switch (bits_per_sample) {
195  case 8:
196  return getConverter<int8_t>()->write(data, len);
197  case 16:
198  return getConverter<int16_t>()->write(data, len);
199  case 24:
200  return getConverter<int24_t>()->write(data, len);
201  case 32:
202  return getConverter<int32_t>()->write(data, len);
203  default:
204  return 0;
205  }
206  }
207 
208  size_t readBytes(uint8_t *data, size_t len) override {
209  LOGD("ChannelFormatConverterStream::readBytes: %d", (int)len);
210  switch (bits_per_sample) {
211  case 8:
212  return getConverter<int8_t>()->readBytes(data, len);
213  case 16:
214  return getConverter<int16_t>()->readBytes(data, len);
215  case 24:
216  return getConverter<int24_t>()->readBytes(data, len);
217  case 32:
218  return getConverter<int32_t>()->readBytes(data, len);
219  default:
220  return 0;
221  }
222  }
223 
224  virtual int available() override {
225  switch (bits_per_sample) {
226  case 8:
227  return getConverter<int8_t>()->available();
228  case 16:
229  return getConverter<int16_t>()->available();
230  case 24:
231  return getConverter<int24_t>()->available();
232  case 32:
233  return getConverter<int32_t>()->available();
234  default:
235  return 0;
236  }
237  }
238 
239  virtual int availableForWrite() override {
240  switch (bits_per_sample) {
241  case 8:
242  return getConverter<int8_t>()->availableForWrite();
243  case 16:
244  return getConverter<int16_t>()->availableForWrite();
245  case 24:
246  return getConverter<int24_t>()->availableForWrite();
247  case 32:
248  return getConverter<int32_t>()->availableForWrite();
249  default:
250  return 0;
251  }
252  }
253 
254  float getByteFactor() {
255  return static_cast<float>(to_channels) / static_cast<float>(from_channels);
256  }
257 
258  protected:
259  void *converter;
260  int bits_per_sample = 0;
261  int to_channels;
262  int from_channels;
263 
264  template <typename T>
265  ChannelFormatConverterStreamT<T> *getConverter() {
266  return (ChannelFormatConverterStreamT<T> *)converter;
267  }
268 
269  bool setupConverter(int fromChannels, int toChannels) {
270  bool result = true;
271  if (p_stream != nullptr) {
272  switch (bits_per_sample) {
273  case 8:
274  converter = new ChannelFormatConverterStreamT<int8_t>(*p_stream);
275  getConverter<int8_t>()->begin(fromChannels, toChannels);
276  break;
277  case 16:
278  converter = new ChannelFormatConverterStreamT<int16_t>(*p_stream);
279  getConverter<int16_t>()->begin(fromChannels, toChannels);
280  break;
281  case 24:
282  converter = new ChannelFormatConverterStreamT<int24_t>(*p_stream);
283  getConverter<int24_t>()->begin(fromChannels, toChannels);
284  break;
285  case 32:
286  converter = new ChannelFormatConverterStreamT<int32_t>(*p_stream);
287  getConverter<int32_t>()->begin(fromChannels, toChannels);
288  break;
289  default:
290  result = false;
291  }
292  } else {
293  switch (bits_per_sample) {
294  case 8:
295  converter = new ChannelFormatConverterStreamT<int8_t>(*p_print);
296  getConverter<int8_t>()->begin(fromChannels, toChannels);
297  break;
298  case 16:
299  converter = new ChannelFormatConverterStreamT<int16_t>(*p_print);
300  getConverter<int16_t>()->begin(fromChannels, toChannels);
301  break;
302  case 24:
303  converter = new ChannelFormatConverterStreamT<int24_t>(*p_print);
304  getConverter<int24_t>()->begin(fromChannels, toChannels);
305  break;
306  case 32:
307  converter = new ChannelFormatConverterStreamT<int32_t>(*p_print);
308  getConverter<int32_t>()->begin(fromChannels, toChannels);
309  break;
310  default:
311  result = false;
312  }
313  }
314  return result;
315  }
316 };
317 
330 template <typename TFrom, typename TTo>
332  public:
333  NumberFormatConverterStreamT() = default;
334  NumberFormatConverterStreamT(float gain) { setGain(gain); }
335  NumberFormatConverterStreamT(Stream &stream) { setStream(stream); }
337  NumberFormatConverterStreamT(Print &print) { setOutput(print); }
338  NumberFormatConverterStreamT(AudioOutput &print) { setOutput(print); }
339 
340  void setAudioInfo(AudioInfo newInfo) override {
341  TRACED();
342  if (newInfo.bits_per_sample == sizeof(TFrom) * 8) {
343  LOGE("Invalid bits_per_sample %d", newInfo.bits_per_sample);
344  }
346  }
347 
348  AudioInfo audioInfoOut() override {
349  AudioInfo to_format;
350  to_format.copyFrom(info);
351  to_format.bits_per_sample = sizeof(TTo) * 8;
352  return to_format;
353  }
354 
355  bool begin() override {
356  LOGI("begin %d -> %d bits", (int)sizeof(TFrom), (int)sizeof(TTo));
357  //is_output_notify = false;
358  return true;
359  }
360 
361  virtual size_t write(const uint8_t *data, size_t len) override {
362  TRACED();
363  if (p_print == nullptr) return 0;
364  //addNotifyOnFirstWrite();
365 
366 #ifdef USE_TYPETRAITS
367  if (std::is_same<TFrom, TTo>::value) return p_print->write(data, len);
368 #else
369  if (sizeof(TFrom) == sizeof(TTo)) return p_print->write(data, len);
370 #endif
371 
372  size_t samples = len / sizeof(TFrom);
373  size_t result_size = 0;
374  TFrom *data_source = (TFrom *)data;
375 
376  if (!is_buffered) {
377  for (size_t j = 0; j < samples; j++) {
378  TTo value = NumberConverter::convert<TFrom, TTo>(data_source[j]);
379  result_size += p_print->write((uint8_t *)&value, sizeof(TTo));
380  }
381  } else {
382  int size_bytes = sizeof(TTo) * samples;
383  buffer.resize(size_bytes);
384  NumberConverter::convertArray<TFrom, TTo>(
385  data_source, (TTo *)buffer.data(), samples, gain);
386  p_print->write((uint8_t *)buffer.address(), size_bytes);
387  buffer.reset();
388  }
389 
390  return len;
391  }
392 
393  size_t readBytes(uint8_t *data, size_t len) override {
394  LOGD("NumberFormatConverterStreamT::readBytes: %d", (int)len);
395  if (p_stream == nullptr) return 0;
396  size_t samples = len / sizeof(TTo);
397  TTo *data_target = (TTo *)data;
398  TFrom source;
399  if (!is_buffered) {
400  for (size_t j = 0; j < samples; j++) {
401  source = 0;
402  p_stream->readBytes((uint8_t *)&source, sizeof(TFrom));
403  data_target[j] = NumberConverter::convert<TFrom, TTo>(source);
404  }
405  } else {
406  buffer.resize(sizeof(TFrom) * samples);
407  readSamples<TFrom>(p_stream, (TFrom *)buffer.address(), samples);
408  TFrom *data = (TFrom *)buffer.address();
409  NumberConverter::convertArray<TFrom, TTo>(data, data_target, samples,
410  gain);
411  buffer.reset();
412  }
413  return len;
414  }
415 
416  virtual int available() override {
417  return p_stream != nullptr ? p_stream->available() : 0;
418  }
419 
420  virtual int availableForWrite() override {
421  return p_print == nullptr ? 0 : p_print->availableForWrite();
422  }
423 
426  void setBuffered(bool flag) { is_buffered = flag; }
427 
429  void setGain(float value) { gain = value; }
430 
431  float getByteFactor() {
432  return static_cast<float>(sizeof(TTo)) / static_cast<float>(sizeof(TFrom));
433  }
434 
435  protected:
436  SingleBuffer<uint8_t> buffer{0};
437  bool is_buffered = true;
438  float gain = 1.0f;
439 };
440 
450  public:
451  NumberFormatConverterStream() = default;
452  NumberFormatConverterStream(Stream &stream) { setStream(stream); }
454  NumberFormatConverterStream(Print &print) { setOutput(print); }
455  NumberFormatConverterStream(AudioOutput &print) { setOutput(print); }
456 
457  void setAudioInfo(AudioInfo newInfo) override {
458  TRACED();
459  this->from_bit_per_samples = newInfo.bits_per_sample;
460  LOGI("-> NumberFormatConverterStream:")
461  AudioStream::setAudioInfo(newInfo);
462  }
463 
464  AudioInfo audioInfoOut() override {
465  AudioInfo result = audioInfo();
466  result.bits_per_sample = to_bit_per_samples;
467  return result;
468  }
469 
470  bool begin(AudioInfo info, AudioInfo to, float gain = 1.0f) {
471  if (info.sample_rate != to.sample_rate){
472  LOGE("sample_rate does not match")
473  return false;
474  }
475  if (info.channels != to.channels){
476  LOGE("channels do not match")
477  return false;
478  }
479  return begin(info, to.bits_per_sample, gain);
480  }
481 
482  bool begin(AudioInfo info, int toBits, float gain = 1.0f) {
483  setAudioInfo(info);
484  return begin(info.bits_per_sample, toBits, gain);
485  }
486 
487  bool begin() { return begin(from_bit_per_samples, to_bit_per_samples, gain); }
488 
489  void setToBits(uint8_t bits) { to_bit_per_samples = bits; }
490 
491  bool begin(int from_bit_per_samples, int to_bit_per_samples,
492  float gain = 1.0) {
493  assert(to_bit_per_samples > 0);
494  //is_output_notify = false;
495  this->gain = gain;
496  LOGI("begin %d -> %d bits", from_bit_per_samples, to_bit_per_samples);
497  bool result = true;
498  this->from_bit_per_samples = from_bit_per_samples;
499  this->to_bit_per_samples = to_bit_per_samples;
500 
501  if (from_bit_per_samples == to_bit_per_samples) {
502  LOGI("no bit conversion: %d -> %d", from_bit_per_samples,
503  to_bit_per_samples);
504  } else if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
505  converter = new NumberFormatConverterStreamT<int8_t, int16_t>(gain);
506  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
507  converter = new NumberFormatConverterStreamT<int16_t, int8_t>(gain);
508  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
509  converter = new NumberFormatConverterStreamT<int24_t, int16_t>(gain);
510  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
511  converter = new NumberFormatConverterStreamT<int16_t, int24_t>(gain);
512  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
513  converter = new NumberFormatConverterStreamT<int32_t, int16_t>(gain);
514  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
515  converter = new NumberFormatConverterStreamT<int16_t, int32_t>(gain);
516  } else {
517  result = false;
518  LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
519  to_bit_per_samples);
520  }
521 
522  if (from_bit_per_samples != to_bit_per_samples) {
523  setupStream();
524  }
525 
526  if (!result) {
527  TRACEE()
528  }
529  return result;
530  }
531 
532  virtual size_t write(const uint8_t *data, size_t len) override {
533  LOGD("NumberFormatConverterStream::write: %d", (int)len);
534  if (p_print == nullptr) return 0;
535  if (from_bit_per_samples == to_bit_per_samples) {
536  return p_print->write(data, len);
537  }
538 
539  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
540  return getConverter<int8_t, int16_t>()->write(data, len);
541  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
542  return getConverter<int16_t, int8_t>()->write(data, len);
543  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
544  return getConverter<int24_t, int16_t>()->write(data, len);
545  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
546  return getConverter<int16_t, int24_t>()->write(data, len);
547  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
548  return getConverter<int32_t, int16_t>()->write(data, len);
549  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
550  return getConverter<int16_t, int32_t>()->write(data, len);
551  } else {
552  LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
553  to_bit_per_samples);
554  return 0;
555  }
556  }
557 
558  size_t readBytes(uint8_t *data, size_t len) override {
559  LOGD("NumberFormatConverterStream::readBytes: %d", (int)len);
560  if (from_bit_per_samples == to_bit_per_samples) {
561  return p_stream->readBytes(data, len);
562  }
563  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
564  return getConverter<int8_t, int16_t>()->readBytes(data, len);
565  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
566  return getConverter<int16_t, int8_t>()->readBytes(data, len);
567  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
568  return getConverter<int24_t, int16_t>()->readBytes(data, len);
569  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
570  return getConverter<int16_t, int24_t>()->readBytes(data, len);
571  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
572  return getConverter<int32_t, int16_t>()->readBytes(data, len);
573  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
574  return getConverter<int16_t, int32_t>()->readBytes(data, len);
575  } else {
576  TRACEE();
577  return 0;
578  }
579  }
580 
581  virtual int available() override {
582  if (from_bit_per_samples == to_bit_per_samples) {
583  return p_stream->available();
584  }
585  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
586  return getConverter<int8_t, int16_t>()->available();
587  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
588  return getConverter<int16_t, int8_t>()->available();
589  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
590  return getConverter<int24_t, int16_t>()->available();
591  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
592  return getConverter<int16_t, int24_t>()->available();
593  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
594  return getConverter<int32_t, int16_t>()->available();
595  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
596  return getConverter<int16_t, int32_t>()->available();
597  } else {
598  TRACEE();
599  return 0;
600  }
601  }
602 
603  virtual int availableForWrite() override {
604  if (p_print == nullptr) return 0;
605  if (from_bit_per_samples == to_bit_per_samples) {
606  return p_print->availableForWrite();
607  }
608  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
609  return getConverter<int8_t, int16_t>()->availableForWrite();
610  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
611  return getConverter<int16_t, int8_t>()->availableForWrite();
612  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
613  return getConverter<int24_t, int16_t>()->availableForWrite();
614  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
615  return getConverter<int16_t, int24_t>()->availableForWrite();
616  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
617  return getConverter<int32_t, int16_t>()->availableForWrite();
618  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
619  return getConverter<int16_t, int32_t>()->availableForWrite();
620  } else {
621  TRACEE();
622  return 0;
623  }
624  }
625 
626  void setBuffered(bool flag) {
627  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
628  getConverter<int8_t, int16_t>()->setBuffered(flag);
629  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
630  getConverter<int16_t, int8_t>()->setBuffered(flag);
631  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
632  getConverter<int24_t, int16_t>()->setBuffered(flag);
633  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
634  getConverter<int16_t, int24_t>()->setBuffered(flag);
635  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
636  getConverter<int32_t, int16_t>()->setBuffered(flag);
637  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
638  getConverter<int16_t, int32_t>()->setBuffered(flag);
639  }
640  }
641 
642  float getByteFactor() {
643  return static_cast<float>(to_bit_per_samples) /
644  static_cast<float>(from_bit_per_samples);
645  }
646 
647  protected:
648  void *converter = nullptr;
649  int from_bit_per_samples = 16;
650  int to_bit_per_samples = 0;
651  float gain = 1.0;
652 
653  template <typename TFrom, typename TTo>
654  NumberFormatConverterStreamT<TFrom, TTo> *getConverter() {
655  return (NumberFormatConverterStreamT<TFrom, TTo> *)converter;
656  }
657 
658  void setupStream() {
659  if (p_stream != nullptr) {
660  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
661  getConverter<int8_t, int16_t>()->setStream(*p_stream);
662  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
663  getConverter<int16_t, int8_t>()->setStream(*p_stream);
664  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
665  getConverter<int24_t, int16_t>()->setStream(*p_stream);
666  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
667  getConverter<int16_t, int24_t>()->setStream(*p_stream);
668  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
669  getConverter<int32_t, int16_t>()->setStream(*p_stream);
670  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
671  getConverter<int16_t, int32_t>()->setStream(*p_stream);
672  } else {
673  TRACEE();
674  }
675  } else {
676  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
677  getConverter<int8_t, int16_t>()->setOutput(*p_print);
678  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
679  getConverter<int16_t, int8_t>()->setOutput(*p_print);
680  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
681  getConverter<int24_t, int16_t>()->setOutput(*p_print);
682  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
683  getConverter<int16_t, int24_t>()->setOutput(*p_print);
684  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
685  getConverter<int32_t, int16_t>()->setOutput(*p_print);
686  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
687  getConverter<int16_t, int32_t>()->setOutput(*p_print);
688  } else {
689  TRACEE();
690  }
691  }
692  }
693 };
694 
704  public:
705  FormatConverterStream() = default;
706  FormatConverterStream(Stream &stream) { setStream(stream); }
707  FormatConverterStream(Print &print) { setOutput(print); }
709  to_cfg = stream.audioInfo();
710  from_cfg = stream.audioInfo();
711  setStream(stream);
712  }
714  to_cfg = print.audioInfo();
715  setOutput(print);
716  }
717 
718  void setStream(Stream &io) override {
719  TRACED();
721  sampleRateConverter.setStream(io);
722  }
723 
724  void setStream(AudioStream &io) override {
725  TRACED();
727  sampleRateConverter.setStream(io);
728  }
729 
730  void setOutput(Print &print) override {
731  TRACED();
732  ReformatBaseStream::setOutput(print);
733  sampleRateConverter.setOutput(print);
734  }
735 
736  void setOutput(AudioOutput &print) override {
737  TRACED();
738  ReformatBaseStream::setOutput(print);
739  sampleRateConverter.setOutput(print);
740  }
741 
742  void setAudioInfo(AudioInfo info) override {
743  TRACED();
744  from_cfg = info;
745  sampleRateConverter.setAudioInfo(info);
746  numberFormatConverter.setAudioInfo(info);
747  channelFormatConverter.setAudioInfo(info);
749  }
750 
751  void setAudioInfoOut(AudioInfo to) { to_cfg = to; }
752 
753  AudioInfo audioInfoOut() override { return to_cfg; }
754 
755  bool begin(AudioInfo from, AudioInfo to) {
756  TRACED();
757  setAudioInfoOut(to);
758  return begin(from);
759  }
760 
762  bool begin(AudioInfo from) {
763  setAudioInfo(from);
764  return begin();
765  }
766 
768  bool begin() override {
769  TRACED();
770  //is_output_notify = false;
771  // build output chain
772  if (getStream() != nullptr) {
773  sampleRateConverter.setStream(*getStream());
774  }
775  if (getPrint() != nullptr) {
776  sampleRateConverter.setOutput(*getPrint());
777  }
778  numberFormatConverter.setStream(sampleRateConverter);
779  channelFormatConverter.setStream(numberFormatConverter);
780 
781  // start individual converters
782  bool result = channelFormatConverter.begin(from_cfg, to_cfg.channels);
783 
784  AudioInfo from_actual_cfg(from_cfg);
785  from_actual_cfg.channels = to_cfg.channels;
786  result &= numberFormatConverter.begin(from_actual_cfg.bits_per_sample,
787  to_cfg.bits_per_sample);
788 
789  numberFormatConverter.setBuffered(is_buffered);
790  sampleRateConverter.setBuffered(is_buffered);
791 
792  from_actual_cfg.bits_per_sample = to_cfg.bits_per_sample;
793  result &= sampleRateConverter.begin(from_actual_cfg, to_cfg.sample_rate);
794 
795  // setup reader to support readBytes()
796  setupReader();
797 
798  if (!result) {
799  LOGE("begin failed");
800  }
801  return result;
802  }
803 
804  virtual size_t write(const uint8_t *data, size_t len) override {
805  LOGD("FormatConverterStream::write: %d", (int)len);
806  //addNotifyOnFirstWrite();
807  return channelFormatConverter.write(data, len);
808  }
809 
811  void setBuffered(bool active) { is_buffered = active; }
812 
813  float getByteFactor() {
814  return numberFormatConverter.getByteFactor() *
815  channelFormatConverter.getByteFactor();
816  }
817 
818  protected:
819  AudioInfo from_cfg;
820  AudioInfo to_cfg;
821  NumberFormatConverterStream numberFormatConverter;
822  ChannelFormatConverterStream channelFormatConverter;
823  ResampleStream sampleRateConverter;
824  bool is_buffered = true;
825 
828  float byteFactor() {
829  return (float)from_cfg.channels / (float)to_cfg.channels *
830  (float)from_cfg.bits_per_sample / (float)to_cfg.bits_per_sample;
831  }
832 };
833 
834 } // namespace audio_tools
Abstract Audio Ouptut class.
Definition: AudioOutput.h:22
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition: AudioOutput.h:59
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
Channel converter which does not use a template.
Definition: AudioStreamsConverter.h:121
AudioInfo audioInfoOut() override
Returns the AudioInfo with the to_channels.
Definition: AudioStreamsConverter.h:152
void setAudioInfo(AudioInfo cfg) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:130
Converter for reducing or increasing the number of Channels.
Definition: AudioStreamsConverter.h:15
AudioInfo audioInfoOut() override
Returns the AudioInfo with the to_channels.
Definition: AudioStreamsConverter.h:74
void setAudioInfo(AudioInfo cfg) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:68
Converter which converts bits_per_sample, channels and the sample_rate. The conversion is supported b...
Definition: AudioStreamsConverter.h:703
void setOutput(Print &print) override
Defines/Changes the output target.
Definition: AudioStreamsConverter.h:730
void setBuffered(bool active)
Buffering is active by default to minimize the number of output calls.
Definition: AudioStreamsConverter.h:811
float byteFactor()
Definition: AudioStreamsConverter.h:828
bool begin(AudioInfo from)
Starts the processing: call setAudioInfoOut before to define the target.
Definition: AudioStreamsConverter.h:762
AudioInfo audioInfoOut() override
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition: AudioStreamsConverter.h:753
bool begin() override
(Re-)Starts the processing: call setAudioInfo and setAudioInfoOut before
Definition: AudioStreamsConverter.h:768
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:742
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreamsConverter.h:718
Converter which converts between bits_per_sample and 16 bits. The templated NumberFormatConverterStre...
Definition: AudioStreamsConverter.h:449
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:457
AudioInfo audioInfoOut() override
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition: AudioStreamsConverter.h:464
A more generic templated Converter which converts from a source type to a target type: You can use e....
Definition: AudioStreamsConverter.h:331
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:340
void setBuffered(bool flag)
Definition: AudioStreamsConverter.h:426
void setGain(float value)
Defines the gain (only available when buffered is true)
Definition: AudioStreamsConverter.h:429
AudioInfo audioInfoOut() override
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition: AudioStreamsConverter.h:348
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
T * address() override
Provides address to beginning of the buffer.
Definition: Buffers.h:249
T * data()
Provides address of actual data.
Definition: Buffers.h:252
void reset() override
clears the buffer
Definition: Buffers.h:254
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
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:107
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
void setAudioInfo(AudioInfo info)
Same as set.
Definition: AudioTypes.h:102
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:59