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
941
949template <typename T = int16_t, typename SumT = float>
951 public:
952 ChannelMixer(int channels = 2) { this->channels = channels; }
953 size_t convert(uint8_t *data, size_t size) {
954 if (channels <= 1) return size; // No mixing needed for single channel
955 T *srcT = (T *)data;
956 T *targetT = (T *)data;
957 int samples = size / sizeof(T);
958 assert(samples % channels == 0);
959 for (int j = 0; j < samples; j += channels) {
960 SumT sum = 0;
961 for (int ch = 0; ch < channels; ch++) {
962 sum += srcT[j + ch];
963 }
964 T avg = sum / channels;
965 for (int ch = 0; ch < channels; ch++) {
966 targetT[j + ch] = avg;
967 }
968 }
969 return size;
970 }
971
972 protected:
973 int channels = 2;
974};
975
989template <typename T = int16_t, typename AvgT = float>
991 public:
992 ChannelAvgT() {}
993
994 size_t convert(uint8_t *src, size_t size) override {
995 return convert(src, src, size);
996 }
997
998 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
999 if (size % (sizeof(T) * 2) > 0) {
1000 LOGE("Buffer size is not even");
1001 return 0;
1002 }
1003
1004 int sample_count =
1005 size /
1006 (sizeof(T) * 2); // Each pair of channels produces one output sample
1007 T *p_result = (T *)target;
1008 T *p_source = (T *)src;
1009
1010 for (int i = 0; i < sample_count; i++) {
1011 // *p_result++ = (*p_source++ + *p_source++) / 2; // Average the pair of
1012 // channels
1013 AvgT tmp = *p_source++;
1014 tmp += *p_source++;
1015 *p_result++ = tmp / 2;
1016 }
1017
1018 LOGD("channel average %d samples, %d bytes", sample_count, (int)size);
1019
1020 return sizeof(T) * sample_count;
1021 }
1022};
1023
1024
1039 public:
1040 ChannelAvg() = default;
1041 ChannelAvg(int bitsPerSample) { setBits(bitsPerSample); }
1042 void setBits(int bits) { this->bits = bits; }
1043
1044 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1045 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1046 switch (bits) {
1047#ifdef PREFER_FIXEDPOINT
1048 case 8: {
1050 return ca8.convert(target, src, size);
1051 }
1052 case 16: {
1054 return ca16.convert(target, src, size);
1055 }
1056 case 24: {
1058 return ca24.convert(target, src, size);
1059 }
1060#else
1061 case 8: {
1063 return ca8.convert(target, src, size);
1064 }
1065 case 16: {
1067 return ca16.convert(target, src, size);
1068 }
1069 case 24: {
1071 return ca24.convert(target, src, size);
1072 }
1073#endif
1074 case 32: {
1076 return ca32.convert(target, src, size);
1077 }
1078 default: {
1079 LOGE("Number of bits %d not supported.", bits);
1080 return 0;
1081 }
1082 }
1083 }
1084
1085 protected:
1086 int bits = 16;
1087};
1088
1102template <typename T = int16_t>
1104 public:
1105 ChannelBinDiffT() = default;
1106 ChannelBinDiffT(int binSize, int channels, bool average) {
1107 setChannels(channels);
1108 setBinSize(binSize);
1109 setAverage(average);
1110 this->partialBinSize = 0;
1111 // this->partialBin = new T[channels];
1112 // std::fill(this->partialBin, this->partialBin + channels, 0); //
1113 // Initialize partialBin with zeros
1114 this->partialBin = new T[channels]();
1115 }
1116
1117 ~ChannelBinDiffT() { delete[] this->partialBin; }
1118
1119 void setChannels(int channels) {
1120 if ((channels % 2) > 0) {
1121 LOGE("Number of channels needs to be even");
1122 this->channels = channels + 1;
1123 }
1124 this->channels = channels;
1125 }
1126 void setBinSize(int binSize) { this->binSize = binSize; }
1127 void setAverage(bool average) { this->average = average; }
1128
1129 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1130
1131 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1132 // The binning works the same as in the BinT class
1133 // Here we add subtraction before we store the bins
1134
1135 if (size % (sizeof(T) * channels) > 0) {
1136 LOGE("Buffer size needs to be multiple of channels")
1137 return 0;
1138 }
1139
1140 int sample_count =
1141 size / (sizeof(T) * channels); // new available samples in each channel
1142 int total_samples =
1143 partialBinSize +
1144 sample_count; // total samples available for each channel including
1145 // previous number of sample in partial bin
1146 int bin_count = total_samples / binSize; // number of bins we can make
1147 int remaining_samples =
1148 total_samples % binSize; // remaining samples after binning
1149 T *p_target = (T *)target;
1150 T *p_source = (T *)src;
1151 size_t result_size = 0;
1152
1153 // Allocate sum for each channel with appropriate type
1154 typename AppropriateSumType<T>::type sums[channels];
1155 int current_sample = 0; // current sample index
1156
1157 // Is there a partial bin from the previous call?
1158 // ----
1159 if (partialBinSize > 0) {
1160 // LOGD("Deal with partial bins");
1161
1162 int samples_needed = binSize - partialBinSize;
1163 bool have_enough_samples = (samples_needed < sample_count);
1164 int samples_to_bin = have_enough_samples ? samples_needed : sample_count;
1165
1166 // initialize
1167 for (int ch = 0; ch < channels; ch++) {
1168 sums[ch] = partialBin[ch];
1169 }
1170
1171 // continue binning
1172 for (int j = 0; j < samples_to_bin; j++) {
1173 for (int ch = 0; ch < channels; ch++) {
1174 sums[ch] += p_source[current_sample * channels + ch];
1175 }
1176 current_sample++;
1177 }
1178
1179 // store the bin results or update the partial bin
1180 if (have_enough_samples) {
1181 // Subtract two channels and store the completed bin
1182 if (average) {
1183 for (int ch = 0; ch < channels; ch += 2) {
1184 p_target[result_size / sizeof(T)] =
1185 static_cast<T>((sums[ch] - sums[ch + 1]) / binSize);
1186 result_size += sizeof(T);
1187 }
1188 } else {
1189 for (int ch = 0; ch < channels; ch += 2) {
1190 p_target[result_size / sizeof(T)] =
1191 static_cast<T>((sums[ch] - sums[ch + 1]));
1192 result_size += sizeof(T);
1193 }
1194 }
1195 partialBinSize = 0;
1196 // LOGD("Partial bins are empty");
1197
1198 } else {
1199 // Not enough samples to complete the bin, update partialBin
1200 for (int ch = 0; ch < channels; ch++) {
1201 partialBin[ch] = sums[ch];
1202 }
1203 partialBinSize += current_sample;
1204 LOGD(
1205 "bin & channel subtract %d: %d of %d remaining %d samples, %d "
1206 "> %d "
1207 "bytes",
1208 binSize, current_sample, total_samples, partialBinSize, (int)size,
1209 (int)result_size);
1210 // LOGD("Partial bins were updated");
1211 return result_size;
1212 }
1213 }
1214
1215 // Fill bins
1216 // ----
1217 // LOGD("Fillin bins");
1218 for (int i = 0; i < bin_count; i++) {
1219 // LOGD("Current sample %d", current_sample);
1220
1221 for (int ch = 0; ch < channels; ch++) {
1222 sums[ch] = p_source[current_sample * channels +
1223 ch]; // Initialize sums with first value in the
1224 // input buffer
1225 }
1226
1227 for (int j = 1; j < binSize; j++) {
1228 for (int ch = 0; ch < channels; ch++) {
1229 sums[ch] += p_source[(current_sample + j) * channels + ch];
1230 }
1231 }
1232 current_sample += binSize;
1233
1234 // Finish binning, then subtact two channel and store the result
1235 if (average) {
1236 for (int ch = 0; ch < channels; ch += 2) {
1237 p_target[result_size / sizeof(T)] =
1238 static_cast<T>((sums[ch] - sums[ch + 1]) / binSize);
1239 result_size += sizeof(T);
1240 }
1241 } else {
1242 for (int ch = 0; ch < channels; ch += 2) {
1243 p_target[result_size / sizeof(T)] =
1244 static_cast<T>((sums[ch] - sums[ch + 1]));
1245 result_size += sizeof(T);
1246 }
1247 }
1248 }
1249
1250 // Store the remaining samples in the partial bin
1251 // ----
1252 // LOGD("Updating partial bins");
1253 for (int i = 0; i < remaining_samples; i++) {
1254 for (int ch = 0; ch < channels; ch++) {
1255 partialBin[ch] += p_source[(current_sample + i) * channels + ch];
1256 }
1257 }
1258 partialBinSize = remaining_samples;
1259
1260 LOGD(
1261 "bin & channel subtract %d: %d of %d remaining %d samples, %d > %d "
1262 "bytes",
1263 binSize, current_sample, total_samples, partialBinSize, (int)size,
1264 (int)result_size);
1265
1266 return result_size;
1267 }
1268
1269 protected:
1270 int channels = 2;
1271 int binSize = 4;
1272 bool average = true;
1273 T *partialBin;
1274 int partialBinSize;
1275};
1276
1285 public:
1286 ChannelBinDiff() = default;
1287 ChannelBinDiff(int binSize, int channels, bool average, int bits_per_sample) {
1288 setChannels(channels);
1289 setBinSize(binSize);
1290 setAverage(average);
1291 setBits(bits_per_sample);
1292 }
1293
1294 void setChannels(int channels) {
1295 if ((channels % 2) == 0) {
1296 this->channels = channels;
1297 } else {
1298 LOGE("Number of channels needs to be even");
1299 this->channels = channels + 1;
1300 }
1301 }
1302
1303 void setBits(int bits) { this->bits = bits; }
1304 void setBinSize(int binSize) { this->binSize = binSize; }
1305 void setAverage(bool average) { this->average = average; }
1306
1307 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1308 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1309 switch (bits) {
1310 case 8: {
1311 ChannelBinDiffT<int8_t> bd8(binSize, channels, average);
1312 return bd8.convert(target, src, size);
1313 }
1314 case 16: {
1315 ChannelBinDiffT<int16_t> bd16(binSize, channels, average);
1316 return bd16.convert(target, src, size);
1317 }
1318 case 24: {
1319 ChannelBinDiffT<int24_t> bd24(binSize, channels, average);
1320 return bd24.convert(target, src, size);
1321 }
1322 case 32: {
1323 ChannelBinDiffT<int32_t> bd32(binSize, channels, average);
1324 return bd32.convert(target, src, size);
1325 }
1326 default: {
1327 LOGE("Number of bits %d not supported.", bits);
1328 return 0;
1329 }
1330 }
1331 }
1332
1333 protected:
1334 int channels = 2;
1335 int bits = 16;
1336 int binSize = 4;
1337 bool average = true;
1338};
1339
1345template <typename T = int16_t>
1347 public:
1348 ChannelEnhancer() = default;
1349
1350 ChannelEnhancer(int channelCountOfTarget, int channelCountOfSource) {
1351 from_channels = channelCountOfSource;
1352 to_channels = channelCountOfTarget;
1353 }
1354
1355 void setSourceChannels(int channelCountOfSource) {
1356 from_channels = channelCountOfSource;
1357 }
1358
1359 void setTargetChannels(int channelCountOfTarget) {
1360 to_channels = channelCountOfTarget;
1361 }
1362
1363 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1364 if (from_channels == 0) return size;
1365 int frame_count = size / (sizeof(T) * from_channels);
1366 size_t result_size = 0;
1367 T *result = (T *)target;
1368 T *source = (T *)src;
1369 T value = (int16_t)0;
1370 for (int i = 0; i < frame_count; i++) {
1371 // copy available channels
1372 for (int j = 0; j < from_channels; j++) {
1373 value = *source++;
1374 *result++ = value;
1375 result_size += sizeof(T);
1376 }
1377 // repeat last value
1378 for (int j = from_channels; j < to_channels; j++) {
1379 *result++ = value;
1380 result_size += sizeof(T);
1381 }
1382 }
1383 return result_size;
1384 }
1385
1387 size_t resultSize(size_t inSize) {
1388 return inSize * to_channels / from_channels;
1389 }
1390
1391 protected:
1392 int from_channels = 0;
1393 int to_channels = 0;
1394};
1395
1401template <typename T = int16_t>
1403 public:
1404 ChannelConverter() = default;
1405
1406 ChannelConverter(int channelCountOfTarget, int channelCountOfSource) {
1407 from_channels = channelCountOfSource;
1408 to_channels = channelCountOfTarget;
1409 }
1410
1411 void setSourceChannels(int channelCountOfSource) {
1412 from_channels = channelCountOfSource;
1413 }
1414
1415 void setTargetChannels(int channelCountOfTarget) {
1416 to_channels = channelCountOfTarget;
1417 }
1418
1419 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1420 if (from_channels == to_channels) {
1421 memcpy(target, src, size);
1422 return size;
1423 }
1424 // setup channels
1425 if (from_channels > to_channels) {
1426 reducer.setSourceChannels(from_channels);
1427 reducer.setTargetChannels(to_channels);
1428 } else {
1429 enhancer.setSourceChannels(from_channels);
1430 enhancer.setTargetChannels(to_channels);
1431 }
1432
1433 // execute conversion
1434 if (from_channels > to_channels) {
1435 return reducer.convert(target, src, size);
1436 } else {
1437 return enhancer.convert(target, src, size);
1438 }
1439 }
1440
1441 protected:
1442 ChannelEnhancer<T> enhancer;
1443 ChannelReducerT<T> reducer;
1444 int from_channels;
1445 int to_channels;
1446};
1447
1453template <typename T = int16_t>
1455 public:
1456 MultiConverter() {}
1457
1458 MultiConverter(BaseConverter &c1) { add(c1); }
1459
1461 add(c1);
1462 add(c2);
1463 }
1464
1466 add(c1);
1467 add(c2);
1468 add(c3);
1469 }
1470
1471 // adds a converter
1472 void add(BaseConverter &converter) { converters.push_back(&converter); }
1473
1474 // The data is provided as int24_t tgt[][2] but returned as int24_t
1475 size_t convert(uint8_t *src, size_t size) {
1476 for (int i = 0; i < converters.size(); i++) {
1477 converters[i]->convert(src, size);
1478 }
1479 return size;
1480 }
1481
1482 private:
1483 Vector<BaseConverter *> converters;
1484};
1485
1491 public:
1492 NumberReader(Stream &in) { stream_ptr = &in; }
1493
1494 NumberReader() {}
1495
1496 bool read(int inBits, int outBits, bool outSigned, int n, int32_t *result) {
1497 bool result_bool = false;
1498 int len = inBits / 8 * n;
1499 if (stream_ptr != nullptr && stream_ptr->available() > len) {
1500 uint8_t buffer[len];
1501 stream_ptr->readBytes((uint8_t *)buffer, n * len);
1502 result_bool =
1503 toNumbers((void *)buffer, inBits, outBits, outSigned, n, result);
1504 }
1505 return result_bool;
1506 }
1507
1509 bool toNumbers(void *bufferIn, int inBits, int outBits, bool outSigned, int n,
1510 int32_t *result) {
1511 bool result_bool = false;
1512 switch (inBits) {
1513 case 8: {
1514 int8_t *buffer = (int8_t *)bufferIn;
1515 for (int j = 0; j < n; j++) {
1516 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1517 }
1518 result_bool = true;
1519 } break;
1520 case 16: {
1521 int16_t *buffer = (int16_t *)bufferIn;
1522 for (int j = 0; j < n; j++) {
1523 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1524 }
1525 result_bool = true;
1526 } break;
1527 case 32: {
1528 int32_t *buffer = (int32_t *)bufferIn;
1529 for (int j = 0; j < n; j++) {
1530 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1531 }
1532 result_bool = true;
1533 } break;
1534 }
1535 return result_bool;
1536 }
1537
1538 protected:
1539 Stream *stream_ptr = nullptr;
1540
1542 int32_t scale(int32_t value, int inBits, int outBits, bool outSigned = true) {
1543 int32_t result = static_cast<float>(value) /
1546 if (!outSigned) {
1547 result += (NumberConverter::maxValue(outBits) / 2);
1548 }
1549 return result;
1550 }
1551};
1552
1559template <typename T = int16_t>
1561 public:
1562 Converter1Channel(Filter<T> &filter) { this->p_filter = &filter; }
1563
1564 size_t convert(uint8_t *src, size_t size) override {
1565 T *data = (T *)src;
1566 for (size_t j = 0; j < size; j++) {
1567 data[j] = p_filter->process(data[j]);
1568 }
1569 return size;
1570 }
1571
1572 protected:
1573 Filter<T> *p_filter = nullptr;
1574};
1575
1582template <typename T, typename FT>
1584 public:
1586 ConverterNChannels(int channels) {
1587 this->channels = channels;
1588 filters = new Filter<FT> *[channels];
1589 // make sure that we have 1 filter per channel
1590 for (int j = 0; j < channels; j++) {
1591 filters[j] = nullptr;
1592 }
1593 }
1594
1597 for (int j = 0; j < channels; j++) {
1598 if (filters[j] != nullptr) {
1599 delete filters[j];
1600 }
1601 }
1602 delete[] filters;
1603 filters = 0;
1604 }
1605
1607 void setFilter(int channel, Filter<FT> *filter) {
1608 if (channel < channels) {
1609 if (filters[channel] != nullptr) {
1610 delete filters[channel];
1611 }
1612 filters[channel] = filter;
1613 } else {
1614 LOGE("Invalid channel nummber %d - max channel is %d", channel,
1615 channels - 1);
1616 }
1617 }
1618
1619 // convert all samples for each channel separately
1620 size_t convert(uint8_t *src, size_t size) {
1621 int count = size / channels / sizeof(T);
1622 T *sample = (T *)src;
1623 for (size_t j = 0; j < count; j++) {
1624 for (int channel = 0; channel < channels; channel++) {
1625 if (filters[channel] != nullptr) {
1626 *sample = filters[channel]->process(*sample);
1627 }
1628 sample++;
1629 }
1630 }
1631 return size;
1632 }
1633
1634 int getChannels() { return channels; }
1635
1636 protected:
1637 Filter<FT> **filters = nullptr;
1638 int channels;
1639};
1640
1650template <typename T = int16_t>
1652 public:
1653 SilenceRemovalConverter(int n = 8, int aplidudeLimit = 2) {
1654 set(n, aplidudeLimit);
1655 }
1656
1657 virtual size_t convert(uint8_t *data, size_t size) override {
1658 if (!active) {
1659 // no change to the data
1660 return size;
1661 }
1662 size_t sample_count = size / sizeof(T);
1663 size_t write_count = 0;
1664 T *audio = (T *)data;
1665
1666 // find relevant data
1667 T *p_buffer = (T *)data;
1668 for (int j = 0; j < sample_count; j++) {
1669 int pos = findLastAudioPos(audio, j);
1670 if (pos < n) {
1671 write_count++;
1672 *p_buffer++ = audio[j];
1673 }
1674 }
1675
1676 // write audio data w/o silence
1677 size_t write_size = write_count * sizeof(T);
1678 LOGI("filtered silence from %d -> %d", (int)size, (int)write_size);
1679
1680 // number of empty samples of prior buffer
1681 priorLastAudioPos = findLastAudioPos(audio, sample_count - 1);
1682
1683 // return new data size
1684 return write_size;
1685 }
1686
1687 protected:
1688 bool active = false;
1689 const uint8_t *buffer = nullptr;
1690 int n;
1691 int priorLastAudioPos = 0;
1692 int amplidude_limit = 0;
1693
1694 void set(int n = 5, int aplidudeLimit = 2) {
1695 LOGI("begin(n=%d, aplidudeLimit=%d", n, aplidudeLimit);
1696 this->n = n;
1697 this->amplidude_limit = aplidudeLimit;
1698 this->priorLastAudioPos = n + 1; // ignore first values
1699 this->active = n > 0;
1700 }
1701
1702 // find last position which contains audible data
1703 int findLastAudioPos(T *audio, int pos) {
1704 for (int j = 0; j < n; j++) {
1705 // we are before the start of the current buffer
1706 if (pos - j <= 0) {
1707 return priorLastAudioPos;
1708 }
1709 // we are in the current buffer
1710 if (abs(audio[pos - j]) > amplidude_limit) {
1711 return j;
1712 }
1713 }
1714 return n + 1;
1715 }
1716};
1717
1725template <typename T = int16_t>
1727 public:
1728 PoppingSoundRemover(int channels, bool fromBeginning, bool fromEnd) {
1729 this->channels = channels;
1730 from_beginning = fromBeginning;
1731 from_end = fromEnd;
1732 }
1733 virtual size_t convert(uint8_t *src, size_t size) {
1734 for (int ch = 0; ch < channels; ch++) {
1735 if (from_beginning)
1736 clearUpTo1stTransition(channels, ch, (T *)src, size / sizeof(T));
1737 if (from_end)
1738 clearAfterLastTransition(channels, ch, (T *)src, size / sizeof(T));
1739 }
1740 return size;
1741 }
1742
1743 protected:
1744 bool from_beginning;
1745 bool from_end;
1746 int channels;
1747
1748 void clearUpTo1stTransition(int channels, int channel, T *values,
1749 int sampleCount) {
1750 T first = values[channel];
1751 for (int j = 0; j < sampleCount; j += channels) {
1752 T act = values[j];
1753 if ((first <= 0.0 && act >= 0.0) || (first >= 0.0 && act <= 0.0)) {
1754 // we found the last transition so we are done
1755 break;
1756 } else {
1757 values[j] = 0;
1758 }
1759 }
1760 }
1761
1762 void clearAfterLastTransition(int channels, int channel, T *values,
1763 int sampleCount) {
1764 int lastPos = sampleCount - channels + channel;
1765 T last = values[lastPos];
1766 for (int j = lastPos; j >= 0; j -= channels) {
1767 T act = values[j];
1768 if ((last <= 0.0 && act >= 0.0) || (last >= 0.0 && act <= 0.0)) {
1769 // we found the last transition so we are done
1770 break;
1771 } else {
1772 values[j] = 0;
1773 }
1774 }
1775 }
1776};
1777
1784template <typename T = int16_t>
1786 public:
1787 SmoothTransition(int channels, bool fromBeginning, bool fromEnd,
1788 float inc = 0.01) {
1789 this->channels = channels;
1790 this->inc = inc;
1791 from_beginning = fromBeginning;
1792 from_end = fromEnd;
1793 }
1794 virtual size_t convert(uint8_t *src, size_t size) {
1795 for (int ch = 0; ch < channels; ch++) {
1796 if (from_beginning)
1797 processStart(channels, ch, (T *)src, size / sizeof(T));
1798 if (from_end) processEnd(channels, ch, (T *)src, size / sizeof(T));
1799 }
1800 return size;
1801 }
1802
1803 protected:
1804 bool from_beginning;
1805 bool from_end;
1806 int channels;
1807 float inc = 0.01;
1808 float factor = 0;
1809
1810 void processStart(int channels, int channel, T *values, int sampleCount) {
1811 for (int j = 0; j < sampleCount; j += channels) {
1812 if (factor >= 0.8) {
1813 break;
1814 } else {
1815 values[j] = factor * values[j];
1816 }
1817 factor += inc;
1818 }
1819 }
1820
1821 void processEnd(int channels, int channel, T *values, int sampleCount) {
1822 int lastPos = sampleCount - channels + channel;
1823 for (int j = lastPos; j >= 0; j -= channels) {
1824 if (factor >= 0.8) {
1825 break;
1826 } else {
1827 values[j] = factor * values[j];
1828 }
1829 }
1830 }
1831};
1832
1839template <typename T, size_t Cn, size_t Cx, size_t S>
1841 public:
1842 CopyChannels() : _max_val(0), _counter(0), _prev_ms(0) {}
1843
1844 size_t convert(uint8_t *src, size_t size) {
1845 T *chan = (T *)src;
1846 size_t samples = (size / Cn) / sizeof(T);
1847 for (size_t s = 0; s < samples; s++) {
1848 chan[s * Cn + Cx] = (Cx < Cn) ? chan[s * Cn + Cx] << S : 0;
1849
1850 for (size_t c = 0; c < Cn; c++) {
1851 if (c != Cx) {
1852 chan[s * Cn + c] = chan[s * Cn + Cx];
1853 }
1854 }
1855
1856 if (_max_val < chan[s * Cn]) {
1857 _max_val = chan[s * Cn];
1858 }
1859
1860 _counter++;
1861 uint32_t now = millis();
1862 if (now - _prev_ms > 1000) {
1863 _prev_ms = now;
1864 LOGI("CopyChannels samples: %u, amplitude: %d", _counter, _max_val);
1865 _max_val = 0;
1866 }
1867 }
1868 return samples * Cn * sizeof(T);
1869 }
1870
1871 private:
1872 T _max_val;
1873 uint32_t _counter;
1874 uint32_t _prev_ms;
1875};
1876
1882template <typename T = int16_t>
1884 public:
1885 CallbackConverterT(T (*callback)(T in, int channel), int channels = 2) {
1886 this->callback = callback;
1887 this->channels = channels;
1888 }
1889
1890 size_t convert(uint8_t *src, size_t size) {
1891 int samples = size / sizeof(T);
1892 T *srcT = (T *)src;
1893 for (int j = 0; j < samples; j++) {
1894 srcT[j] = callback(srcT[j], j % channels);
1895 }
1896 return size;
1897 }
1898
1899 protected:
1900 T (*callback)(T in, int channel);
1901 int channels;
1902};
1903
1904} // 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:1883
We average pairs of channels in a datastream. E.g. if we have 4 channels we end up with 2 channels....
Definition BaseConverter.h:1038
We average pairs of channels in a datastream. E.g. if we have 4 channels we end up with 2 channels....
Definition BaseConverter.h:990
Provides combination of binning and subtracting channels.
Definition BaseConverter.h:1284
We first bin the channels then we calculate the difference between pairs of channels in a datastream....
Definition BaseConverter.h:1103
Increasing or decreasing the number of channels.
Definition BaseConverter.h:1402
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:1346
size_t resultSize(size_t inSize)
Determine the size of the conversion result.
Definition BaseConverter.h:1387
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:950
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:1560
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:1583
~ConverterNChannels()
Destructor.
Definition BaseConverter.h:1596
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition BaseConverter.h:1607
ConverterNChannels(int channels)
Default Constructor.
Definition BaseConverter.h:1586
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:1840
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:1454
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:1490
int32_t scale(int32_t value, int inBits, int outBits, bool outSigned=true)
scale the value
Definition BaseConverter.h:1542
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:1509
Big value gaps (at the beginning and the end of a recording) can lead to some popping sounds....
Definition BaseConverter.h:1726
Removes any silence from the buffer that is longer then n samples with a amplitude below the indicate...
Definition BaseConverter.h:1651
Changes the samples at the beginning or at the end to slowly ramp up the volume.
Definition BaseConverter.h:1785
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