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