arduino-audio-tools
AudioStreamsConverter.h
1 #pragma once
2 #include "AudioIO.h"
3 #include "AudioTools/AudioStreams.h"
4 #include "AudioTools/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;
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;
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;
365  if (sizeof(TFrom) == sizeof(TTo)) return p_print->write(data, len);
366  size_t samples = len / sizeof(TFrom);
367  size_t result_size = 0;
368  TFrom *data_source = (TFrom *)data;
369 
370  if (!is_buffered) {
371  for (size_t j = 0; j < samples; j++) {
372  TTo value = NumberConverter::convert<TFrom, TTo>(data_source[j]);
373  result_size += p_print->write((uint8_t *)&value, sizeof(TTo));
374  }
375  } else {
376  int size_bytes = sizeof(TTo) * samples;
377  buffer.resize(size_bytes);
378  NumberConverter::convertArray<TFrom, TTo>(
379  data_source, (TTo *)buffer.data(), samples, gain);
380  p_print->write((uint8_t *)buffer.address(), size_bytes);
381  buffer.reset();
382  }
383 
384  return len;
385  }
386 
387  size_t readBytes(uint8_t *data, size_t len) override {
388  LOGD("NumberFormatConverterStreamT::readBytes: %d", (int)len);
389  if (p_stream == nullptr) return 0;
390  size_t samples = len / sizeof(TTo);
391  TTo *data_target = (TTo *)data;
392  TFrom source;
393  if (!is_buffered) {
394  for (size_t j = 0; j < samples; j++) {
395  source = 0;
396  p_stream->readBytes((uint8_t *)&source, sizeof(TFrom));
397  data_target[j] = NumberConverter::convert<TFrom, TTo>(source);
398  }
399  } else {
400  buffer.resize(sizeof(TFrom) * samples);
401  readSamples<TFrom>(p_stream, (TFrom *)buffer.address(), samples);
402  TFrom *data = (TFrom *)buffer.address();
403  NumberConverter::convertArray<TFrom, TTo>(data, data_target, samples,
404  gain);
405  buffer.reset();
406  }
407  return len;
408  }
409 
410  virtual int available() override {
411  return p_stream != nullptr ? p_stream->available() : 0;
412  }
413 
414  virtual int availableForWrite() override {
415  return p_print == nullptr ? 0 : p_print->availableForWrite();
416  }
417 
420  void setBuffered(bool flag) { is_buffered = flag; }
421 
423  void setGain(float value) { gain = value; }
424 
425  float getByteFactor() {
426  return static_cast<float>(sizeof(TTo)) / static_cast<float>(sizeof(TFrom));
427  }
428 
429  protected:
430  SingleBuffer<uint8_t> buffer{0};
431  bool is_buffered = true;
432  float gain = 1.0f;
433 };
434 
444  public:
445  NumberFormatConverterStream() = default;
446  NumberFormatConverterStream(Stream &stream) { setStream(stream); }
448  NumberFormatConverterStream(Print &print) { setOutput(print); }
449  NumberFormatConverterStream(AudioOutput &print) { setOutput(print); }
450 
451  void setAudioInfo(AudioInfo newInfo) override {
452  TRACED();
453  this->from_bit_per_samples = newInfo.bits_per_sample;
454  LOGI("-> NumberFormatConverterStream:")
455  AudioStream::setAudioInfo(newInfo);
456  }
457 
458  AudioInfo audioInfoOut() override {
459  AudioInfo result = audioInfo();
460  result.bits_per_sample = to_bit_per_samples;
461  return result;
462  }
463 
464  bool begin(AudioInfo info, AudioInfo to, float gain = 1.0f) {
465  if (info.sample_rate != to.sample_rate){
466  LOGE("sample_rate does not match")
467  return false;
468  }
469  if (info.channels != to.channels){
470  LOGE("channels do not match")
471  return false;
472  }
473  return begin(info, to.bits_per_sample, gain);
474  }
475 
476  bool begin(AudioInfo info, int toBits, float gain = 1.0f) {
477  setAudioInfo(info);
478  return begin(info.bits_per_sample, toBits, gain);
479  }
480 
481  bool begin() { return begin(from_bit_per_samples, to_bit_per_samples, gain); }
482 
483  void setToBits(uint8_t bits) { to_bit_per_samples = bits; }
484 
485  bool begin(int from_bit_per_samples, int to_bit_per_samples,
486  float gain = 1.0) {
487  assert(to_bit_per_samples > 0);
488  is_output_notify = false;
489  this->gain = gain;
490  LOGI("begin %d -> %d bits", from_bit_per_samples, to_bit_per_samples);
491  bool result = true;
492  this->from_bit_per_samples = from_bit_per_samples;
493  this->to_bit_per_samples = to_bit_per_samples;
494 
495  if (from_bit_per_samples == to_bit_per_samples) {
496  LOGI("no bit conversion: %d -> %d", from_bit_per_samples,
497  to_bit_per_samples);
498  } else if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
499  converter = new NumberFormatConverterStreamT<int8_t, int16_t>(gain);
500  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
501  converter = new NumberFormatConverterStreamT<int16_t, int8_t>(gain);
502  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
503  converter = new NumberFormatConverterStreamT<int24_t, int16_t>(gain);
504  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
505  converter = new NumberFormatConverterStreamT<int16_t, int24_t>(gain);
506  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
507  converter = new NumberFormatConverterStreamT<int32_t, int16_t>(gain);
508  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
509  converter = new NumberFormatConverterStreamT<int16_t, int32_t>(gain);
510  } else {
511  result = false;
512  LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
513  to_bit_per_samples);
514  }
515 
516  if (from_bit_per_samples != to_bit_per_samples) {
517  setupStream();
518  }
519 
520  if (!result) {
521  TRACEE()
522  }
523  return result;
524  }
525 
526  virtual size_t write(const uint8_t *data, size_t len) override {
527  LOGD("NumberFormatConverterStream::write: %d", (int)len);
528  if (p_print == nullptr) return 0;
529  if (from_bit_per_samples == to_bit_per_samples) {
530  return p_print->write(data, len);
531  }
532 
533  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
534  return getConverter<int8_t, int16_t>()->write(data, len);
535  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
536  return getConverter<int16_t, int8_t>()->write(data, len);
537  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
538  return getConverter<int24_t, int16_t>()->write(data, len);
539  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
540  return getConverter<int16_t, int24_t>()->write(data, len);
541  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
542  return getConverter<int32_t, int16_t>()->write(data, len);
543  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
544  return getConverter<int16_t, int32_t>()->write(data, len);
545  } else {
546  LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
547  to_bit_per_samples);
548  return 0;
549  }
550  }
551 
552  size_t readBytes(uint8_t *data, size_t len) override {
553  LOGD("NumberFormatConverterStream::readBytes: %d", (int)len);
554  if (from_bit_per_samples == to_bit_per_samples) {
555  return p_stream->readBytes(data, len);
556  }
557  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
558  return getConverter<int8_t, int16_t>()->readBytes(data, len);
559  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
560  return getConverter<int16_t, int8_t>()->readBytes(data, len);
561  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
562  return getConverter<int24_t, int16_t>()->readBytes(data, len);
563  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
564  return getConverter<int16_t, int24_t>()->readBytes(data, len);
565  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
566  return getConverter<int32_t, int16_t>()->readBytes(data, len);
567  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
568  return getConverter<int16_t, int32_t>()->readBytes(data, len);
569  } else {
570  TRACEE();
571  return 0;
572  }
573  }
574 
575  virtual int available() override {
576  if (from_bit_per_samples == to_bit_per_samples) {
577  return p_stream->available();
578  }
579  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
580  return getConverter<int8_t, int16_t>()->available();
581  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
582  return getConverter<int16_t, int8_t>()->available();
583  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
584  return getConverter<int24_t, int16_t>()->available();
585  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
586  return getConverter<int16_t, int24_t>()->available();
587  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
588  return getConverter<int32_t, int16_t>()->available();
589  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
590  return getConverter<int16_t, int32_t>()->available();
591  } else {
592  TRACEE();
593  return 0;
594  }
595  }
596 
597  virtual int availableForWrite() override {
598  if (p_print == nullptr) return 0;
599  if (from_bit_per_samples == to_bit_per_samples) {
600  return p_print->availableForWrite();
601  }
602  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
603  return getConverter<int8_t, int16_t>()->availableForWrite();
604  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
605  return getConverter<int16_t, int8_t>()->availableForWrite();
606  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
607  return getConverter<int24_t, int16_t>()->availableForWrite();
608  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
609  return getConverter<int16_t, int24_t>()->availableForWrite();
610  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
611  return getConverter<int32_t, int16_t>()->availableForWrite();
612  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
613  return getConverter<int16_t, int32_t>()->availableForWrite();
614  } else {
615  TRACEE();
616  return 0;
617  }
618  }
619 
620  void setBuffered(bool flag) {
621  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
622  getConverter<int8_t, int16_t>()->setBuffered(flag);
623  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
624  getConverter<int16_t, int8_t>()->setBuffered(flag);
625  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
626  getConverter<int24_t, int16_t>()->setBuffered(flag);
627  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
628  getConverter<int16_t, int24_t>()->setBuffered(flag);
629  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
630  getConverter<int32_t, int16_t>()->setBuffered(flag);
631  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
632  getConverter<int16_t, int32_t>()->setBuffered(flag);
633  }
634  }
635 
636  float getByteFactor() {
637  return static_cast<float>(to_bit_per_samples) /
638  static_cast<float>(from_bit_per_samples);
639  }
640 
641  protected:
642  void *converter = nullptr;
643  int from_bit_per_samples = 16;
644  int to_bit_per_samples = 0;
645  float gain = 1.0;
646 
647  template <typename TFrom, typename TTo>
648  NumberFormatConverterStreamT<TFrom, TTo> *getConverter() {
649  return (NumberFormatConverterStreamT<TFrom, TTo> *)converter;
650  }
651 
652  void setupStream() {
653  if (p_stream != nullptr) {
654  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
655  getConverter<int8_t, int16_t>()->setStream(*p_stream);
656  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
657  getConverter<int16_t, int8_t>()->setStream(*p_stream);
658  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
659  getConverter<int24_t, int16_t>()->setStream(*p_stream);
660  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
661  getConverter<int16_t, int24_t>()->setStream(*p_stream);
662  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
663  getConverter<int32_t, int16_t>()->setStream(*p_stream);
664  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
665  getConverter<int16_t, int32_t>()->setStream(*p_stream);
666  } else {
667  TRACEE();
668  }
669  } else {
670  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
671  getConverter<int8_t, int16_t>()->setOutput(*p_print);
672  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
673  getConverter<int16_t, int8_t>()->setOutput(*p_print);
674  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
675  getConverter<int24_t, int16_t>()->setOutput(*p_print);
676  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
677  getConverter<int16_t, int24_t>()->setOutput(*p_print);
678  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
679  getConverter<int32_t, int16_t>()->setOutput(*p_print);
680  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
681  getConverter<int16_t, int32_t>()->setOutput(*p_print);
682  } else {
683  TRACEE();
684  }
685  }
686  }
687 };
688 
698  public:
699  FormatConverterStream() = default;
700  FormatConverterStream(Stream &stream) { setStream(stream); }
701  FormatConverterStream(Print &print) { setOutput(print); }
703  to_cfg = stream.audioInfo();
704  from_cfg = stream.audioInfo();
705  setStream(stream);
706  }
708  to_cfg = print.audioInfo();
709  setOutput(print);
710  }
711 
712  void setStream(Stream &io) override {
713  TRACED();
715  sampleRateConverter.setStream(io);
716  }
717 
718  void setStream(AudioStream &io) override {
719  TRACED();
721  sampleRateConverter.setStream(io);
722  }
723 
724  void setOutput(Print &print) override {
725  TRACED();
726  ReformatBaseStream::setOutput(print);
727  sampleRateConverter.setOutput(print);
728  }
729 
730  void setOutput(AudioOutput &print) override {
731  TRACED();
732  ReformatBaseStream::setOutput(print);
733  sampleRateConverter.setOutput(print);
734  }
735 
736  void setAudioInfo(AudioInfo info) override {
737  TRACED();
738  from_cfg = info;
739  sampleRateConverter.setAudioInfo(info);
741  }
742 
743  void setAudioInfoOut(AudioInfo to) { to_cfg = to; }
744 
745  AudioInfo audioInfoOut() override { return to_cfg; }
746 
747  bool begin(AudioInfo from, AudioInfo to) {
748  TRACED();
749  setAudioInfoOut(to);
750  return begin(from);
751  }
752 
753  bool begin(AudioInfo from) {
754  TRACED();
755  is_output_notify = false;
756  setAudioInfo(from);
757 
758  // build output chain
759  if (getStream() != nullptr) {
760  sampleRateConverter.setStream(*getStream());
761  }
762  if (getPrint() != nullptr) {
763  sampleRateConverter.setOutput(*getPrint());
764  }
765  numberFormatConverter.setStream(sampleRateConverter);
766  channelFormatConverter.setStream(numberFormatConverter);
767 
768  // start individual converters
769  bool result = channelFormatConverter.begin(from_cfg, to_cfg.channels);
770 
771  AudioInfo from_actual_cfg(from_cfg);
772  from_actual_cfg.channels = to_cfg.channels;
773  result &= numberFormatConverter.begin(from_actual_cfg.bits_per_sample,
774  to_cfg.bits_per_sample);
775 
776  numberFormatConverter.setBuffered(is_buffered);
777  sampleRateConverter.setBuffered(is_buffered);
778 
779  from_actual_cfg.bits_per_sample = to_cfg.bits_per_sample;
780  result &= sampleRateConverter.begin(from_actual_cfg, to_cfg.sample_rate);
781 
782  // setup reader to support readBytes()
783  setupReader();
784 
785  if (!result) {
786  LOGE("begin failed");
787  }
788  return result;
789  }
790 
791  virtual size_t write(const uint8_t *data, size_t len) override {
792  LOGD("FormatConverterStream::write: %d", (int)len);
794  return channelFormatConverter.write(data, len);
795  }
796 
798  void setBuffered(bool active) { is_buffered = active; }
799 
800  float getByteFactor() {
801  return numberFormatConverter.getByteFactor() *
802  channelFormatConverter.getByteFactor();
803  }
804 
805  protected:
806  AudioInfo from_cfg;
807  AudioInfo to_cfg;
808  NumberFormatConverterStream numberFormatConverter;
809  ChannelFormatConverterStream channelFormatConverter;
810  ResampleStream sampleRateConverter;
811  bool is_buffered = true;
812 
815  float byteFactor() {
816  return (float)from_cfg.channels / (float)to_cfg.channels *
817  (float)from_cfg.bits_per_sample / (float)to_cfg.bits_per_sample;
818  }
819 };
820 
821 } // 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:697
void setOutput(Print &print) override
Defines/Changes the output target.
Definition: AudioStreamsConverter.h:724
void setBuffered(bool active)
Buffering is active by default to minimize the number of output calls.
Definition: AudioStreamsConverter.h:798
float byteFactor()
Definition: AudioStreamsConverter.h:815
AudioInfo audioInfoOut() override
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition: AudioStreamsConverter.h:745
void setAudioInfo(AudioInfo info) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:736
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition: AudioStreamsConverter.h:712
Converter which converts between bits_per_sample and 16 bits. The templated NumberFormatConverterStre...
Definition: AudioStreamsConverter.h:443
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:451
AudioInfo audioInfoOut() override
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition: AudioStreamsConverter.h:458
Converter which converts from source bits_per_sample to target bits_per_sample.
Definition: AudioStreamsConverter.h:331
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition: AudioStreamsConverter.h:340
void setBuffered(bool flag)
Definition: AudioStreamsConverter.h:420
void setGain(float value)
Defines the gain (only available when buffered is true)
Definition: AudioStreamsConverter.h:423
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:142
void addNotifyOnFirstWrite()
Add notification on first call of write.
Definition: AudioIO.h:204
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition: AudioIO.h:144
T * address() override
Provides address to beginning of the buffer.
Definition: Buffers.h:243
T * data()
Provides address of actual data.
Definition: Buffers.h:246
void reset() override
clears the buffer
Definition: Buffers.h:248
Definition: NoArduino.h:125
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudioArduino.h:12
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:105
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:55
void setAudioInfo(AudioInfo info)
Same as set.
Definition: AudioTypes.h:100
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57