arduino-audio-tools
Loading...
Searching...
No Matches
FrequencyDetection.h
1#include "AudioTools/CoreAudio/AudioStreams.h"
2
3namespace audio_tools {
4
13 public:
15
17 p_out = &out;
18 };
19
21 p_out = ∈
22 p_in = ∈
23 };
24
25 bool begin(AudioInfo info){
26 setAudioInfo(info);
27 return AudioStream::begin();
28 }
29
30 int available()override{
31 if (p_in) return p_in->available();
32 return 0;
33 }
34
35 int availableForWrite()override{
36 if (p_out) return p_out->availableForWrite();
37 return DEFAULT_BUFFER_SIZE;
38 }
39
40 size_t readBytes(uint8_t *data, size_t len) override {
41 size_t result = p_in->readBytes(data, len);
42 switch(info.bits_per_sample){
43 case 16:
44 detect<int16_t>((int16_t*)data, len/sizeof(int16_t));
45 break;
46 case 24:
47 detect<int24_t>((int24_t*)data, len/sizeof(int24_t));
48 break;
49 case 32:
50 detect<int32_t>((int32_t*)data, len/sizeof(int32_t));
51 break;
52 }
53 return result;
54 }
55
56 virtual size_t write(const uint8_t *data, size_t len) override {
57 switch(info.bits_per_sample){
58 case 16:
59 detect<int16_t>((int16_t*)data, len/sizeof(int16_t));
60 break;
61 case 24:
62 detect<int24_t>((int24_t*)data, len/sizeof(int24_t));
63 break;
64 case 32:
65 detect<int32_t>((int32_t*)data, len/sizeof(int32_t));
66 break;
67 }
68
69 size_t result = len;
70 if (p_out!=nullptr) result = p_out->write(data, len);
71 return result;
72 }
73
75 float frequency(int channel) {
76 if(channel>=info.channels) {
77 LOGE("Invalid channel: %d", channel);
78 return 0;
79 }
80 return freq[channel];
81 }
82
83 protected:
84 Vector<float> freq;
85 Print *p_out=nullptr;
86 Stream *p_in = nullptr;
87 float sum=0, sum_old=0;
88
89 template <class T>
90 void detect(T* samples, size_t len) {
91 freq.resize(info.channels);
92 for (int ch=0; ch<info.channels; ch++){
93 freq[ch] = detectChannel(ch, samples, len);
94 }
95 }
96
97 template <class T>
98 float detectChannel(int channel, T* samples, size_t len) {
99 int thresh = 0;
100 uint8_t pd_state = 0;
101 int period = 0;
102 T max_value = NumberConverter::maxValue(info.bits_per_sample);
103 // Autocorrelation
104 for(int i = channel; i < len; i+=info.channels) {
105 sum_old = sum;
106 sum = 0;
107 for(int k = channel; k < len-i; k+=info.channels) {
108 sum += (samples[k])*(samples[k+i]); // / max_value;
109 }
110
111 // Peak Detect State Machine
112 if (pd_state == 2 && (sum-sum_old) <=0) {
113 period = i;
114 pd_state = 3;
115 }
116 if (pd_state == 1 && (sum > thresh) && (sum-sum_old) > 0) {
117 pd_state = 2;
118 }
119 if (pd_state == 0) {
120 thresh = sum * 0.5;
121 pd_state = 1;
122 }
123 }
124 // Frequency identified in Hz
125 return static_cast<float>(info.sample_rate) / period;
126 }
127};
128
137 public:
138 FrequncyZeroCrossingStream() = default;
139
141 p_out = &out;
142 };
143
145 p_out = &in;
146 p_in = &in;
147 };
148
149 bool begin(AudioInfo info){
150 setAudioInfo(info);
151 return AudioStream::begin();
152 }
153
154 int available()override{
155 if (p_in) return p_in->available();
156 return 0;
157 }
158
159 int availableForWrite()override{
160 if (p_out) return p_out->availableForWrite();
161 return DEFAULT_BUFFER_SIZE;
162 }
163
164 size_t readBytes(uint8_t *data, size_t len) override {
165 size_t result = p_in->readBytes(data, len);
166 switch(info.bits_per_sample){
167 case 16:
168 detect<int16_t>((int16_t*)data, len/sizeof(int16_t));
169 break;
170 case 24:
171 detect<int24_t>((int24_t*)data, len/sizeof(int24_t));
172 break;
173 case 32:
174 detect<int32_t>((int32_t*)data, len/sizeof(int32_t));
175 break;
176 }
177 return result;
178 }
179
180 virtual size_t write(const uint8_t *data, size_t len) override {
181 switch(info.bits_per_sample){
182 case 16:
183 detect<int16_t>((int16_t*)data, len/sizeof(int16_t));
184 break;
185 case 24:
186 detect<int24_t>((int24_t*)data, len/sizeof(int24_t));
187 break;
188 case 32:
189 detect<int32_t>((int32_t*)data, len/sizeof(int32_t));
190 break;
191 }
192
193 size_t result = len;
194 if (p_out!=nullptr) result = p_out->write(data, len);
195 return result;
196 }
197
199 float frequency(int channel) {
200 if(channel>=info.channels) {
201 LOGE("Invalid channel: %d", channel);
202 return 0;
203 }
204 return freq[channel];
205 }
206
207 void setFrequencyCallback(void (*callback)(int channel, float freq)){
208 notify = callback;
209 }
210
211 protected:
212 Vector<float> freq;
213 Print *p_out=nullptr;
214 Stream *p_in = nullptr;
215 int count = 0;
216 bool active = false;
217 void (*notify)(int channel, float freq);
218
219 template <class T>
220 void detect(T* samples, size_t len) {
221 freq.resize(info.channels);
222 for (int ch=0; ch<info.channels; ch++){
223 detectChannel(ch, samples, len);
224 }
225 }
226
227 template <class T>
228 void detectChannel(int channel, T* samples, size_t len) {
229 for(int i = channel; i < (len-info.channels); i+=info.channels) {
230 // start counter at first crossing
231 if (active) count++;
232 // update frequncy at each upward zero crossing
233 if (samples[i]<=0 && samples[i+info.channels]>0) {
234 freq[channel] = (1.0f * info.sample_rate) / count;
235 if (notify) notifyAudioChange(channel, freq[channel]);
236 count = 0;
237 active = true;
238 }
239 }
240 }
241};
242
243
244}
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:115
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:123
Determine Frequency using Audio Correlation. based on https://github.com/akellyirl/AutoCorr_Freq_dete...
Definition FrequencyDetection.h:12
float frequency(int channel)
provides the determined frequncy
Definition FrequencyDetection.h:75
Determine Frequency using upward 0 crossings.
Definition FrequencyDetection.h:136
float frequency(int channel)
provides the determined frequncy
Definition FrequencyDetection.h:199
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:311
Definition NoArduino.h:62
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
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioConfig.h:885
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:52
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
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