arduino-audio-tools
Loading...
Searching...
No Matches
BaseConverter.h
1#pragma once
2#include "AudioFilter/Filter.h"
3#include "AudioTools/CoreAudio/AudioBasic/Collections.h"
4#include "AudioTypes.h"
5
14namespace audio_tools {
15
25 public:
26 BaseConverter() = default;
27 BaseConverter(BaseConverter const &) = delete;
28 virtual ~BaseConverter() = default;
29
30 BaseConverter &operator=(BaseConverter const &) = delete;
31
32 virtual size_t convert(uint8_t *src, size_t size) = 0;
33};
34
41 public:
42 size_t convert(uint8_t(*src), size_t size) override { return size; };
43};
44
54template <typename T = int16_t>
56 public:
57 ConverterScaler(float factor, T offset, T maxValue, int channels = 2) {
58 this->factor_value = factor;
59 this->maxValue = maxValue;
60 this->offset_value = offset;
61 this->channels = channels;
62 }
63
64 size_t convert(uint8_t *src, size_t byte_count) {
65 T *sample = (T *)src;
66 int size = byte_count / channels / sizeof(T);
67 for (size_t j = 0; j < size; j++) {
68 for (int i = 0; i < channels; i++) {
69 *sample = (*sample + offset_value) * factor_value;
70 if (*sample > maxValue) {
71 *sample = maxValue;
72 } else if (*sample < -maxValue) {
73 *sample = -maxValue;
74 }
75 sample++;
76 }
77 }
78 return byte_count;
79 }
80
82 void setFactor(float factor) { this->factor_value = factor; }
83
85 void setOffset(T offset) { this->offset_value = offset; }
86
88 float factor() { return factor_value; }
89
91 T offset() { return offset_value; }
92
93 protected:
94 int channels;
95 float factor_value;
96 T maxValue;
97 T offset_value;
98};
99
105template <typename T = int16_t>
107 public:
108 ConverterAutoCenterT(int channels = 2, bool isDynamic = false) {
109 this->channels = channels;
110 this->is_dynamic = isDynamic;
111 }
112
113 void clear() { resetState(); }
114 void reset() { clear(); }
115
116 size_t convert(uint8_t(*src), size_t byte_count) override {
117 size_t size = byte_count / channels / sizeof(T);
118 T *sample = (T *)src;
119 setup((T *)src, size);
120 // convert data
121 if (is_setup) {
122 if (!is_dynamic) {
123 for (size_t j = 0; j < size; j++) {
124 for (int ch = 0; ch < channels; ch++) {
125 sample[(j * channels) + ch] =
126 sample[(j * channels) + ch] - offset_to[ch];
127 }
128 }
129 } else {
130 for (size_t j = 0; j < size; j++) {
131 for (int ch = 0; ch < channels; ch++) {
132 sample[(j * channels) + ch] = sample[(j * channels) + ch] -
133 offset_from[ch] +
134 (offset_step[ch] * size);
135 }
136 }
137 }
138 }
139 return byte_count;
140 }
141
142 protected:
143 Vector<float> offset_from{0};
144 Vector<float> offset_to{0};
145 Vector<float> offset_step{0};
146 Vector<float> total{0};
147 float left = 0.0;
148 float right = 0.0;
149 bool is_setup = false;
150 bool is_dynamic;
151 int channels;
152
153 void resetState() {
154 offset_from.clear();
155 offset_to.clear();
156 offset_step.clear();
157 total.clear();
158 left = 0.0;
159 right = 0.0;
160 is_setup = false;
161 }
162
163 void setup(T *src, size_t size) {
164 if (size == 0) return;
165 if (!is_setup || is_dynamic) {
166 if (offset_from.size() == 0) {
167 offset_from.resize(channels);
168 offset_to.resize(channels);
169 offset_step.resize(channels);
170 total.resize(channels);
171 }
172
173 // save last offset
174 for (int ch = 0; ch < channels; ch++) {
175 offset_from[ch] = offset_to[ch];
176 total[ch] = 0.0;
177 }
178
179 // calculate new offset
180 for (size_t j = 0; j < size; j++) {
181 for (int ch = 0; ch < channels; ch++) {
182 total[ch] += src[(j * channels) + ch];
183 }
184 }
185 for (int ch = 0; ch < channels; ch++) {
186 offset_to[ch] = total[ch] / size;
187 offset_step[ch] = (offset_to[ch] - offset_from[ch]) / size;
188 }
189 is_setup = true;
190 }
191 }
192};
193
199 public:
200 ConverterAutoCenter() = default;
201
203 begin(info.channels, info.bits_per_sample);
204 }
205
206 ConverterAutoCenter(int channels, int bitsPerSample) {
207 begin(channels, bitsPerSample);
208 }
209 ~ConverterAutoCenter() { end(); }
210
211 void end() {
212 if (p_converter != nullptr) {
213 delete p_converter;
214 p_converter = nullptr;
215 }
216 }
217
218 bool begin(AudioInfo info, bool isDynamic = false) {
219 return begin(info.channels, info.bits_per_sample, isDynamic);
220 }
221
222 bool begin(int channels, int bitsPerSample, bool isDynamic = false) {
223 // check if we need to create a new converter
224 if (p_converter != nullptr && channels == this->channels &&
225 bitsPerSample == this->bits_per_sample && isDynamic == this->is_dynamic) {
226 return true;
227 }
228 this->channels = channels;
229 this->bits_per_sample = bitsPerSample;
230 this->is_dynamic = isDynamic;
231 end();
232 assert(p_converter == nullptr);
233 switch (bits_per_sample) {
234 case 8: {
235 p_converter = new ConverterAutoCenterT<int8_t>(channels, isDynamic);
236 break;
237 }
238 case 16: {
239 p_converter = new ConverterAutoCenterT<int16_t>(channels, isDynamic);
240 break;
241 }
242 case 24: {
243 p_converter = new ConverterAutoCenterT<int24_t>(channels, isDynamic);
244 break;
245 }
246 case 32: {
247 p_converter = new ConverterAutoCenterT<int32_t>(channels, isDynamic);
248 break;
249 }
250 }
251 return p_converter != nullptr;
252 }
253
254 size_t convert(uint8_t *src, size_t size) override {
255 if (p_converter == nullptr) return 0;
256 return p_converter->convert(src, size);
257 }
258
259 void clear() {
260 end();
261 if (channels > 0 && bits_per_sample > 0) {
262 begin(channels, bits_per_sample, is_dynamic);
263 }
264 }
265 void reset() { clear(); }
266
267 protected:
268 int channels = 0;
269 int bits_per_sample = 0;
270 bool is_dynamic = false;
271 BaseConverter *p_converter = nullptr;
272};
273
282template <typename T = int16_t>
284 public:
285 ConverterSwitchLeftAndRight(int channels = 2) { this->channels = channels; }
286
287 size_t convert(uint8_t *src, size_t byte_count) override {
288 if (channels == 2) {
289 int size = byte_count / channels / sizeof(T);
290 T *sample = (T *)src;
291 for (size_t j = 0; j < size; j++) {
292 T temp = *sample;
293 *sample = *(sample + 1);
294 *(sample + 1) = temp;
295 sample += 2;
296 }
297 }
298 return byte_count;
299 }
300
301 protected:
302 int channels = 2;
303};
304
309enum FillLeftAndRightStatus { Auto, LeftIsEmpty, RightIsEmpty };
310
321template <typename T = int16_t>
323 public:
325 int channels = 2) {
326 this->channels = channels;
327 switch (config) {
328 case LeftIsEmpty:
329 left_empty = true;
330 right_empty = false;
331 is_setup = true;
332 break;
333 case RightIsEmpty:
334 left_empty = false;
335 right_empty = true;
336 is_setup = true;
337 break;
338 case Auto:
339 is_setup = false;
340 break;
341 }
342 }
343
344 size_t convert(uint8_t *src, size_t byte_count) {
345 if (channels == 2) {
346 int size = byte_count / channels / sizeof(T);
347 setup((T *)src, size);
348 if (left_empty && !right_empty) {
349 T *sample = (T *)src;
350 for (size_t j = 0; j < size; j++) {
351 *sample = *(sample + 1);
352 sample += 2;
353 }
354 } else if (!left_empty && right_empty) {
355 T *sample = (T *)src;
356 for (size_t j = 0; j < size; j++) {
357 *(sample + 1) = *sample;
358 sample += 2;
359 }
360 }
361 }
362 return byte_count;
363 }
364
365 private:
366 bool is_setup = false;
367 bool left_empty = true;
368 bool right_empty = true;
369 int channels;
370
371 void setup(T *src, size_t size) {
372 if (!is_setup) {
373 for (int j = 0; j < size; j++) {
374 if (*src != 0) {
375 left_empty = false;
376 break;
377 }
378 src += 2;
379 }
380 for (int j = 0; j < size - 1; j++) {
381 if (*(src) != 0) {
382 right_empty = false;
383 break;
384 }
385 src += 2;
386 }
387 // stop setup as soon as we found some data
388 if (!right_empty || !left_empty) {
389 is_setup = true;
390 }
391 }
392 }
393};
394
404template <typename T = int16_t>
406 public:
407 ConverterToInternalDACFormat(int channels = 2) { this->channels = channels; }
408
409 size_t convert(uint8_t *src, size_t byte_count) override {
410 int size = byte_count / channels / sizeof(T);
411 T *sample = (T *)src;
412 for (int i = 0; i < size; i++) {
413 for (int j = 0; j < channels; j++) {
414 *sample = *sample + 0x8000;
415 sample++;
416 }
417 }
418 return byte_count;
419 }
420
421 protected:
422 int channels;
423};
424
432template <typename T = int16_t>
434 public:
435 ChannelReducerT() = default;
436
437 ChannelReducerT(int channelCountOfTarget, int channelCountOfSource) {
438 from_channels = channelCountOfSource;
439 to_channels = channelCountOfTarget;
440 }
441
442 void setSourceChannels(int channelCountOfSource) {
443 from_channels = channelCountOfSource;
444 }
445
446 void setTargetChannels(int channelCountOfTarget) {
447 to_channels = channelCountOfTarget;
448 }
449
450 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
451
452 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
453 LOGD("convert %d -> %d", from_channels, to_channels);
454 assert(to_channels <= from_channels);
455 int frame_count = size / (sizeof(T) * from_channels);
456 size_t result_size = 0;
457 T *result = (T *)target;
458 T *source = (T *)src;
459 int reduceDiv = from_channels - to_channels + 1;
460
461 for (int i = 0; i < frame_count; i++) {
462 // copy first to_channels-1
463 for (int j = 0; j < to_channels - 1; j++) {
464 *result++ = *source++;
465 result_size += sizeof(T);
466 }
467 // commbined last channels
468 T total = (int16_t)0;
469 for (int j = to_channels - 1; j < from_channels; j++) {
470 total += *source++ / reduceDiv;
471 }
472 *result++ = total;
473 result_size += sizeof(T);
474 }
475 return result_size;
476 }
477
478 protected:
479 int from_channels;
480 int to_channels;
481};
482
490 public:
491 ChannelReducer(int channelCountOfTarget, int channelCountOfSource,
492 int bitsPerSample) {
493 from_channels = channelCountOfSource;
494 to_channels = channelCountOfTarget;
495 bits = bitsPerSample;
496 }
497
498 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
499
500 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
501 switch (bits) {
502 case 8: {
503 ChannelReducerT<int8_t> cr8(to_channels, from_channels);
504 return cr8.convert(target, src, size);
505 }
506 case 16: {
507 ChannelReducerT<int16_t> cr16(to_channels, from_channels);
508 return cr16.convert(target, src, size);
509 }
510 case 24: {
511 ChannelReducerT<int24_t> cr24(to_channels, from_channels);
512 return cr24.convert(target, src, size);
513 }
514 case 32: {
515 ChannelReducerT<int32_t> cr32(to_channels, from_channels);
516 return cr32.convert(target, src, size);
517 }
518 }
519 return 0;
520 }
521
522 protected:
523 int from_channels;
524 int to_channels;
525 int bits;
526};
527
532template <typename T = int16_t>
533class DecimateT : public BaseConverter {
534 public:
535 DecimateT(int factor, int channels) {
536 setChannels(channels);
537 setFactor(factor);
538 count = 0; // Initialize count to 0
539 }
540
542 void setChannels(int channels) {
543 this->channels = channels;
544 resetState();
545 }
546
548 void setFactor(int factor) {
549 this->factor = factor;
550 resetState();
551 }
552 void clear() { resetState(); }
553 void reset() { clear(); }
554
555 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
556
557 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
558 if (!isConfigValid()) return 0;
559 if (size % (sizeof(T) * channels) > 0) {
560 LOGE("Buffer size %d is not a multiple of the number of channels %d",
561 (int)size, channels);
562 return 0;
563 }
564
565 int frame_count = size / (sizeof(T) * channels);
566 T *p_target = (T *)target;
567 T *p_source = (T *)src;
568 size_t result_size = 0;
569
570 for (int i = 0; i < frame_count; i++) {
571 if (++count == factor) {
572 count = 0;
573 // Only keep every "factor" samples
574 for (int ch = 0; ch < channels; ch++) {
575 *p_target++ = p_source[i * channels + ch]; // Corrected indexing
576 result_size += sizeof(T);
577 }
578 }
579 }
580
581 LOGD("decimate %d: %d -> %d bytes", factor, (int)size, (int)result_size);
582 return result_size;
583 }
584
585 operator bool() { return factor > 1; }
586
587 protected:
588 bool isConfigValid() {
589 if (channels <= 0) {
590 LOGE("Number of channels must be > 0");
591 return false;
592 }
593 if (factor <= 0) {
594 LOGE("Decimation factor must be > 0");
595 return false;
596 }
597 return true;
598 }
599
600 void resetState() { count = 0; }
601
602 int channels = 2;
603 int factor = 1;
604 uint16_t count = 0;
605};
606
613class Decimate : public BaseConverter {
614 public:
615 Decimate() = default;
616 Decimate(int factor, int channels, int bits_per_sample) {
617 setFactor(factor);
618 setChannels(channels);
619 setBits(bits_per_sample);
620 }
622 void setChannels(int channels) {
623 this->channels = channels;
624 resetState();
625 }
626 void setBits(int bits) {
627 this->bits = bits;
628 resetState();
629 }
631 void setFactor(int factor) {
632 this->factor = factor;
633 resetState();
634 }
635 ~Decimate() override { delete state; }
636 void clear() {
637 if (state != nullptr) {
638 state->reset();
639 }
640 }
641 void reset() { clear(); }
642
643 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
644 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
645 if (!isConfigValid()) return 0;
646 if (state == nullptr) {
647 switch (bits) {
648 case 8:
649 state = new DecimateStateT<int8_t>(factor, channels);
650 break;
651 case 16:
652 state = new DecimateStateT<int16_t>(factor, channels);
653 break;
654 case 24:
655 state = new DecimateStateT<int24_t>(factor, channels);
656 break;
657 case 32:
658 state = new DecimateStateT<int32_t>(factor, channels);
659 break;
660 default:
661 LOGE("Number of bits %d not supported.", bits);
662 return 0;
663 }
664 }
665 return state->convert(target, src, size);
666 }
667
668 operator bool() { return factor > 1; };
669
670 protected:
672 virtual ~DecimateState() = default;
673 virtual size_t convert(uint8_t *target, uint8_t *src, size_t size) = 0;
674 virtual void reset() = 0;
675 };
676
677 template <typename T>
679 DecimateStateT(int factor, int channels) : converter(factor, channels) {}
680
681 size_t convert(uint8_t *target, uint8_t *src, size_t size) override {
682 return converter.convert(target, src, size);
683 }
684
685 void reset() override { converter.reset(); }
686
687 DecimateT<T> converter;
688 };
689
690 bool isConfigValid() {
691 if (channels <= 0) {
692 LOGE("Number of channels must be > 0");
693 return false;
694 }
695 if (factor <= 0) {
696 LOGE("Decimation factor must be > 0");
697 return false;
698 }
699 return true;
700 }
701
702 void resetState() {
703 delete state;
704 state = nullptr;
705 }
706
707 int channels = 2;
708 int bits = 16;
709 int factor = 1;
710 DecimateState *state = nullptr;
711};
712
722// Helper template to define the integer type for the summation based on input
723// data type T
724template <typename T = int16_t>
726 using type = T;
727};
728
729template <>
730struct AppropriateSumType<int8_t> {
731 using type = int16_t;
732};
733
734template <>
735struct AppropriateSumType<int16_t> {
736 using type = int32_t;
737};
738
739template <>
741 using type = int32_t; // Assuming int24_t is a custom 24-bit integer type
742};
743
744template <>
745struct AppropriateSumType<int32_t> {
746 using type = int64_t;
747};
748
749template <typename T = int16_t>
750class BinT : public BaseConverter {
751 public:
752 BinT() = default;
753 BinT(int binSize, int channels, bool average) {
754 setChannels(channels);
755 setBinSize(binSize);
756 setAverage(average);
757 resetState();
758 }
759
760 ~BinT() { delete[] this->partialBin; }
761
762 void setChannels(int channels) {
763 this->channels = channels;
764 resizeState();
765 }
766 void setBinSize(int binSize) {
767 this->binSize = binSize;
768 resetState();
769 }
770 void setAverage(bool average) { this->average = average; }
771 void clear() { resetState(); }
772 void reset() { clear(); }
773
774 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
775
776 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
777 if (!isConfigValid()) return 0;
778
779 // The binning takes the following into account
780 // 1) if size is too small it will add up data to partialBin and return 0
781 // size 2) if there is sufficient data to fill Bins but there is partial
782 // data remaining it will be added to the partial Bin 3) if there was
783 // previous partial Bin it will be filled with the new data 4) if there is
784 // insufficient new data to fill the partial Bin it will fill the partial
785 // Bin with the new data
786
787 if (size % (sizeof(T) * channels) > 0) {
788 LOGE("Buffer size %d is not a multiple of the number of channels %d",
789 (int)size, channels);
790 return 0;
791 }
792
793 T *p_target = (T *)target;
794 T *p_source = (T *)src;
795 size_t result_size = 0;
796 int sample_count = size / (sizeof(T) * channels);
797
798 for (int sample = 0; sample < sample_count; sample++) {
799 for (int ch = 0; ch < channels; ch++) {
800 partialBin[ch] += p_source[sample * channels + ch];
801 }
802 partialBinSize++;
803
804 if (partialBinSize == binSize) {
805 for (int ch = 0; ch < channels; ch++) {
806 p_target[result_size / sizeof(T)] =
807 average ? static_cast<T>(partialBin[ch] / binSize)
808 : static_cast<T>(partialBin[ch]);
809 result_size += sizeof(T);
810 }
811 resetState();
812 }
813 }
814
815 LOGD("bin %d: processed %d samples, %d remaining, %d > %d bytes", binSize,
816 sample_count, partialBinSize, (int)size, (int)result_size);
817
818 return result_size;
819 }
820
821 protected:
822 using SumT = typename AppropriateSumType<T>::type;
823
824 bool isConfigValid() {
825 if (channels <= 0) {
826 LOGE("Number of channels must be > 0");
827 return false;
828 }
829 if (binSize <= 0) {
830 LOGE("Bin size must be > 0");
831 return false;
832 }
833 return true;
834 }
835
836 void resizeState() {
837 delete[] partialBin;
838 partialBin = channels > 0 ? new SumT[channels]() : nullptr;
839 partialBinSize = 0;
840 }
841
842 void resetState() {
843 if (partialBin == nullptr && channels > 0) {
844 partialBin = new SumT[channels]();
845 } else if (partialBin != nullptr) {
846 for (int ch = 0; ch < channels; ch++) {
847 partialBin[ch] = 0;
848 }
849 }
850 partialBinSize = 0;
851 }
852
853 int channels = 2;
854 int binSize = 1;
855 bool average = true;
856 SumT *partialBin = nullptr;
857 int partialBinSize = 0;
858};
859
865class Bin : public BaseConverter {
866 public:
867 Bin() = default;
868 Bin(int binSize, int channels, bool average, int bits_per_sample) {
869 setChannels(channels);
870 setBinSize(binSize);
871 setAverage(average);
872 setBits(bits_per_sample);
873 }
874 ~Bin() override { delete state; }
875
876 void setChannels(int channels) {
877 this->channels = channels;
878 resetState();
879 }
880 void setBits(int bits) {
881 this->bits = bits;
882 resetState();
883 }
884 void setBinSize(int binSize) {
885 this->binSize = binSize;
886 resetState();
887 }
888 void setAverage(bool average) {
889 this->average = average;
890 resetState();
891 }
892 void clear() {
893 if (state != nullptr) {
894 state->reset();
895 }
896 }
897 void reset() { clear(); }
898
899 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
900 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
901 if (!isConfigValid()) return 0;
902 if (state == nullptr) {
903 switch (bits) {
904 case 8:
905 state = new BinStateT<int8_t>(binSize, channels, average);
906 break;
907 case 16:
908 state = new BinStateT<int16_t>(binSize, channels, average);
909 break;
910 case 24:
911 state = new BinStateT<int24_t>(binSize, channels, average);
912 break;
913 case 32:
914 state = new BinStateT<int32_t>(binSize, channels, average);
915 break;
916 default:
917 LOGE("Number of bits %d not supported.", bits);
918 return 0;
919 }
920 }
921 return state->convert(target, src, size);
922 }
923
924 protected:
925 struct BinState {
926 virtual ~BinState() = default;
927 virtual size_t convert(uint8_t *target, uint8_t *src, size_t size) = 0;
928 virtual void reset() = 0;
929 };
930
931 template <typename T>
933 BinStateT(int binSize, int channels, bool average)
934 : converter(binSize, channels, average) {}
935
936 size_t convert(uint8_t *target, uint8_t *src, size_t size) override {
937 return converter.convert(target, src, size);
938 }
939
940 void reset() override { converter.reset(); }
941
942 BinT<T> converter;
943 };
944
945 bool isConfigValid() {
946 if (channels <= 0) {
947 LOGE("Number of channels must be > 0");
948 return false;
949 }
950 if (binSize <= 0) {
951 LOGE("Bin size must be > 0");
952 return false;
953 }
954 return true;
955 }
956
957 void resetState() {
958 delete state;
959 state = nullptr;
960 }
961
962 int channels = 2;
963 int bits = 16;
964 int binSize = 1;
965 bool average = false;
966 BinState *state = nullptr;
967};
968
983template <typename T = int16_t>
985 public:
986 ChannelDiffT() {}
987
988 size_t convert(uint8_t *src, size_t size) override {
989 return convert(src, src, size);
990 }
991
992 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
993 LOGD("channel subtract %d samples, %d bytes", (int)(size / sizeof(T)),
994 (int)size);
995
996 // Ensure the buffer size is even for pairs of channels
997 if (size % (sizeof(T) * 2) > 0) {
998 LOGE("Buffer size is not even");
999 return 0;
1000 }
1001
1002 int sample_count =
1003 size /
1004 (sizeof(T) * 2); // Each pair of channels produces one output sample
1005 T *p_result = (T *)target;
1006 T *p_source = (T *)src;
1007
1008 for (int i = 0; i < sample_count; i++) {
1009 // *p_result++ = *p_source++ - *p_source++;
1010 auto tmp = *p_source++;
1011 tmp -= *p_source++;
1012 *p_result++ = tmp;
1013 }
1014
1015 return sizeof(T) * sample_count;
1016 }
1017};
1018
1020 public:
1021 ChannelDiff() = default;
1022 ChannelDiff(int bitsPerSample) { setBits(bitsPerSample); }
1023 void setBits(int bits) { this->bits = bits; }
1024
1025 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1026 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1027 switch (bits) {
1028 case 8: {
1030 return cd8.convert(target, src, size);
1031 }
1032 case 16: {
1034 return cd16.convert(target, src, size);
1035 }
1036 case 24: {
1038 return cd24.convert(target, src, size);
1039 }
1040 case 32: {
1042 return cd32.convert(target, src, size);
1043 }
1044 default: {
1045 LOGE("Number of bits %d not supported.", bits);
1046 return 0;
1047 }
1048 }
1049 }
1050
1051 protected:
1052 int bits = 16;
1053};
1054
1055
1063template <typename T = int16_t, typename SumT = float>
1065 public:
1066 ChannelMixer(int channels = 2) { this->channels = channels; }
1067 size_t convert(uint8_t *data, size_t size) {
1068 if (channels <= 1) return size; // No mixing needed for single channel
1069 T *srcT = (T *)data;
1070 T *targetT = (T *)data;
1071 int samples = size / sizeof(T);
1072 assert(samples % channels == 0);
1073 for (int j = 0; j < samples; j += channels) {
1074 SumT sum = 0;
1075 for (int ch = 0; ch < channels; ch++) {
1076 sum += srcT[j + ch];
1077 }
1078 T avg = sum / channels;
1079 for (int ch = 0; ch < channels; ch++) {
1080 targetT[j + ch] = avg;
1081 }
1082 }
1083 return size;
1084 }
1085
1086 protected:
1087 int channels = 2;
1088};
1089
1103template <typename T = int16_t, typename AvgT = float>
1105 public:
1106 ChannelAvgT() {}
1107
1108 size_t convert(uint8_t *src, size_t size) override {
1109 return convert(src, src, size);
1110 }
1111
1112 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1113 if (size % (sizeof(T) * 2) > 0) {
1114 LOGE("Buffer size is not even");
1115 return 0;
1116 }
1117
1118 int sample_count =
1119 size /
1120 (sizeof(T) * 2); // Each pair of channels produces one output sample
1121 T *p_result = (T *)target;
1122 T *p_source = (T *)src;
1123
1124 for (int i = 0; i < sample_count; i++) {
1125 // *p_result++ = (*p_source++ + *p_source++) / 2; // Average the pair of
1126 // channels
1127 AvgT tmp = *p_source++;
1128 tmp += *p_source++;
1129 *p_result++ = tmp / 2;
1130 }
1131
1132 LOGD("channel average %d samples, %d bytes", sample_count, (int)size);
1133
1134 return sizeof(T) * sample_count;
1135 }
1136};
1137
1138
1153 public:
1154 ChannelAvg() = default;
1155 ChannelAvg(int bitsPerSample) { setBits(bitsPerSample); }
1156 void setBits(int bits) { this->bits = bits; }
1157
1158 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1159 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1160 switch (bits) {
1161#ifdef PREFER_FIXEDPOINT
1162 case 8: {
1164 return ca8.convert(target, src, size);
1165 }
1166 case 16: {
1168 return ca16.convert(target, src, size);
1169 }
1170 case 24: {
1172 return ca24.convert(target, src, size);
1173 }
1174#else
1175 case 8: {
1177 return ca8.convert(target, src, size);
1178 }
1179 case 16: {
1181 return ca16.convert(target, src, size);
1182 }
1183 case 24: {
1185 return ca24.convert(target, src, size);
1186 }
1187#endif
1188 case 32: {
1190 return ca32.convert(target, src, size);
1191 }
1192 default: {
1193 LOGE("Number of bits %d not supported.", bits);
1194 return 0;
1195 }
1196 }
1197 }
1198
1199 protected:
1200 int bits = 16;
1201};
1202
1216template <typename T = int16_t>
1218 public:
1219 ChannelBinDiffT() = default;
1220 ChannelBinDiffT(int binSize, int channels, bool average) {
1221 setChannels(channels);
1222 setBinSize(binSize);
1223 setAverage(average);
1224 resetState();
1225 }
1226
1227 ~ChannelBinDiffT() { delete[] this->partialBin; }
1228
1229 void setChannels(int channels) {
1230 if ((channels % 2) > 0) {
1231 LOGE("Number of channels needs to be even");
1232 this->channels = channels + 1;
1233 } else {
1234 this->channels = channels;
1235 }
1236 resizeState();
1237 }
1238 void setBinSize(int binSize) {
1239 this->binSize = binSize;
1240 resetState();
1241 }
1242 void setAverage(bool average) { this->average = average; }
1243 void clear() { resetState(); }
1244 void reset() { clear(); }
1245
1246 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1247
1248 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1249 if (!isConfigValid()) return 0;
1250
1251 // The binning works the same as in the BinT class
1252 // Here we add subtraction before we store the bins
1253
1254 if (size % (sizeof(T) * channels) > 0) {
1255 LOGE("Buffer size needs to be multiple of channels");
1256 return 0;
1257 }
1258
1259 T *p_target = (T *)target;
1260 T *p_source = (T *)src;
1261 size_t result_size = 0;
1262 int sample_count = size / (sizeof(T) * channels);
1263
1264 for (int sample = 0; sample < sample_count; sample++) {
1265 for (int ch = 0; ch < channels; ch++) {
1266 partialBin[ch] += p_source[sample * channels + ch];
1267 }
1268 partialBinSize++;
1269
1270 if (partialBinSize == binSize) {
1271 for (int ch = 0; ch < channels; ch += 2) {
1272 SumT diff = partialBin[ch] - partialBin[ch + 1];
1273 p_target[result_size / sizeof(T)] =
1274 average ? static_cast<T>(diff / binSize)
1275 : static_cast<T>(diff);
1276 result_size += sizeof(T);
1277 }
1278 resetState();
1279 }
1280 }
1281
1282 LOGD(
1283 "bin & channel subtract %d: processed %d samples, %d remaining, %d > "
1284 "%d bytes",
1285 binSize, sample_count, partialBinSize, (int)size,
1286 (int)result_size);
1287
1288 return result_size;
1289 }
1290
1291 protected:
1292 using SumT = typename AppropriateSumType<T>::type;
1293
1294 bool isConfigValid() {
1295 if (channels <= 0) {
1296 LOGE("Number of channels must be > 0");
1297 return false;
1298 }
1299 if (binSize <= 0) {
1300 LOGE("Bin size must be > 0");
1301 return false;
1302 }
1303 return true;
1304 }
1305
1306 void resizeState() {
1307 delete[] partialBin;
1308 partialBin = channels > 0 ? new SumT[channels]() : nullptr;
1309 partialBinSize = 0;
1310 }
1311
1312 void resetState() {
1313 if (partialBin == nullptr && channels > 0) {
1314 partialBin = new SumT[channels]();
1315 } else if (partialBin != nullptr) {
1316 for (int ch = 0; ch < channels; ch++) {
1317 partialBin[ch] = 0;
1318 }
1319 }
1320 partialBinSize = 0;
1321 }
1322
1323 int channels = 2;
1324 int binSize = 4;
1325 bool average = true;
1326 SumT *partialBin = nullptr;
1327 int partialBinSize = 0;
1328};
1329
1338 public:
1339 ChannelBinDiff() = default;
1340 ChannelBinDiff(int binSize, int channels, bool average, int bits_per_sample) {
1341 setChannels(channels);
1342 setBinSize(binSize);
1343 setAverage(average);
1344 setBits(bits_per_sample);
1345 }
1346 ~ChannelBinDiff() override { delete state; }
1347
1348 void setChannels(int channels) {
1349 if ((channels % 2) == 0) {
1350 this->channels = channels;
1351 } else {
1352 LOGE("Number of channels needs to be even");
1353 this->channels = channels + 1;
1354 }
1355 resetState();
1356 }
1357
1358 void setBits(int bits) {
1359 this->bits = bits;
1360 resetState();
1361 }
1362 void setBinSize(int binSize) {
1363 this->binSize = binSize;
1364 resetState();
1365 }
1366 void setAverage(bool average) {
1367 this->average = average;
1368 resetState();
1369 }
1370 void clear() {
1371 if (state != nullptr) {
1372 state->reset();
1373 }
1374 }
1375 void reset() { clear(); }
1376
1377 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1378 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1379 if (!isConfigValid()) return 0;
1380 if (state == nullptr) {
1381 switch (bits) {
1382 case 8:
1383 state = new ChannelBinDiffStateT<int8_t>(binSize, channels, average);
1384 break;
1385 case 16:
1386 state = new ChannelBinDiffStateT<int16_t>(binSize, channels, average);
1387 break;
1388 case 24:
1389 state = new ChannelBinDiffStateT<int24_t>(binSize, channels, average);
1390 break;
1391 case 32:
1392 state = new ChannelBinDiffStateT<int32_t>(binSize, channels, average);
1393 break;
1394 default:
1395 LOGE("Number of bits %d not supported.", bits);
1396 return 0;
1397 }
1398 }
1399 return state->convert(target, src, size);
1400 }
1401
1402 protected:
1404 virtual ~ChannelBinDiffState() = default;
1405 virtual size_t convert(uint8_t *target, uint8_t *src, size_t size) = 0;
1406 virtual void reset() = 0;
1407 };
1408
1409 template <typename T>
1411 ChannelBinDiffStateT(int binSize, int channels, bool average)
1412 : converter(binSize, channels, average) {}
1413
1414 size_t convert(uint8_t *target, uint8_t *src, size_t size) override {
1415 return converter.convert(target, src, size);
1416 }
1417
1418 void reset() override { converter.reset(); }
1419
1420 ChannelBinDiffT<T> converter;
1421 };
1422
1423 bool isConfigValid() {
1424 if (channels <= 0) {
1425 LOGE("Number of channels must be > 0");
1426 return false;
1427 }
1428 if (binSize <= 0) {
1429 LOGE("Bin size must be > 0");
1430 return false;
1431 }
1432 return true;
1433 }
1434
1435 void resetState() {
1436 delete state;
1437 state = nullptr;
1438 }
1439
1440 int channels = 2;
1441 int bits = 16;
1442 int binSize = 4;
1443 bool average = true;
1444 ChannelBinDiffState *state = nullptr;
1445};
1446
1452template <typename T = int16_t>
1454 public:
1455 ChannelEnhancer() = default;
1456
1457 ChannelEnhancer(int channelCountOfTarget, int channelCountOfSource) {
1458 from_channels = channelCountOfSource;
1459 to_channels = channelCountOfTarget;
1460 }
1461
1462 void setSourceChannels(int channelCountOfSource) {
1463 from_channels = channelCountOfSource;
1464 }
1465
1466 void setTargetChannels(int channelCountOfTarget) {
1467 to_channels = channelCountOfTarget;
1468 }
1469
1470 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1471 if (from_channels == 0) return size;
1472 int frame_count = size / (sizeof(T) * from_channels);
1473 size_t result_size = 0;
1474 T *result = (T *)target;
1475 T *source = (T *)src;
1476 T value = (int16_t)0;
1477 for (int i = 0; i < frame_count; i++) {
1478 // copy available channels
1479 for (int j = 0; j < from_channels; j++) {
1480 value = *source++;
1481 *result++ = value;
1482 result_size += sizeof(T);
1483 }
1484 // repeat last value
1485 for (int j = from_channels; j < to_channels; j++) {
1486 *result++ = value;
1487 result_size += sizeof(T);
1488 }
1489 }
1490 return result_size;
1491 }
1492
1494 size_t resultSize(size_t inSize) {
1495 return inSize * to_channels / from_channels;
1496 }
1497
1498 protected:
1499 int from_channels = 0;
1500 int to_channels = 0;
1501};
1502
1508template <typename T = int16_t>
1510 public:
1511 ChannelConverter() = default;
1512
1513 ChannelConverter(int channelCountOfTarget, int channelCountOfSource) {
1514 from_channels = channelCountOfSource;
1515 to_channels = channelCountOfTarget;
1516 }
1517
1518 void setSourceChannels(int channelCountOfSource) {
1519 from_channels = channelCountOfSource;
1520 }
1521
1522 void setTargetChannels(int channelCountOfTarget) {
1523 to_channels = channelCountOfTarget;
1524 }
1525
1526 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1527 if (from_channels == to_channels) {
1528 memcpy(target, src, size);
1529 return size;
1530 }
1531 // setup channels
1532 if (from_channels > to_channels) {
1533 reducer.setSourceChannels(from_channels);
1534 reducer.setTargetChannels(to_channels);
1535 } else {
1536 enhancer.setSourceChannels(from_channels);
1537 enhancer.setTargetChannels(to_channels);
1538 }
1539
1540 // execute conversion
1541 if (from_channels > to_channels) {
1542 return reducer.convert(target, src, size);
1543 } else {
1544 return enhancer.convert(target, src, size);
1545 }
1546 }
1547
1548 protected:
1549 ChannelEnhancer<T> enhancer;
1550 ChannelReducerT<T> reducer;
1551 int from_channels;
1552 int to_channels;
1553};
1554
1560template <typename T = int16_t>
1562 public:
1563 MultiConverter() {}
1564
1565 MultiConverter(BaseConverter &c1) { add(c1); }
1566
1568 add(c1);
1569 add(c2);
1570 }
1571
1573 add(c1);
1574 add(c2);
1575 add(c3);
1576 }
1577
1578 // adds a converter
1579 void add(BaseConverter &converter) { converters.push_back(&converter); }
1580
1581 // The data is provided as int24_t tgt[][2] but returned as int24_t
1582 size_t convert(uint8_t *src, size_t size) {
1583 for (int i = 0; i < converters.size(); i++) {
1584 converters[i]->convert(src, size);
1585 }
1586 return size;
1587 }
1588
1589 private:
1590 Vector<BaseConverter *> converters;
1591};
1592
1598 public:
1599 NumberReader(Stream &in) { stream_ptr = &in; }
1600
1601 NumberReader() {}
1602
1603 bool read(int inBits, int outBits, bool outSigned, int n, int32_t *result) {
1604 bool result_bool = false;
1605 int len = inBits / 8 * n;
1606 if (stream_ptr != nullptr && stream_ptr->available() > len) {
1607 uint8_t buffer[len];
1608 stream_ptr->readBytes((uint8_t *)buffer, n * len);
1609 result_bool =
1610 toNumbers((void *)buffer, inBits, outBits, outSigned, n, result);
1611 }
1612 return result_bool;
1613 }
1614
1616 bool toNumbers(void *bufferIn, int inBits, int outBits, bool outSigned, int n,
1617 int32_t *result) {
1618 bool result_bool = false;
1619 switch (inBits) {
1620 case 8: {
1621 int8_t *buffer = (int8_t *)bufferIn;
1622 for (int j = 0; j < n; j++) {
1623 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1624 }
1625 result_bool = true;
1626 } break;
1627 case 16: {
1628 int16_t *buffer = (int16_t *)bufferIn;
1629 for (int j = 0; j < n; j++) {
1630 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1631 }
1632 result_bool = true;
1633 } break;
1634 case 32: {
1635 int32_t *buffer = (int32_t *)bufferIn;
1636 for (int j = 0; j < n; j++) {
1637 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1638 }
1639 result_bool = true;
1640 } break;
1641 }
1642 return result_bool;
1643 }
1644
1645 protected:
1646 Stream *stream_ptr = nullptr;
1647
1649 int32_t scale(int32_t value, int inBits, int outBits, bool outSigned = true) {
1650 int32_t result = static_cast<float>(value) /
1653 if (!outSigned) {
1654 result += (NumberConverter::maxValue(outBits) / 2);
1655 }
1656 return result;
1657 }
1658};
1659
1666template <typename T = int16_t>
1668 public:
1669 Converter1Channel(Filter<T> &filter) { this->p_filter = &filter; }
1670
1671 size_t convert(uint8_t *src, size_t size) override {
1672 T *data = (T *)src;
1673 for (size_t j = 0; j < size; j++) {
1674 data[j] = p_filter->process(data[j]);
1675 }
1676 return size;
1677 }
1678
1679 protected:
1680 Filter<T> *p_filter = nullptr;
1681};
1682
1689template <typename T, typename FT>
1691 public:
1693 ConverterNChannels(int channels) {
1694 this->channels = channels;
1695 filters = new Filter<FT> *[channels];
1696 // make sure that we have 1 filter per channel
1697 for (int j = 0; j < channels; j++) {
1698 filters[j] = nullptr;
1699 }
1700 }
1701
1704 for (int j = 0; j < channels; j++) {
1705 if (filters[j] != nullptr) {
1706 delete filters[j];
1707 }
1708 }
1709 delete[] filters;
1710 filters = 0;
1711 }
1712
1714 void setFilter(int channel, Filter<FT> *filter) {
1715 if (channel < channels) {
1716 if (filters[channel] != nullptr) {
1717 delete filters[channel];
1718 }
1719 filters[channel] = filter;
1720 } else {
1721 LOGE("Invalid channel nummber %d - max channel is %d", channel,
1722 channels - 1);
1723 }
1724 }
1725
1726 // convert all samples for each channel separately
1727 size_t convert(uint8_t *src, size_t size) {
1728 int count = size / channels / sizeof(T);
1729 T *sample = (T *)src;
1730 for (size_t j = 0; j < count; j++) {
1731 for (int channel = 0; channel < channels; channel++) {
1732 if (filters[channel] != nullptr) {
1733 *sample = filters[channel]->process(*sample);
1734 }
1735 sample++;
1736 }
1737 }
1738 return size;
1739 }
1740
1741 int getChannels() { return channels; }
1742
1743 protected:
1744 Filter<FT> **filters = nullptr;
1745 int channels;
1746};
1747
1757template <typename T = int16_t>
1759 public:
1760 SilenceRemovalConverter(int n = 8, int aplidudeLimit = 2) {
1761 set(n, aplidudeLimit);
1762 }
1763
1764 void clear() { priorLastAudioPos = n + 1; }
1765 void reset() { clear(); }
1766
1767 virtual size_t convert(uint8_t *data, size_t size) override {
1768 if (!active) {
1769 // no change to the data
1770 return size;
1771 }
1772 size_t sample_count = size / sizeof(T);
1773 size_t write_count = 0;
1774 T *audio = (T *)data;
1775
1776 // find relevant data
1777 T *p_buffer = (T *)data;
1778 for (int j = 0; j < sample_count; j++) {
1779 int pos = findLastAudioPos(audio, j);
1780 if (pos < n) {
1781 write_count++;
1782 *p_buffer++ = audio[j];
1783 }
1784 }
1785
1786 // write audio data w/o silence
1787 size_t write_size = write_count * sizeof(T);
1788 LOGI("filtered silence from %d -> %d", (int)size, (int)write_size);
1789
1790 // number of empty samples of prior buffer
1791 priorLastAudioPos = findLastAudioPos(audio, sample_count - 1);
1792
1793 // return new data size
1794 return write_size;
1795 }
1796
1797 protected:
1798 bool active = false;
1799 const uint8_t *buffer = nullptr;
1800 int n;
1801 int priorLastAudioPos = 0;
1802 int amplidude_limit = 0;
1803
1804 void set(int n = 5, int aplidudeLimit = 2) {
1805 LOGI("begin(n=%d, aplidudeLimit=%d", n, aplidudeLimit);
1806 this->n = n;
1807 this->amplidude_limit = aplidudeLimit;
1808 this->priorLastAudioPos = n + 1; // ignore first values
1809 this->active = n > 0;
1810 }
1811
1812 // find last position which contains audible data
1813 int findLastAudioPos(T *audio, int pos) {
1814 for (int j = 0; j < n; j++) {
1815 // we are before the start of the current buffer
1816 if (pos - j <= 0) {
1817 return priorLastAudioPos;
1818 }
1819 // we are in the current buffer
1820 if (abs(audio[pos - j]) > amplidude_limit) {
1821 return j;
1822 }
1823 }
1824 return n + 1;
1825 }
1826};
1827
1835template <typename T = int16_t>
1837 public:
1838 PoppingSoundRemover(int channels, bool fromBeginning, bool fromEnd) {
1839 this->channels = channels;
1840 from_beginning = fromBeginning;
1841 from_end = fromEnd;
1842 }
1843 virtual size_t convert(uint8_t *src, size_t size) {
1844 for (int ch = 0; ch < channels; ch++) {
1845 if (from_beginning)
1846 clearUpTo1stTransition(channels, ch, (T *)src, size / sizeof(T));
1847 if (from_end)
1848 clearAfterLastTransition(channels, ch, (T *)src, size / sizeof(T));
1849 }
1850 return size;
1851 }
1852
1853 protected:
1854 bool from_beginning;
1855 bool from_end;
1856 int channels;
1857
1858 void clearUpTo1stTransition(int channels, int channel, T *values,
1859 int sampleCount) {
1860 T first = values[channel];
1861 for (int j = 0; j < sampleCount; j += channels) {
1862 T act = values[j];
1863 if ((first <= 0.0 && act >= 0.0) || (first >= 0.0 && act <= 0.0)) {
1864 // we found the last transition so we are done
1865 break;
1866 } else {
1867 values[j] = 0;
1868 }
1869 }
1870 }
1871
1872 void clearAfterLastTransition(int channels, int channel, T *values,
1873 int sampleCount) {
1874 int lastPos = sampleCount - channels + channel;
1875 T last = values[lastPos];
1876 for (int j = lastPos; j >= 0; j -= channels) {
1877 T act = values[j];
1878 if ((last <= 0.0 && act >= 0.0) || (last >= 0.0 && act <= 0.0)) {
1879 // we found the last transition so we are done
1880 break;
1881 } else {
1882 values[j] = 0;
1883 }
1884 }
1885 }
1886};
1887
1894template <typename T = int16_t>
1896 public:
1897 SmoothTransition(int channels, bool fromBeginning, bool fromEnd,
1898 float inc = 0.01) {
1899 this->channels = channels;
1900 this->inc = inc;
1901 from_beginning = fromBeginning;
1902 from_end = fromEnd;
1903 }
1904 void clear() {
1905 start_factor = 0;
1906 end_factor = 0;
1907 }
1908 void reset() { clear(); }
1909 virtual size_t convert(uint8_t *src, size_t size) {
1910 int sample_count = size / sizeof(T);
1911 int frame_count = channels > 0 ? sample_count / channels : 0;
1912 if (from_beginning) processStart((T *)src, frame_count);
1913 if (from_end) processEnd((T *)src, frame_count);
1914 return size;
1915 }
1916
1917 protected:
1918 bool from_beginning;
1919 bool from_end;
1920 int channels;
1921 float inc = 0.01;
1922 float start_factor = 0;
1923 float end_factor = 0;
1924
1925 void processStart(T *values, int frameCount) {
1926 float factor = start_factor;
1927 for (int frame = 0; frame < frameCount; ++frame) {
1928 if (factor >= 0.8) {
1929 break;
1930 }
1931 int pos = frame * channels;
1932 for (int ch = 0; ch < channels; ++ch) {
1933 values[pos + ch] = factor * values[pos + ch];
1934 }
1935 factor += inc;
1936 }
1937 start_factor = factor;
1938 }
1939
1940 void processEnd(T *values, int frameCount) {
1941 float factor = end_factor;
1942 for (int frame = frameCount - 1; frame >= 0; --frame) {
1943 if (factor >= 0.8) {
1944 break;
1945 }
1946 int pos = frame * channels;
1947 for (int ch = 0; ch < channels; ++ch) {
1948 values[pos + ch] = factor * values[pos + ch];
1949 }
1950 factor += inc;
1951 }
1952 end_factor = factor;
1953 }
1954};
1955
1962template <typename T, size_t Cn, size_t Cx, size_t S>
1964 public:
1965 CopyChannels() : _max_val(0), _counter(0), _prev_ms(0) {}
1966
1967 size_t convert(uint8_t *src, size_t size) {
1968 T *chan = (T *)src;
1969 size_t samples = (size / Cn) / sizeof(T);
1970 for (size_t s = 0; s < samples; s++) {
1971 chan[s * Cn + Cx] = (Cx < Cn) ? chan[s * Cn + Cx] << S : 0;
1972
1973 for (size_t c = 0; c < Cn; c++) {
1974 if (c != Cx) {
1975 chan[s * Cn + c] = chan[s * Cn + Cx];
1976 }
1977 }
1978
1979 if (_max_val < chan[s * Cn]) {
1980 _max_val = chan[s * Cn];
1981 }
1982
1983 _counter++;
1984 uint32_t now = millis();
1985 if (now - _prev_ms > 1000) {
1986 _prev_ms = now;
1987 LOGI("CopyChannels samples: %u, amplitude: %d", _counter, _max_val);
1988 _max_val = 0;
1989 }
1990 }
1991 return samples * Cn * sizeof(T);
1992 }
1993
1994 private:
1995 T _max_val;
1996 uint32_t _counter;
1997 uint32_t _prev_ms;
1998};
1999
2005template <typename T = int16_t>
2007 public:
2008 CallbackConverterT(T (*callback)(T in, int channel), int channels = 2) {
2009 this->callback = callback;
2010 this->channels = channels;
2011 }
2012
2013 size_t convert(uint8_t *src, size_t size) {
2014 int samples = size / sizeof(T);
2015 T *srcT = (T *)src;
2016 for (int j = 0; j < samples; j++) {
2017 srcT[j] = callback(srcT[j], j % channels);
2018 }
2019 return size;
2020 }
2021
2022 protected:
2023 T (*callback)(T in, int channel);
2024 int channels;
2025};
2026
2027} // namespace audio_tools
Abstract Base class for Converters A converter is processing the data in the indicated array.
Definition BaseConverter.h:24
Provides reduced sampling rates through binning.
Definition BaseConverter.h:865
Definition BaseConverter.h:750
You can provide a lambda expression to convert the data.
Definition BaseConverter.h:2006
We average pairs of channels in a datastream. E.g. if we have 4 channels we end up with 2 channels....
Definition BaseConverter.h:1152
We average pairs of channels in a datastream. E.g. if we have 4 channels we end up with 2 channels....
Definition BaseConverter.h:1104
Provides combination of binning and subtracting channels.
Definition BaseConverter.h:1337
We first bin the channels then we calculate the difference between pairs of channels in a datastream....
Definition BaseConverter.h:1217
Increasing or decreasing the number of channels.
Definition BaseConverter.h:1509
Definition BaseConverter.h:1019
We calculate the difference between pairs of channels in a datastream. E.g. if we have 4 channels we ...
Definition BaseConverter.h:984
Increases the channel count.
Definition BaseConverter.h:1453
size_t resultSize(size_t inSize)
Determine the size of the conversion result.
Definition BaseConverter.h:1494
We mix all input channels in a datastream. E.g. if we have stereo input data we end up with 2 identic...
Definition BaseConverter.h:1064
We combine a datastream which consists of multiple channels into less channels. E....
Definition BaseConverter.h:489
We combine a datastream which consists of multiple channels into less channels. E....
Definition BaseConverter.h:433
Converter for 1 Channel which applies the indicated Filter.
Definition BaseConverter.h:1667
Makes sure that the avg of the signal is set to 0.
Definition BaseConverter.h:198
Makes sure that the avg of the signal is set to 0.
Definition BaseConverter.h:106
Make sure that both channels contain any data. We copy the data from the non-empty channel to the emp...
Definition BaseConverter.h:322
Converter for n Channels which applies the indicated Filter.
Definition BaseConverter.h:1690
~ConverterNChannels()
Destructor.
Definition BaseConverter.h:1703
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition BaseConverter.h:1714
ConverterNChannels(int channels)
Default Constructor.
Definition BaseConverter.h:1693
Multiplies the values with the indicated factor adds the offset and clips at maxValue....
Definition BaseConverter.h:55
void setFactor(float factor)
Defines the factor (volume)
Definition BaseConverter.h:82
T offset()
Determines the offset value.
Definition BaseConverter.h:91
float factor()
Determines the actual factor (volume)
Definition BaseConverter.h:88
void setOffset(T offset)
Defines the offset.
Definition BaseConverter.h:85
Switches the left and right channel.
Definition BaseConverter.h:283
special case for internal DAC output for the ESP32. The incomming PCM buffer needs to be converted fr...
Definition BaseConverter.h:405
Copy channel Cx value of type T shifted by S bits to all Cn channels.
Definition BaseConverter.h:1963
Provides a reduced sampling rate by taking a sample at every factor location (ingoring factor-1 sampl...
Definition BaseConverter.h:613
void setFactor(int factor)
Sets the factor: e.g. with 4 we keep every forth sample.
Definition BaseConverter.h:631
void setChannels(int channels)
Defines the number of channels.
Definition BaseConverter.h:622
Provides reduced sampling rates.
Definition BaseConverter.h:533
void setFactor(int factor)
Sets the factor: e.g. with 4 we keep every fourth sample.
Definition BaseConverter.h:548
void setChannels(int channels)
Defines the number of channels.
Definition BaseConverter.h:542
Abstract filter interface definition;.
Definition Filter.h:28
Combines multiple converters.
Definition BaseConverter.h:1561
Dummy converter which does nothing.
Definition BaseConverter.h:40
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:301
Reads n numbers from an Arduino Stream.
Definition BaseConverter.h:1597
int32_t scale(int32_t value, int inBits, int outBits, bool outSigned=true)
scale the value
Definition BaseConverter.h:1649
bool toNumbers(void *bufferIn, int inBits, int outBits, bool outSigned, int n, int32_t *result)
converts a buffer to a number array
Definition BaseConverter.h:1616
Big value gaps (at the beginning and the end of a recording) can lead to some popping sounds....
Definition BaseConverter.h:1836
Removes any silence from the buffer that is longer then n samples with a amplitude below the indicate...
Definition BaseConverter.h:1758
Changes the samples at the beginning or at the end to slowly ramp up the volume.
Definition BaseConverter.h:1895
Definition NoArduino.h:142
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition Int24_4bytes_t.h:16
FillLeftAndRightStatus
Configure ConverterFillLeftAndRight.
Definition BaseConverter.h:309
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
We reduce the number of samples in a datastream by summing (binning) or averaging....
Definition BaseConverter.h:725
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
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
Definition BaseConverter.h:925
Definition BaseConverter.h:932
Definition BaseConverter.h:671
Definition BaseConverter.h:678