arduino-audio-tools
AudioStreamsConverter.h
1 #pragma once
2 #include "AudioTools/AudioStreams.h"
3 #include "AudioTools/ResampleStream.h"
4 
5 namespace audio_tools {
6 
13 template <typename T>
15  public:
16  ChannelFormatConverterStreamT(Stream &stream) { setStream(stream); }
17  ChannelFormatConverterStreamT(Print &print) { setStream(print); }
20 
21 
22  bool begin(int fromChannels, int toChannels) {
23  LOGI("begin %d -> %d channels", fromChannels, toChannels);
24  from_channels = fromChannels;
25  to_channels = toChannels;
26  factor = static_cast<float>(toChannels) / static_cast<float>(fromChannels);
27 
28  converter.setSourceChannels(from_channels);
29  converter.setTargetChannels(to_channels);
30 
31  return true;
32  }
33 
34  virtual size_t write(const uint8_t *data, size_t size) override {
35  TRACED();
36  if (from_channels == to_channels) {
37  return p_print->write(data, size);
38  }
39  size_t resultBytes = convert(data, size);
40  assert(resultBytes = factor * size);
41  p_print->write((uint8_t *)buffer.data(), resultBytes);
42  return size;
43  }
44 
45  size_t readBytes(uint8_t *data, size_t size) override {
46  TRACED();
47  if (p_stream == nullptr) return 0;
48  if (from_channels == to_channels) {
49  return p_stream->readBytes(data, size);
50  }
51  size_t in_bytes = 1.0f / factor * size;
52  bufferTmp.resize(in_bytes);
53  p_stream->readBytes(bufferTmp.data(), in_bytes);
54  size_t resultBytes = convert(bufferTmp.data(), in_bytes);
55  assert(size == resultBytes);
56  memcpy(data, (uint8_t *)buffer.data(), size);
57  return size;
58  }
59 
60  void setAudioInfo(AudioInfo cfg) override {
61  from_channels = cfg.channels;
62  AudioStream::setAudioInfo(cfg);
63  }
64 
65  virtual int available() override {
66  return p_stream != nullptr ? p_stream->available() : 0;
67  }
68 
69  virtual int availableForWrite() override {
70  return 1.0f / factor * p_print->availableForWrite();
71  }
72 
73  float getByteFactor() { return static_cast<float>(to_channels)/static_cast<float>(from_channels);}
74 
75  protected:
76  int from_channels = 2;
77  int to_channels = 2;
78  float factor = 1;
79  Vector<T> buffer{0};
80  Vector<uint8_t> bufferTmp{0};
81  ChannelConverter<T> converter;
82 
83 
84  size_t convert(const uint8_t *in_data, size_t size) {
85  size_t result;
86  size_t result_samples = size / sizeof(T) * factor;
87  buffer.resize(result_samples);
88  result =
89  converter.convert((uint8_t *)buffer.data(), (uint8_t *)in_data, size);
90  if (result != result_samples * sizeof(T)) {
91  LOGE("size %d -> result: %d - expeced: %d", (int)size, (int)result,
92  static_cast<int>(result_samples * sizeof(T)));
93  }
94  return result;
95  }
96 };
97 
105  public:
106  ChannelFormatConverterStream() = default;
107  ChannelFormatConverterStream(Stream &stream) { setStream(stream); }
108  ChannelFormatConverterStream(Print &print) { setStream(print); }
110  ChannelFormatConverterStream &operator=(
111  ChannelFormatConverterStream const &) = delete;
112 
113  void setAudioInfo(AudioInfo cfg) override {
114  TRACED();
115  from_channels = cfg.channels;
116  AudioStream::setAudioInfo(cfg);
117  switch (bits_per_sample) {
118  case 8:
119  getConverter<int8_t>()->setAudioInfo(cfg);
120  break;
121  case 16:
122  getConverter<int16_t>()->setAudioInfo(cfg);
123  break;
124  case 24:
125  getConverter<int24_t>()->setAudioInfo(cfg);
126  break;
127  case 32:
128  getConverter<int32_t>()->setAudioInfo(cfg);
129  break;
130  }
131  }
132 
133  bool begin(AudioInfo cfg, int toChannels) {
134  assert(toChannels!=0);
135  to_channels = toChannels;
136  from_channels = cfg.channels;
137  bits_per_sample = cfg.bits_per_sample;
138  AudioStream::setAudioInfo(cfg);
139  LOGI("begin %d -> %d channels", cfg.channels, toChannels);
140  bool result = setupConverter(cfg.channels, toChannels);
141  if (!result) {
142  TRACEE()
143  }
144  return result;
145  }
146 
147  virtual size_t write(const uint8_t *data, size_t size) override {
148  LOGD("ChannelFormatConverterStream::write: %d", (int)size);
149  switch (bits_per_sample) {
150  case 8:
151  return getConverter<int8_t>()->write(data, size);
152  case 16:
153  return getConverter<int16_t>()->write(data, size);
154  case 24:
155  return getConverter<int24_t>()->write(data, size);
156  case 32:
157  return getConverter<int32_t>()->write(data, size);
158  default:
159  return 0;
160  }
161  }
162 
163  size_t readBytes(uint8_t *data, size_t size) override {
164  LOGD("ChannelFormatConverterStream::readBytes: %d", (int)size);
165  switch (bits_per_sample) {
166  case 8:
167  return getConverter<int8_t>()->readBytes(data, size);
168  case 16:
169  return getConverter<int16_t>()->readBytes(data, size);
170  case 24:
171  return getConverter<int24_t>()->readBytes(data, size);
172  case 32:
173  return getConverter<int32_t>()->readBytes(data, size);
174  default:
175  return 0;
176  }
177  }
178 
179  virtual int available() override {
180  switch (bits_per_sample) {
181  case 8:
182  return getConverter<int8_t>()->available();
183  case 16:
184  return getConverter<int16_t>()->available();
185  case 24:
186  return getConverter<int24_t>()->available();
187  case 32:
188  return getConverter<int32_t>()->available();
189  default:
190  return 0;
191  }
192  }
193 
194  virtual int availableForWrite() override {
195  switch (bits_per_sample) {
196  case 8:
197  return getConverter<int8_t>()->availableForWrite();
198  case 16:
199  return getConverter<int16_t>()->availableForWrite();
200  case 24:
201  return getConverter<int24_t>()->availableForWrite();
202  case 32:
203  return getConverter<int32_t>()->availableForWrite();
204  default:
205  return 0;
206  }
207  }
208 
209  float getByteFactor() { return static_cast<float>(to_channels)/static_cast<float>(from_channels);}
210 
211  protected:
212  void *converter;
213  int bits_per_sample = 0;
214  int to_channels;
215  int from_channels;
216 
217  template <typename T>
218  ChannelFormatConverterStreamT<T> *getConverter() {
219  return (ChannelFormatConverterStreamT<T> *)converter;
220  }
221 
222  bool setupConverter(int fromChannels, int toChannels) {
223  bool result = true;
224  if (p_stream != nullptr) {
225  switch (bits_per_sample) {
226  case 8:
227  converter = new ChannelFormatConverterStreamT<int8_t>(*p_stream);
228  getConverter<int8_t>()->begin(fromChannels, toChannels);
229  break;
230  case 16:
231  converter = new ChannelFormatConverterStreamT<int16_t>(*p_stream);
232  getConverter<int16_t>()->begin(fromChannels, toChannels);
233  break;
234  case 24:
235  converter = new ChannelFormatConverterStreamT<int24_t>(*p_stream);
236  getConverter<int24_t>()->begin(fromChannels, toChannels);
237  break;
238  case 32:
239  converter = new ChannelFormatConverterStreamT<int32_t>(*p_stream);
240  getConverter<int32_t>()->begin(fromChannels, toChannels);
241  break;
242  default:
243  result = false;
244  }
245  } else {
246  switch (bits_per_sample) {
247  case 8:
248  converter = new ChannelFormatConverterStreamT<int8_t>(*p_print);
249  getConverter<int8_t>()->begin(fromChannels, toChannels);
250  break;
251  case 16:
252  converter = new ChannelFormatConverterStreamT<int16_t>(*p_print);
253  getConverter<int16_t>()->begin(fromChannels, toChannels);
254  break;
255  case 24:
256  converter = new ChannelFormatConverterStreamT<int24_t>(*p_print);
257  getConverter<int24_t>()->begin(fromChannels, toChannels);
258  break;
259  case 32:
260  converter = new ChannelFormatConverterStreamT<int32_t>(*p_print);
261  getConverter<int32_t>()->begin(fromChannels, toChannels);
262  break;
263  default:
264  result = false;
265  }
266  }
267  return result;
268  }
269 };
270 
283 template <typename TFrom, typename TTo>
285  public:
286  NumberFormatConverterStreamT() = default;
287  NumberFormatConverterStreamT(float gain) { setGain(gain); }
288  NumberFormatConverterStreamT(Stream &stream) { setStream(stream); }
289  NumberFormatConverterStreamT(Print &print) { setStream(print); }
290  NumberFormatConverterStreamT(AudioStream &stream) { setStream(stream); }
291  NumberFormatConverterStreamT(AudioOutput &print) { setStream(print); }
292 
293  void setAudioInfo (AudioInfo info) override {
294  TRACED();
295  this->info = info;
296  if (info.bits_per_sample == sizeof(TFrom)*8){
297  LOGE("Invalid bits_per_sample %d", info.bits_per_sample);
298  }
299  info.logInfo();
300 
301  // notify format change with target bit per sample
302  AudioInfo to_format;
303  to_format.copyFrom(info);
304  to_format.bits_per_sample = sizeof(TTo)*8;
305  if (to_format) notifyAudioChange(to_format);
306  }
307 
308  bool begin() override {
309  LOGI("begin %d -> %d bits", (int) sizeof(TFrom),(int) sizeof(TTo));
310  return true;
311  }
312 
313  virtual size_t write(const uint8_t *data, size_t size) override {
314  TRACED();
315  if (sizeof(TFrom) == sizeof(TTo)) return p_print->write(data, size);
316  size_t samples = size / sizeof(TFrom);
317  size_t result_size = 0;
318  TFrom *data_source = (TFrom *)data;
319 
320  if (!is_buffered) {
321  for (size_t j = 0; j < samples; j++) {
322  TTo value = NumberConverter::convert<TFrom, TTo>(data_source[j]);
323  result_size += p_print->write((uint8_t *)&value, sizeof(TTo));
324  }
325  } else {
326  int size_bytes = sizeof(TTo) * samples;
327  buffer.resize(size_bytes);
328  NumberConverter::convertArray<TFrom, TTo>(data_source,(TTo*) buffer.data(), samples, gain);
329  p_print->write((uint8_t *)buffer.address(), size_bytes);
330  buffer.reset();
331  }
332 
333  return size;
334  }
335 
336  size_t readBytes(uint8_t *data, size_t size) override {
337  LOGD("NumberFormatConverterStreamT::readBytes: %d", (int)size);
338  if (p_stream == nullptr) return 0;
339  size_t samples = size / sizeof(TTo);
340  TTo *data_target = (TTo *)data;
341  TFrom source;
342  if (!is_buffered) {
343  for (size_t j = 0; j < samples; j++) {
344  source = 0;
345  p_stream->readBytes((uint8_t *)&source, sizeof(TFrom));
346  data_target[j] = NumberConverter::convert<TFrom, TTo>(source);
347  }
348  } else {
349  buffer.resize(sizeof(TFrom) * samples);
350  readSamples<TFrom>(p_stream, (TFrom *)buffer.address(), samples);
351  TFrom *data = (TFrom *)buffer.address();
352  NumberConverter::convertArray<TFrom, TTo>(data, data_target, samples, gain);
353  buffer.reset();
354  }
355  return size;
356  }
357 
358  virtual int available() override {
359  return p_stream != nullptr ? p_stream->available() : 0;
360  }
361 
362  virtual int availableForWrite() override {
363  return p_print->availableForWrite();
364  }
365 
368  void setBuffered(bool flag) { is_buffered = flag; }
369 
371  void setGain(float value){
372  gain = value;
373  }
374 
375  float getByteFactor() { return static_cast<float>(sizeof(TTo))/static_cast<float>(sizeof(TFrom));}
376 
377  protected:
378  SingleBuffer<uint8_t> buffer{0};
379  bool is_buffered = true;
380  float gain = 1.0f;
381 };
382 
392  public:
393  NumberFormatConverterStream() = default;
394  NumberFormatConverterStream(Stream &stream) { setStream(stream); }
395  NumberFormatConverterStream(Print &print) { setStream(print); }
396  NumberFormatConverterStream(AudioStream &stream) { setStream(stream); }
397  NumberFormatConverterStream(AudioOutput &print) { setStream(print); }
398 
399  void setAudioInfo (AudioInfo info) override {
400  TRACED();
401  this->from_bit_per_samples = info.bits_per_sample;
402  this->info = info;
403  info.logInfo();
404  // notify format change with target bit per sample
405  AudioInfo to_format;
406  to_format.copyFrom(info);
407  to_format.bits_per_sample = this->to_bit_per_samples;
408  if (to_format) notifyAudioChange(to_format);
409  }
410 
411  bool begin(AudioInfo info, int to_bit_per_samples, float gain=1.0f) {
412  setAudioInfo(info);
413  return begin(info.bits_per_sample, to_bit_per_samples, gain);
414  }
415 
416  bool begin(int from_bit_per_samples, int to_bit_per_samples, float gain = 1.0) {
417  assert(to_bit_per_samples > 0);
418  LOGI("begin %d -> %d bits", from_bit_per_samples, to_bit_per_samples);
419  bool result = true;
420  this->from_bit_per_samples = from_bit_per_samples;
421  this->to_bit_per_samples = to_bit_per_samples;
422 
423  if (from_bit_per_samples == to_bit_per_samples) {
424  LOGI("no bit conversion: %d -> %d", from_bit_per_samples,
425  to_bit_per_samples);
426  } else if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
427  converter = new NumberFormatConverterStreamT<int8_t, int16_t>(gain);
428  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
429  converter = new NumberFormatConverterStreamT<int16_t, int8_t>(gain);
430  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
432  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
434  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
436  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
438  } else {
439  result = false;
440  LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
441  to_bit_per_samples);
442  }
443 
444  if (from_bit_per_samples != to_bit_per_samples){
445  setupStream();
446  }
447 
448  if (!result) {
449  TRACEE()
450  }
451  return result;
452  }
453 
454  virtual size_t write(const uint8_t *data, size_t size) override {
455  LOGD("NumberFormatConverterStream::write: %d", (int) size);
456  if (from_bit_per_samples == to_bit_per_samples) {
457  return p_print->write(data, size);
458  }
459 
460  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
461  return getConverter<int8_t, int16_t>()->write(data, size);
462  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
463  return getConverter<int16_t, int8_t>()->write(data, size);
464  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
465  return getConverter<int24_t, int16_t>()->write(data, size);
466  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
467  return getConverter<int16_t, int24_t>()->write(data, size);
468  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
469  return getConverter<int32_t, int16_t>()->write(data, size);
470  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
471  return getConverter<int16_t, int32_t>()->write(data, size);
472  } else {
473  LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
474  to_bit_per_samples);
475  return 0;
476  }
477  }
478 
479  size_t readBytes(uint8_t *data, size_t size) override {
480  LOGD("NumberFormatConverterStream::readBytes: %d", (int)size);
481  if (from_bit_per_samples == to_bit_per_samples) {
482  return p_stream->readBytes(data, size);
483  }
484  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
485  return getConverter<int8_t, int16_t>()->readBytes(data, size);
486  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
487  return getConverter<int16_t, int8_t>()->readBytes(data, size);
488  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
489  return getConverter<int24_t, int16_t>()->readBytes(data, size);
490  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
491  return getConverter<int16_t, int24_t>()->readBytes(data, size);
492  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
493  return getConverter<int32_t, int16_t>()->readBytes(data, size);
494  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
495  return getConverter<int16_t, int32_t>()->readBytes(data, size);
496  } else {
497  TRACEE();
498  return 0;
499  }
500  }
501 
502  virtual int available() override {
503  if (from_bit_per_samples == to_bit_per_samples) {
504  return p_stream->available();
505  }
506  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
507  return getConverter<int8_t, int16_t>()->available();
508  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
509  return getConverter<int16_t, int8_t>()->available();
510  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
511  return getConverter<int24_t, int16_t>()->available();
512  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
513  return getConverter<int16_t, int24_t>()->available();
514  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
515  return getConverter<int32_t, int16_t>()->available();
516  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
517  return getConverter<int16_t, int32_t>()->available();
518  } else {
519  TRACEE();
520  return 0;
521  }
522  }
523 
524  virtual int availableForWrite() override {
525  if (from_bit_per_samples == to_bit_per_samples) {
526  return p_print->availableForWrite();
527  }
528  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
529  return getConverter<int8_t, int16_t>()->availableForWrite();
530  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
531  return getConverter<int16_t, int8_t>()->availableForWrite();
532  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
533  return getConverter<int24_t, int16_t>()->availableForWrite();
534  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
535  return getConverter<int16_t, int24_t>()->availableForWrite();
536  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
537  return getConverter<int32_t, int16_t>()->availableForWrite();
538  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
539  return getConverter<int16_t, int32_t>()->availableForWrite();
540  } else {
541  TRACEE();
542  return 0;
543  }
544  }
545 
546  void setBuffered(bool flag) {
547  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
548  getConverter<int8_t, int16_t>()->setBuffered(flag);
549  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
550  getConverter<int16_t, int8_t>()->setBuffered(flag);
551  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
552  getConverter<int24_t, int16_t>()->setBuffered(flag);
553  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
554  getConverter<int16_t, int24_t>()->setBuffered(flag);
555  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
556  getConverter<int32_t, int16_t>()->setBuffered(flag);
557  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
558  getConverter<int16_t, int32_t>()->setBuffered(flag);
559  }
560  }
561 
562  float getByteFactor() { return static_cast<float>(to_bit_per_samples)/static_cast<float>(from_bit_per_samples);}
563 
564  protected:
565  void *converter = nullptr;
566  int from_bit_per_samples = 0;
567  int to_bit_per_samples = 0;
568 
569  template <typename TFrom, typename TTo>
571  return (NumberFormatConverterStreamT<TFrom, TTo> *)converter;
572  }
573 
574  void setupStream() {
575  if (p_stream != nullptr) {
576  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
577  getConverter<int8_t, int16_t>()->setStream(*p_stream);
578  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
579  getConverter<int16_t, int8_t>()->setStream(*p_stream);
580  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
581  getConverter<int24_t, int16_t>()->setStream(*p_stream);
582  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
583  getConverter<int16_t, int24_t>()->setStream(*p_stream);
584  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
585  getConverter<int32_t, int16_t>()->setStream(*p_stream);
586  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
587  getConverter<int16_t, int32_t>()->setStream(*p_stream);
588  } else {
589  TRACEE();
590  }
591  } else {
592  if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
593  getConverter<int8_t, int16_t>()->setStream(*p_print);
594  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
595  getConverter<int16_t, int8_t>()->setStream(*p_print);
596  } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
597  getConverter<int24_t, int16_t>()->setStream(*p_print);
598  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
599  getConverter<int16_t, int24_t>()->setStream(*p_print);
600  } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
601  getConverter<int32_t, int16_t>()->setStream(*p_print);
602  } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
603  getConverter<int16_t, int32_t>()->setStream(*p_print);
604  } else {
605  TRACEE();
606  }
607  }
608  }
609 };
610 
620  public:
621  FormatConverterStream() = default;
622  FormatConverterStream(Stream &stream) { setStream(stream); }
623  FormatConverterStream(Print &print) { setStream(print); }
625  to_cfg = stream.audioInfo();
626  setStream(stream);
627  }
629  to_cfg = print.audioInfo();
630  setStream(print);
631  }
632 
633  void setStream(Stream &io) override {
634  TRACED();
635  //p_print = &print;
636  ReformatBaseStream::setStream(io);
637  sampleRateConverter.setStream(io);
638  }
639 
640  void setStream(AudioStream &io) override {
641  TRACED();
642  //p_print = &print;
643  ReformatBaseStream::setStream(io);
644  sampleRateConverter.setStream(io);
645  }
646 
647  void setStream(Print &print) override {
648  TRACED();
649  //p_print = &print;
650  ReformatBaseStream::setStream(print);
651  sampleRateConverter.setStream(print);
652  }
653 
654  void setStream(AudioOutput &print) override {
655  TRACED();
656  //p_print = &print;
657  ReformatBaseStream::setStream(print);
658  sampleRateConverter.setStream(print);
659  }
660 
661  void setAudioInfo(AudioInfo info) override {
662  TRACED();
663  from_cfg = info;
664  sampleRateConverter.setAudioInfo(info);
665  ReformatBaseStream::setAudioInfo(info);
666  }
667 
668  bool begin(AudioInfo from, AudioInfo to) {
669  TRACED();
670  to_cfg = to;
671  return begin(from);
672  }
673 
674  bool begin(AudioInfo from) {
675  TRACED();
676  setAudioInfo(from);
677 
678  // build output chain
679  if (getStream()!=nullptr){
680  sampleRateConverter.setStream(*getStream());
681  }
682  if(getPrint()!=nullptr){
683  sampleRateConverter.setStream(*getPrint());
684  }
685  numberFormatConverter.setStream(sampleRateConverter);
686  channelFormatConverter.setStream(numberFormatConverter);
687 
688  // start individual converters
689  bool result = channelFormatConverter.begin(from_cfg, to_cfg.channels);
690 
691  AudioInfo from_actual_cfg(from_cfg);
692  from_actual_cfg.channels = to_cfg.channels;
693  result &= numberFormatConverter.begin(from_actual_cfg.bits_per_sample,
694  to_cfg.bits_per_sample);
695 
696  numberFormatConverter.setBuffered(is_buffered);
697  sampleRateConverter.setBuffered(is_buffered);
698 
699 
700  from_actual_cfg.bits_per_sample = to_cfg.bits_per_sample;
701  result &= sampleRateConverter.begin(from_actual_cfg, to_cfg.sample_rate);
702 
703  // setup reader to support readBytes()
704  if (getStream()!=nullptr){
705  setupReader();
706  }
707 
708  if (!result) {
709  LOGE("begin failed");
710  }
711  return result;
712  }
713 
714  virtual size_t write(const uint8_t *data, size_t size) override {
715  LOGD("FormatConverterStream::write: %d", (int)size);
716  return channelFormatConverter.write(data, size);
717  }
718 
720  void setBuffered(bool active){
721  is_buffered = active;
722  }
723 
724  float getByteFactor() { return numberFormatConverter.getByteFactor()*channelFormatConverter.getByteFactor();}
725 
726  protected:
727  AudioInfo from_cfg;
728  AudioInfo to_cfg;
729  NumberFormatConverterStream numberFormatConverter;
730  ChannelFormatConverterStream channelFormatConverter;
731  ResampleStream sampleRateConverter;
732  bool is_buffered = true;
733 
736  float byteFactor() {
737  return (float)from_cfg.channels / (float)to_cfg.channels *
738  (float)from_cfg.bits_per_sample / (float)to_cfg.bits_per_sample;
739  }
740 };
741 
742 } // namespace audio_tools
Abstract Audio Ouptut class.
Definition: AudioOutput.h:22
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition: AudioStreams.h:40
Increasing or decreasing the number of channels.
Definition: BaseConverter.h:789
Channel converter which does not use a template.
Definition: AudioStreamsConverter.h:104
Converter for reducing or increasing the number of Channels.
Definition: AudioStreamsConverter.h:14
Converter which converts bits_per_sample, channels and the sample_rate. The conversion is supported b...
Definition: AudioStreamsConverter.h:619
void setBuffered(bool active)
Buffering is active by default to minimize the number of output calls.
Definition: AudioStreamsConverter.h:720
float byteFactor()
Definition: AudioStreamsConverter.h:736
Converter which converts between bits_per_sample and 16 bits. The templated NumberFormatConverterStre...
Definition: AudioStreamsConverter.h:391
Converter which converts from source bits_per_sample to target bits_per_sample.
Definition: AudioStreamsConverter.h:284
void setBuffered(bool flag)
Definition: AudioStreamsConverter.h:368
void setGain(float value)
Defines the gain (only available when buffered is true)
Definition: AudioStreamsConverter.h:371
Definition: NoArduino.h:58
Base class for chained converting streams.
Definition: ResampleStream.h:119
void setBuffered(bool active)
Activates buffering to avoid small incremental writes.
Definition: ResampleStream.h:303
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
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:103
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
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57