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