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