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>
998 public:
999 ChannelMixer(int channels = 2) { this->channels = channels; }
1000 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1001 T *srcT = (T *)src;
1002 T *targetT = (T *)target;
1003 int samples = size / sizeof(T);
1004 assert(samples % channels == 0);
1005 for (int j = 0; j < samples; j += channels) {
1006 float sum = 0;
1007 for (int ch = 0; ch < channels; ch++) {
1008 sum += srcT[j + ch];
1009 }
1010 T avg = sum / channels;
1011 for (int ch = 0; ch < channels; ch++) {
1012 targetT[j + ch] = avg;
1013 }
1014 }
1015 return size;
1016 }
1017
1018 protected:
1019 int channels = 2;
1020};
1021
1036 public:
1037 ChannelAvg() = default;
1038 ChannelAvg(int bitsPerSample) { setBits(bitsPerSample); }
1039 void setBits(int bits) { this->bits = bits; }
1040
1041 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1042 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1043 switch (bits) {
1044 case 8: {
1046 return ca8.convert(target, src, size);
1047 }
1048 case 16: {
1050 return ca16.convert(target, src, size);
1051 }
1052 case 24: {
1054 return ca24.convert(target, src, size);
1055 }
1056 case 32: {
1058 return ca32.convert(target, src, size);
1059 }
1060 default: {
1061 LOGE("Number of bits %d not supported.", bits);
1062 return 0;
1063 }
1064 }
1065 }
1066
1067 protected:
1068 int bits = 16;
1069};
1070
1084template <typename T = int16_t>
1086 public:
1087 ChannelBinDiffT() = default;
1088 ChannelBinDiffT(int binSize, int channels, bool average) {
1089 setChannels(channels);
1090 setBinSize(binSize);
1091 setAverage(average);
1092 this->partialBinSize = 0;
1093 // this->partialBin = new T[channels];
1094 // std::fill(this->partialBin, this->partialBin + channels, 0); //
1095 // Initialize partialBin with zeros
1096 this->partialBin = new T[channels]();
1097 }
1098
1099 ~ChannelBinDiffT() { delete[] this->partialBin; }
1100
1101 void setChannels(int channels) {
1102 if ((channels % 2) > 0) {
1103 LOGE("Number of channels needs to be even");
1104 this->channels = channels + 1;
1105 }
1106 this->channels = channels;
1107 }
1108 void setBinSize(int binSize) { this->binSize = binSize; }
1109 void setAverage(bool average) { this->average = average; }
1110
1111 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1112
1113 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1114 // The binning works the same as in the BinT class
1115 // Here we add subtraction before we store the bins
1116
1117 if (size % (sizeof(T) * channels) > 0) {
1118 LOGE("Buffer size needs to be multiple of channels")
1119 return 0;
1120 }
1121
1122 int sample_count =
1123 size / (sizeof(T) * channels); // new available samples in each channel
1124 int total_samples =
1125 partialBinSize +
1126 sample_count; // total samples available for each channel including
1127 // previous number of sample in partial bin
1128 int bin_count = total_samples / binSize; // number of bins we can make
1129 int remaining_samples =
1130 total_samples % binSize; // remaining samples after binning
1131 T *p_target = (T *)target;
1132 T *p_source = (T *)src;
1133 size_t result_size = 0;
1134
1135 // Allocate sum for each channel with appropriate type
1136 typename AppropriateSumType<T>::type sums[channels];
1137 int current_sample = 0; // current sample index
1138
1139 // Is there a partial bin from the previous call?
1140 // ----
1141 if (partialBinSize > 0) {
1142 // LOGD("Deal with partial bins");
1143
1144 int samples_needed = binSize - partialBinSize;
1145 bool have_enough_samples = (samples_needed < sample_count);
1146 int samples_to_bin = have_enough_samples ? samples_needed : sample_count;
1147
1148 // initialize
1149 for (int ch = 0; ch < channels; ch++) {
1150 sums[ch] = partialBin[ch];
1151 }
1152
1153 // continue binning
1154 for (int j = 0; j < samples_to_bin; j++) {
1155 for (int ch = 0; ch < channels; ch++) {
1156 sums[ch] += p_source[current_sample * channels + ch];
1157 }
1158 current_sample++;
1159 }
1160
1161 // store the bin results or update the partial bin
1162 if (have_enough_samples) {
1163 // Subtract two channels and store the completed bin
1164 if (average) {
1165 for (int ch = 0; ch < channels; ch += 2) {
1166 p_target[result_size / sizeof(T)] =
1167 static_cast<T>((sums[ch] - sums[ch + 1]) / binSize);
1168 result_size += sizeof(T);
1169 }
1170 } else {
1171 for (int ch = 0; ch < channels; ch += 2) {
1172 p_target[result_size / sizeof(T)] =
1173 static_cast<T>((sums[ch] - sums[ch + 1]));
1174 result_size += sizeof(T);
1175 }
1176 }
1177 partialBinSize = 0;
1178 // LOGD("Partial bins are empty");
1179
1180 } else {
1181 // Not enough samples to complete the bin, update partialBin
1182 for (int ch = 0; ch < channels; ch++) {
1183 partialBin[ch] = sums[ch];
1184 }
1185 partialBinSize += current_sample;
1186 LOGD(
1187 "bin & channel subtract %d: %d of %d remaining %d samples, %d "
1188 "> %d "
1189 "bytes",
1190 binSize, current_sample, total_samples, partialBinSize, (int)size,
1191 (int)result_size);
1192 // LOGD("Partial bins were updated");
1193 return result_size;
1194 }
1195 }
1196
1197 // Fill bins
1198 // ----
1199 // LOGD("Fillin bins");
1200 for (int i = 0; i < bin_count; i++) {
1201 // LOGD("Current sample %d", current_sample);
1202
1203 for (int ch = 0; ch < channels; ch++) {
1204 sums[ch] = p_source[current_sample * channels +
1205 ch]; // Initialize sums with first value in the
1206 // input buffer
1207 }
1208
1209 for (int j = 1; j < binSize; j++) {
1210 for (int ch = 0; ch < channels; ch++) {
1211 sums[ch] += p_source[(current_sample + j) * channels + ch];
1212 }
1213 }
1214 current_sample += binSize;
1215
1216 // Finish binning, then subtact two channel and store the result
1217 if (average) {
1218 for (int ch = 0; ch < channels; ch += 2) {
1219 p_target[result_size / sizeof(T)] =
1220 static_cast<T>((sums[ch] - sums[ch + 1]) / binSize);
1221 result_size += sizeof(T);
1222 }
1223 } else {
1224 for (int ch = 0; ch < channels; ch += 2) {
1225 p_target[result_size / sizeof(T)] =
1226 static_cast<T>((sums[ch] - sums[ch + 1]));
1227 result_size += sizeof(T);
1228 }
1229 }
1230 }
1231
1232 // Store the remaining samples in the partial bin
1233 // ----
1234 // LOGD("Updating partial bins");
1235 for (int i = 0; i < remaining_samples; i++) {
1236 for (int ch = 0; ch < channels; ch++) {
1237 partialBin[ch] += p_source[(current_sample + i) * channels + ch];
1238 }
1239 }
1240 partialBinSize = remaining_samples;
1241
1242 LOGD(
1243 "bin & channel subtract %d: %d of %d remaining %d samples, %d > %d "
1244 "bytes",
1245 binSize, current_sample, total_samples, partialBinSize, (int)size,
1246 (int)result_size);
1247
1248 return result_size;
1249 }
1250
1251 protected:
1252 int channels = 2;
1253 int binSize = 4;
1254 bool average = true;
1255 T *partialBin;
1256 int partialBinSize;
1257};
1258
1267 public:
1268 ChannelBinDiff() = default;
1269 ChannelBinDiff(int binSize, int channels, bool average, int bits_per_sample) {
1270 setChannels(channels);
1271 setBinSize(binSize);
1272 setAverage(average);
1273 setBits(bits_per_sample);
1274 }
1275
1276 void setChannels(int channels) {
1277 if ((channels % 2) == 0) {
1278 this->channels = channels;
1279 } else {
1280 LOGE("Number of channels needs to be even");
1281 this->channels = channels + 1;
1282 }
1283 }
1284
1285 void setBits(int bits) { this->bits = bits; }
1286 void setBinSize(int binSize) { this->binSize = binSize; }
1287 void setAverage(bool average) { this->average = average; }
1288
1289 size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
1290 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1291 switch (bits) {
1292 case 8: {
1293 ChannelBinDiffT<int8_t> bd8(binSize, channels, average);
1294 return bd8.convert(target, src, size);
1295 }
1296 case 16: {
1297 ChannelBinDiffT<int16_t> bd16(binSize, channels, average);
1298 return bd16.convert(target, src, size);
1299 }
1300 case 24: {
1301 ChannelBinDiffT<int24_t> bd24(binSize, channels, average);
1302 return bd24.convert(target, src, size);
1303 }
1304 case 32: {
1305 ChannelBinDiffT<int32_t> bd32(binSize, channels, average);
1306 return bd32.convert(target, src, size);
1307 }
1308 default: {
1309 LOGE("Number of bits %d not supported.", bits);
1310 return 0;
1311 }
1312 }
1313 }
1314
1315 protected:
1316 int channels = 2;
1317 int bits = 16;
1318 int binSize = 4;
1319 bool average = true;
1320};
1321
1327template <typename T = int16_t>
1329 public:
1330 ChannelEnhancer() = default;
1331
1332 ChannelEnhancer(int channelCountOfTarget, int channelCountOfSource) {
1333 from_channels = channelCountOfSource;
1334 to_channels = channelCountOfTarget;
1335 }
1336
1337 void setSourceChannels(int channelCountOfSource) {
1338 from_channels = channelCountOfSource;
1339 }
1340
1341 void setTargetChannels(int channelCountOfTarget) {
1342 to_channels = channelCountOfTarget;
1343 }
1344
1345 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1346 if (from_channels == 0) return size;
1347 int frame_count = size / (sizeof(T) * from_channels);
1348 size_t result_size = 0;
1349 T *result = (T *)target;
1350 T *source = (T *)src;
1351 T value = (int16_t)0;
1352 for (int i = 0; i < frame_count; i++) {
1353 // copy available channels
1354 for (int j = 0; j < from_channels; j++) {
1355 value = *source++;
1356 *result++ = value;
1357 result_size += sizeof(T);
1358 }
1359 // repeat last value
1360 for (int j = from_channels; j < to_channels; j++) {
1361 *result++ = value;
1362 result_size += sizeof(T);
1363 }
1364 }
1365 return result_size;
1366 }
1367
1369 size_t resultSize(size_t inSize) {
1370 return inSize * to_channels / from_channels;
1371 }
1372
1373 protected:
1374 int from_channels = 0;
1375 int to_channels = 0;
1376};
1377
1383template <typename T = int16_t>
1385 public:
1386 ChannelConverter() = default;
1387
1388 ChannelConverter(int channelCountOfTarget, int channelCountOfSource) {
1389 from_channels = channelCountOfSource;
1390 to_channels = channelCountOfTarget;
1391 }
1392
1393 void setSourceChannels(int channelCountOfSource) {
1394 from_channels = channelCountOfSource;
1395 }
1396
1397 void setTargetChannels(int channelCountOfTarget) {
1398 to_channels = channelCountOfTarget;
1399 }
1400
1401 size_t convert(uint8_t *target, uint8_t *src, size_t size) {
1402 if (from_channels == to_channels) {
1403 memcpy(target, src, size);
1404 return size;
1405 }
1406 // setup channels
1407 if (from_channels > to_channels) {
1408 reducer.setSourceChannels(from_channels);
1409 reducer.setTargetChannels(to_channels);
1410 } else {
1411 enhancer.setSourceChannels(from_channels);
1412 enhancer.setTargetChannels(to_channels);
1413 }
1414
1415 // execute conversion
1416 if (from_channels > to_channels) {
1417 return reducer.convert(target, src, size);
1418 } else {
1419 return enhancer.convert(target, src, size);
1420 }
1421 }
1422
1423 protected:
1424 ChannelEnhancer<T> enhancer;
1425 ChannelReducerT<T> reducer;
1426 int from_channels;
1427 int to_channels;
1428};
1429
1435template <typename T = int16_t>
1437 public:
1438 MultiConverter() {}
1439
1440 MultiConverter(BaseConverter &c1) { add(c1); }
1441
1443 add(c1);
1444 add(c2);
1445 }
1446
1448 add(c1);
1449 add(c2);
1450 add(c3);
1451 }
1452
1453 // adds a converter
1454 void add(BaseConverter &converter) { converters.push_back(&converter); }
1455
1456 // The data is provided as int24_t tgt[][2] but returned as int24_t
1457 size_t convert(uint8_t *src, size_t size) {
1458 for (int i = 0; i < converters.size(); i++) {
1459 converters[i]->convert(src, size);
1460 }
1461 return size;
1462 }
1463
1464 private:
1465 Vector<BaseConverter *> converters;
1466};
1467
1473 public:
1474 NumberReader(Stream &in) { stream_ptr = &in; }
1475
1476 NumberReader() {}
1477
1478 bool read(int inBits, int outBits, bool outSigned, int n, int32_t *result) {
1479 bool result_bool = false;
1480 int len = inBits / 8 * n;
1481 if (stream_ptr != nullptr && stream_ptr->available() > len) {
1482 uint8_t buffer[len];
1483 stream_ptr->readBytes((uint8_t *)buffer, n * len);
1484 result_bool =
1485 toNumbers((void *)buffer, inBits, outBits, outSigned, n, result);
1486 }
1487 return result_bool;
1488 }
1489
1491 bool toNumbers(void *bufferIn, int inBits, int outBits, bool outSigned, int n,
1492 int32_t *result) {
1493 bool result_bool = false;
1494 switch (inBits) {
1495 case 8: {
1496 int8_t *buffer = (int8_t *)bufferIn;
1497 for (int j = 0; j < n; j++) {
1498 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1499 }
1500 result_bool = true;
1501 } break;
1502 case 16: {
1503 int16_t *buffer = (int16_t *)bufferIn;
1504 for (int j = 0; j < n; j++) {
1505 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1506 }
1507 result_bool = true;
1508 } break;
1509 case 32: {
1510 int32_t *buffer = (int32_t *)bufferIn;
1511 for (int j = 0; j < n; j++) {
1512 result[j] = scale(buffer[j], inBits, outBits, outSigned);
1513 }
1514 result_bool = true;
1515 } break;
1516 }
1517 return result_bool;
1518 }
1519
1520 protected:
1521 Stream *stream_ptr = nullptr;
1522
1524 int32_t scale(int32_t value, int inBits, int outBits, bool outSigned = true) {
1525 int32_t result = static_cast<float>(value) /
1528 if (!outSigned) {
1529 result += (NumberConverter::maxValue(outBits) / 2);
1530 }
1531 return result;
1532 }
1533};
1534
1541template <typename T = int16_t>
1543 public:
1544 Converter1Channel(Filter<T> &filter) { this->p_filter = &filter; }
1545
1546 size_t convert(uint8_t *src, size_t size) override {
1547 T *data = (T *)src;
1548 for (size_t j = 0; j < size; j++) {
1549 data[j] = p_filter->process(data[j]);
1550 }
1551 return size;
1552 }
1553
1554 protected:
1555 Filter<T> *p_filter = nullptr;
1556};
1557
1564template <typename T, typename FT>
1566 public:
1568 ConverterNChannels(int channels) {
1569 this->channels = channels;
1570 filters = new Filter<FT> *[channels];
1571 // make sure that we have 1 filter per channel
1572 for (int j = 0; j < channels; j++) {
1573 filters[j] = nullptr;
1574 }
1575 }
1576
1579 for (int j = 0; j < channels; j++) {
1580 if (filters[j] != nullptr) {
1581 delete filters[j];
1582 }
1583 }
1584 delete[] filters;
1585 filters = 0;
1586 }
1587
1589 void setFilter(int channel, Filter<FT> *filter) {
1590 if (channel < channels) {
1591 if (filters[channel] != nullptr) {
1592 delete filters[channel];
1593 }
1594 filters[channel] = filter;
1595 } else {
1596 LOGE("Invalid channel nummber %d - max channel is %d", channel,
1597 channels - 1);
1598 }
1599 }
1600
1601 // convert all samples for each channel separately
1602 size_t convert(uint8_t *src, size_t size) {
1603 int count = size / channels / sizeof(T);
1604 T *sample = (T *)src;
1605 for (size_t j = 0; j < count; j++) {
1606 for (int channel = 0; channel < channels; channel++) {
1607 if (filters[channel] != nullptr) {
1608 *sample = filters[channel]->process(*sample);
1609 }
1610 sample++;
1611 }
1612 }
1613 return size;
1614 }
1615
1616 int getChannels() { return channels; }
1617
1618 protected:
1619 Filter<FT> **filters = nullptr;
1620 int channels;
1621};
1622
1632template <typename T = int16_t>
1634 public:
1635 SilenceRemovalConverter(int n = 8, int aplidudeLimit = 2) {
1636 set(n, aplidudeLimit);
1637 }
1638
1639 virtual size_t convert(uint8_t *data, size_t size) override {
1640 if (!active) {
1641 // no change to the data
1642 return size;
1643 }
1644 size_t sample_count = size / sizeof(T);
1645 size_t write_count = 0;
1646 T *audio = (T *)data;
1647
1648 // find relevant data
1649 T *p_buffer = (T *)data;
1650 for (int j = 0; j < sample_count; j++) {
1651 int pos = findLastAudioPos(audio, j);
1652 if (pos < n) {
1653 write_count++;
1654 *p_buffer++ = audio[j];
1655 }
1656 }
1657
1658 // write audio data w/o silence
1659 size_t write_size = write_count * sizeof(T);
1660 LOGI("filtered silence from %d -> %d", (int)size, (int)write_size);
1661
1662 // number of empty samples of prior buffer
1663 priorLastAudioPos = findLastAudioPos(audio, sample_count - 1);
1664
1665 // return new data size
1666 return write_size;
1667 }
1668
1669 protected:
1670 bool active = false;
1671 const uint8_t *buffer = nullptr;
1672 int n;
1673 int priorLastAudioPos = 0;
1674 int amplidude_limit = 0;
1675
1676 void set(int n = 5, int aplidudeLimit = 2) {
1677 LOGI("begin(n=%d, aplidudeLimit=%d", n, aplidudeLimit);
1678 this->n = n;
1679 this->amplidude_limit = aplidudeLimit;
1680 this->priorLastAudioPos = n + 1; // ignore first values
1681 this->active = n > 0;
1682 }
1683
1684 // find last position which contains audible data
1685 int findLastAudioPos(T *audio, int pos) {
1686 for (int j = 0; j < n; j++) {
1687 // we are before the start of the current buffer
1688 if (pos - j <= 0) {
1689 return priorLastAudioPos;
1690 }
1691 // we are in the current buffer
1692 if (abs(audio[pos - j]) > amplidude_limit) {
1693 return j;
1694 }
1695 }
1696 return n + 1;
1697 }
1698};
1699
1707template <typename T = int16_t>
1709 public:
1710 PoppingSoundRemover(int channels, bool fromBeginning, bool fromEnd) {
1711 this->channels = channels;
1712 from_beginning = fromBeginning;
1713 from_end = fromEnd;
1714 }
1715 virtual size_t convert(uint8_t *src, size_t size) {
1716 for (int ch = 0; ch < channels; ch++) {
1717 if (from_beginning)
1718 clearUpTo1stTransition(channels, ch, (T *)src, size / sizeof(T));
1719 if (from_end)
1720 clearAfterLastTransition(channels, ch, (T *)src, size / sizeof(T));
1721 }
1722 return size;
1723 }
1724
1725 protected:
1726 bool from_beginning;
1727 bool from_end;
1728 int channels;
1729
1730 void clearUpTo1stTransition(int channels, int channel, T *values,
1731 int sampleCount) {
1732 T first = values[channel];
1733 for (int j = 0; j < sampleCount; j += channels) {
1734 T act = values[j];
1735 if ((first <= 0.0 && act >= 0.0) || (first >= 0.0 && act <= 0.0)) {
1736 // we found the last transition so we are done
1737 break;
1738 } else {
1739 values[j] = 0;
1740 }
1741 }
1742 }
1743
1744 void clearAfterLastTransition(int channels, int channel, T *values,
1745 int sampleCount) {
1746 int lastPos = sampleCount - channels + channel;
1747 T last = values[lastPos];
1748 for (int j = lastPos; j >= 0; j -= channels) {
1749 T act = values[j];
1750 if ((last <= 0.0 && act >= 0.0) || (last >= 0.0 && act <= 0.0)) {
1751 // we found the last transition so we are done
1752 break;
1753 } else {
1754 values[j] = 0;
1755 }
1756 }
1757 }
1758};
1759
1766template <typename T = int16_t>
1768 public:
1769 SmoothTransition(int channels, bool fromBeginning, bool fromEnd,
1770 float inc = 0.01) {
1771 this->channels = channels;
1772 this->inc = inc;
1773 from_beginning = fromBeginning;
1774 from_end = fromEnd;
1775 }
1776 virtual size_t convert(uint8_t *src, size_t size) {
1777 for (int ch = 0; ch < channels; ch++) {
1778 if (from_beginning)
1779 processStart(channels, ch, (T *)src, size / sizeof(T));
1780 if (from_end) processEnd(channels, ch, (T *)src, size / sizeof(T));
1781 }
1782 return size;
1783 }
1784
1785 protected:
1786 bool from_beginning;
1787 bool from_end;
1788 int channels;
1789 float inc = 0.01;
1790 float factor = 0;
1791
1792 void processStart(int channels, int channel, T *values, int sampleCount) {
1793 for (int j = 0; j < sampleCount; j += channels) {
1794 if (factor >= 0.8) {
1795 break;
1796 } else {
1797 values[j] = factor * values[j];
1798 }
1799 factor += inc;
1800 }
1801 }
1802
1803 void processEnd(int channels, int channel, T *values, int sampleCount) {
1804 int lastPos = sampleCount - channels + channel;
1805 for (int j = lastPos; j >= 0; j -= channels) {
1806 if (factor >= 0.8) {
1807 break;
1808 } else {
1809 values[j] = factor * values[j];
1810 }
1811 }
1812 }
1813};
1814
1821template <typename T, size_t Cn, size_t Cx, size_t S>
1823 public:
1824 CopyChannels() : _max_val(0), _counter(0), _prev_ms(0) {}
1825
1826 size_t convert(uint8_t *src, size_t size) {
1827 T *chan = (T *)src;
1828 size_t samples = (size / Cn) / sizeof(T);
1829 for (size_t s = 0; s < samples; s++) {
1830 chan[s * Cn + Cx] = (Cx < Cn) ? chan[s * Cn + Cx] << S : 0;
1831
1832 for (size_t c = 0; c < Cn; c++) {
1833 if (c != Cx) {
1834 chan[s * Cn + c] = chan[s * Cn + Cx];
1835 }
1836 }
1837
1838 if (_max_val < chan[s * Cn]) {
1839 _max_val = chan[s * Cn];
1840 }
1841
1842 _counter++;
1843 uint32_t now = millis();
1844 if (now - _prev_ms > 1000) {
1845 _prev_ms = now;
1846 LOGI("CopyChannels samples: %u, amplitude: %d", _counter, _max_val);
1847 _max_val = 0;
1848 }
1849 }
1850 return samples * Cn * sizeof(T);
1851 }
1852
1853 private:
1854 T _max_val;
1855 uint32_t _counter;
1856 uint32_t _prev_ms;
1857};
1858
1864template <typename T = int16_t>
1866 public:
1867 CallbackConverterT(T (*callback)(T in, int channel), int channels = 2) {
1868 this->callback = callback;
1869 this->channels = channels;
1870 }
1871
1872 size_t convert(uint8_t *src, size_t size) {
1873 int samples = size / sizeof(T);
1874 T *srcT = (T *)src;
1875 for (int j = 0; j < samples; j++) {
1876 srcT[j] = callback(srcT[j], j % channels);
1877 }
1878 return size;
1879 }
1880
1881 protected:
1882 T (*callback)(T in, int channel);
1883 int channels;
1884};
1885
1886} // 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:1865
We average pairs of channels in a datastream. E.g. if we have 4 channels we end up with 2 channels....
Definition BaseConverter.h:1035
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:1266
We first bin the channels then we calculate the difference between pairs of channels in a datastream....
Definition BaseConverter.h:1085
Increasing or decreasing the number of channels.
Definition BaseConverter.h:1384
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:1328
size_t resultSize(size_t inSize)
Determine the size of the conversion result.
Definition BaseConverter.h:1369
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:1542
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:1565
~ConverterNChannels()
Destructor.
Definition BaseConverter.h:1578
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition BaseConverter.h:1589
ConverterNChannels(int channels)
Default Constructor.
Definition BaseConverter.h:1568
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:1822
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:1436
Dummy converter which does nothing.
Definition BaseConverter.h:40
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:299
Reads n numbers from an Arduino Stream.
Definition BaseConverter.h:1472
int32_t scale(int32_t value, int inBits, int outBits, bool outSigned=true)
scale the value
Definition BaseConverter.h:1524
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:1491
Big value gaps (at the beginning and the end of a recording) can lead to some popping sounds....
Definition BaseConverter.h:1708
Removes any silence from the buffer that is longer then n samples with a amplitude below the indicate...
Definition BaseConverter.h:1633
Changes the samples at the beginning or at the end to slowly ramp up the volume.
Definition BaseConverter.h:1767
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:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59