BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

commit 803e1cfc61f0a40585fc5d69c429ebe2336578f5
parent 29afc01e386f3c97a56b4fe37cd05519dfe91fa9
Author: Matt Demanett <matt@demanett.net>
Date:   Sun,  3 Dec 2017 15:12:01 -0500

Analyzer: drawing fixes; add peak frequency display.

Diffstat:
Msrc/Analyzer.cpp | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 85 insertions(+), 21 deletions(-)

diff --git a/src/Analyzer.cpp b/src/Analyzer.cpp @@ -18,11 +18,12 @@ struct ChannelAnalyzer : SpectrumAnalyzer { SpectrumAnalyzer::Overlap overlap, SpectrumAnalyzer::WindowType windowType, float sampleRate, - int averageN + int averageN, + int binSize ) : SpectrumAnalyzer(size, overlap, windowType, sampleRate) , _averageN(averageN) - , _binsN(size / 2) + , _binsN(size / binSize) , _bins(new float[size] {}) , _frames(new float[_averageN * _binsN] {}) , _currentFrame(0) @@ -30,11 +31,11 @@ struct ChannelAnalyzer : SpectrumAnalyzer { } virtual ~ChannelAnalyzer() { delete[] _bins; - delete[] _frames; } virtual bool step(float sample) override; + float getPeak(); }; bool ChannelAnalyzer::step(float sample) { @@ -56,6 +57,21 @@ bool ChannelAnalyzer::step(float sample) { return false; } +float ChannelAnalyzer::getPeak() { + float max = 0.0; + float sum = 0.0; + int maxBin = 0; + for (int bin = 0; bin < _binsN; ++bin) { + if( _bins[bin] > max) { + max = _bins[bin]; + maxBin = bin; + } + sum += _bins[bin]; + } + const float fWidth = _sampleRate / (float)(_size / (_size / _binsN)); + return (maxBin + 1)*fWidth - fWidth/2.0; +} + struct Analyzer : Module { enum ParamsIds { @@ -87,6 +103,7 @@ struct Analyzer : Module { ChannelAnalyzer* _channelB = NULL; float _range = 0.0; float _smooth = 0.0; + const int _binAverageN = 2; Analyzer() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { reset(); @@ -138,7 +155,8 @@ void Analyzer::stepChannel(ChannelAnalyzer*& channelPointer, bool running, Input SpectrumAnalyzer::OVERLAP_2, SpectrumAnalyzer::WINDOW_HAMMING, engineGetSampleRate(), - _averageN + _averageN, + _binAverageN ); } @@ -157,10 +175,11 @@ void Analyzer::stepChannel(ChannelAnalyzer*& channelPointer, bool running, Input struct AnalyzerDisplay : TransparentWidget { - const int _insetLeft = 14; - const int _insetRight = 4; - const int _insetTop = 2; - const int _insetBottom = 11; + const int _insetAround = 2; + const int _insetLeft = _insetAround + 12; + const int _insetRight = _insetAround + 2; + const int _insetTop = _insetAround + 13; + const int _insetBottom = _insetAround + 9; const float _refDB0 = 20.0; // arbitrary; makes a 10.0-amplitude sine wave reach to about 0db on the output. const float _displayDB = 120.0; @@ -190,24 +209,34 @@ struct AnalyzerDisplay : TransparentWidget { void draw(NVGcontext* vg) override; void drawBackground(NVGcontext* vg); + void drawHeader(NVGcontext* vg); void drawYAxis(NVGcontext* vg); void drawXAxis(NVGcontext* vg); void drawXAxisLine(NVGcontext* vg, float hz, float maxHz); - void drawLine(NVGcontext* vg, float* bins, int binsN, NVGcolor color); - void drawText(NVGcontext* vg, const char* s, float x, float y, float rotation = 0.0); + void drawGraph(NVGcontext* vg, float* bins, int binsN, NVGcolor color); + void drawText(NVGcontext* vg, const char* s, float x, float y, float rotation = 0.0, const NVGcolor* color = NULL); int binValueToHeight(float value); }; void AnalyzerDisplay::draw(NVGcontext* vg) { drawBackground(vg); - drawYAxis(vg); - drawXAxis(vg); - if (_module->_channelA) { - drawLine(vg, _module->_channelA->_bins, _module->_channelA->_binsN, _channelAColor); - } - if (_module->_channelB) { - drawLine(vg, _module->_channelB->_bins, _module->_channelB->_binsN, _channelBColor); + if (_module->_channelA || _module->_channelB) { + nvgSave(vg); + nvgScissor(vg, _insetAround, _insetAround, _size.x - _insetAround, _size.y - _insetAround); + { + drawHeader(vg); + drawYAxis(vg); + drawXAxis(vg); + + if (_module->_channelA) { + drawGraph(vg, _module->_channelA->_bins, _module->_channelA->_binsN, _channelAColor); + } + if (_module->_channelB) { + drawGraph(vg, _module->_channelB->_bins, _module->_channelB->_binsN, _channelBColor); + } + } + nvgRestore(vg); } } @@ -222,6 +251,34 @@ void AnalyzerDisplay::drawBackground(NVGcontext* vg) { nvgRestore(vg); } +void AnalyzerDisplay::drawHeader(NVGcontext* vg) { + nvgSave(vg); + + const int textY = -4; + const int charPx = 5; + const int sLen = 100; + char s[sLen]; + int x = _insetAround + 2; + + int n = snprintf(s, sLen, "Peaks (+/-%0.1f):", engineGetSampleRate() / (float)(_module->_size / (2 * _module->_binAverageN))); + drawText(vg, s, x, _insetTop + textY); + x += n * charPx - 2; + + if (_module->_channelA) { + n = snprintf(s, sLen, "A:%7.1f", _module->_channelA->getPeak()); + drawText(vg, s, x, _insetTop + textY, 0.0, &_channelAColor); + x += n * charPx + 3; + } + + if (_module->_channelB) { + n = snprintf(s, sLen, "B:%7.1f", _module->_channelB->getPeak()); + drawText(vg, s, x, _insetTop + textY, 0.0, &_channelBColor); + x += n * charPx + 3; + } + + nvgRestore(vg); +} + void AnalyzerDisplay::drawYAxis(NVGcontext* vg) { nvgSave(vg); nvgStrokeColor(vg, _axisColor); @@ -230,7 +287,13 @@ void AnalyzerDisplay::drawYAxis(NVGcontext* vg) { const float textR = -M_PI/2.0; nvgBeginPath(vg); - int lineY = _insetTop + (_graphSize.y - _graphSize.y*(_displayDB - 20.0)/_displayDB); + int lineY = _insetTop; + nvgMoveTo(vg, lineX, lineY); + nvgLineTo(vg, _size.x - _insetRight, lineY); + nvgStroke(vg); + + nvgBeginPath(vg); + lineY = _insetTop + (_graphSize.y - _graphSize.y*(_displayDB - 20.0)/_displayDB); nvgMoveTo(vg, lineX, lineY); nvgLineTo(vg, _size.x - _insetRight, lineY); nvgStroke(vg); @@ -324,9 +387,10 @@ void AnalyzerDisplay::drawXAxisLine(NVGcontext* vg, float hz, float maxHz) { } } -void AnalyzerDisplay::drawLine(NVGcontext* vg, float* bins, int binsN, NVGcolor color) { +void AnalyzerDisplay::drawGraph(NVGcontext* vg, float* bins, int binsN, NVGcolor color) { const int pointsN = roundf(_module->_range*(_module->_size/2)); nvgSave(vg); + nvgScissor(vg, _insetLeft, _insetTop, _graphSize.x, _graphSize.y); nvgStrokeColor(vg, color); nvgBeginPath(vg); for (int i = 0; i < pointsN; ++i) { @@ -343,13 +407,13 @@ void AnalyzerDisplay::drawLine(NVGcontext* vg, float* bins, int binsN, NVGcolor nvgRestore(vg); } -void AnalyzerDisplay::drawText(NVGcontext* vg, const char* s, float x, float y, float rotation) { +void AnalyzerDisplay::drawText(NVGcontext* vg, const char* s, float x, float y, float rotation, const NVGcolor* color) { nvgSave(vg); nvgTranslate(vg, x, y); nvgRotate(vg, rotation); nvgFontSize(vg, 10); nvgFontFaceId(vg, _font->handle); - nvgFillColor(vg, _textColor); + nvgFillColor(vg, color ? *color : _textColor); nvgText(vg, 0, 0, s, NULL); nvgRestore(vg); }