/*************************************************************************** Graphical spline display for equalizer (c) 2004 Mark Kretschmann (c) 2005 Markus Brueffer Based on code from XMMS (c) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "amarokconfig.h" #include "equalizergraph.h" #include #include #include #include EqualizerGraph::EqualizerGraph( TQWidget* parent ) : TQWidget( parent, 0, TQt::WNoAutoErase ) , m_backgroundPixmap( new TQPixmap() ) , m_composePixmap( new TQPixmap() ) { } EqualizerGraph::~EqualizerGraph() { delete m_backgroundPixmap; delete m_composePixmap; } ///////////////////////////////////////////////////////////////////////////////////// // PROTECTED ///////////////////////////////////////////////////////////////////////////////////// void EqualizerGraph::resizeEvent( TQResizeEvent* ) { drawBackground(); } TQSize EqualizerGraph::sizeHint() const { return TQSize( 100, 60 ); } void EqualizerGraph::paintEvent( TQPaintEvent* ) { bitBlt( m_composePixmap, 0, 0, m_backgroundPixmap ); TQPainter p( m_composePixmap ); // Draw middle line int middleLineY = (int) ( ( height() - 1 ) / 2.0 + AmarokConfig::equalizerPreamp() * ( height() - 1 ) / 200.0 ); TQPen pen( colorGroup().dark(), 0, TQt::DotLine); p.setPen( pen ); p.drawLine( 8, middleLineY, width() - 1, middleLineY ); TQColor color( colorGroup().highlight() ); int h, s, v; color.getHsv( &h, &s, &v ); int i, y, ymin, ymax, py = 0; float x[NUM_BANDS], yf[NUM_BANDS]; float gains[NUM_BANDS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Don't calculate 0 and NUM_BANDS-1 for accuracy reasons for ( i = 1; i < NUM_BANDS -1 ; i++) x[i] = ( width() - 8 ) * i / ( NUM_BANDS -1 ) + 8; x[ 0 ] = 8; x[ NUM_BANDS - 1 ] = width() - 1; if ( AmarokConfig::equalizerEnabled() ) for ( i = 0; i < NUM_BANDS; i++ ) gains[i] = ( height() - 1 ) * AmarokConfig::equalizerGains()[i] / 200.0; init_spline( x, gains, NUM_BANDS, yf ); for ( i = 8; i < width(); i++ ) { y = (int) ( ( height() - 1 ) / 2 - eval_spline( x, gains, yf, NUM_BANDS, i ) ); if ( y < 0 ) y = 0; if ( y > height() - 1 ) y = height() - 1; if ( i == 8 ) py = y; if ( y < py ) { ymin = y; ymax = py; } else { ymin = py; ymax = y; } py = y; for ( y = ymin; y <= ymax; y++ ) { // Absolute carthesian coordinate s = y - ( height() - 1 ) / 2; s = TQABS(s); // Normalise to a base of 256 // short for: s / ( ( height() / 2.0 ) * 255; s = (int) ( s * 510.0 / height() ); color.setHsv( h, 255 - s, v ); p.setPen( color ); p.drawPoint( i, y ); } } p.end(); bitBlt( this, 0, 0, m_composePixmap ); } ///////////////////////////////////////////////////////////////////////////////////// // PRIVATE ///////////////////////////////////////////////////////////////////////////////////// void EqualizerGraph::drawBackground() { m_backgroundPixmap->resize( size() ); m_composePixmap->resize( size() ); m_backgroundPixmap->fill( colorGroup().background().dark( 105 ) ); TQPainter p( m_backgroundPixmap ); // Erase background for scale p.fillRect( 0, 0, 7, height() -1, colorGroup().background()); // Draw scale p.setPen( colorGroup().shadow() ); p.drawLine( 7, 0, 7, height() - 1 ); p.drawLine( 0, 0, 7, 0 ); p.drawLine( 0, height() / 2 - 1, 7, height() / 2 - 1 ); p.drawLine( 0, height() - 1, 7, height() - 1 ); } void EqualizerGraph::init_spline( float* x, float* y, int n, float* y2 ) { int i, k; float p, qn, sig, un; TQMemArray u(n * sizeof(float)); y2[ 0 ] = u[ 0 ] = 0.0; for ( i = 1; i < n - 1; i++ ) { sig = ( (float)x[i] - x[i-1] ) / ( (float)x[i+1] - x[i-1] ); p = sig * y2[i-1] + 2.0; y2[i] = ( sig - 1.0 ) / p; u[i] = ( ( (float)y[i+1] - y[i] ) / ( x[i+1] - x[i] ) ) - ( ( (float)y[i] - y[i-1] ) / ( x[i] - x[i-1] ) ); u[i] = ( 6.0 * u[i] / ( x[i+1] - x[i-1] ) - sig * u[i-1] ) / p; } qn = un = 0.0; y2[n-1] = ( un - qn * u[n-2] ) / ( qn * y2[n-2] + 1.0 ); for ( k = n - 2; k >= 0; k-- ) y2[k] = y2[k] * y2[k+1] + u[k]; } float EqualizerGraph::eval_spline( float xa[], float ya[], float y2a[], int n, float x ) { int klo, khi, k; float h, b, a; klo = 0; khi = n - 1; while ( khi - klo > 1 ) { k = ( khi + klo ) >> 1; if ( xa[k] > x ) khi = k; else klo = k; } h = xa[khi] - xa[klo]; a = ( xa[khi] - x ) / h; b = ( x - xa[klo] ) / h; return ( a * ya[klo] + b * ya[khi] + ( ( a*a*a - a ) * y2a[klo] + ( b*b*b - b ) * y2a[khi] ) * ( h*h ) / 6.0 ); }