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