EqCurve.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*
  2. * EqCurve.cpp - declaration of EqCurve and EqHandle classes.
  3. *
  4. * Copyright (c) 2015 Steffen Baranowsky <BaraMGB/at/freenet/dot/de>
  5. *
  6. * This file is part of LMMS - https://lmms.io
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public
  19. * License along with this program (see COPYING); if not, write to the
  20. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301 USA.
  22. *
  23. */
  24. #include "EqCurve.h"
  25. #include "Effect.h"
  26. #include "embed.h"
  27. #include "lmms_math.h"
  28. EqHandle::EqHandle( int num, int x, int y ):
  29. m_numb( num ),
  30. m_width( x ),
  31. m_heigth( y ),
  32. m_mousePressed( false ),
  33. m_active( false )
  34. {
  35. setFlag( ItemIsMovable );
  36. setFlag( ItemSendsGeometryChanges );
  37. setAcceptHoverEvents( true );
  38. float totalHeight = 36;
  39. m_pixelsPerUnitHeight = ( m_heigth ) / ( totalHeight );
  40. setMouseHover( false );
  41. }
  42. QRectF EqHandle::boundingRect() const
  43. {
  44. return QRectF( - m_circlePixmap.width() / 2, - m_circlePixmap.height() / 2, m_circlePixmap.width(), m_circlePixmap.height() );
  45. }
  46. float EqHandle::freqToXPixel( float freq , int w )
  47. {
  48. float min = log10f( 20 );
  49. float max = log10f( 20000 );
  50. float range = max - min;
  51. return ( log10f( freq ) - min ) / range * w;
  52. }
  53. float EqHandle::xPixelToFreq( float x , int w )
  54. {
  55. float min = log10f( 20 );
  56. float max = log10f( 20000 );
  57. float range = max - min;
  58. return powf( 10 , x * ( range / w ) + min );
  59. }
  60. float EqHandle::gainToYPixel(float gain , int h, float pixelPerUnitHeight )
  61. {
  62. return h * 0.5 - gain * pixelPerUnitHeight;
  63. }
  64. float EqHandle::yPixelToGain(float y , int h, float pixelPerUnitHeight )
  65. {
  66. return ( ( h * 0.5 ) - y ) / pixelPerUnitHeight;
  67. }
  68. void EqHandle::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
  69. {
  70. painter->setRenderHint( QPainter::Antialiasing, true );
  71. if ( m_mousePressed )
  72. {
  73. emit positionChanged();
  74. }
  75. // graphics for the handles
  76. loadPixmap();
  77. painter->drawPixmap( - ( m_circlePixmap.width() / 2 ) - 1 , - ( m_circlePixmap.height() / 2 ), m_circlePixmap );
  78. // on mouse hover draw an info box and change the pixmap of the handle
  79. if ( isMouseHover() )
  80. {
  81. // keeps the info box in view
  82. float rectX = -40;
  83. float rectY = -40;
  84. if ( EqHandle::y() < 40 )
  85. {
  86. rectY = rectY + 40 - EqHandle::y();
  87. }
  88. if ( EqHandle::x() < 40 )
  89. {
  90. rectX = rectX + 40 - EqHandle::x();
  91. }
  92. if ( EqHandle::x() > m_width - 40 )
  93. {
  94. rectX = rectX - ( 40 - ( m_width - EqHandle::x() ) );
  95. }
  96. QPixmap hover = PLUGIN_NAME::getIconPixmap( "handlehover" );
  97. painter->drawPixmap( - ( hover.width() / 2) - 1, - ( hover.height() / 2 ), hover );
  98. QRectF textRect = QRectF ( rectX, rectY, 80, 30 );
  99. QRectF textRect2 = QRectF ( rectX+1, rectY+1, 80, 30 );
  100. QString freq = QString::number( xPixelToFreq( EqHandle::x(), m_width ) );
  101. QString res;
  102. if ( getType() != para )
  103. {
  104. res = tr( "Reso: ") + QString::number( getResonance() );
  105. }
  106. else
  107. {
  108. res = tr( "BW: " ) + QString::number( getResonance() );
  109. }
  110. QFont painterFont = painter->font();
  111. painterFont.setPointSizeF( painterFont.pointSizeF() * 0.7 );
  112. painter->setFont( painterFont );
  113. painter->setPen( Qt::black );
  114. painter->drawRect( textRect );
  115. painter->fillRect( textRect, QBrush( QColor( 6, 106, 43, 180 ) ) );
  116. painter->setPen ( QColor( 0, 0, 0 ) );
  117. painter->drawText( textRect2, Qt::AlignCenter,
  118. QString( tr( "Freq: " ) + freq + "\n" + res ) );
  119. painter->setPen( QColor( 255, 255, 255 ) );
  120. painter->drawText( textRect, Qt::AlignCenter,
  121. QString( tr( "Freq: " ) + freq + "\n" + res ) );
  122. }
  123. }
  124. QPainterPath EqHandle::getCurvePath()
  125. {
  126. QPainterPath path;
  127. float y = m_heigth * 0.5;
  128. for ( float x = 0 ; x < m_width; x++ )
  129. {
  130. if ( m_type == highpass ) y = getLowCutCurve( x );
  131. if ( m_type == lowshelf ) y = getLowShelfCurve( x );
  132. if ( m_type == para ) y = getPeakCurve( x );
  133. if ( m_type == highshelf ) y = getHighShelfCurve( x );
  134. if ( m_type == lowpass ) y = getHighCutCurve( x );
  135. if ( x == 0 ) path.moveTo( x, y ); // sets the begin of Path
  136. path.lineTo( x, y );
  137. }
  138. return path;
  139. }
  140. void EqHandle::loadPixmap()
  141. {
  142. QString fileName = "handle" + QString::number(m_numb+1);
  143. if ( !isActiveHandle() ) { fileName = fileName + "inactive"; }
  144. m_circlePixmap = PLUGIN_NAME::getIconPixmap( fileName.toLatin1() );
  145. }
  146. bool EqHandle::mousePressed() const
  147. {
  148. return m_mousePressed;
  149. }
  150. float EqHandle::getPeakCurve( float x )
  151. {
  152. double freqZ = xPixelToFreq( EqHandle::x(), m_width );
  153. const int SR = Engine::mixer()->processingSampleRate();
  154. double w0 = 2 * LD_PI * freqZ / SR ;
  155. double c = cosf( w0 );
  156. double s = sinf( w0 );
  157. double Q = getResonance();
  158. double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 40 );
  159. double alpha = s * sinh( log( 2 ) / 2 * Q * w0 / sinf( w0 ) );
  160. double a0, a1, a2, b0, b1, b2; // coeffs to calculate
  161. //calc coefficents
  162. b0 = 1 + alpha * A;
  163. b1 = -2 * c;
  164. b2 = 1 - alpha * A;
  165. a0 = 1 + alpha / A;
  166. a1 = -2 * c;
  167. a2 = 1 - alpha / A;
  168. //normalise
  169. b0 /= a0;
  170. b1 /= a0;
  171. b2 /= a0;
  172. a1 /= a0;
  173. a2 /= a0;
  174. a0 = 1;
  175. double freq = xPixelToFreq( x, m_width );
  176. double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
  177. float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );
  178. return y;
  179. }
  180. float EqHandle::getHighShelfCurve( float x )
  181. {
  182. double freqZ = xPixelToFreq( EqHandle::x(), m_width );
  183. const int SR = Engine::mixer()->processingSampleRate();
  184. double w0 = 2 * LD_PI * freqZ / SR;
  185. double c = cosf( w0 );
  186. double s = sinf( w0 );
  187. double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) * 0.025 );
  188. double beta = sqrt( A ) / m_resonance;
  189. double a0, a1, a2, b0, b1, b2; // coeffs to calculate
  190. //calc coefficents
  191. b0 = A * ( ( A + 1 ) + ( A - 1 ) * c + beta * s);
  192. b1 = -2 * A * ( ( A - 1 ) + ( A + 1 ) * c );
  193. b2 = A * ( ( A + 1 ) + ( A - 1 ) * c - beta * s);
  194. a0 = ( A + 1 ) - ( A - 1 ) * c + beta * s;
  195. a1 = 2 * ( ( A - 1 ) - ( A + 1 ) * c );
  196. a2 = ( A + 1 ) - ( A - 1 ) * c - beta * s;
  197. //normalise
  198. b0 /= a0;
  199. b1 /= a0;
  200. b2 /= a0;
  201. a1 /= a0;
  202. a2 /= a0;
  203. a0 = 1;
  204. double freq = xPixelToFreq( x, m_width );
  205. double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
  206. float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );
  207. return y;
  208. }
  209. float EqHandle::getLowShelfCurve( float x )
  210. {
  211. double freqZ = xPixelToFreq( EqHandle::x(), m_width );
  212. const int SR = Engine::mixer()->processingSampleRate();
  213. double w0 = 2 * LD_PI * freqZ / SR ;
  214. double c = cosf( w0 );
  215. double s = sinf( w0 );
  216. double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 40 );
  217. double beta = sqrt( A ) / m_resonance;
  218. double a0, a1, a2, b0, b1, b2; // coeffs to calculate
  219. //calc coefficents
  220. b0 = A * ( ( A + 1 ) - ( A - 1 ) * c + beta * s );
  221. b1 = 2 * A * ( ( A - 1 ) - ( A + 1 ) * c ) ;
  222. b2 = A * ( ( A + 1 ) - ( A - 1 ) * c - beta * s);
  223. a0 = ( A + 1 ) + ( A - 1 ) * c + beta * s;
  224. a1 = -2 * ( ( A - 1 ) + ( A + 1 ) * c );
  225. a2 = ( A + 1 ) + ( A - 1) * c - beta * s;
  226. //normalise
  227. b0 /= a0;
  228. b1 /= a0;
  229. b2 /= a0;
  230. a1 /= a0;
  231. a2 /= a0;
  232. a0 = 1;
  233. double freq = xPixelToFreq( x, m_width );
  234. double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
  235. float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );
  236. return y;
  237. }
  238. float EqHandle::getLowCutCurve( float x )
  239. {
  240. double freqZ = xPixelToFreq( EqHandle::x(), m_width );
  241. const int SR = Engine::mixer()->processingSampleRate();
  242. double w0 = 2 * LD_PI * freqZ / SR ;
  243. double c = cosf( w0 );
  244. double s = sinf( w0 );
  245. double resonance = getResonance();
  246. double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20);
  247. double alpha = s / 2 * sqrt ( ( A +1/A ) * ( 1 / resonance -1 ) +2 );
  248. double a0, a1, a2, b0, b1, b2; // coeffs to calculate
  249. b0 = ( 1 + c ) * 0.5;
  250. b1 = ( -( 1 + c ) );
  251. b2 = ( 1 + c ) * 0.5;
  252. a0 = 1 + alpha;
  253. a1 = ( -2 * c );
  254. a2 = 1 - alpha;
  255. //normalise
  256. b0 /= a0;
  257. b1 /= a0;
  258. b2 /= a0;
  259. a1 /= a0;
  260. a2 /= a0;
  261. a0 = 1;
  262. double freq = xPixelToFreq( x, m_width );
  263. double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
  264. if ( m_hp24 )
  265. {
  266. gain = gain * 2;
  267. }
  268. if ( m_hp48 )
  269. {
  270. gain = gain * 3;
  271. }
  272. float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );
  273. return y;
  274. }
  275. float EqHandle::getHighCutCurve( float x )
  276. {
  277. double freqZ = xPixelToFreq( EqHandle::x(), m_width );
  278. const int SR = Engine::mixer()->processingSampleRate();
  279. double w0 = 2 * LD_PI * freqZ / SR ;
  280. double c = cosf( w0 );
  281. double s = sinf( w0 );
  282. double resonance = getResonance();
  283. double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20 );
  284. double alpha = s / 2 * sqrt ( ( A + 1 / A ) * ( 1 / resonance -1 ) +2 );
  285. double a0, a1, a2, b0, b1, b2; // coeffs to calculate
  286. b0 = ( 1 - c ) * 0.5;
  287. b1 = 1 - c;
  288. b2 = ( 1 - c ) * 0.5;
  289. a0 = 1 + alpha;
  290. a1 = -2 * c;
  291. a2 = 1 - alpha;
  292. //normalise
  293. b0 /= a0;
  294. b1 /= a0;
  295. b2 /= a0;
  296. a1 /= a0;
  297. a2 /= a0;
  298. a0 = 1;
  299. double freq = xPixelToFreq( x, m_width );
  300. double gain = calculateGain( freq, a1, a2, b0, b1, b2 );
  301. if ( m_lp24 )
  302. {
  303. gain = gain * 2;
  304. }
  305. if ( m_lp48 )
  306. {
  307. gain = gain * 3;
  308. }
  309. float y = gainToYPixel( gain, m_heigth, m_pixelsPerUnitHeight );
  310. return y;
  311. }
  312. float EqHandle::getResonance()
  313. {
  314. return m_resonance;
  315. }
  316. int EqHandle::getNum()
  317. {
  318. return m_numb;
  319. }
  320. void EqHandle::setType( int t )
  321. {
  322. EqHandle::m_type = t;
  323. }
  324. void EqHandle::setResonance( float r )
  325. {
  326. EqHandle::m_resonance = r;
  327. }
  328. bool EqHandle::isMouseHover()
  329. {
  330. return m_mouseHover;
  331. }
  332. void EqHandle::setMouseHover( bool d )
  333. {
  334. m_mouseHover = d;
  335. }
  336. int EqHandle::getType()
  337. {
  338. return m_type;
  339. }
  340. bool EqHandle::isActiveHandle()
  341. {
  342. return m_active;
  343. }
  344. void EqHandle::setHandleActive( bool a )
  345. {
  346. EqHandle::m_active = a;
  347. }
  348. void EqHandle::sethp12()
  349. {
  350. m_hp12 = true;
  351. m_hp24 = false;
  352. m_hp48 = false;
  353. }
  354. void EqHandle::sethp24()
  355. {
  356. m_hp12 = false;
  357. m_hp24 = true;
  358. m_hp48 = false;
  359. }
  360. void EqHandle::sethp48()
  361. {
  362. m_hp12 = false;
  363. m_hp24 = false;
  364. m_hp48 = true;
  365. }
  366. void EqHandle::setlp12()
  367. {
  368. m_lp12 = true;
  369. m_lp24 = false;
  370. m_lp48 = false;
  371. }
  372. void EqHandle::setlp24()
  373. {
  374. m_lp12 = false;
  375. m_lp24 = true;
  376. m_lp48 = false;
  377. }
  378. void EqHandle::setlp48()
  379. {
  380. m_lp12 = false;
  381. m_lp24 = false;
  382. m_lp48 = true;
  383. }
  384. double EqHandle::calculateGain(const double freq, const double a1, const double a2, const double b0, const double b1, const double b2 )
  385. {
  386. const int SR = Engine::mixer()->processingSampleRate();
  387. const double w = 2 * LD_PI * freq / SR ;
  388. const double PHI = pow( sin( w / 2 ), 2 ) * 4;
  389. double gain = 10 * log10( pow( b0 + b1 + b2 , 2 ) + ( b0 * b2 * PHI - ( b1 * ( b0 + b2 )
  390. + 4 * b0 * b2 ) ) * PHI ) - 10 * log10( pow( 1 + a1 + a2, 2 )
  391. + ( 1 * a2 * PHI - ( a1 * ( 1 + a2 ) + 4 * 1 * a2 ) ) * PHI );
  392. return gain;
  393. }
  394. void EqHandle::mousePressEvent( QGraphicsSceneMouseEvent *event )
  395. {
  396. if( event->button() == Qt::LeftButton )
  397. {
  398. m_mousePressed = true;
  399. QGraphicsItem::mousePressEvent( event );
  400. }
  401. }
  402. void EqHandle::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
  403. {
  404. if( event->button() == Qt::LeftButton )
  405. {
  406. m_mousePressed = false;
  407. QGraphicsItem::mouseReleaseEvent( event );
  408. }
  409. }
  410. void EqHandle::wheelEvent( QGraphicsSceneWheelEvent *wevent )
  411. {
  412. float highestBandwich;
  413. if( m_type != para )
  414. {
  415. highestBandwich = 10;
  416. }
  417. else
  418. {
  419. highestBandwich = 4;
  420. }
  421. int numDegrees = wevent->delta() / 120;
  422. float numSteps = 0;
  423. if( wevent->modifiers() == Qt::ControlModifier )
  424. {
  425. numSteps = numDegrees * 0.01;
  426. }
  427. else
  428. {
  429. numSteps = numDegrees * 0.15;
  430. }
  431. if( wevent->orientation() == Qt::Vertical )
  432. {
  433. m_resonance = m_resonance + ( numSteps );
  434. if( m_resonance < 0.1 )
  435. {
  436. m_resonance = 0.1;
  437. }
  438. if( m_resonance > highestBandwich )
  439. {
  440. m_resonance = highestBandwich;
  441. }
  442. emit positionChanged();
  443. }
  444. wevent->accept();
  445. }
  446. void EqHandle::hoverEnterEvent( QGraphicsSceneHoverEvent *hevent )
  447. {
  448. setMouseHover( true );
  449. }
  450. void EqHandle::hoverLeaveEvent( QGraphicsSceneHoverEvent *hevent )
  451. {
  452. setMouseHover( false );
  453. }
  454. QVariant EqHandle::itemChange( QGraphicsItem::GraphicsItemChange change, const QVariant &value )
  455. {
  456. if( change == ItemPositionChange )
  457. {
  458. // pass filter don't move in y direction
  459. if ( m_type == highpass || m_type == lowpass )
  460. {
  461. float newX = value.toPointF().x();
  462. if( newX < 0 )
  463. {
  464. newX = 0;
  465. }
  466. if( newX > m_width )
  467. {
  468. newX = m_width;
  469. }
  470. return QPointF(newX, m_heigth/2);
  471. }
  472. }
  473. QPointF newPos = value.toPointF();
  474. QRectF rect = QRectF( 0, 0, m_width, m_heigth );
  475. if( !rect.contains( newPos ) )
  476. {
  477. // Keep the item inside the scene rect.
  478. newPos.setX( qMin( rect.right(), qMax( newPos.x(), rect.left() ) ) );
  479. newPos.setY( qMin( rect.bottom(), qMax( newPos.y(), rect.top() ) ) );
  480. return newPos;
  481. }
  482. return QGraphicsItem::itemChange( change, value );
  483. }
  484. // ----------------------------------------------------------------------
  485. //
  486. // Class EqCurve
  487. //
  488. // Every Handle calculates its own curve.
  489. // But EqCurve generates an average curve.
  490. //
  491. // ----------------------------------------------------------------------
  492. EqCurve::EqCurve( QList<EqHandle*> *handle, int x, int y ) :
  493. m_handle( handle ),
  494. m_width( x ),
  495. m_heigth( y ),
  496. m_alpha( 0 ),
  497. m_modelChanged( false )
  498. {
  499. }
  500. QRectF EqCurve::boundingRect() const
  501. {
  502. return QRect( 0, 0, m_width, m_heigth );
  503. }
  504. void EqCurve::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
  505. {
  506. painter->setRenderHint( QPainter::Antialiasing, true );
  507. if( m_modelChanged )
  508. {
  509. setModelChanged( false );
  510. //counts the active bands
  511. int activeHandles=0;
  512. for ( int thatHandle = 0; thatHandle<m_handle->count(); thatHandle++ )
  513. {
  514. if ( m_handle->at(thatHandle)->isActiveHandle() == true )
  515. {
  516. activeHandles++;
  517. }
  518. }
  519. //Computes the main curve
  520. //if a band is active the curve will be computed by averaging the curves of each band
  521. QMap<float,float> mainCurve;
  522. for ( int thatHandle = 0; thatHandle<m_handle->count(); thatHandle++ )
  523. {
  524. if ( m_handle->at(thatHandle)->isActiveHandle() == true )
  525. {
  526. for ( int x = 0; x < m_width ; x=x+1 )
  527. {
  528. if ( m_handle->at( thatHandle )->getType() == highpass )
  529. {
  530. mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
  531. }
  532. if ( m_handle->at(thatHandle)->getType() == lowshelf )
  533. {
  534. mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
  535. }
  536. if ( m_handle->at( thatHandle )->getType() == para )
  537. {
  538. mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getPeakCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
  539. }
  540. if ( m_handle->at( thatHandle )->getType() == highshelf )
  541. {
  542. mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
  543. }
  544. if ( m_handle->at(thatHandle)->getType() == lowpass )
  545. {
  546. mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) );
  547. }
  548. }
  549. }
  550. }
  551. //compute a QPainterPath
  552. m_curve = QPainterPath();
  553. for ( int x = 0; x < m_width ; x++ )
  554. {
  555. mainCurve[x] = ( ( mainCurve[x] / activeHandles ) ) - ( m_heigth/2 );
  556. if ( x==0 )
  557. {
  558. m_curve.moveTo( x, mainCurve[x] );
  559. }
  560. m_curve.lineTo( x, mainCurve[x] );
  561. }
  562. //we cache the curve painting in a pixmap for saving cpu
  563. QPixmap cacheMap( boundingRect().size().toSize() );
  564. cacheMap.fill( QColor( 0, 0, 0, 0 ) );
  565. QPainter cachePainter( &cacheMap );
  566. cachePainter.setRenderHint( QPainter::Antialiasing, true );
  567. QPen pen;
  568. pen.setWidth( 2 );
  569. pen.setColor( Qt::white );
  570. cachePainter.setPen( pen );
  571. cachePainter.drawPath( m_curve );
  572. cachePainter.end();
  573. m_curvePixmapCache.fill( QColor( 0, 0, 0, 0 ) );
  574. m_curvePixmapCache.swap( cacheMap );
  575. }
  576. //we paint our cached curve pixmap
  577. painter->drawPixmap( 0, 0, m_width, m_heigth, m_curvePixmapCache );
  578. // if mouse hover a handle, m_alpha counts up slow for blend in the filled EQ curve
  579. // todo: a smarter way of this "if-monster"
  580. QColor curveColor;
  581. if( m_handle->at( 0 )->isMouseHover()
  582. || m_handle->at( 1 )->isMouseHover()
  583. || m_handle->at( 2 )->isMouseHover()
  584. || m_handle->at( 3 )->isMouseHover()
  585. || m_handle->at( 4 )->isMouseHover()
  586. || m_handle->at( 5 )->isMouseHover()
  587. || m_handle->at( 6 )->isMouseHover()
  588. || m_handle->at( 7 )->isMouseHover()
  589. )
  590. {
  591. if ( m_alpha < 40 )
  592. {
  593. m_alpha = m_alpha + 10;
  594. }
  595. }
  596. else
  597. {
  598. if ( m_alpha > 0 )
  599. {
  600. m_alpha = m_alpha - 10;
  601. }
  602. }
  603. //draw on mouse hover the curve of hovered filter in different colors
  604. for ( int i = 0; i < m_handle->count(); i++ )
  605. {
  606. if ( m_handle->at(i)->isMouseHover() )
  607. {
  608. curveColor = QColor( qRgba( 6, 106, 43, 242 ));
  609. QPen pen ( curveColor);
  610. pen.setWidth( 2 );
  611. painter->setPen( pen );
  612. painter->drawPath( m_handle->at( i )->getCurvePath() );
  613. }
  614. }
  615. //draw on mouse hover the EQ curve filled. with m_alpha it blends in and out smooth
  616. QPainterPath cPath;
  617. cPath.addPath( m_curve );
  618. cPath.lineTo( cPath.currentPosition().x(), m_heigth );
  619. cPath.lineTo( cPath.elementAt( 0 ).x , m_heigth );
  620. painter->fillPath( cPath, QBrush ( QColor( 255,255,255, m_alpha ) ) );
  621. }
  622. void EqCurve::setModelChanged( bool mc )
  623. {
  624. m_modelChanged = mc;
  625. }