arduino-audio-tools
BaseConverter.h
1 #pragma once
2 #include "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  virtual size_t convert(uint8_t(*src), size_t size) { 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(T 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) {
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) delete p_converter;
198  }
199 
200  void begin(int channels, int bitsPerSample, bool isDynamic = false) {
201  this->channels = channels;
202  this->bits_per_sample = bitsPerSample;
203  if (p_converter != nullptr) delete p_converter;
204  switch (bits_per_sample) {
205  case 16: {
206  p_converter = new ConverterAutoCenterT<int16_t>(channels, isDynamic);
207  break;
208  }
209  case 24: {
210  p_converter = new ConverterAutoCenterT<int24_t>(channels, isDynamic);
211  break;
212  }
213  case 32: {
214  p_converter = new ConverterAutoCenterT<int32_t>(channels, isDynamic);
215  break;
216  }
217  }
218  }
219 
220  size_t convert(uint8_t *src, size_t size) override {
221  if (p_converter == nullptr) return 0;
222  return p_converter->convert(src, size);
223  }
224 
225  protected:
226  int channels;
227  int bits_per_sample;
228  BaseConverter *p_converter = nullptr;
229 };
230 
239 template <typename T>
241  public:
242  ConverterSwitchLeftAndRight(int channels = 2) { this->channels = channels; }
243 
244  size_t convert(uint8_t *src, size_t byte_count) {
245  if (channels == 2) {
246  int size = byte_count / channels / sizeof(T);
247  T *sample = (T *)src;
248  for (size_t j = 0; j < size; j++) {
249  T temp = *sample;
250  *sample = *(sample + 1) * (sample + 1) = temp;
251  sample += 2;
252  }
253  }
254  return byte_count;
255  }
256 
257  protected:
258  int channels = 2;
259 };
260 
265 enum FillLeftAndRightStatus { Auto, LeftIsEmpty, RightIsEmpty };
266 
276 template <typename T>
278  public:
280  int channels = 2) {
281  this->channels = channels;
282  switch (config) {
283  case LeftIsEmpty:
284  left_empty = true;
285  right_empty = false;
286  is_setup = true;
287  break;
288  case RightIsEmpty:
289  left_empty = false;
290  right_empty = true;
291  is_setup = true;
292  break;
293  case Auto:
294  is_setup = false;
295  break;
296  }
297  }
298 
299  size_t convert(uint8_t *src, size_t byte_count) {
300  if (channels == 2) {
301  int size = byte_count / channels / sizeof(T);
302  setup((T *)src, size);
303  if (left_empty && !right_empty) {
304  T *sample = (T *)src;
305  for (size_t j = 0; j < size; j++) {
306  *sample = *(sample + 1);
307  sample += 2;
308  }
309  } else if (!left_empty && right_empty) {
310  T *sample = (T *)src;
311  for (size_t j = 0; j < size; j++) {
312  *(sample + 1) = *sample;
313  sample += 2;
314  }
315  }
316  }
317  return byte_count;
318  }
319 
320  private:
321  bool is_setup = false;
322  bool left_empty = true;
323  bool right_empty = true;
324  int channels;
325 
326  void setup(T *src, size_t size) {
327  if (!is_setup) {
328  for (int j = 0; j < size; j++) {
329  if (*src != 0) {
330  left_empty = false;
331  break;
332  }
333  src += 2;
334  }
335  for (int j = 0; j < size - 1; j++) {
336  if (*(src) != 0) {
337  right_empty = false;
338  break;
339  }
340  src += 2;
341  }
342  // stop setup as soon as we found some data
343  if (!right_empty || !left_empty) {
344  is_setup = true;
345  }
346  }
347  }
348 };
349 
359 template <typename T>
361  public:
362  ConverterToInternalDACFormat(int channels = 2) { this->channels = channels; }
363 
364  size_t convert(uint8_t *src, size_t byte_count) {
365  int size = byte_count / channels / sizeof(T);
366  T *sample = (T *)src;
367  for (int i = 0; i < size; i++) {
368  for (int j = 0; j < channels; j++) {
369  *sample = *sample + 0x8000;
370  sample++;
371  }
372  }
373  return byte_count;
374  }
375 
376  protected:
377  int channels;
378 };
379 
387 template <typename T>
389  public:
390  ChannelReducerT() = default;
391 
392  ChannelReducerT(int channelCountOfTarget, int channelCountOfSource) {
393  from_channels = channelCountOfSource;
394  to_channels = channelCountOfTarget;
395  }
396 
397  void setSourceChannels(int channelCountOfSource) {
398  from_channels = channelCountOfSource;
399  }
400 
401  void setTargetChannels(int channelCountOfTarget) {
402  to_channels = channelCountOfTarget;
403  }
404 
405  size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
406 
407  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
408  LOGD("convert %d -> %d", from_channels, to_channels);
409  assert(to_channels <= from_channels);
410  int frame_count = size / (sizeof(T) * from_channels);
411  size_t result_size = 0;
412  T *result = (T *)target;
413  T *source = (T *)src;
414  int reduceDiv = from_channels - to_channels + 1;
415 
416  for (int i = 0; i < frame_count; i++) {
417  // copy first to_channels-1
418  for (int j = 0; j < to_channels - 1; j++) {
419  *result++ = *source++;
420  result_size += sizeof(T);
421  }
422  // commbined last channels
423  T total = (int16_t)0;
424  for (int j = to_channels - 1; j < from_channels; j++) {
425  total += *source++ / reduceDiv;
426  }
427  *result++ = total;
428  result_size += sizeof(T);
429  }
430  return result_size;
431  }
432 
433  protected:
434  int from_channels;
435  int to_channels;
436 };
437 
445  public:
446  ChannelReducer(int channelCountOfTarget, int channelCountOfSource,
447  int bitsPerSample) {
448  from_channels = channelCountOfSource;
449  to_channels = channelCountOfTarget;
450  bits = bitsPerSample;
451  }
452 
453  size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
454 
455  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
456  switch (bits) {
457  case 16: {
458  ChannelReducerT<int16_t> cr16(to_channels, from_channels);
459  return cr16.convert(target, src, size);
460  }
461  case 24: {
462  ChannelReducerT<int24_t> cr24(to_channels, from_channels);
463  return cr24.convert(target, src, size);
464  }
465  case 32: {
466  ChannelReducerT<int32_t> cr32(to_channels, from_channels);
467  return cr32.convert(target, src, size);
468  }
469  }
470  return 0;
471  }
472 
473  protected:
474  int from_channels;
475  int to_channels;
476  int bits;
477 };
478 
483 template <typename T>
484 class DecimateT : public BaseConverter {
485  public:
486  DecimateT(int factor, int channels) {
487  setChannels(channels);
488  setFactor(factor);
489  }
491  void setChannels(int channels) { this->channels = channels; }
492 
494  void setFactor(int factor) { this->factor = factor; }
495 
496  size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
497 
498  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
499  int frame_count = size / (sizeof(T) * channels);
500  T *p_target = (T *)target;
501  T *p_source = (T *)src;
502  size_t result_size = 0;
503 
504  for (int i = 0; i < frame_count; i++) {
505  if (++count == factor) {
506  count = 0;
507  // only keep even samples
508  for (int ch = 0; ch < channels; ch++) {
509  *p_target++ = p_source[i + ch];
510  result_size += sizeof(T);
511  }
512  }
513  }
514  // LOGI("%d: %d -> %d ",factor, (int)size, (int)result_size);
515  return result_size;
516  }
517 
518  operator bool() { return factor > 1; };
519 
520  protected:
521  int channels = 2;
522  int factor = 1;
523  uint16_t count = 0;
524 };
525 
531 class Decimate : public BaseConverter {
532  public:
533  Decimate() = default;
534  Decimate(int factor, int channels, int bits_per_sample) {
535  setFactor(factor);
536  setChannels(channels);
537  setBits(bits_per_sample);
538  }
540  void setChannels(int channels) { this->channels = channels; }
541  void setBits(int bits) { this->bits = bits; }
543  void setFactor(int factor) { this->factor = factor; }
544 
545  size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
546  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
547  switch (bits) {
548  case 16: {
549  DecimateT<int16_t> dec16(factor, channels);
550  return dec16.convert(target, src, size);
551  }
552  case 24: {
553  DecimateT<int24_t> dec24(factor, channels);
554  return dec24.convert(target, src, size);
555  }
556  case 32: {
557  DecimateT<int32_t> dec32(factor, channels);
558  return dec32.convert(target, src, size);
559  }
560  }
561  return 0;
562  }
563 
564  operator bool() { return factor > 1; };
565 
566  protected:
567  int channels = 2;
568  int bits = 16;
569  int factor = 1;
570 };
571 
577 // Helper template to define the integer type for the summation based on input
578 // data type T
579 template <typename T>
581 template <>
582 struct AppropriateSumType<int8_t> {
583  using type = int16_t;
584 };
585 template <>
586 struct AppropriateSumType<int16_t> {
587  using type = int32_t;
588 };
589 template <>
591  using type = int32_t;
592 };
593 template <>
594 struct AppropriateSumType<int32_t> {
595  using type = int64_t;
596 };
597 
603 template <typename T>
604 class BinT : public BaseConverter {
605  public:
606  BinT(int binSize, int channels, bool average) {
607  setChannels(channels);
608  setBinSize(binSize);
609  setAverage(average);
610  }
612  void setChannels(int channels) { this->channels = channels; }
613 
615  void setBinSize(int binSize) { this->binSize = binSize; }
616 
618  void setAverage(bool average) { this->average = average; }
619 
620  size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
621 
622  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
623  int frame_count = size / (sizeof(T) * channels);
624  T *p_target = (T *)target;
625  T *p_source = (T *)src;
626  size_t result_size = 0;
627 
628  // Allocate stack memory for sums to avoid dynamic allocation overhead.
629  // Ensure you have enough stack space or adjust accordingly for your
630  // environment.
631  typename AppropriateSumType<T>::type sums[channels];
632 
633  for (int i = 0; i < frame_count; i += binSize) {
634  // Initialize sums for each channel to the first element in the bin
635  for (int ch = 0; ch < channels; ch++) {
636  sums[ch] = (i * channels + ch < frame_count * channels)
637  ? p_source[i * channels + ch]
638  : static_cast<T>(0);
639  }
640 
641  // Sum up binSize number of samples for each channel, starting from the
642  // second sample in the bin
643  for (int j = 1; j < binSize && (i + j) < frame_count; j++) {
644  for (int ch = 0; ch < channels; ch++) {
645  sums[ch] += p_source[(i + j) * channels + ch];
646  }
647  }
648 
649  // Compute average or sum for each channel and write to target buffer
650  for (int ch = 0; ch < channels; ch++) {
651  if (average) {
652  T avg = static_cast<T>(sums[ch] / binSize);
653  *p_target++ = avg;
654  } else {
655  *p_target++ = static_cast<T>(sums[ch]);
656  }
657  }
658  result_size += sizeof(T) * channels;
659  }
660 
661  // LOGI("%d: %d -> %d avg:%s", binSize, (int)size, (int)result_size, average
662  // ? "on" : "off");
663  return result_size;
664  }
665 
666  operator bool() { return binSize > 1; };
667 
668  protected:
669  int channels = 2;
670  int binSize = 1;
671  bool average = true;
672  uint16_t count = 0;
673 };
674 
680 class Bin : public BaseConverter {
681  public:
682  Bin() = default;
683  Bin(int binSize, int channels, bool average, int bits_per_sample) {
684  setBinSize(binSize);
685  setChannels(channels);
686  setAverage(average);
687  setBits(bits_per_sample);
688  }
690  void setChannels(int channels) { this->channels = channels; }
691  void setBits(int bits) { this->bits = bits; }
693  void setBinSize(int binSize) { this->binSize = binSize; }
695  void setAverage(bool average) { this->average = average; }
696 
697  size_t convert(uint8_t *src, size_t size) { return convert(src, src, size); }
698  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
699  switch (bits) {
700  case 8: {
701  BinT<int8_t> bin8(binSize, channels, average);
702  return bin8.convert(target, src, size);
703  }
704  case 16: {
705  BinT<int16_t> bin16(binSize, channels, average);
706  return bin16.convert(target, src, size);
707  }
708  case 24: {
709  BinT<int24_t> bin24(binSize, channels, average);
710  return bin24.convert(target, src, size);
711  }
712  case 32: {
713  BinT<int32_t> bin32(binSize, channels, average);
714  return bin32.convert(target, src, size);
715  }
716  default: {
717  LOGE("Number of bits %d not supported.", bits);
718  return 0;
719  }
720  }
721  return 0;
722  }
723 
724  operator bool() { return binSize > 1; };
725 
726  protected:
727  int channels = 2;
728  int bits = 16;
729  int binSize = 1;
730  bool average = false;
731 };
732 
738 template <typename T>
740  public:
741  ChannelEnhancer() = default;
742 
743  ChannelEnhancer(int channelCountOfTarget, int channelCountOfSource) {
744  from_channels = channelCountOfSource;
745  to_channels = channelCountOfTarget;
746  }
747 
748  void setSourceChannels(int channelCountOfSource) {
749  from_channels = channelCountOfSource;
750  }
751 
752  void setTargetChannels(int channelCountOfTarget) {
753  to_channels = channelCountOfTarget;
754  }
755 
756  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
757  int frame_count = size / (sizeof(T) * from_channels);
758  size_t result_size = 0;
759  T *result = (T *)target;
760  T *source = (T *)src;
761  T value = (int16_t)0;
762  for (int i = 0; i < frame_count; i++) {
763  // copy available channels
764  for (int j = 0; j < from_channels; j++) {
765  value = *source++;
766  *result++ = value;
767  result_size += sizeof(T);
768  }
769  // repeat last value
770  for (int j = from_channels; j < to_channels; j++) {
771  *result++ = value;
772  result_size += sizeof(T);
773  }
774  }
775  return result_size;
776  }
777 
779  size_t resultSize(size_t inSize) {
780  return inSize * to_channels / from_channels;
781  }
782 
783  protected:
784  int from_channels;
785  int to_channels;
786 };
787 
793 template <typename T>
795  public:
796  ChannelConverter() = default;
797 
798  ChannelConverter(int channelCountOfTarget, int channelCountOfSource) {
799  from_channels = channelCountOfSource;
800  to_channels = channelCountOfTarget;
801  }
802 
803  void setSourceChannels(int channelCountOfSource) {
804  from_channels = channelCountOfSource;
805  }
806 
807  void setTargetChannels(int channelCountOfTarget) {
808  to_channels = channelCountOfTarget;
809  }
810 
811  size_t convert(uint8_t *target, uint8_t *src, size_t size) {
812  if (from_channels == to_channels) {
813  memcpy(target, src, size);
814  return size;
815  }
816  // setup channels
817  if (from_channels > to_channels) {
818  reducer.setSourceChannels(from_channels);
819  reducer.setTargetChannels(to_channels);
820  } else {
821  enhancer.setSourceChannels(from_channels);
822  enhancer.setTargetChannels(to_channels);
823  }
824 
825  // execute conversion
826  if (from_channels > to_channels) {
827  return reducer.convert(target, src, size);
828  } else {
829  return enhancer.convert(target, src, size);
830  }
831  }
832 
833  protected:
834  ChannelEnhancer<T> enhancer;
835  ChannelReducerT<T> reducer;
836  int from_channels;
837  int to_channels;
838 };
839 
845 template <typename T>
847  public:
848  MultiConverter() {}
849 
850  MultiConverter(BaseConverter &c1) { add(c1); }
851 
853  add(c1);
854  add(c2);
855  }
856 
858  add(c1);
859  add(c2);
860  add(c3);
861  }
862 
863  // adds a converter
864  void add(BaseConverter &converter) { converters.push_back(&converter); }
865 
866  // The data is provided as int24_t tgt[][2] but returned as int24_t
867  size_t convert(uint8_t *src, size_t size) {
868  for (int i = 0; i < converters.size(); i++) {
869  converters[i]->convert(src, size);
870  }
871  return size;
872  }
873 
874  private:
875  Vector<BaseConverter *> converters;
876 };
877 
878 // /**
879 // * @brief Converts e.g. 24bit data to the indicated smaller or bigger data
880 // type
881 // * @ingroup convert
882 // * @author Phil Schatzmann
883 // * @copyright GPLv3
884 // *
885 // * @tparam T
886 // */
887 // template<typename FromType, typename ToType>
888 // class FormatConverter {
889 // public:
890 // FormatConverter(ToType (*converter)(FromType v)){
891 // this->convert_ptr = converter;
892 // }
893 
894 // FormatConverter( float factor, float clip){
895 // this->factor = factor;
896 // this->clip = clip;
897 // }
898 
899 // // The data is provided as int24_t tgt[][2] but returned as int24_t
900 // size_t convert(uint8_t *src, uint8_t *target, size_t byte_count_src)
901 // {
902 // return convert((FromType *)src, (ToType*)target, byte_count_src
903 // );
904 // }
905 
906 // // The data is provided as int24_t tgt[][2] but returned as int24_t
907 // size_t convert(FromType *src, ToType *target, size_t byte_count_src)
908 // {
909 // int size = byte_count_src / sizeof(FromType);
910 // FromType *s = src;
911 // ToType *t = target;
912 // if (convert_ptr!=nullptr){
913 // // standard conversion
914 // for (int i=size; i>0; i--) {
915 // *t = (*convert_ptr)(*s);
916 // t++;
917 // s++;
918 // }
919 // } else {
920 // // conversion using indicated factor
921 // for (int i=size; i>0; i--) {
922 // float tmp = factor * *s;
923 // if (tmp>clip){
924 // tmp=clip;
925 // } else if (tmp<-clip){
926 // tmp = -clip;
927 // }
928 // *t = tmp;
929 // t++;
930 // s++;
931 // }
932 // }
933 // return size*sizeof(ToType);
934 // }
935 
936 // private:
937 // ToType (*convert_ptr)(FromType v) = nullptr;
938 // float factor=0;
939 // float clip=0;
940 
941 // };
942 
948  public:
949  NumberReader(Stream &in) { stream_ptr = &in; }
950 
951  NumberReader() {}
952 
953  bool read(int inBits, int outBits, bool outSigned, int n, int32_t *result) {
954  bool result_bool = false;
955  int len = inBits / 8 * n;
956  if (stream_ptr != nullptr && stream_ptr->available() > len) {
957  uint8_t buffer[len];
958  stream_ptr->readBytes((uint8_t *)buffer, n * len);
959  result_bool =
960  toNumbers((void *)buffer, inBits, outBits, outSigned, n, result);
961  }
962  return result_bool;
963  }
964 
966  bool toNumbers(void *bufferIn, int inBits, int outBits, bool outSigned, int n,
967  int32_t *result) {
968  bool result_bool = false;
969  switch (inBits) {
970  case 8: {
971  int8_t *buffer = (int8_t *)bufferIn;
972  for (int j = 0; j < n; j++) {
973  result[j] = scale(buffer[j], inBits, outBits, outSigned);
974  }
975  result_bool = true;
976  } break;
977  case 16: {
978  int16_t *buffer = (int16_t *)bufferIn;
979  for (int j = 0; j < n; j++) {
980  result[j] = scale(buffer[j], inBits, outBits, outSigned);
981  }
982  result_bool = true;
983  } break;
984  case 32: {
985  int32_t *buffer = (int32_t *)bufferIn;
986  for (int j = 0; j < n; j++) {
987  result[j] = scale(buffer[j], inBits, outBits, outSigned);
988  }
989  result_bool = true;
990  } break;
991  }
992  return result_bool;
993  }
994 
995  protected:
996  Stream *stream_ptr = nullptr;
997 
999  int32_t scale(int32_t value, int inBits, int outBits, bool outSigned = true) {
1000  int32_t result = static_cast<float>(value) /
1001  NumberConverter::maxValue(inBits) *
1002  NumberConverter::maxValue(outBits);
1003  if (!outSigned) {
1004  result += (NumberConverter::maxValue(outBits) / 2);
1005  }
1006  return result;
1007  }
1008 };
1009 
1016 template <typename T>
1018  public:
1019  Converter1Channel(Filter<T> &filter) { this->p_filter = &filter; }
1020 
1021  size_t convert(uint8_t *src, size_t size) {
1022  T *data = (T *)src;
1023  for (size_t j = 0; j < size; j++) {
1024  data[j] = p_filter->process(data[j]);
1025  }
1026  return size;
1027  }
1028 
1029  protected:
1030  Filter<T> *p_filter = nullptr;
1031 };
1032 
1039 template <typename T, typename FT>
1041  public:
1043  ConverterNChannels(int channels) {
1044  this->channels = channels;
1045  filters = new Filter<FT> *[channels];
1046  // make sure that we have 1 filter per channel
1047  for (int j = 0; j < channels; j++) {
1048  filters[j] = nullptr;
1049  }
1050  }
1051 
1054  for (int j = 0; j < channels; j++) {
1055  if (filters[j] != nullptr) {
1056  delete filters[j];
1057  }
1058  }
1059  delete[] filters;
1060  filters = 0;
1061  }
1062 
1064  void setFilter(int channel, Filter<FT> *filter) {
1065  if (channel < channels) {
1066  if (filters[channel] != nullptr) {
1067  delete filters[channel];
1068  }
1069  filters[channel] = filter;
1070  } else {
1071  LOGE("Invalid channel nummber %d - max channel is %d", channel,
1072  channels - 1);
1073  }
1074  }
1075 
1076  // convert all samples for each channel separately
1077  size_t convert(uint8_t *src, size_t size) {
1078  int count = size / channels / sizeof(T);
1079  T *sample = (T *)src;
1080  for (size_t j = 0; j < count; j++) {
1081  for (int channel = 0; channel < channels; channel++) {
1082  if (filters[channel] != nullptr) {
1083  *sample = filters[channel]->process(*sample);
1084  }
1085  sample++;
1086  }
1087  }
1088  return size;
1089  }
1090 
1091  int getChannels() { return channels; }
1092 
1093  protected:
1094  Filter<FT> **filters = nullptr;
1095  int channels;
1096 };
1097 
1106 template <typename T>
1108  public:
1109  SilenceRemovalConverter(int n = 8, int aplidudeLimit = 2) {
1110  set(n, aplidudeLimit);
1111  }
1112 
1113  virtual size_t convert(uint8_t *data, size_t size) override {
1114  if (!active) {
1115  // no change to the data
1116  return size;
1117  }
1118  size_t sample_count = size / sizeof(T);
1119  size_t write_count = 0;
1120  T *audio = (T *)data;
1121 
1122  // find relevant data
1123  T *p_buffer = (T *)data;
1124  for (int j = 0; j < sample_count; j++) {
1125  int pos = findLastAudioPos(audio, j);
1126  if (pos < n) {
1127  write_count++;
1128  *p_buffer++ = audio[j];
1129  }
1130  }
1131 
1132  // write audio data w/o silence
1133  size_t write_size = write_count * sizeof(T);
1134  LOGI("filtered silence from %d -> %d", (int)size, (int)write_size);
1135 
1136  // number of empty samples of prior buffer
1137  priorLastAudioPos = findLastAudioPos(audio, sample_count - 1);
1138 
1139  // return new data size
1140  return write_size;
1141  }
1142 
1143  protected:
1144  bool active = false;
1145  const uint8_t *buffer = nullptr;
1146  int n;
1147  int priorLastAudioPos = 0;
1148  int amplidude_limit = 0;
1149 
1150  void set(int n = 5, int aplidudeLimit = 2) {
1151  LOGI("begin(n=%d, aplidudeLimit=%d", n, aplidudeLimit);
1152  this->n = n;
1153  this->amplidude_limit = aplidudeLimit;
1154  this->priorLastAudioPos = n + 1; // ignore first values
1155  this->active = n > 0;
1156  }
1157 
1158  // find last position which contains audible data
1159  int findLastAudioPos(T *audio, int pos) {
1160  for (int j = 0; j < n; j++) {
1161  // we are before the start of the current buffer
1162  if (pos - j <= 0) {
1163  return priorLastAudioPos;
1164  }
1165  // we are in the current buffer
1166  if (abs(audio[pos - j]) > amplidude_limit) {
1167  return j;
1168  }
1169  }
1170  return n + 1;
1171  }
1172 };
1173 
1181 template <typename T>
1183  public:
1184  PoppingSoundRemover(int channels, bool fromBeginning, bool fromEnd) {
1185  this->channels = channels;
1186  from_beginning = fromBeginning;
1187  from_end = fromEnd;
1188  }
1189  virtual size_t convert(uint8_t *src, size_t size) {
1190  for (int ch = 0; ch < channels; ch++) {
1191  if (from_beginning)
1192  clearUpTo1stTransition(channels, ch, (T *)src, size / sizeof(T));
1193  if (from_end)
1194  clearAfterLastTransition(channels, ch, (T *)src, size / sizeof(T));
1195  }
1196  return size;
1197  }
1198 
1199  protected:
1200  bool from_beginning;
1201  bool from_end;
1202  int channels;
1203 
1204  void clearUpTo1stTransition(int channels, int channel, T *values,
1205  int sampleCount) {
1206  T first = values[channel];
1207  for (int j = 0; j < sampleCount; j += channels) {
1208  T act = values[j];
1209  if ((first <= 0.0 && act >= 0.0) || (first >= 0.0 && act <= 0.0)) {
1210  // we found the last transition so we are done
1211  break;
1212  } else {
1213  values[j] = 0;
1214  }
1215  }
1216  }
1217 
1218  void clearAfterLastTransition(int channels, int channel, T *values,
1219  int sampleCount) {
1220  int lastPos = sampleCount - channels + channel;
1221  T last = values[lastPos];
1222  for (int j = lastPos; j >= 0; j -= channels) {
1223  T act = values[j];
1224  if ((last <= 0.0 && act >= 0.0) || (last >= 0.0 && act <= 0.0)) {
1225  // we found the last transition so we are done
1226  break;
1227  } else {
1228  values[j] = 0;
1229  }
1230  }
1231  }
1232 };
1233 
1240 template <typename T>
1242  public:
1243  SmoothTransition(int channels, bool fromBeginning, bool fromEnd,
1244  float inc = 0.01) {
1245  this->channels = channels;
1246  this->inc = inc;
1247  from_beginning = fromBeginning;
1248  from_end = fromEnd;
1249  }
1250  virtual size_t convert(uint8_t *src, size_t size) {
1251  for (int ch = 0; ch < channels; ch++) {
1252  if (from_beginning)
1253  processStart(channels, ch, (T *)src, size / sizeof(T));
1254  if (from_end) processEnd(channels, ch, (T *)src, size / sizeof(T));
1255  }
1256  return size;
1257  }
1258 
1259  protected:
1260  bool from_beginning;
1261  bool from_end;
1262  int channels;
1263  float inc = 0.01;
1264  float factor = 0;
1265 
1266  void processStart(int channels, int channel, T *values, int sampleCount) {
1267  for (int j = 0; j < sampleCount; j += channels) {
1268  if (factor >= 0.8) {
1269  break;
1270  } else {
1271  values[j] = factor * values[j];
1272  }
1273  factor += inc;
1274  }
1275  }
1276 
1277  void processEnd(int channels, int channel, T *values, int sampleCount) {
1278  int lastPos = sampleCount - channels + channel;
1279  for (int j = lastPos; j >= 0; j -= channels) {
1280  if (factor >= 0.8) {
1281  break;
1282  } else {
1283  values[j] = factor * values[j];
1284  }
1285  }
1286  }
1287 };
1288 
1294 template <typename T, size_t Cn, size_t Cx, size_t S>
1295 class CopyChannels : public BaseConverter {
1296  public:
1297  CopyChannels() : _max_val(0), _counter(0), _prev_ms(0) {}
1298 
1299  size_t convert(uint8_t *src, size_t size) {
1300  T *chan = (T *)src;
1301  size_t samples = (size / Cn) / sizeof(T);
1302  for (size_t s = 0; s < samples; s++) {
1303  chan[s * Cn + Cx] = (Cx < Cn) ? chan[s * Cn + Cx] << S : 0;
1304 
1305  for (size_t c = 0; c < Cn; c++) {
1306  if (c != Cx) {
1307  chan[s * Cn + c] = chan[s * Cn + Cx];
1308  }
1309  }
1310 
1311  if (_max_val < chan[s * Cn]) {
1312  _max_val = chan[s * Cn];
1313  }
1314 
1315  _counter++;
1316  uint32_t now = millis();
1317  if (now - _prev_ms > 1000) {
1318  _prev_ms = now;
1319  LOGI("CopyChannels samples: %u, amplitude: %d", _counter, _max_val);
1320  _max_val = 0;
1321  }
1322  }
1323  return samples * Cn * sizeof(T);
1324  }
1325 
1326  private:
1327  T _max_val;
1328  uint32_t _counter;
1329  uint32_t _prev_ms;
1330 };
1331 
1337 template <typename T>
1339  public:
1340  CallbackConverterT(T(*callback)(T in, int channel), int channels = 2) {
1341  this->callback = callback;
1342  this->channels = channels;
1343  }
1344 
1345  size_t convert(uint8_t *src, size_t size) {
1346  int samples = size / sizeof(T);
1347  for (int j = 0; j < samples; j++) {
1348  src[j] = callback(src[j], j % channels);
1349  }
1350  return size;
1351  }
1352 
1353  protected:
1354  T(*callback)(T in, int channel);
1355  int channels;
1356 };
1357 
1358 } // 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:680
void setAverage(bool average)
Enables averaging: e.g. when true it divides the sum by number of bins.
Definition: BaseConverter.h:695
void setChannels(int channels)
Defines the number of channels.
Definition: BaseConverter.h:690
void setBinSize(int binSize)
Sets the binning size: e.g. with 4 we sum 4 samples.
Definition: BaseConverter.h:693
Provides reduced sampling rates through binning: typed implementation.
Definition: BaseConverter.h:604
void setAverage(bool average)
Enables averaging: e.g. when true it divides the sum by number of bins.
Definition: BaseConverter.h:618
void setChannels(int channels)
Defines the number of channels.
Definition: BaseConverter.h:612
void setBinSize(int binSize)
Sets the bins: e.g. with 4 we sum 4 sample.
Definition: BaseConverter.h:615
You can provide a lambda expression to conver the data.
Definition: BaseConverter.h:1338
Increasing or decreasing the number of channels.
Definition: BaseConverter.h:794
Increases the channel count.
Definition: BaseConverter.h:739
size_t resultSize(size_t inSize)
Determine the size of the conversion result.
Definition: BaseConverter.h:779
We combine a datastream which consists of multiple channels into less channels. E....
Definition: BaseConverter.h:444
We combine a datastream which consists of multiple channels into less channels. E....
Definition: BaseConverter.h:388
Converter for 1 Channel which applies the indicated Filter.
Definition: BaseConverter.h:1017
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:277
Converter for n Channels which applies the indicated Filter.
Definition: BaseConverter.h:1040
~ConverterNChannels()
Destructor.
Definition: BaseConverter.h:1053
void setFilter(int channel, Filter< FT > *filter)
defines the filter for an individual channel - the first channel is 0
Definition: BaseConverter.h:1064
ConverterNChannels(int channels)
Default Constructor.
Definition: BaseConverter.h:1043
Multiplies the values with the indicated factor adds the offset and clips at maxValue....
Definition: BaseConverter.h:55
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
void setFactor(T factor)
Defines the factor (volume)
Definition: BaseConverter.h:82
Switches the left and right channel.
Definition: BaseConverter.h:240
special case for internal DAC output, the incomming PCM buffer needs to be converted from signed 16bi...
Definition: BaseConverter.h:360
Copy channel Cx value of type T shifted by S bits to all Cn channels.
Definition: BaseConverter.h:1295
Provides a reduced sampling rate by ignoring a defined rate of samples.
Definition: BaseConverter.h:531
void setFactor(int factor)
Sets the factor: e.g. with 4 we keep every forth sample.
Definition: BaseConverter.h:543
void setChannels(int channels)
Defines the number of channels.
Definition: BaseConverter.h:540
Provides reduced sampling rates.
Definition: BaseConverter.h:484
void setFactor(int factor)
Sets the factor: e.g. with 4 we keep every forth sample.
Definition: BaseConverter.h:494
void setChannels(int channels)
Defines the number of channels.
Definition: BaseConverter.h:491
Abstract filter interface definition;.
Definition: Filter.h:28
Combines multiple converters.
Definition: BaseConverter.h:846
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:330
Reads n numbers from an Arduino Stream.
Definition: BaseConverter.h:947
int32_t scale(int32_t value, int inBits, int outBits, bool outSigned=true)
scale the value
Definition: BaseConverter.h:999
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:966
Big value gaps (at the beginning and the end of a recording) can lead to some popping sounds....
Definition: BaseConverter.h:1182
Removes any silence from the buffer that is longer then n samples with a amplitude below the indicate...
Definition: BaseConverter.h:1107
Changes the samples at the beginning or at the end to slowly ramp up the volume.
Definition: BaseConverter.h:1241
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:265
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
uint32_t millis()
Returns the milliseconds since the start.
Definition: Millis.h:18
Provides a reduced sampling rate through binning.
Definition: BaseConverter.h:580
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57