arduino-audio-tools
MetaDataFilter.h
1 #pragma once
2 #include "AudioTools/AudioLogger.h"
3 
4 namespace audio_tools {
5 
12 template <class Decoder>
14  public:
16  MetaDataFilter() = default;
17 
19  MetaDataFilter(Decoder *decoder){
20  setDecoder(decoder);
21  }
22 
24  void setDecoder(Decoder *decoder){
25  p_decoder = decoder;
26  }
27 
29  void begin() {
30  TRACED();
31  start = 0;
32  }
33 
35  size_t write(uint8_t* data, size_t len){
36  TRACED();
37  if (p_decoder==nullptr) return 0;
38  int pos=0; int meta_len=0;
39  if (findTag(data, len, pos, meta_len)){
40  LOGD("pos: %d len: %d",pos, meta_len);
41  if (start<pos){
42  p_decoder->write(data+start,pos);
43  }
44 
45  int start_idx2 = pos+meta_len;
46  int len2 = len-start_idx2;
47  if (start_idx2<len){
48  // we still have some audio to write
49  p_decoder->write(data+start_idx2,len2);
50  } else {
51  // ignore audio of next write
52  start = meta_len - len2;
53  }
54  } else {
55  // ignore start number of characters
56  if (start>=len){
57  start -= len;
58  } else {
59  p_decoder->write(data+start,len-start);
60  start = 0;
61  }
62  }
63  return len;
64  }
65 
66  protected:
67  Decoder *p_decoder=nullptr;
68  enum MetaType {TAG, TAG_PLUS, ID3};
69  int start = 0;
71  struct ID3v2 {
72  uint8_t header[3]; // ID3
73  uint8_t version[2];
74  uint8_t flags;
75  uint8_t size[4];
76  } tagv2;
77 
79  bool findTag(uint8_t* data, size_t len, int &pos_tag, int &meta_len){
80  MetaType tag_type;
81  if (find((const char*)data, len, pos_tag, tag_type)){
82  switch(tag_type){
83  case TAG:
84  LOGD("TAG");
85  meta_len = 128;
86  break;
87  case TAG_PLUS:
88  LOGD("TAG+");
89  meta_len = 227;
90  break;
91  case ID3:
92  LOGD("ID3");
93  memcpy(&tagv2, data+pos_tag, sizeof(ID3v2));
94  meta_len = calcSizeID3v2(tagv2.size);
95  break;
96 
97  }
98  return true;
99  }
100  return false;
101  }
102 
103  // calculate the synch save size for ID3v2
104  uint32_t calcSizeID3v2(uint8_t chars[4]) {
105  uint32_t byte0 = chars[0];
106  uint32_t byte1 = chars[1];
107  uint32_t byte2 = chars[2];
108  uint32_t byte3 = chars[3];
109  return byte0 << 21 | byte1 << 14 | byte2 << 7 | byte3;
110  }
111 
113  bool find(const char*str, size_t len, int &pos, MetaType &type){
114  if (str==nullptr || len<=0) return false;
115  for (size_t j=0;j<=len-3;j++){
116  if (str[j]=='T' && str[j+1]=='A' && str[j+2]=='G'){
117  type = str[j+3]=='+' ? TAG_PLUS : TAG;
118  return true;
119  } else if (str[j]=='I' && str[j+1]=='D' && str[j+2]=='3'){
120  type = ID3;
121  return true;
122  }
123  }
124  return false;
125  }
126 };
127 
128 }
Class which filters out ID3v1 and ID3v2 Metadata and provides only the audio data to the decoder.
Definition: MetaDataFilter.h:13
bool find(const char *str, size_t len, int &pos, MetaType &type)
find the tag position in the string;
Definition: MetaDataFilter.h:113
size_t write(uint8_t *data, size_t len)
Writes the data to the decoder.
Definition: MetaDataFilter.h:35
void setDecoder(Decoder *decoder)
Defines the decoder to which we write the data.
Definition: MetaDataFilter.h:24
bool findTag(uint8_t *data, size_t len, int &pos_tag, int &meta_len)
determines if the data conatins a ID3v1 or ID3v2 tag
Definition: MetaDataFilter.h:79
void begin()
(Re)starts the processing
Definition: MetaDataFilter.h:29
MetaDataFilter()=default
Default Constructor.
MetaDataFilter(Decoder *decoder)
Constructor which assigns the decoder.
Definition: MetaDataFilter.h:19
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
ID3 verion 2 TAG Header (10 bytes)
Definition: MetaDataFilter.h:71