summaryrefslogtreecommitdiff
path: root/src/ui/levelmeter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/levelmeter.cpp')
-rw-r--r--src/ui/levelmeter.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/ui/levelmeter.cpp b/src/ui/levelmeter.cpp
new file mode 100644
index 0000000..52412de
--- /dev/null
+++ b/src/ui/levelmeter.cpp
@@ -0,0 +1,67 @@
+#include "levelmeter.h"
+#include <tqpainter.h>
+#include <math.h>
+
+LevelMeter::LevelMeter( TQWidget *parent )
+ : TQWidget(parent), m_level(0.0f)
+{
+ setBackgroundMode( NoBackground );
+}
+
+// Map linear 0..1 amplitude to dB display position 0..1 over a 60dB range.
+// -60dB = bottom, 0dB = top. Matches how real VU meters look.
+static float toDisplayLevel( float linear )
+{
+ if ( linear < 0.001f ) return 0.0f;
+ float db = 20.0f * log10f( linear ); // e.g. 0.3 → -10.5 dB
+ float pos = ( db + 60.0f ) / 60.0f; // -60..0 dB → 0..1
+ if ( pos < 0.0f ) pos = 0.0f;
+ if ( pos > 1.0f ) pos = 1.0f;
+ return pos;
+}
+
+void LevelMeter::setLevel( float level )
+{
+ if ( level < 0.0f ) level = 0.0f;
+ if ( level > 1.0f ) level = 1.0f;
+
+ float display = toDisplayLevel( level );
+ if ( display > m_level )
+ m_level = m_level * 0.3f + display * 0.7f; // fast attack, not instant
+ else {
+ m_level *= 0.94f; // slow decay ~1.5s to floor
+ if ( m_level < 0.001f ) m_level = 0.0f;
+ }
+ update();
+}
+
+TQSize LevelMeter::sizeHint() const
+{
+ return TQSize( 8, 48 );
+}
+
+void LevelMeter::paintEvent( TQPaintEvent * )
+{
+ TQPainter p( this );
+ int w = width();
+ int h = height();
+
+ p.fillRect( 0, 0, w, h, TQColor( 40, 40, 40 ) );
+
+ if ( m_level <= 0.0f ) return;
+
+ struct Zone { float lo, hi; TQColor col; };
+ static const Zone zones[3] = {
+ { 0.00f, 0.70f, TQColor( 50, 200, 50 ) },
+ { 0.70f, 0.90f, TQColor( 230, 200, 0 ) },
+ { 0.90f, 1.00f, TQColor( 220, 40, 40 ) },
+ };
+
+ for ( int z = 0; z < 3; z++ ) {
+ if ( m_level <= zones[z].lo ) break;
+ float segEnd = ( m_level < zones[z].hi ) ? m_level : zones[z].hi;
+ int yTop = h - (int)( segEnd * h );
+ int yBot = h - (int)( zones[z].lo * h );
+ p.fillRect( 0, yTop, w, yBot - yTop, zones[z].col );
+ }
+}