arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
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>
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>
107 public:
108 ConverterAutoCenterT(int channels = 2, bool isDynamic = false) {
109 this->channels = channels;
110 this->is_dynamic = isDynamic;
111 }
112
113 size_t convert(uint8_t(*src), size_t byte_count) override {
114 size_t size = byte_count / channels / sizeof(T);
115 T *sample = (T *)src;
116 setup((T *)src, size);
117 // convert data
118 if (is_setup) {
119 if (!is_dynamic) {
120 for (size_t j = 0; j < size; j++) {
121 for (int ch = 0; ch < channels; ch++) {
122 sample[(j * channels) + ch] =
123 sample[(j * channels) + ch] - offset_to[ch];
124 }
125 }
126 } else {
127 for (size_t j = 0; j < size; j++) {
128 for (int ch = 0; ch < channels; ch++) {
129 sample[(j * channels) + ch] = sample[(j * channels) + ch] -
130 offset_from[ch] +
131 (offset_step[ch] * size);
132 }
133 }
134 }
135 }
136 return byte_count;
137 }
138
139 protected:
140 Vector<float> offset_from{0};
141 Vector<float> offset_to{0};
142 Vector<float> offset_step{0};
143 Vector<float> total{0};
144 float left = 0.0;
145 float right = 0.0;
146 bool is_setup = false;
147 bool is_dynamic;
148 int channels;
149
150 void setup(T *src, size_t size) {
151 if (size == 0) return;
152 if (!is_setup || is_dynamic) {
153 if (offset_from.size() == 0) {
154 offset_from.resize(channels);
155 offset_to.resize(channels);
156 offset_step.resize(channels);
157 total.resize(channels);
158 }
159
160 // save last offset
161 for (int ch = 0; ch < channels; ch++) {
162 offset_from[ch] = offset_to[ch];
163 total[ch] = 0.0;
164 }
165
166 // calculate new offset
167 for (size_t j = 0; j < size; j++) {
168 for (int ch = 0; ch < channels; ch++) {
169 total[ch] += src[(j * channels) + ch];
170 }
171 }
172 for (int ch = 0; ch < channels; ch++) {
173 offset_to[ch] = total[ch] / size;
174 offset_step[ch] = (offset_to[ch] - offset_from[ch]) / size;
175 }
176 is_setup = true;
177 }
178 }
179};
180
186 public:
187 ConverterAutoCenter() = default;
188
190 begin(info.channels, info.bits_per_sample);
191 }
192
193 ConverterAutoCenter(int channels, int bitsPerSample) {
194 begin(channels, bitsPerSample);
195 }
196 ~ConverterAutoCenter() { end(); }
197
198 void end() {
199 if (p_converter != nullptr) {
200 delete p_converter;
201 p_converter = nullptr;
202 }
203 }
204
205 bool begin(AudioInfo info, bool isDynamic = false) {
206 return begin(info.channels, info.bits_per_sample, isDynamic);
207 }
208
209 bool begin(int channels, int bitsPerSample, bool isDynamic = false) {
210 // check if we need to create a new converter
211 if (p_converter != nullptr && channels == this->channels && bitsPerSample == this->bits_per_sample){
212 return true;
213 }
214 this->channels = channels;
215 this->bits_per_sample = bitsPerSample;
216 end();
217 assert(p_converter == nullptr);
218 switch (bits_per_sample) {
219 case 8: {
220 p_converter = new ConverterAutoCenterT<int8_t>(channels, isDynamic);
221 break;
222 }
223 case 16: {
224 p_converter = new ConverterAutoCenterT<int16_t>(channels, isDynamic);
225 break;
226 }
227 case 24: {
228 p_converter = new ConverterAutoCenterT<int24_t>(channels, isDynamic);
229 break;
230 }
231 case 32: {
232 p_converter = new ConverterAutoCenterT<int32_t>(channels, isDynamic);
233 break;
234 }
235 }
236 return p_converter != nullptr;
237 }
238
239 size_t convert(uint8_t *src, size_t size) override {
240 if (p_converter == nullptr) return 0;
241 return p_converter->convert(src, size);
242 }
243
244 protected:
245 int channels = 0;
246 int bits_per_sample = 0;
247 BaseConverter *p_converter = nullptr;
248};
249
258template <typename T>
260 public:
261 ConverterSwitchLeftAndRight(int channels = 2) { this->channels = channels; }
262
263 size_t convert(uint8_t *src, size_t byte_count) override {
264 if (channels == 2) {
265 int size = byte_count / channels / sizeof(T);
266 T *sample = (T *)src;
267 for (size_t j = 0; j < size; j++) {
268 T temp = *sample;
269 *sample = *(sample + 1);
270 *(sample + 1) = temp;
271 sample += 2;
272 }
273 }
274 return byte_count;
275 }
276
277 protected:
278 int channels = 2;
279};
280
285enum FillLeftAndRightStatus { Auto, LeftIsEmpty, RightIsEmpty };
286
296template <typename T>
298 public:
300 int channels = 2) {
301 this->channels = channels;
302 switch (config) {
303 case LeftIsEmpty:
304 left_empty = true;
305 right_empty = false;
306 is_setup = true;
307 break;
308 case RightIsEmpty:
309 left_empty = false;
310 right_empty = true;
311 is_setup = true;
312 break;
313 case Auto:
314 is_setup = false;
315 break;
316 }
317 }
318
319 size_t convert(uint8_t *src, size_t byte_count) {
320 if (channels == 2) {
321 int size = byte_count / channels / sizeof(T);
322 setup((T *)src, size);
323 if (left_empty && !right_empty) {
324 T *sample = (T *)src;
325 for (size_t j = 0; j < size; j++) {
326 *sample = *(sample + 1);
327 sample += 2;
328 }
329 } else if (!left_empty && right_empty) {
330 T *sample = (T *)src;
331 for (size_t j = 0; j < size; j++) {
332 *(sample + 1) = *sample;
333 sample += 2;
334 }
335 }
336 }
337 return byte_count;
338 }
339
340 private:
341 bool is_setup = false;
342 bool left_empty = true;
343 bool right_empty = true;
344 int channels;
345
346 void setup(T *src, size_t size) {
347 if (!is_setup) {
348 for (int j = 0; j < size; j++) {
349 if (*src != 0) {
350 left_empty = false;
351 break;
352 }
353 src += 2;
354 }
355 for (int j = 0; j < size - 1; j++) {
356 if (*(src) != 0) {
357 right_empty = false;
358 break;
359 }
360 src += 2;
361 }
362 // stop setup as soon as we found some data
363 if (!right_empty || !left_empty) {
364 is_setup = true;
365 }
366 }
367 }
368};
369
379template <typename T>
381 public:
382 ConverterToInternalDACFormat(int channels = 2) { this->channels = channels; }
383
384 size_t convert(uint8_t *src, size_t byte_count) override {
385 int size = byte_count / channels / sizeof(T);
386 T *sample = (T *)src;
387 for (int i = 0; i < size; i++) {
388 for (int j = 0; j < channels; j++) {
389 *sample = *sample + 0x8000;
390 sample++;
391 }
392 }
393 return byte_count;
394 }
395
396 protected:
397 int channels;
398};
399
407template <typename T>
409 public:
410 ChannelReducerT() = default;
411
412 ChannelReducerT(int channelCountOfTarget, int channelCountOfSource) {
413 from_channels = channelCountOfSource;
414 to_channels = channelCountOfTarget;
415 }
416
417 void setSourceChannels(int channelCountOfSource) {
418 from_channels = channelCountOfSource;
419 }
420
421 void setTargetChannels(int channelCountOfTarget) {
422 to_channels = channelCountOfTarget;
423 }
424
425 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
426
427 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
428 LOGD("convert %d -> %d", from_channels, to_channels);
429 assert(to_channels <= from_channels);
430 int frame_count = size / (sizeof(T) * from_channels);
431 size_t result_size = 0;
432 T *result = (T *)target;
433 T *source = (T *)src;
434 int reduceDiv = from_channels - to_channels + 1;
435
436 for (int i = 0; i < frame_count; i++) {
437 // copy first to_channels-1
438 for (int j = 0; j < to_channels - 1; j++) {
439 *result++ = *source++;
440 result_size += sizeof(T);
441 }
442 // commbined last channels
443 T total = (int16_t)0;
444 for (int j = to_channels - 1; j < from_channels; j++) {
445 total += *source++ / reduceDiv;
446 }
447 *result++ = total;
448 result_size += sizeof(T);
449 }
450 return result_size;
451 }
452
453 protected:
454 int from_channels;
455 int to_channels;
456};
457
465 public:
466 ChannelReducer(int channelCountOfTarget, int channelCountOfSource,
467 int bitsPerSample) {
468 from_channels = channelCountOfSource;
469 to_channels = channelCountOfTarget;
470 bits = bitsPerSample;
471 }
472
473 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
474
475 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
476 switch (bits) {
477 case 8: {
478 ChannelReducerT<int8_t> cr8(to_channels, from_channels);
479 return cr8.convert(target, src, size);
480 }
481 case 16: {
482 ChannelReducerT<int16_t> cr16(to_channels, from_channels);
483 return cr16.convert(target, src, size);
484 }
485 case 24: {
486 ChannelReducerT<int24_t> cr24(to_channels, from_channels);
487 return cr24.convert(target, src, size);
488 }
489 case 32: {
490 ChannelReducerT<int32_t> cr32(to_channels, from_channels);
491 return cr32.convert(target, src, size);
492 }
493 }
494 return 0;
495 }
496
497 protected:
498 int from_channels;
499 int to_channels;
500 int bits;
501};
502
507template <typename T>
508class DecimateT : public BaseConverter {
509 public:
510 DecimateT(int factor, int channels) {
511 setChannels(channels);
512 setFactor(factor);
513 count = 0; // Initialize count to 0
514 }
515
517 void setChannels(int channels) { this->channels = channels; }
518
520 void setFactor(int factor) { this->factor = factor; }
521
522 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
523
524 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
525 if (size % (sizeof(T) * channels) > 0) {
526 LOGE("Buffer size %d is not a multiple of the number of channels %d",
527 (int)size, channels);
528 return 0;
529 }
530
531 int frame_count = size / (sizeof(T) * channels);
532 T *p_target = (T *)target;
533 T *p_source = (T *)src;
534 size_t result_size = 0;
535
536 for (int i = 0; i < frame_count; i++) {
537 if (++count == factor) {
538 count = 0;
539 // Only keep every "factor" samples
540 for (int ch = 0; ch < channels; ch++) {
541 *p_target++ = p_source[i * channels + ch]; // Corrected indexing
542 result_size += sizeof(T);
543 }
544 }
545 }
546
547 LOGD("decimate %d: %d -> %d bytes", factor, (int)size, (int)result_size);
548 return result_size;
549 }
550
551 operator bool() { return factor > 1; }
552
553 protected:
554 int channels = 2;
555 int factor = 1;
556 uint16_t count;
557};
558
565class Decimate : public BaseConverter {
566 public:
567 Decimate() = default;
568 Decimate(int factor, int channels, int bits_per_sample) {
569 setFactor(factor);
570 setChannels(channels);
571 setBits(bits_per_sample);
572 }
574 void setChannels(int channels) { this->channels = channels; }
575 void setBits(int bits) { this->bits = bits; }
577 void setFactor(int factor) { this->factor = factor; }
578
579 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
580 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
581 switch (bits) {
582 case 8: {
583 DecimateT<int8_t> dec8(factor, channels);
584 return dec8.convert(target, src, size);
585 }
586 case 16: {
587 DecimateT<int16_t> dec16(factor, channels);
588 return dec16.convert(target, src, size);
589 }
590 case 24: {
591 DecimateT<int24_t> dec24(factor, channels);
592 return dec24.convert(target, src, size);
593 }
594 case 32: {
595 DecimateT<int32_t> dec32(factor, channels);
596 return dec32.convert(target, src, size);
597 }
598 }
599 return 0;
600 }
601
602 operator bool() { return factor > 1; };
603
604 protected:
605 int channels = 2;
606 int bits = 16;
607 int factor = 1;
608};
609
619// Helper template to define the integer type for the summation based on input
620// data type T
621template <typename T>
623 using type = T;
624};
625
626template <>
627struct AppropriateSumType<int8_t> {
628 using type = int16_t;
629};
630
631template <>
632struct AppropriateSumType<int16_t> {
633 using type = int32_t;
634};
635
636template <>
638 using type = int32_t; // Assuming int24_t is a custom 24-bit integer type
639};
640
641template <>
642struct AppropriateSumType<int32_t> {
643 using type = int64_t;
644};
645
646template <typename T>
647class BinT : public BaseConverter {
648 public:
649 BinT() = default;
650 BinT(int binSize, int channels, bool average) {
651 setChannels(channels);
652 setBinSize(binSize);
653 setAverage(average);
654 this->partialBinSize = 0;
655 this->partialBin = new T[channels]();
656 }
657
658 ~BinT() { delete[] this->partialBin; }
659
660 void setChannels(int channels) { this->channels = channels; }
661 void setBinSize(int binSize) { this->binSize = binSize; }
662 void setAverage(bool average) { this->average = average; }
663
664 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
665
666 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
667 // The binning takes the following into account
668 // 1) if size is too small it will add up data to partialBin and return 0
669 // size 2) if there is sufficient data to fill Bins but there is partial
670 // data remaining it will be added to the partial Bin 3) if there was
671 // previous partial Bin it will be filled with the new data 4) if there is
672 // insufficient new data to fill the partial Bin it will fill the partial
673 // Bin with the new data
674
675 if (size % (sizeof(T) * channels) > 0) {
676 LOGE("Buffer size %d is not a multiple of the number of channels %d",
677 (int)size, channels);
678 return 0;
679 }
680
681 int sample_count =
682 size / (sizeof(T) * channels); // new available samples in each channel
683 int total_samples =
684 partialBinSize +
685 sample_count; // total samples available for each channel including
686 // previous number of sample in partial bin
687 int bin_count = total_samples / binSize; // number of bins we can make
688 int remaining_samples =
689 total_samples % binSize; // remaining samples after binning
690 T *p_target = (T *)target;
691 T *p_source = (T *)src;
692 size_t result_size = 0;
693
694 // Allocate sum for each channel with appropriate type
695 typename AppropriateSumType<T>::type sums[channels];
696 int current_sample = 0; // current sample index
697
698 // Is there a partial bin from the previous call?
699 // ----
700 if (partialBinSize > 0) {
701 int samples_needed = binSize - partialBinSize;
702 bool have_enough_samples = (samples_needed < sample_count);
703 int samples_to_bin = have_enough_samples ? samples_needed : sample_count;
704
705 for (int ch = 0; ch < channels; ch++) {
706 sums[ch] = partialBin[ch];
707 }
708
709 for (int j = 0; j < samples_to_bin; j++) {
710 for (int ch = 0; ch < channels; ch++) {
711 sums[ch] += p_source[current_sample * channels + ch];
712 }
713 current_sample++;
714 }
715
716 if (have_enough_samples) {
717 // Store the completed bin
718 if (average) {
719 for (int ch = 0; ch < channels; ch++) {
720 p_target[result_size / sizeof(T)] =
721 static_cast<T>(sums[ch] / binSize);
722 result_size += sizeof(T);
723 }
724 } else {
725 for (int ch = 0; ch < channels; ch++) {
726 p_target[result_size / sizeof(T)] = static_cast<T>(sums[ch]);
727 result_size += sizeof(T);
728 }
729 }
730 partialBinSize = 0;
731 } else {
732 // Not enough samples to complete the bin, update partialBin
733 for (int ch = 0; ch < channels; ch++) {
734 partialBin[ch] = sums[ch];
735 }
736 partialBinSize += current_sample;
737
738 LOGD("bin %d: %d of %d remaining %d samples, %d > %d bytes", binSize,
739 current_sample, total_samples, partialBinSize, (int)size,
740 (int)result_size);
741 return result_size;
742 }
743 }
744
745 // Fill bins
746 // ----
747 for (int i = 0; i < bin_count; i++) {
748 for (int ch = 0; ch < channels; ch++) {
749 sums[ch] = p_source[current_sample * channels +
750 ch]; // Initialize sums with first value in the
751 // input buffer
752 }
753
754 for (int j = 1; j < binSize; j++) {
755 for (int ch = 0; ch < channels; ch++) {
756 sums[ch] += p_source[(current_sample + j) * channels + ch];
757 }
758 }
759 current_sample += binSize;
760
761 // Store the bin result
762 if (average) {
763 for (int ch = 0; ch < channels; ch++) {
764 p_target[result_size / sizeof(T)] =
765 static_cast<T>(sums[ch] / binSize);
766 result_size += sizeof(T);
767 }
768 } else {
769 for (int ch = 0; ch < channels; ch++) {
770 p_target[result_size / sizeof(T)] = static_cast<T>(sums[ch]);
771 result_size += sizeof(T);
772 }
773 }
774 }
775
776 // Store the remaining samples in the partial bin
777 // ----
778 for (int i = 0; i < remaining_samples; i++) {
779 for (int ch = 0; ch < channels; ch++) {
780 partialBin[ch] += p_source[(current_sample + i) * channels + ch];
781 }
782 }
783 partialBinSize = remaining_samples;
784
785 LOGD("bin %d: %d of %d remaining %d samples, %d > %d bytes", binSize,
786 current_sample, total_samples, partialBinSize, (int)size,
787 (int)result_size);
788
789 return result_size;
790 }
791
792 protected:
793 int channels = 2;
794 int binSize = 1;
795 bool average = true;
796 T *partialBin;
797 int partialBinSize;
798};
799
805class Bin : public BaseConverter {
806 public:
807 Bin() = default;
808 Bin(int binSize, int channels, bool average, int bits_per_sample) {
809 setChannels(channels);
810 setBinSize(binSize);
811 setAverage(average);
812 setBits(bits_per_sample);
813 }
814
815 void setChannels(int channels) { this->channels = channels; }
816 void setBits(int bits) { this->bits = bits; }
817 void setBinSize(int binSize) { this->binSize = binSize; }
818 void setAverage(bool average) { this->average = average; }
819
820 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
821 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
822 switch (bits) {
823 case 8: {
824 BinT<int8_t> bin8(binSize, channels, average);
825 return bin8.convert(target, src, size);
826 }
827 case 16: {
828 BinT<int16_t> bin16(binSize, channels, average);
829 return bin16.convert(target, src, size);
830 }
831 case 24: {
832 BinT<int24_t> bin24(binSize, channels, average);
833 return bin24.convert(target, src, size);
834 }
835 case 32: {
836 BinT<int32_t> bin32(binSize, channels, average);
837 return bin32.convert(target, src, size);
838 }
839 default: {
840 LOGE("Number of bits %d not supported.", bits);
841 return 0;
842 }
843 }
844 }
845
846 protected:
847 int channels = 2;
848 int bits = 16;
849 int binSize = 1;
850 bool average = false;
851};
852
867template <typename T>
869 public:
870 ChannelDiffT() {}
871
872 size_t convert(uint8_t *src, size_t size) override {
873 return convert(src, src, size);
874 }
875
876 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
877 LOGD("channel subtract %d samples, %d bytes", (int)(size / sizeof(T)),
878 (int)size);
879
880 // Ensure the buffer size is even for pairs of channels
881 if (size % (sizeof(T) * 2) > 0) {
882 LOGE("Buffer size is not even");
883 return 0;
884 }
885
886 int sample_count =
887 size /
888 (sizeof(T) * 2); // Each pair of channels produces one output sample
889 T *p_result = (T *)target;
890 T *p_source = (T *)src;
891
892 for (int i = 0; i < sample_count; i++) {
893 // *p_result++ = *p_source++ - *p_source++;
894 auto tmp = *p_source++;
895 tmp -= *p_source++;
896 *p_result++ = tmp;
897 }
898
899 return sizeof(T) * sample_count;
900 }
901};
902
904 public:
905 ChannelDiff() = default;
906 ChannelDiff(int bitsPerSample) { setBits(bitsPerSample); }
907 void setBits(int bits) { this->bits = bits; }
908
909 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
910 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
911 switch (bits) {
912 case 8: {
914 return cd8.convert(target, src, size);
915 }
916 case 16: {
918 return cd16.convert(target, src, size);
919 }
920 case 24: {
922 return cd24.convert(target, src, size);
923 }
924 case 32: {
926 return cd32.convert(target, src, size);
927 }
928 default: {
929 LOGE("Number of bits %d not supported.", bits);
930 return 0;
931 }
932 }
933 }
934
935 protected:
936 int bits = 16;
937};
938
952template <typename T>
954 public:
955 ChannelAvgT() {}
956
957 size_t convert(uint8_t *src, size_t size) override {
958 return convert(src, src, size);
959 }
960
961 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
962 if (size % (sizeof(T) * 2) > 0) {
963 LOGE("Buffer size is not even");
964 return 0;
965 }
966
967 int sample_count =
968 size /
969 (sizeof(T) * 2); // Each pair of channels produces one output sample
970 T *p_result = (T *)target;
971 T *p_source = (T *)src;
972
973 for (int i = 0; i < sample_count; i++) {
974 // *p_result++ = (*p_source++ + *p_source++) / 2; // Average the pair of
975 // channels
976 auto tmp = *p_source++;
977 tmp += *p_source++;
978 *p_result++ = tmp / 2;
979 }
980
981 LOGD("channel average %d samples, %d bytes", sample_count, (int)size);
982
983 return sizeof(T) * sample_count;
984 }
985};
986
987class ChannelAvg : public BaseConverter {
988 public:
989 ChannelAvg() = default;
990 ChannelAvg(int bitsPerSample) { setBits(bitsPerSample); }
991 void setBits(int bits) { this->bits = bits; }
992
993 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
994 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
995 switch (bits) {
996 case 8: {
998 return ca8.convert(target, src, size);
999 }
1000 case 16: {
1002 return ca16.convert(target, src, size);
1003 }
1004 case 24: {
1006 return ca24.convert(target, src, size);
1007 }
1008 case 32: {
1010 return ca32.convert(target, src, size);
1011 }
1012 default: {
1013 LOGE("Number of bits %d not supported.", bits);
1014 return 0;
1015 }
1016 }
1017 }
1018
1019 protected:
1020 int bits = 16;
1021};
1022
1036template <typename T>
1038 public:
1039 ChannelBinDiffT() = default;
1040 ChannelBinDiffT(int binSize, int channels, bool average) {
1041 setChannels(channels);
1042 setBinSize(binSize);
1043 setAverage(average);
1044 this->partialBinSize = 0;
1045 // this->partialBin = new T[channels];
1046 // std::fill(this->partialBin, this->partialBin + channels, 0); //
1047 // Initialize partialBin with zeros
1048 this->partialBin = new T[channels]();
1049 }
1050
1051 ~ChannelBinDiffT() { delete[] this->partialBin; }
1052
1053 void setChannels(int channels) {
1054 if ((channels % 2) > 0) {
1055 LOGE("Number of channels needs to be even");
1056 this->channels = channels + 1;
1057 }
1058 this->channels = channels;
1059 }
1060 void setBinSize(int binSize) { this->binSize = binSize; }
1061 void setAverage(bool average) { this->average = average; }
1062
1063 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1064
1065 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1066 // The binning works the same as in the BinT class
1067 // Here we add subtraction before we store the bins
1068
1069 if (size % (sizeof(T) * channels) > 0) {
1070 LOGE("Buffer size needs to be multiple of channels")
1071 return 0;
1072 }
1073
1074 int sample_count =
1075 size / (sizeof(T) * channels); // new available samples in each channel
1076 int total_samples =
1077 partialBinSize +
1078 sample_count; // total samples available for each channel including
1079 // previous number of sample in partial bin
1080 int bin_count = total_samples / binSize; // number of bins we can make
1081 int remaining_samples =
1082 total_samples % binSize; // remaining samples after binning
1083 T *p_target = (T *)target;
1084 T *p_source = (T *)src;
1085 size_t result_size = 0;
1086
1087 // Allocate sum for each channel with appropriate type
1088 typename AppropriateSumType<T>::type sums[channels];
1089 int current_sample = 0; // current sample index
1090
1091 // Is there a partial bin from the previous call?
1092 // ----
1093 if (partialBinSize > 0) {
1094 // LOGD("Deal with partial bins");
1095
1096 int samples_needed = binSize - partialBinSize;
1097 bool have_enough_samples = (samples_needed < sample_count);
1098 int samples_to_bin = have_enough_samples ? samples_needed : sample_count;
1099
1100 // initialize
1101 for (int ch = 0; ch < channels; ch++) {
1102 sums[ch] = partialBin[ch];
1103 }
1104
1105 // continue binning
1106 for (int j = 0; j < samples_to_bin; j++) {
1107 for (int ch = 0; ch < channels; ch++) {
1108 sums[ch] += p_source[current_sample * channels + ch];
1109 }
1110 current_sample++;
1111 }
1112
1113 // store the bin results or update the partial bin
1114 if (have_enough_samples) {
1115 // Subtract two channels and store the completed bin
1116 if (average) {
1117 for (int ch = 0; ch < channels; ch += 2) {
1118 p_target[result_size / sizeof(T)] =
1119 static_cast<T>((sums[ch] - sums[ch + 1]) / binSize);
1120 result_size += sizeof(T);
1121 }
1122 } else {
1123 for (int ch = 0; ch < channels; ch += 2) {
1124 p_target[result_size / sizeof(T)] =
1125 static_cast<T>((sums[ch] - sums[ch + 1]));
1126 result_size += sizeof(T);
1127 }
1128 }
1129 partialBinSize = 0;
1130 // LOGD("Partial bins are empty");
1131
1132 } else {
1133 // Not enough samples to complete the bin, update partialBin
1134 for (int ch = 0; ch < channels; ch++) {
1135 partialBin[ch] = sums[ch];
1136 }
1137 partialBinSize += current_sample;
1138 LOGD(
1139 "bin & channel subtract %d: %d of %d remaining %d samples, %d > %d "
1140 "bytes",
1141 binSize, current_sample, total_samples, partialBinSize, (int)size,
1142 (int)result_size);
1143 // LOGD("Partial bins were updated");
1144 return result_size;
1145 }
1146 }
1147
1148 // Fill bins
1149 // ----
1150 // LOGD("Fillin bins");
1151 for (int i = 0; i < bin_count; i++) {
1152 // LOGD("Current sample %d", current_sample);
1153
1154 for (int ch = 0; ch < channels; ch++) {
1155 sums[ch] = p_source[current_sample * channels +
1156 ch]; // Initialize sums with first value in the
1157 // input buffer
1158 }
1159
1160 for (int j = 1; j < binSize; j++) {
1161 for (int ch = 0; ch < channels; ch++) {
1162 sums[ch] += p_source[(current_sample + j) * channels + ch];
1163 }
1164 }
1165 current_sample += binSize;
1166
1167 // Finish binning, then subtact two channel and store the result
1168 if (average) {
1169 for (int ch = 0; ch < channels; ch += 2) {
1170 p_target[result_size / sizeof(T)] =
1171 static_cast<T>((sums[ch] - sums[ch + 1]) / binSize);
1172 result_size += sizeof(T);
1173 }
1174 } else {
1175 for (int ch = 0; ch < channels; ch += 2) {
1176 p_target[result_size / sizeof(T)] =
1177 static_cast<T>((sums[ch] - sums[ch + 1]));
1178 result_size += sizeof(T);
1179 }
1180 }
1181 }
1182
1183 // Store the remaining samples in the partial bin
1184 // ----
1185 // LOGD("Updating partial bins");
1186 for (int i = 0; i < remaining_samples; i++) {
1187 for (int ch = 0; ch < channels; ch++) {
1188 partialBin[ch] += p_source[(current_sample + i) * channels + ch];
1189 }
1190 }
1191 partialBinSize = remaining_samples;
1192
1193 LOGD(
1194 "bin & channel subtract %d: %d of %d remaining %d samples, %d > %d "
1195 "bytes",
1196 binSize, current_sample, total_samples, partialBinSize, (int)size,
1197 (int)result_size);
1198
1199 return result_size;
1200 }
1201
1202 protected:
1203 int channels = 2;
1204 int binSize = 4;
1205 bool average = true;
1206 T *partialBin;
1207 int partialBinSize;
1208};
1209
1218 public:
1219 ChannelBinDiff() = default;
1220 ChannelBinDiff(int binSize, int channels, bool average, int bits_per_sample) {
1221 setChannels(channels);
1222 setBinSize(binSize);
1223 setAverage(average);
1224 setBits(bits_per_sample);
1225 }
1226
1227 void setChannels(int channels) {
1228 if ((channels % 2) == 0) {
1229 this->channels = channels;
1230 } else {
1231 LOGE("Number of channels needs to be even");
1232 this->channels = channels + 1;
1233 }
1234 }
1235
1236 void setBits(int bits) { this->bits = bits; }
1237 void setBinSize(int binSize) { this->binSize = binSize; }
1238 void setAverage(bool average) { this->average = average; }
1239
1240 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1241 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1242 switch (bits) {
1243 case 8: {
1244 ChannelBinDiffT<int8_t> bd8(binSize, channels, average);
1245 return bd8.convert(target, src, size);
1246 }
1247 case 16: {
1248 ChannelBinDiffT<int16_t> bd16(binSize, channels, average);
1249 return bd16.convert(target, src, size);
1250 }
1251 case 24: {
1252 ChannelBinDiffT<int24_t> bd24(binSize, channels, average);
1253 return bd24.convert(target, src, size);
1254 }
1255 case 32: {
1256 ChannelBinDiffT<int32_t> bd32(binSize, channels, average);
1257 return bd32.convert(target, src, size);
1258 }
1259 default: {
1260 LOGE("Number of bits %d not supported.", bits);
1261 return 0;
1262 }
1263 }
1264 }
1265
1266 protected:
1267 int channels = 2;
1268 int bits = 16;
1269 int binSize = 4;
1270 bool average = true;
1271};
1272
1278template <typename T>
1280 public:
1281 ChannelEnhancer() = default;
1282
1283 ChannelEnhancer(int channelCountOfTarget, int channelCountOfSource) {
1284 from_channels = channelCountOfSource;
1285 to_channels = channelCountOfTarget;
1286 }
1287
1288 void setSourceChannels(int channelCountOfSource) {
1289 from_channels = channelCountOfSource;
1290 }
1291
1292 void setTargetChannels(int channelCountOfTarget) {
1293 to_channels = channelCountOfTarget;
1294 }
1295
1296 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1297 int frame_count = size / (sizeof(T) * from_channels);
1298 size_t result_size = 0;
1299 T *result = (T *)target;
1300 T *source = (T *)src;
1301 T value = (int16_t)0;
1302 for (int i = 0; i < frame_count; i++) {
1303 // copy available channels
1304 for (int j = 0; j < from_channels; j++) {
1305 value = *source++;
1306 *result++ = value;
1307 result_size += sizeof(T);
1308 }
1309 // repeat last value
1310 for (int j = from_channels; j < to_channels; j++) {
1311 *result++ = value;
1312 result_size += sizeof(T);
1313 }
1314 }
1315 return result_size;
1316 }
1317
1319 size_t resultSize(size_t inSize) {
1320 return inSize * to_channels / from_channels;
1321 }
1322
1323 protected:
1324 int from_channels;
1325 int to_channels;
1326};
1327
1333template <typename T>
1335 public:
1336 ChannelConverter() = default;
1337
1338 ChannelConverter(int channelCountOfTarget, int channelCountOfSource) {
1339 from_channels = channelCountOfSource;
1340 to_channels = channelCountOfTarget;
1341 }
1342
1343 void setSourceChannels(int channelCountOfSource) {
1344 from_channels = channelCountOfSource;
1345 }
1346
1347 void setTargetChannels(int channelCountOfTarget) {
1348 to_channels = channelCountOfTarget;
1349 }
1350
1351 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1352 if (from_channels == to_channels) {
1353 memcpy(target, src, size);
1354 return size;
1355 }
1356 // setup channels
1357 if (from_channels > to_channels) {
1358 reducer.setSourceChannels(from_channels);
1359 reducer.setTargetChannels(to_channels);
1360 } else {
1361 enhancer.setSourceChannels(from_channels);
1362 enhancer.setTargetChannels(to_channels);
1363 }
1364
1365 // execute conversion
1366 if (from_channels > to_channels) {
1367 return reducer.convert(target, src, size);
1368 } else {
1369 return enhancer.convert(target, src, size);
1370 }
1371 }
1372
1373 protected:
1374 ChannelEnhancer<T> enhancer;
1375 ChannelReducerT<T> reducer;
1376 int from_channels;
1377 int to_channels;
1378};
1379
1385template <typename T>
1387 public:
1388 MultiConverter() {}
1389
1390 MultiConverter(BaseConverter &c1) { add(c1); }
1391
1393 add(c1);
1394 add(c2);
1395 }
1396
1398 add(c1);
1399 add(c2);
1400 add(c3);
1401 }
1402
1403 // adds a converter
1404 void add(BaseConverter &converter) { converters.push_back(&converter); }
1405
1406 // The data is provided as int24_t tgt[][2] but returned as int24_t
1407 size_t convert(uint8_t *src, size_t size) {
1408 for (int i = 0; i < converters.size(); i++) {
1409 converters[i]->convert(src, size);
1410 }
1411 return size;
1412 }
1413
1414 private:
1415 Vector<BaseConverter *> converters;
1416};
1417
1418// /**
1419// * @brief Converts e.g. 24bit data to the indicated smaller or bigger data
1420// type
1421// * @ingroup convert
1422// * @author Phil Schatzmann
1423// * @copyright GPLv3
1424// *
1425// * @tparam T
1426// */
1427// template<typename FromType, typename ToType>
1428// class FormatConverter {
1429// public:
1430// FormatConverter(ToType (*converter)(FromType v)){
1431// this->convert_ptr = converter;
1432// }
1433
1434// FormatConverter( float factor, float clip){
1435// this->factor = factor;
1436// this->clip = clip;
1437// }
1438
1439// // The data is provided as int24_t tgt[][2] but returned as int24_t
1440// size_t convert(uint8_t *src, uint8_t *target, size_t byte_count_src)
1441// {
1442// return convert((FromType *)src, (ToType*)target, byte_count_src
1443// );
1444// }
1445
1446// // The data is provided as int24_t tgt[][2] but returned as int24_t
1447// size_t convert(FromType *src, ToType *target, size_t byte_count_src)
1448// {
1449// int size = byte_count_src / sizeof(FromType);
1450// FromType *s = src;
1451// ToType *t = target;
1452// if (convert_ptr!=nullptr){
1453// // standard conversion
1454// for (int i=size; i>0; i--) {
1455// *t = (*convert_ptr)(*s);
1456// t++;
1457// s++;
1458// }
1459// } else {
1460// // conversion using indicated factor
1461// for (int i=size; i>0; i--) {
1462// float tmp = factor * *s;
1463// if (tmp>clip){
1464// tmp=clip;
1465// } else if (tmp<-clip){
1466// tmp = -clip;
1467// }
1468// *t = tmp;
1469// t++;
1470// s++;
1471// }
1472// }
1473// return size*sizeof(ToType);
1474// }
1475
1476// private:
1477// ToType (*convert_ptr)(FromType v) = nullptr;
1478// float factor=0;
1479// float clip=0;
1480
1481// };
1482
1488 public:
1489 NumberReader(Stream &in) { stream_ptr = &in; }
1490
1491 NumberReader() {}
1492
1493 bool read(int inBits, int outBits, bool outSigned, int n, int32_t *result) {
1494 bool result_bool = false;
1495 int len = inBits / 8 * n;
1496 if (stream_ptr != nullptr && stream_ptr->available() > len) {
1497 uint8_t buffer[len];
1498 stream_ptr->readBytes((uint8_t *)buffer, n * len);
1499 result_bool =
1500 toNumbers((void *)buffer, inBits, outBits, outSigned, n, result);
1501 }
1502 return result_bool;
1503 }
1504
1506 bool toNumbers(void *bufferIn, int inBits, int outBits, bool outSigned, int n,
1507 int32_t *result) {
1508 bool result_bool = false;
1509 switch (inBits) {
1510 case 8: {
1511 int8_t *buffer = (int8_t *)bufferIn;
1512 for (int j = 0; j < n; j++) {
1513 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1514 }
1515 result_bool = true;
1516 } break;
1517 case 16: {
1518 int16_t *buffer = (int16_t *)bufferIn;
1519 for (int j = 0; j < n; j++) {
1520 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1521 }
1522 result_bool = true;
1523 } break;
1524 case 32: {
1525 int32_t *buffer = (int32_t *)bufferIn;
1526 for (int j = 0; j < n; j++) {
1527 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1528 }
1529 result_bool = true;
1530 } break;
1531 }
1532 return result_bool;
1533 }
1534
1535 protected:
1536 Stream *stream_ptr = nullptr;
1537
1539 int32_t scale(int32_t value, int inBits, int outBits, bool outSigned = true) {
1540 int32_t result = static_cast<float>(value) /
1543 if (!outSigned) {
1544 result += (NumberConverter::maxValue(outBits) / 2);
1545 }
1546 return result;
1547 }
1548};
1549
1556template <typename T>
1558 public:
1559 Converter1Channel(Filter<T> &filter) { this->p_filter = &filter; }
1560
1561 size_t convert(uint8_t *src, size_t size) override {
1562 T *data = (T *)src;
1563 for (size_t j = 0; j < size; j++) {
1564 data[j] = p_filter->process(data[j]);
1565 }
1566 return size;
1567 }
1568
1569 protected:
1570 Filter<T> *p_filter = nullptr;
1571};
1572
1579template <typename T, typename FT>
1581 public:
1583 ConverterNChannels(int channels) {
1584 this->channels = channels;
1585 filters = new Filter<FT> *[channels];
1586 // make sure that we have 1 filter per channel
1587 for (int j = 0; j < channels; j++) {
1588 filters[j] = nullptr;
1589 }
1590 }
1591
1594 for (int j = 0; j < channels; j++) {
1595 if (filters[j] != nullptr) {
1596 delete filters[j];
1597 }
1598 }
1599 delete[] filters;
1600 filters = 0;
1601 }
1602
1604 void setFilter(int channel, Filter<FT> *filter) {
1605 if (channel < channels) {
1606 if (filters[channel] != nullptr) {
1607 delete filters[channel];
1608 }
1609 filters[channel] = filter;
1610 } else {
1611 LOGE("Invalid channel nummber %d - max channel is %d", channel,
1612 channels - 1);
1613 }
1614 }
1615
1616 // convert all samples for each channel separately
1617 size_t convert(uint8_t *src, size_t size) {
1618 int count = size / channels / sizeof(T);
1619 T *sample = (T *)src;
1620 for (size_t j = 0; j < count; j++) {
1621 for (int channel = 0; channel < channels; channel++) {
1622 if (filters[channel] != nullptr) {
1623 *sample = filters[channel]->process(*sample);
1624 }
1625 sample++;
1626 }
1627 }
1628 return size;
1629 }
1630
1631 int getChannels() { return channels; }
1632
1633 protected:
1634 Filter<FT> **filters = nullptr;
1635 int channels;
1636};
1637
1646template <typename T>
1648 public:
1649 SilenceRemovalConverter(int n = 8, int aplidudeLimit = 2) {
1650 set(n, aplidudeLimit);
1651 }
1652
1653 virtual size_t convert(uint8_t *data, size_t size) override {
1654 if (!active) {
1655 // no change to the data
1656 return size;
1657 }
1658 size_t sample_count = size / sizeof(T);
1659 size_t write_count = 0;
1660 T *audio = (T *)data;
1661
1662 // find relevant data
1663 T *p_buffer = (T *)data;
1664 for (int j = 0; j < sample_count; j++) {
1665 int pos = findLastAudioPos(audio, j);
1666 if (pos < n) {
1667 write_count++;
1668 *p_buffer++ = audio[j];
1669 }
1670 }
1671
1672 // write audio data w/o silence
1673 size_t write_size = write_count * sizeof(T);
1674 LOGI("filtered silence from %d -> %d", (int)size, (int)write_size);
1675
1676 // number of empty samples of prior buffer
1677 priorLastAudioPos = findLastAudioPos(audio, sample_count - 1);
1678
1679 // return new data size
1680 return write_size;
1681 }
1682
1683 protected:
1684 bool active = false;
1685 const uint8_t *buffer = nullptr;
1686 int n;
1687 int priorLastAudioPos = 0;
1688 int amplidude_limit = 0;
1689
1690 void set(int n = 5, int aplidudeLimit = 2) {
1691 LOGI("begin(n=%d, aplidudeLimit=%d", n, aplidudeLimit);
1692 this->n = n;
1693 this->amplidude_limit = aplidudeLimit;
1694 this->priorLastAudioPos = n + 1; // ignore first values
1695 this->active = n > 0;
1696 }
1697
1698 // find last position which contains audible data
1699 int findLastAudioPos(T *audio, int pos) {
1700 for (int j = 0; j < n; j++) {
1701 // we are before the start of the current buffer
1702 if (pos - j <= 0) {
1703 return priorLastAudioPos;
1704 }
1705 // we are in the current buffer
1706 if (abs(audio[pos - j]) > amplidude_limit) {
1707 return j;
1708 }
1709 }
1710 return n + 1;
1711 }
1712};
1713
1721template <typename T>
1723 public:
1724 PoppingSoundRemover(int channels, bool fromBeginning, bool fromEnd) {
1725 this->channels = channels;
1726 from_beginning = fromBeginning;
1727 from_end = fromEnd;
1728 }
1729 virtual size_t convert(uint8_t *src, size_t size) {
1730 for (int ch = 0; ch < channels; ch++) {
1731 if (from_beginning)
1732 clearUpTo1stTransition(channels, ch, (T *)src, size / sizeof(T));
1733 if (from_end)
1734 clearAfterLastTransition(channels, ch, (T *)src, size / sizeof(T));
1735 }
1736 return size;
1737 }
1738
1739 protected:
1740 bool from_beginning;
1741 bool from_end;
1742 int channels;
1743
1744 void clearUpTo1stTransition(int channels, int channel, T *values,
1745 int sampleCount) {
1746 T first = values[channel];
1747 for (int j = 0; j < sampleCount; j += channels) {
1748 T act = values[j];
1749 if ((first <= 0.0 && act >= 0.0) || (first >= 0.0 && act <= 0.0)) {
1750 // we found the last transition so we are done
1751 break;
1752 } else {
1753 values[j] = 0;
1754 }
1755 }
1756 }
1757
1758 void clearAfterLastTransition(int channels, int channel, T *values,
1759 int sampleCount) {
1760 int lastPos = sampleCount - channels + channel;
1761 T last = values[lastPos];
1762 for (int j = lastPos; j >= 0; j -= channels) {
1763 T act = values[j];
1764 if ((last <= 0.0 && act >= 0.0) || (last >= 0.0 && act <= 0.0)) {
1765 // we found the last transition so we are done
1766 break;
1767 } else {
1768 values[j] = 0;
1769 }
1770 }
1771 }
1772};
1773
1780template <typename T>
1782 public:
1783 SmoothTransition(int channels, bool fromBeginning, bool fromEnd,
1784 float inc = 0.01) {
1785 this->channels = channels;
1786 this->inc = inc;
1787 from_beginning = fromBeginning;
1788 from_end = fromEnd;
1789 }
1790 virtual size_t convert(uint8_t *src, size_t size) {
1791 for (int ch = 0; ch < channels; ch++) {
1792 if (from_beginning)
1793 processStart(channels, ch, (T *)src, size / sizeof(T));
1794 if (from_end) processEnd(channels, ch, (T *)src, size / sizeof(T));
1795 }
1796 return size;
1797 }
1798
1799 protected:
1800 bool from_beginning;
1801 bool from_end;
1802 int channels;
1803 float inc = 0.01;
1804 float factor = 0;
1805
1806 void processStart(int channels, int channel, T *values, int sampleCount) {
1807 for (int j = 0; j < sampleCount; j += channels) {
1808 if (factor >= 0.8) {
1809 break;
1810 } else {
1811 values[j] = factor * values[j];
1812 }
1813 factor += inc;
1814 }
1815 }
1816
1817 void processEnd(int channels, int channel, T *values, int sampleCount) {
1818 int lastPos = sampleCount - channels + channel;
1819 for (int j = lastPos; j >= 0; j -= channels) {
1820 if (factor >= 0.8) {
1821 break;
1822 } else {
1823 values[j] = factor * values[j];
1824 }
1825 }
1826 }
1827};
1828
1834template <typename T, size_t Cn, size_t Cx, size_t S>
1836 public:
1837 CopyChannels() : _max_val(0), _counter(0), _prev_ms(0) {}
1838
1839 size_t convert(uint8_t *src, size_t size) {
1840 T *chan = (T *)src;
1841 size_t samples = (size / Cn) / sizeof(T);
1842 for (size_t s = 0; s < samples; s++) {
1843 chan[s * Cn + Cx] = (Cx < Cn) ? chan[s * Cn + Cx] << S : 0;
1844
1845 for (size_t c = 0; c < Cn; c++) {
1846 if (c != Cx) {
1847 chan[s * Cn + c] = chan[s * Cn + Cx];
1848 }
1849 }
1850
1851 if (_max_val < chan[s * Cn]) {
1852 _max_val = chan[s * Cn];
1853 }
1854
1855 _counter++;
1856 uint32_t now = millis();
1857 if (now - _prev_ms > 1000) {
1858 _prev_ms = now;
1859 LOGI("CopyChannels samples: %u, amplitude: %d", _counter, _max_val);
1860 _max_val = 0;
1861 }
1862 }
1863 return samples * Cn * sizeof(T);
1864 }
1865
1866 private:
1867 T _max_val;
1868 uint32_t _counter;
1869 uint32_t _prev_ms;
1870};
1871
1877template <typename T>
1879 public:
1880 CallbackConverterT(T (*callback)(T in, int channel), int channels = 2) {
1881 this->callback = callback;
1882 this->channels = channels;
1883 }
1884
1885 size_t convert(uint8_t *src, size_t size) {
1886 int samples = size / sizeof(T);
1887 for (int j = 0; j < samples; j++) {
1888 src[j] = callback(src[j], j % channels);
1889 }
1890 return size;
1891 }
1892
1893 protected:
1894 T (*callback)(T in, int channel);
1895 int channels;
1896};
1897
1898} // 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:805
Definition BaseConverter.h:647
You can provide a lambda expression to conver the data.
Definition BaseConverter.h:1878
Definition BaseConverter.h:987
We average pairs of channels in a datastream. E.g. if we have 4 channels we end up with 2 channels....
Definition BaseConverter.h:953
Provides combination of binning and subtracting channels.
Definition BaseConverter.h:1217
We first bin the channels then we calculate the difference between pairs of channels in a datastream....
Definition BaseConverter.h:1037
Increasing or decreasing the number of channels.
Definition BaseConverter.h:1334
Definition BaseConverter.h:903
We calculate the difference between pairs of channels in a datastream. E.g. if we have 4 channels we ...
Definition BaseConverter.h:868
Increases the channel count.
Definition BaseConverter.h:1279
size_t resultSize(size_t inSize)
Determine the size of the conversion result.
Definition BaseConverter.h:1319
We combine a datastream which consists of multiple channels into less channels. E....
Definition BaseConverter.h:464
We combine a datastream which consists of multiple channels into less channels. E....
Definition BaseConverter.h:408
Converter for 1 Channel which applies the indicated Filter.
Definition BaseConverter.h:1557
Makes sure that the avg of the signal is set to 0.
Definition BaseConverter.h:185
Makes sure that the avg of the signal is set to 0.
Definition BaseConverter.h:106
Make sure that both channels contain any data.
Definition BaseConverter.h:297
Converter for n Channels which applies the indicated Filter.
Definition BaseConverter.h:1580
~ConverterNChannels()
Destructor.
Definition BaseConverter.h:1593
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition BaseConverter.h:1604
ConverterNChannels(int channels)
Default Constructor.
Definition BaseConverter.h:1583
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:259
special case for internal DAC output, the incomming PCM buffer needs to be converted from signed 16bi...
Definition BaseConverter.h:380
Copy channel Cx value of type T shifted by S bits to all Cn channels.
Definition BaseConverter.h:1835
Provides a reduced sampling rate by taking a sample at every factor location (ingoring factor-1 sampl...
Definition BaseConverter.h:565
void setFactor(int factor)
Sets the factor: e.g. with 4 we keep every forth sample.
Definition BaseConverter.h:577
void setChannels(int channels)
Defines the number of channels.
Definition BaseConverter.h:574
Provides reduced sampling rates.
Definition BaseConverter.h:508
void setFactor(int factor)
Sets the factor: e.g. with 4 we keep every fourth sample.
Definition BaseConverter.h:520
void setChannels(int channels)
Defines the number of channels.
Definition BaseConverter.h:517
Abstract filter interface definition;.
Definition Filter.h:28
Combines multiple converters.
Definition BaseConverter.h:1386
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:299
Reads n numbers from an Arduino Stream.
Definition BaseConverter.h:1487
int32_t scale(int32_t value, int inBits, int outBits, bool outSigned=true)
scale the value
Definition BaseConverter.h:1539
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:1506
Big value gaps (at the beginning and the end of a recording) can lead to some popping sounds....
Definition BaseConverter.h:1722
Removes any silence from the buffer that is longer then n samples with a amplitude below the indicate...
Definition BaseConverter.h:1647
Changes the samples at the beginning or at the end to slowly ramp up the volume.
Definition BaseConverter.h:1781
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:285
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:622
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
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