#pragma once #include #include "FastFilter.h" class VolAnalyzer { public: VolAnalyzer (int pin = -1) { volF.setDt(20); volF.setPass(FF_PASS_MAX); maxF.setPass(FF_PASS_MAX); setVolK(25); setAmpliK(31); if (pin != -1) setPin(pin); } void setPin(int pin) { _pin = pin; pinMode(_pin, INPUT); } void setDt(int dt) { _dt = dt; } void setPeriod(int period) { _period = period; } void setVolDt(int volDt) { volF.setDt(volDt); } void setAmpliDt(int ampliDt) { _ampliDt = ampliDt; } void setWindow(int window) { _window = window; } void setVolK(byte k) { volF.setK(k); } void setAmpliK(byte k) { maxF.setK(k); minF.setK(k); } void setVolMin(int scale) { _volMin = scale; } void setVolMax(int scale) { _volMax = scale; } void setTrsh(int trsh) { _trsh = trsh; } bool tick(int thisRead = -1) { volF.compute(); if (millis() - tmr4 >= _ampliDt) { // период сглаживания амплитуды tmr4 = millis(); maxF.setRaw(maxs); minF.setRaw(mins); maxF.compute(); minF.compute(); maxs = 0; mins = 1023; } if (_period == 0 || millis() - tmr1 >= _period) { // период между захватом сэмплов if (_dt == 0 || micros() - tmr2 >= _dt) { // период выборки tmr2 = micros(); if (thisRead == -1) thisRead = analogRead(_pin); if (thisRead > max) max = thisRead; // ищем максимум if (!_first) { _first = 1; maxF.setFil(thisRead); minF.setFil(thisRead); } if (++count >= _window) { // выборка завершена tmr1 = millis(); raw = max; if (max > maxs) maxs = max; // максимумы среди максимумов if (max < mins) mins = max; // минимумы реди максимумов maxF.checkPass(max); // проверка выше максимума if (getMax() - getMin() < _trsh) max = 0; // если окно громкости меньше порого то 0 else max = constrain(map(max, getMin(), getMax(), _volMin, _volMax), _volMin, _volMax); // перевод в громкость volF.setRaw(max); // фильтр столбика громкости if (volF.checkPass(max)) _pulse = 1; // проверка выше максимума max = count = 0; return true; // выборка завершена } } } return false; } int getRaw() { return raw; } int getVol() { return volF.getFil(); } int getMin() { return minF.getFil(); } int getMax() { return maxF.getFil(); } bool getPulse() { if (_pulse) { _pulse = false; return true; } return false; } private: int _pin; int _dt = 600; // 600 мкс между сэмплами достаточно для музыки int _period = 5; // 5 мс между выборами достаточно int _ampliDt = 150; int _window = 20; // при таком размере окна получаем длительность оцифровки 12 мс, вполне хватает uint32_t tmr1 = 0, tmr2 = 0, tmr3 = 0, tmr4 = 0; int raw = 0; int max = 0, count = 0; int maxs = 0, mins = 1023; int _volMin = 0, _volMax = 100, _trsh = 30; bool _pulse = 0, _first = 0; FastFilter minF, maxF, volF; };