add mp3 and ogg torrent url info to JamendoAlbum
[amarok.git] / src / equalizergraph.cpp
blob8e3164e8d645c6a6ed7d3afda683eff823f0647d
1 /***************************************************************************
2 Graphical spline display for equalizer
4 (c) 2004 Mark Kretschmann <markey@web.de>
5 (c) 2005 Markus Brueffer <markus@brueffer.de>
6 Based on code from XMMS
7 (c) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
8 ***************************************************************************/
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18 #include "equalizergraph.h"
20 #include "amarokconfig.h"
22 #include <QPainter>
23 #include <QPixmap>
24 #include <QVector>
27 EqualizerGraph::EqualizerGraph( QWidget* parent )
28 : QWidget( parent, 0, Qt::WNoAutoErase )
29 , m_backgroundPixmap( new QPixmap() )
33 EqualizerGraph::~EqualizerGraph()
35 delete m_backgroundPixmap;
39 /////////////////////////////////////////////////////////////////////////////////////
40 // PROTECTED
41 /////////////////////////////////////////////////////////////////////////////////////
43 void
44 EqualizerGraph::resizeEvent( QResizeEvent* )
46 drawBackground();
49 QSize
50 EqualizerGraph::sizeHint() const
52 return QSize( 100, 60 );
55 void
56 EqualizerGraph::paintEvent( QPaintEvent* )
58 QPainter p( this );
59 p.drawPixmap( 0, 0, *m_backgroundPixmap );
61 // Draw middle line
62 int middleLineY = (int) ( ( height() - 1 ) / 2.0 + AmarokConfig::equalizerPreamp() * ( height() - 1 ) / 200.0 );
63 QPen pen( colorGroup().dark(), 0, Qt::DotLine);
64 p.setPen( pen );
65 p.drawLine( 8, middleLineY, width() - 1, middleLineY );
67 QColor color( colorGroup().highlight() );
68 int h, s, v;
69 color.getHsv( &h, &s, &v );
71 int i, y, ymin, ymax, py = 0;
72 float x[NUM_BANDS], yf[NUM_BANDS];
73 float gains[NUM_BANDS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0};
75 // Don't calculate 0 and NUM_BANDS-1 for accuracy reasons
76 for ( i = 1; i < NUM_BANDS -1 ; i++)
77 x[i] = ( width() - 8 ) * i / ( NUM_BANDS -1 ) + 8;
78 x[ 0 ] = 8;
79 x[ NUM_BANDS - 1 ] = width() - 1;
81 if ( AmarokConfig::equalizerEnabled() )
82 for ( i = 0; i < NUM_BANDS; i++ )
83 gains[i] = ( height() - 1 ) * AmarokConfig::equalizerGains()[i] / 200.0;
85 init_spline( x, gains, NUM_BANDS, yf );
87 for ( i = 8; i < width(); i++ ) {
88 y = (int) ( ( height() - 1 ) / 2 - eval_spline( x, gains, yf, NUM_BANDS, i ) );
90 if ( y < 0 )
91 y = 0;
93 if ( y > height() - 1 )
94 y = height() - 1;
96 if ( i == 8 )
97 py = y;
99 if ( y < py ) {
100 ymin = y;
101 ymax = py;
102 } else {
103 ymin = py;
104 ymax = y;
107 py = y;
108 for ( y = ymin; y <= ymax; y++ ) {
109 // Absolute carthesian coordinate
110 s = y - ( height() - 1 ) / 2;
111 s = QABS(s);
113 // Normalise to a base of 256
114 // short for: s / ( ( height() / 2.0 ) * 255;
115 s = (int) ( s * 510.0 / height() );
117 color.setHsv( h, 255 - s, v );
118 p.setPen( color );
120 p.drawPoint( i, y );
126 /////////////////////////////////////////////////////////////////////////////////////
127 // PRIVATE
128 /////////////////////////////////////////////////////////////////////////////////////
130 void
131 EqualizerGraph::drawBackground()
133 m_backgroundPixmap->resize( size() );
135 m_backgroundPixmap->fill( colorGroup().background().dark( 105 ) );
136 QPainter p( m_backgroundPixmap );
138 // Erase background for scale
139 p.fillRect( 0, 0, 7, height() -1, colorGroup().background());
141 // Draw scale
142 p.setPen( colorGroup().shadow() );
143 p.drawLine( 7, 0, 7, height() - 1 );
144 p.drawLine( 0, 0, 7, 0 );
145 p.drawLine( 0, height() / 2 - 1, 7, height() / 2 - 1 );
146 p.drawLine( 0, height() - 1, 7, height() - 1 );
150 void
151 EqualizerGraph::init_spline( float* x, float* y, int n, float* y2 )
153 int i, k;
154 float p, qn, sig, un;
155 QVector<float> u(n * sizeof(float));
157 y2[ 0 ] = u[ 0 ] = 0.0;
159 for ( i = 1; i < n - 1; i++ ) {
160 sig = ( (float)x[i] - x[i-1] ) / ( (float)x[i+1] - x[i-1] );
161 p = sig * y2[i-1] + 2.0;
162 y2[i] = ( sig - 1.0 ) / p;
163 u[i] = ( ( (float)y[i+1] - y[i] ) / ( x[i+1] - x[i] ) ) - ( ( (float)y[i] - y[i-1] ) / ( x[i] - x[i-1] ) );
164 u[i] = ( 6.0 * u[i] / ( x[i+1] - x[i-1] ) - sig * u[i-1] ) / p;
166 qn = un = 0.0;
168 y2[n-1] = ( un - qn * u[n-2] ) / ( qn * y2[n-2] + 1.0 );
169 for ( k = n - 2; k >= 0; k-- )
170 y2[k] = y2[k] * y2[k+1] + u[k];
174 float
175 EqualizerGraph::eval_spline( float xa[], float ya[], float y2a[], int n, float x )
177 int klo, khi, k;
178 float h, b, a;
180 klo = 0;
181 khi = n - 1;
182 while ( khi - klo > 1 ) {
183 k = ( khi + klo ) >> 1;
184 if ( xa[k] > x )
185 khi = k;
186 else
187 klo = k;
189 h = xa[khi] - xa[klo];
190 a = ( xa[khi] - x ) / h;
191 b = ( x - xa[klo] ) / h;
192 return ( a * ya[klo] + b * ya[khi] + ( ( a*a*a - a ) * y2a[klo] + ( b*b*b - b ) * y2a[khi] ) * ( h*h ) / 6.0 );