arduino-audio-tools
Loading...
Searching...
No Matches
AudioStreamsConverter.h
1#pragma once
2#include "AudioIO.h"
3#include "AudioTools/CoreAudio/AudioStreams.h"
4#include "AudioTools/CoreAudio/ResampleStream.h"
5
6namespace audio_tools {
7
14template <typename T>
16 public:
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() override { 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
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() override {
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:
124 ChannelFormatConverterStream(Stream &stream) { setStream(stream); }
125 ChannelFormatConverterStream(Print &print) { setOutput(print); }
127 virtual ~ChannelFormatConverterStream() { end(); }
129 copy(from);
130 return *this;
131 }
132
133 void setAudioInfo(AudioInfo cfg) override {
134 TRACED();
135 end();
136 begin(cfg, to_channels);
137 }
138
141 AudioInfo out = audioInfo();
142 out.channels = to_channels;
143 return out;
144 }
145
146 bool begin(AudioInfo from, AudioInfo to) {
147 if (from.sample_rate != to.sample_rate) {
148 LOGE("invalid sample_rate: %d", (int)to.sample_rate);
149 return false;
150 }
151 if (from.bits_per_sample != to.bits_per_sample) {
152 LOGE("invalid bits_per_sample: %d", (int)to.bits_per_sample);
153 return false;
154 }
155 return begin(from, to.channels);
156 }
157
158 bool begin(AudioInfo cfg, int toChannels) {
159 // assert(toChannels != 0);
160 if (toChannels == 0) {
161 LOGE("toChannels is 0");
162 return false;
163 }
164 // is_output_notify = false;
165 to_channels = toChannels;
166 from_channels = cfg.channels;
167 bits_per_sample = cfg.bits_per_sample;
168 LOGI("--> ChannelFormatConverterStream");
170 LOGI("begin %d -> %d channels", cfg.channels, toChannels);
171 is_active = setupConverter(cfg.channels, toChannels);
172 if (!is_active) {
173 TRACEE()
174 }
175 return is_active;
176 }
177
178 bool begin() override { return begin(audioInfo(), to_channels); }
179
180 void end() override {
181 cleanupConverter();
182 is_active = false;
183 }
184
185 void setToChannels(uint16_t channels) { to_channels = channels; }
186
187 virtual size_t write(const uint8_t *data, size_t len) override {
188 LOGD("ChannelFormatConverterStream::write: %d", (int)len);
189 if (p_print == nullptr) return 0;
190 // addNotifyOnFirstWrite();
191 switch (bits_per_sample) {
192 case 8:
193 return getConverter<int8_t>()->write(data, len);
194 case 16:
195 return getConverter<int16_t>()->write(data, len);
196 case 24:
197 return getConverter<int24_t>()->write(data, len);
198 case 32:
199 return getConverter<int32_t>()->write(data, len);
200 default:
201 return 0;
202 }
203 }
204
205 size_t readBytes(uint8_t *data, size_t len) override {
206 LOGD("ChannelFormatConverterStream::readBytes: %d", (int)len);
207 switch (bits_per_sample) {
208 case 8:
209 return getConverter<int8_t>()->readBytes(data, len);
210 case 16:
211 return getConverter<int16_t>()->readBytes(data, len);
212 case 24:
213 return getConverter<int24_t>()->readBytes(data, len);
214 case 32:
215 return getConverter<int32_t>()->readBytes(data, len);
216 default:
217 return 0;
218 }
219 }
220
221 virtual int available() override {
222 switch (bits_per_sample) {
223 case 8:
224 return getConverter<int8_t>()->available();
225 case 16:
226 return getConverter<int16_t>()->available();
227 case 24:
228 return getConverter<int24_t>()->available();
229 case 32:
230 return getConverter<int32_t>()->available();
231 default:
232 return 0;
233 }
234 }
235
236 virtual int availableForWrite() override {
237 switch (bits_per_sample) {
238 case 8:
239 return getConverter<int8_t>()->availableForWrite();
240 case 16:
241 return getConverter<int16_t>()->availableForWrite();
242 case 24:
243 return getConverter<int24_t>()->availableForWrite();
244 case 32:
245 return getConverter<int32_t>()->availableForWrite();
246 default:
247 return 0;
248 }
249 }
250
251 float getByteFactor() override {
252 return static_cast<float>(to_channels) / static_cast<float>(from_channels);
253 }
254
255 protected:
256 void *converter = nullptr;
257 int bits_per_sample = 0;
258 int to_channels = 0;
259 int from_channels = 0;
260 bool is_active = false;
261
262 void copy(ChannelFormatConverterStream &from) {
263 converter = nullptr;
264 if (from.converter != nullptr) {
265 setupConverter(from.from_channels, from.to_channels);
266 }
267 bits_per_sample = from.bits_per_sample;
268 to_channels = from.to_channels;
269 from_channels = from.from_channels;
270 is_active = from.is_active;
271 };
272
273 template <typename T>
274 ChannelFormatConverterStreamT<T> *getConverter() {
275 return (ChannelFormatConverterStreamT<T> *)converter;
276 }
277
278 void cleanupConverter() {
279 if (converter == nullptr) return;
280 switch (bits_per_sample) {
281 case 8:
282 delete getConverter<int8_t>();
283 converter = nullptr;
284 break;
285 case 16:
286 delete getConverter<int16_t>();
287 converter = nullptr;
288 break;
289 case 24:
290 delete getConverter<int24_t>();
291 converter = nullptr;
292 break;
293 case 32:
294 delete getConverter<int32_t>();
295 converter = nullptr;
296 break;
297 }
298 }
299
300 bool setupConverter(int fromChannels, int toChannels) {
301 bool result = true;
302 cleanupConverter();
303 switch (bits_per_sample) {
304 case 8:
305 converter = new ChannelFormatConverterStreamT<int8_t>(*p_stream);
306 getConverter<int8_t>()->begin(fromChannels, toChannels);
307 break;
308 case 16:
309 converter = new ChannelFormatConverterStreamT<int16_t>(*p_stream);
310 getConverter<int16_t>()->begin(fromChannels, toChannels);
311 break;
312 case 24:
313 converter = new ChannelFormatConverterStreamT<int24_t>(*p_stream);
314 getConverter<int24_t>()->begin(fromChannels, toChannels);
315 break;
316 case 32:
317 converter = new ChannelFormatConverterStreamT<int32_t>(*p_stream);
318 getConverter<int32_t>()->begin(fromChannels, toChannels);
319 break;
320 default:
321 result = false;
322 }
323 return result;
324 }
325};
326
340template <typename TFrom, typename TTo>
342 public:
344 NumberFormatConverterStreamT(float gain) { setGain(gain); }
345 NumberFormatConverterStreamT(Stream &stream) { setStream(stream); }
347 NumberFormatConverterStreamT(Print &print) { setOutput(print); }
348 NumberFormatConverterStreamT(AudioOutput &print) { setOutput(print); }
349
350 void setAudioInfo(AudioInfo newInfo) override {
351 TRACED();
352 if (newInfo.bits_per_sample == sizeof(TFrom) * 8) {
353 LOGE("Invalid bits_per_sample %d", newInfo.bits_per_sample);
354 }
356 }
357
359 AudioInfo to_format;
360 to_format.copyFrom(info);
361 to_format.bits_per_sample = sizeof(TTo) * 8;
362 return to_format;
363 }
364
365 bool begin() override {
366 LOGI("begin %d -> %d bits", (int)sizeof(TFrom), (int)sizeof(TTo));
367 // is_output_notify = false;
368 return true;
369 }
370
371 virtual size_t write(const uint8_t *data, size_t len) override {
372 TRACED();
373 if (p_print == nullptr) return 0;
374 // addNotifyOnFirstWrite();
375
376#ifdef USE_TYPETRAITS
377 if (std::is_same<TFrom, TTo>::value) return p_print->write(data, len);
378#else
379 if (sizeof(TFrom) == sizeof(TTo)) return p_print->write(data, len);
380#endif
381
382 size_t samples = len / sizeof(TFrom);
383 size_t result_size = 0;
384 TFrom *data_source = (TFrom *)data;
385
386 if (!is_buffered) {
387 for (size_t j = 0; j < samples; j++) {
388 TTo value = NumberConverter::convert<TFrom, TTo>(data_source[j]);
389 result_size += p_print->write((uint8_t *)&value, sizeof(TTo));
390 }
391 } else {
392 int size_bytes = sizeof(TTo) * samples;
393 buffer.resize(size_bytes);
394 NumberConverter::convertArray<TFrom, TTo>(
395 data_source, (TTo *)buffer.data(), samples, gain);
396 p_print->write((uint8_t *)buffer.address(), size_bytes);
397 buffer.reset();
398 }
399
400 return len;
401 }
402
403 size_t readBytes(uint8_t *data, size_t len) override {
404 LOGD("NumberFormatConverterStreamT::readBytes: %d", (int)len);
405 if (p_stream == nullptr) return 0;
406 size_t samples = len / sizeof(TTo);
407 TTo *data_target = (TTo *)data;
408 TFrom source;
409 if (!is_buffered) {
410 for (size_t j = 0; j < samples; j++) {
411 source = 0;
412 p_stream->readBytes((uint8_t *)&source, sizeof(TFrom));
413 data_target[j] = NumberConverter::convert<TFrom, TTo>(source);
414 }
415 } else {
416 buffer.resize(sizeof(TFrom) * samples);
417 readSamples<TFrom>(p_stream, (TFrom *)buffer.address(), samples);
418 TFrom *data = (TFrom *)buffer.address();
419 NumberConverter::convertArray<TFrom, TTo>(data, data_target, samples,
420 gain);
421 buffer.reset();
422 }
423 return len;
424 }
425
426 virtual int available() override {
427 return p_stream != nullptr ? p_stream->available() : 0;
428 }
429
430 virtual int availableForWrite() override {
431 return p_print == nullptr ? 0 : p_print->availableForWrite();
432 }
433
436 void setBuffered(bool flag) { is_buffered = flag; }
437
439 void setGain(float value) { gain = value; }
440
441 float getByteFactor() override {
442 return static_cast<float>(sizeof(TTo)) / static_cast<float>(sizeof(TFrom));
443 }
444
445 protected:
446 SingleBuffer<uint8_t> buffer{0};
447 bool is_buffered = true;
448 float gain = 1.0f;
449};
450
460 public:
461 NumberFormatConverterStream() = default;
462 NumberFormatConverterStream(Stream &stream) { setStream(stream); }
464 NumberFormatConverterStream(Print &print) { setOutput(print); }
465 NumberFormatConverterStream(AudioOutput &print) { setOutput(print); }
466 virtual ~NumberFormatConverterStream() { end(); }
467
468 void setAudioInfo(AudioInfo newInfo) override {
469 TRACED();
470 this->from_bit_per_samples = newInfo.bits_per_sample;
471 LOGI("-> NumberFormatConverterStream:")
473 }
474
476 AudioInfo result = audioInfo();
477 result.bits_per_sample = to_bit_per_samples;
478 return result;
479 }
480
481 bool begin(AudioInfo info, AudioInfo to, float gain = 1.0f) {
482 if (info.sample_rate != to.sample_rate) {
483 LOGE("sample_rate does not match")
484 return false;
485 }
486 if (info.channels != to.channels) {
487 LOGE("channels do not match")
488 return false;
489 }
490 return begin(info, to.bits_per_sample, gain);
491 }
492
493 bool begin(AudioInfo info, int toBits, float gain = 1.0f) {
494 setAudioInfo(info);
495 return begin(info.bits_per_sample, toBits, gain);
496 }
497
498 bool begin() override {
499 return begin(from_bit_per_samples, to_bit_per_samples, gain);
500 }
501
502 void end() override { cleanupConverter(); }
503
504 void setToBits(uint8_t bits) { to_bit_per_samples = bits; }
505
506 bool begin(int from_bit_per_samples, int to_bit_per_samples,
507 float gain = 1.0) {
508 LOGI("begin %d -> %d bits", from_bit_per_samples, to_bit_per_samples);
509 bool result = true;
510 assert(to_bit_per_samples > 0);
511
513 if (p_converter != nullptr) end();
514
515 // store variables
516 this->gain = gain;
517 this->from_bit_per_samples = from_bit_per_samples;
518 this->to_bit_per_samples = to_bit_per_samples;
519
520 if (from_bit_per_samples == to_bit_per_samples) {
521 LOGI("no bit conversion: %d -> %d", from_bit_per_samples,
522 to_bit_per_samples);
523 } else if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
524 p_converter = new NumberFormatConverterStreamT<int8_t, int16_t>(gain);
525 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
526 p_converter = new NumberFormatConverterStreamT<int16_t, int8_t>(gain);
527 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
529 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
531 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
533 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
535 } else {
536 result = false;
537 LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
538 to_bit_per_samples);
539 }
540
541 if (from_bit_per_samples != to_bit_per_samples) {
542 setupStream();
543 }
544
545 if (!result) {
546 TRACEE()
547 }
548 return result;
549 }
550
551 virtual size_t write(const uint8_t *data, size_t len) override {
552 LOGD("NumberFormatConverterStream::write: %d", (int)len);
553 if (p_print == nullptr) return 0;
554 if (from_bit_per_samples == to_bit_per_samples) {
555 return p_print->write(data, len);
556 }
557
558 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
559 return getConverter<int8_t, int16_t>()->write(data, len);
560 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
561 return getConverter<int16_t, int8_t>()->write(data, len);
562 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
563 return getConverter<int24_t, int16_t>()->write(data, len);
564 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
565 return getConverter<int16_t, int24_t>()->write(data, len);
566 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
567 return getConverter<int32_t, int16_t>()->write(data, len);
568 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
569 return getConverter<int16_t, int32_t>()->write(data, len);
570 } else {
571 LOGE("bit combination not supported %d -> %d", from_bit_per_samples,
572 to_bit_per_samples);
573 return 0;
574 }
575 }
576
577 size_t readBytes(uint8_t *data, size_t len) override {
578 LOGD("NumberFormatConverterStream::readBytes: %d", (int)len);
579 if (from_bit_per_samples == to_bit_per_samples) {
580 return p_stream->readBytes(data, len);
581 }
582 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
583 return getConverter<int8_t, int16_t>()->readBytes(data, len);
584 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
585 return getConverter<int16_t, int8_t>()->readBytes(data, len);
586 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
587 return getConverter<int24_t, int16_t>()->readBytes(data, len);
588 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
589 return getConverter<int16_t, int24_t>()->readBytes(data, len);
590 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
591 return getConverter<int32_t, int16_t>()->readBytes(data, len);
592 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
593 return getConverter<int16_t, int32_t>()->readBytes(data, len);
594 } else {
595 TRACEE();
596 return 0;
597 }
598 }
599
600 virtual int available() override {
601 if (from_bit_per_samples == to_bit_per_samples) {
602 return p_stream->available();
603 }
604 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
605 return getConverter<int8_t, int16_t>()->available();
606 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
607 return getConverter<int16_t, int8_t>()->available();
608 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
609 return getConverter<int24_t, int16_t>()->available();
610 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
611 return getConverter<int16_t, int24_t>()->available();
612 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
613 return getConverter<int32_t, int16_t>()->available();
614 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
615 return getConverter<int16_t, int32_t>()->available();
616 } else {
617 TRACEE();
618 return 0;
619 }
620 }
621
622 virtual int availableForWrite() override {
623 if (p_print == nullptr) return 0;
624 if (from_bit_per_samples == to_bit_per_samples) {
625 return p_print->availableForWrite();
626 }
627 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
628 return getConverter<int8_t, int16_t>()->availableForWrite();
629 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
630 return getConverter<int16_t, int8_t>()->availableForWrite();
631 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
632 return getConverter<int24_t, int16_t>()->availableForWrite();
633 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
634 return getConverter<int16_t, int24_t>()->availableForWrite();
635 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
636 return getConverter<int32_t, int16_t>()->availableForWrite();
637 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
638 return getConverter<int16_t, int32_t>()->availableForWrite();
639 } else {
640 TRACEE();
641 return 0;
642 }
643 }
644
645 void setBuffered(bool flag) {
646 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
647 getConverter<int8_t, int16_t>()->setBuffered(flag);
648 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
649 getConverter<int16_t, int8_t>()->setBuffered(flag);
650 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
651 getConverter<int24_t, int16_t>()->setBuffered(flag);
652 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
653 getConverter<int16_t, int24_t>()->setBuffered(flag);
654 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
655 getConverter<int32_t, int16_t>()->setBuffered(flag);
656 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
657 getConverter<int16_t, int32_t>()->setBuffered(flag);
658 }
659 }
660
661 float getByteFactor() override {
662 return static_cast<float>(to_bit_per_samples) /
663 static_cast<float>(from_bit_per_samples);
664 }
665
666 protected:
667 void *p_converter = nullptr;
668 int from_bit_per_samples = 16;
669 int to_bit_per_samples = 0;
670 float gain = 1.0;
671
672 void cleanupConverter() {
673 if (p_converter == nullptr) return;
674
675 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
676 delete static_cast<NumberFormatConverterStreamT<int8_t, int16_t> *>(
677 p_converter);
678 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
679 delete static_cast<NumberFormatConverterStreamT<int16_t, int8_t> *>(
680 p_converter);
681 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
682 delete static_cast<NumberFormatConverterStreamT<int24_t, int16_t> *>(
683 p_converter);
684 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
685 delete static_cast<NumberFormatConverterStreamT<int16_t, int24_t> *>(
686 p_converter);
687 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
688 delete static_cast<NumberFormatConverterStreamT<int32_t, int16_t> *>(
689 p_converter);
690 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
691 delete static_cast<NumberFormatConverterStreamT<int16_t, int32_t> *>(
692 p_converter);
693 } else {
694 TRACEE();
695 }
696 p_converter = nullptr;
697 }
698
699 template <typename TFrom, typename TTo>
700 NumberFormatConverterStreamT<TFrom, TTo> *getConverter() {
701 return (NumberFormatConverterStreamT<TFrom, TTo> *)p_converter;
702 }
703
704 void setupStream() {
705 if (p_stream != nullptr) {
706 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
707 getConverter<int8_t, int16_t>()->setStream(*p_stream);
708 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
709 getConverter<int16_t, int8_t>()->setStream(*p_stream);
710 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
711 getConverter<int24_t, int16_t>()->setStream(*p_stream);
712 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
713 getConverter<int16_t, int24_t>()->setStream(*p_stream);
714 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
715 getConverter<int32_t, int16_t>()->setStream(*p_stream);
716 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
717 getConverter<int16_t, int32_t>()->setStream(*p_stream);
718 } else {
719 TRACEE();
720 }
721 } else {
722 if (from_bit_per_samples == 8 && to_bit_per_samples == 16) {
723 getConverter<int8_t, int16_t>()->setOutput(*p_print);
724 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 8) {
725 getConverter<int16_t, int8_t>()->setOutput(*p_print);
726 } else if (from_bit_per_samples == 24 && to_bit_per_samples == 16) {
727 getConverter<int24_t, int16_t>()->setOutput(*p_print);
728 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 24) {
729 getConverter<int16_t, int24_t>()->setOutput(*p_print);
730 } else if (from_bit_per_samples == 32 && to_bit_per_samples == 16) {
731 getConverter<int32_t, int16_t>()->setOutput(*p_print);
732 } else if (from_bit_per_samples == 16 && to_bit_per_samples == 32) {
733 getConverter<int16_t, int32_t>()->setOutput(*p_print);
734 } else {
735 TRACEE();
736 }
737 }
738 }
739};
740
750 public:
751 FormatConverterStream() = default;
752 FormatConverterStream(Stream &stream) { setStream(stream); }
753 FormatConverterStream(Print &print) { setOutput(print); }
755 to_cfg = stream.audioInfo();
756 from_cfg = stream.audioInfo();
757 setStream(stream);
758 }
760 to_cfg = print.audioInfo();
761 setOutput(print);
762 }
763
764 void setStream(Stream &io) override {
765 TRACED();
766 ReformatBaseStream::setStream(io);
767 sampleRateConverter.setStream(io);
768 }
769
770 void setStream(AudioStream &io) override {
771 TRACED();
772 ReformatBaseStream::setStream(io);
773 sampleRateConverter.setStream(io);
774 }
775
776 void setOutput(Print &print) override {
777 TRACED();
778 ReformatBaseStream::setOutput(print);
779 sampleRateConverter.setOutput(print);
780 }
781
782 void setOutput(AudioOutput &print) override {
783 TRACED();
784 ReformatBaseStream::setOutput(print);
785 sampleRateConverter.setOutput(print);
786 }
787
789 void setAudioInfo(AudioInfo info) override {
790 TRACEI();
791 info.logInfo("FormatConverterStream");
792 ReformatBaseStream::setAudioInfo(info);
793 // ChannelFormatConverter -> NumberFormatConverter -> SampleRateCoverter
794 channelFormatConverter.setAudioInfo(info);
795 }
796
797 void setAudioInfoOut(AudioInfo to) { to_cfg = to; }
798
799 AudioInfo audioInfoOut() override { return to_cfg; }
800
801 bool begin(AudioInfo from, AudioInfo to) {
802 TRACED();
803 setAudioInfoOut(to);
804 return begin(from);
805 }
806
808 bool begin(AudioInfo from) {
809 setAudioInfo(from);
810 return begin();
811 }
812
814 bool begin() override {
815 TRACED();
816 // is_output_notify = false;
817 // build output chain
818 if (getStream() != nullptr) {
819 sampleRateConverter.setStream(*getStream());
820 }
821 if (getPrint() != nullptr) {
822 sampleRateConverter.setOutput(*getPrint());
823 }
824 numberFormatConverter.setStream(sampleRateConverter);
825 channelFormatConverter.setStream(numberFormatConverter);
826
827 // start individual converters
828 bool result = channelFormatConverter.begin(from_cfg, to_cfg.channels);
829
830 AudioInfo from_actual_cfg(from_cfg);
831 from_actual_cfg.channels = to_cfg.channels;
832 result &= numberFormatConverter.begin(from_actual_cfg.bits_per_sample,
833 to_cfg.bits_per_sample);
834
835 numberFormatConverter.setBuffered(is_buffered);
836 sampleRateConverter.setBuffered(is_buffered);
837
838 from_actual_cfg.bits_per_sample = to_cfg.bits_per_sample;
839 result &= sampleRateConverter.begin(from_actual_cfg, to_cfg.sample_rate);
840
841 // setup reader to support readBytes()
842 setupReader();
843
844 if (!result) {
845 LOGE("begin failed");
846 }
847 return result;
848 }
849
850 virtual size_t write(const uint8_t *data, size_t len) override {
851 LOGD("FormatConverterStream::write: %d", (int)len);
852 // addNotifyOnFirstWrite();
853 return channelFormatConverter.write(data, len);
854 }
855
857 void setBuffered(bool active) { is_buffered = active; }
858
859 float getByteFactor() override {
860 return numberFormatConverter.getByteFactor() *
861 channelFormatConverter.getByteFactor();
862 }
863
864 protected:
865 AudioInfo &from_cfg = info;
866 AudioInfo to_cfg;
867 NumberFormatConverterStream numberFormatConverter;
868 ChannelFormatConverterStream channelFormatConverter;
869 ResampleStream sampleRateConverter;
870 bool is_buffered = true;
871};
872
873} // namespace audio_tools
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
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:122
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:130
virtual AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition BaseStream.h:153
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:140
void setAudioInfo(AudioInfo cfg) override
Defines the input AudioInfo.
Definition AudioStreamsConverter.h:133
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:749
void setOutput(Print &print) override
Defines/Changes the output target.
Definition AudioStreamsConverter.h:776
void setBuffered(bool active)
Buffering is active by default to minimize the number of output calls.
Definition AudioStreamsConverter.h:857
bool begin(AudioInfo from)
Starts the processing: call setAudioInfoOut before to define the target.
Definition AudioStreamsConverter.h:808
AudioInfo audioInfoOut() override
Definition AudioStreamsConverter.h:799
bool begin() override
(Re-)Starts the processing: call setAudioInfo and setAudioInfoOut before
Definition AudioStreamsConverter.h:814
void setAudioInfo(AudioInfo info) override
Set the input audio information.
Definition AudioStreamsConverter.h:789
void setStream(Stream &io) override
Defines/Changes the input & output.
Definition AudioStreamsConverter.h:764
Converter which converts between bits_per_sample and 16 bits. The templated NumberFormatConverterStre...
Definition AudioStreamsConverter.h:459
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioStreamsConverter.h:468
bool begin(int from_bit_per_samples, int to_bit_per_samples, float gain=1.0)
Definition AudioStreamsConverter.h:506
AudioInfo audioInfoOut() override
Definition AudioStreamsConverter.h:475
A more generic templated Converter which converts from a source type to a target type: You can use e....
Definition AudioStreamsConverter.h:341
void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioStreamsConverter.h:350
void setBuffered(bool flag)
Definition AudioStreamsConverter.h:436
void setGain(float value)
Defines the gain (only available when buffered is true)
Definition AudioStreamsConverter.h:439
AudioInfo audioInfoOut() override
Definition AudioStreamsConverter.h:358
Definition NoArduino.h:62
Base class for chained converting streams.
Definition AudioIO.h:156
virtual void setStream(Stream &stream) override
Defines/Changes the input & output.
Definition AudioIO.h:158
T * address() override
Provides address to beginning of the buffer.
Definition Buffers.h:280
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:304
T * data()
Provides address of actual data.
Definition Buffers.h:283
void reset() override
clears the buffer
Definition Buffers.h:285
Definition NoArduino.h:142
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:105
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61