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