#include "levelmeter.h" #include #include 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 ); } }