00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <cmath>
00014 #include <iostream>
00015
00016
00017 #include <qpainter.h>
00018 #include <qpixmap.h>
00019 #include <qimage.h>
00020 #include <qdir.h>
00021 #include <qurl.h>
00022
00023
00024 #include <mythtv/mythdbcon.h>
00025 #include <mythtv/mythcontext.h>
00026
00027
00028 #include "mainvisual.h"
00029 #include "visualize.h"
00030 #include "inlines.h"
00031 #include "decoder.h"
00032 #include "metadata.h"
00033
00034 using namespace std;
00035
00036
00037 #define FFTW_N 512
00038 extern "C" {
00039 void *av_malloc(unsigned int size);
00040 void av_free(void *ptr);
00041 }
00042
00043 Spectrum::Spectrum()
00044 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00045 : lin(NULL), rin(NULL), lout(NULL), rout(NULL)
00046 #endif
00047 {
00048
00049
00050 analyzerBarWidth = 6;
00051 scaleFactor = 2.0;
00052 falloff = 3.0;
00053 fps = 20;
00054
00055 #ifdef FFTW3_SUPPORT
00056 lin = (myth_fftw_float*) av_malloc(sizeof(myth_fftw_float)*FFTW_N);
00057 rin = (myth_fftw_float*) av_malloc(sizeof(myth_fftw_float)*FFTW_N);
00058 lout = (myth_fftw_complex*)
00059 av_malloc(sizeof(myth_fftw_complex)*(FFTW_N/2+1));
00060 rout = (myth_fftw_complex*)
00061 av_malloc(sizeof(myth_fftw_complex)*(FFTW_N/2+1));
00062
00063 lplan = fftw_plan_dft_r2c_1d(FFTW_N, lin, (myth_fftw_complex_cast*)lout, FFTW_MEASURE);
00064 rplan = fftw_plan_dft_r2c_1d(FFTW_N, rin, (myth_fftw_complex_cast*)rout, FFTW_MEASURE);
00065 #elif FFTW2_SUPPORT
00066 lin = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N);
00067 rin = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N);
00068 lout = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N*2);
00069 rout = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N*2);
00070
00071 plan = rfftw_create_plan(FFTW_N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE);
00072 #endif // FFTW2_SUPPORT
00073
00074 startColor = QColor(0,0,255);
00075 targetColor = QColor(255,0,0);
00076 }
00077
00078 Spectrum::~Spectrum()
00079 {
00080 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00081 if (lin)
00082 av_free(lin);
00083 if (rin)
00084 av_free(rin);
00085 if (lout)
00086 av_free(lout);
00087 if (rout)
00088 av_free(rout);
00089 #endif
00090 #ifdef FFTW3_SUPPORT
00091 fftw_destroy_plan(lplan);
00092 fftw_destroy_plan(rplan);
00093 #elif FFTW2_SUPPORT
00094 rfftw_destroy_plan(plan);
00095 #endif
00096 }
00097
00098 void Spectrum::resize(const QSize &newsize)
00099 {
00100
00101
00102
00103
00104
00105
00106 size = newsize;
00107
00108 scale.setMax(192, size.width() / analyzerBarWidth);
00109
00110 rects.resize( scale.range() );
00111 int i = 0, w = 0;
00112 for (; (unsigned) i < rects.count(); i++, w += analyzerBarWidth)
00113 {
00114 rects[i].setRect(w, size.height() / 2, analyzerBarWidth - 1, 1);
00115 }
00116
00117 int os = magnitudes.size();
00118 magnitudes.resize( scale.range() * 2 );
00119 for (; (unsigned) os < magnitudes.size(); os++)
00120 {
00121 magnitudes[os] = 0.0;
00122 }
00123
00124 scaleFactor = double( size.height() / 2 ) / log( (double)(FFTW_N) );
00125 }
00126
00127 template<typename T> T sq(T a) { return a*a; };
00128
00129 bool Spectrum::process(VisualNode *node)
00130 {
00131
00132
00133
00134 bool allZero = TRUE;
00135
00136 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00137 uint i;
00138 long w = 0, index;
00139 QRect *rectsp = rects.data();
00140 double *magnitudesp = magnitudes.data();
00141 double magL, magR, tmp;
00142
00143 if (node)
00144 {
00145 i = node->length;
00146 fast_real_set_from_short(lin, node->left, node->length);
00147 if (node->right)
00148 fast_real_set_from_short(rin, node->right, node->length);
00149 }
00150 else
00151 i = 0;
00152
00153 fast_reals_set(lin + i, rin + i, 0, FFTW_N - i);
00154
00155 #ifdef FFTW3_SUPPORT
00156 fftw_execute(lplan);
00157 fftw_execute(rplan);
00158 #elif FFTW2_SUPPORT
00159 rfftw_one(plan, lin, lout);
00160 rfftw_one(plan, rin, rout);
00161 #endif
00162
00163 index = 1;
00164 for (i = 0; i < rects.count(); i++, w += analyzerBarWidth)
00165 {
00166 #ifdef FFTW3_SUPPORT
00167 magL = (log(sq(real(lout[index])) + sq(real(lout[FFTW_N - index]))) - 22.0) *
00168 scaleFactor;
00169 magR = (log(sq(real(rout[index])) + sq(real(rout[FFTW_N - index]))) - 22.0) *
00170 scaleFactor;
00171 #elif FFTW2_SUPPORT
00172 magL = (log(sq(lout[index]) + sq(lout[FFTW_N - index])) - 22.0) *
00173 scaleFactor;
00174 magR = (log(sq(rout[index]) + sq(rout[FFTW_N - index])) - 22.0) *
00175 scaleFactor;
00176 #endif
00177
00178 if (magL > size.height() / 2)
00179 {
00180 magL = size.height() / 2;
00181 }
00182 if (magL < magnitudesp[i])
00183 {
00184 tmp = magnitudesp[i] - falloff;
00185 if ( tmp < magL )
00186 {
00187 tmp = magL;
00188 }
00189 magL = tmp;
00190 }
00191 if (magL < 1.)
00192 {
00193 magL = 1.;
00194 }
00195
00196 if (magR > size.height() / 2)
00197 {
00198 magR = size.height() / 2;
00199 }
00200 if (magR < magnitudesp[i + scale.range()])
00201 {
00202 tmp = magnitudesp[i + scale.range()] - falloff;
00203 if ( tmp < magR )
00204 {
00205 tmp = magR;
00206 }
00207 magR = tmp;
00208 }
00209 if (magR < 1.)
00210 {
00211 magR = 1.;
00212 }
00213
00214 if (magR != 1 || magL != 1)
00215 {
00216 allZero = FALSE;
00217 }
00218
00219 magnitudesp[i] = magL;
00220 magnitudesp[i + scale.range()] = magR;
00221
00222 rectsp[i].setTop( size.height() / 2 - int( magL ) );
00223 rectsp[i].setBottom( size.height() / 2 + int( magR ) );
00224
00225 index = scale[i];
00226 }
00227 #else
00228 node = node;
00229 #endif
00230 return allZero;
00231 }
00232
00233 double Spectrum::clamp(double cur, double max, double min)
00234 {
00235 if (cur > max)
00236 cur = max;
00237 if (cur < min)
00238 cur = min;
00239 return cur;
00240 }
00241
00242 bool Spectrum::draw(QPainter *p, const QColor &back)
00243 {
00244
00245
00246
00247
00248
00249
00250 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00251 QRect *rectsp = rects.data();
00252 double r, g, b, per;
00253
00254 p->fillRect(0, 0, size.width(), size.height(), back);
00255 for (uint i = 0; i < rects.count(); i++)
00256 {
00257 per = double( rectsp[i].height() - 2 ) / double( size.height() );
00258
00259 per = clamp(per, 1.0, 0.0);
00260
00261 r = startColor.red() +
00262 (targetColor.red() - startColor.red()) * (per * per);
00263 g = startColor.green() +
00264 (targetColor.green() - startColor.green()) * (per * per);
00265 b = startColor.blue() +
00266 (targetColor.blue() - startColor.blue()) * (per * per);
00267
00268 r = clamp(r, 255.0, 0.0);
00269 g = clamp(g, 255.0, 0.0);
00270 b = clamp(b, 255.0, 0.0);
00271
00272 if(rectsp[i].height() > 4)
00273 p->fillRect(rectsp[i], QColor(int(r), int(g), int(b)));
00274 }
00275
00276 #else
00277
00278 drawWarning(p, back, size,
00279 QObject::tr("Visualization requires FFT library") + "\n" +
00280 QObject::tr("Did you run configure?"));
00281 #endif
00282
00283 return true;
00284 }
00285
00286 static class SpectrumFactory : public VisFactory
00287 {
00288 public:
00289 const QString &name(void) const
00290 {
00291 static QString name("Spectrum");
00292 return name;
00293 }
00294
00295 uint plugins(QStringList *list) const
00296 {
00297 *list << name();
00298 return 1;
00299 }
00300
00301 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
00302 {
00303 (void)parent;
00304 (void)winid;
00305 (void)pluginName;
00306 return new Spectrum();
00307 }
00308 }SpectrumFactory;
00309
00310 AlbumArt::AlbumArt(MainVisual *parent)
00311 {
00312 m_pParent = parent;
00313
00314 findFrontCover();
00315
00316 Decoder *dec = m_pParent->decoder();
00317 if (dec)
00318 m_filename = dec->getFilename();
00319
00320 fps = 1;
00321 }
00322
00323 void AlbumArt::findFrontCover(void)
00324 {
00325
00326 AlbumArtImages albumArt(m_pParent->metadata());
00327 if (albumArt.isImageAvailable(IT_FRONTCOVER))
00328 m_currImageType = IT_FRONTCOVER;
00329 else
00330 {
00331
00332 if (albumArt.getImageCount() > 0)
00333 m_currImageType = albumArt.getImageAt(0).imageType;
00334 else
00335 m_currImageType = IT_UNKNOWN;
00336 }
00337 }
00338
00339 AlbumArt::~AlbumArt()
00340 {
00341 }
00342
00343 void AlbumArt::resize(const QSize &newsize)
00344 {
00345 m_size = newsize;
00346 }
00347
00348 bool AlbumArt::process(VisualNode *node)
00349 {
00350 node = node;
00351 return true;
00352 }
00353
00354 void AlbumArt::handleKeyPress(const QString &action)
00355 {
00356 if (action == "SELECT")
00357 {
00358 AlbumArtImages albumArt(m_pParent->metadata());
00359 int newType = m_currImageType;
00360
00361 if (albumArt.getImageCount() > 0)
00362 {
00363 newType++;
00364
00365 while(!albumArt.isImageAvailable((ImageType) newType))
00366 {
00367 newType++;
00368 if (newType == IT_LAST)
00369 newType = IT_UNKNOWN;
00370 }
00371 }
00372
00373 if (newType != m_currImageType)
00374 {
00375 m_currImageType = (ImageType) newType;
00376
00377 m_cursize = QSize(0, 0);
00378 }
00379 }
00380 }
00381
00382 bool AlbumArt::needsUpdate()
00383 {
00384 if (m_cursize != m_size)
00385 return true;
00386
00387 if (m_filename != m_pParent->decoder()->getFilename())
00388 {
00389 m_filename = m_pParent->decoder()->getFilename();
00390 findFrontCover();
00391 return true;
00392 }
00393
00394 return false;
00395 }
00396
00397 bool AlbumArt::draw(QPainter *p, const QColor &back)
00398 {
00399 if (!m_pParent->decoder())
00400 return false;
00401
00402
00403 if (needsUpdate())
00404 {
00405 QImage art(m_pParent->metadata()->getAlbumArt(m_currImageType));
00406 if (art.isNull())
00407 {
00408 m_cursize = m_size;
00409 m_image = QImage();
00410 }
00411 else
00412 {
00413 m_image = art.smoothScale(m_size, QImage::ScaleMin);
00414 }
00415 }
00416
00417 if (m_image.isNull()) {
00418 drawWarning(p, back, m_size, QObject::tr("?"));
00419 return true;
00420 }
00421
00422
00423 p->fillRect(0, 0, m_size.width(), m_size.height(), back);
00424 p->drawPixmap((m_size.width() - m_image.width()) / 2,
00425 (m_size.height() - m_image.height()) / 2,
00426 m_image);
00427
00428
00429 m_cursize = m_size;
00430
00431 return true;
00432 }
00433
00434 static class AlbumArtFactory : public VisFactory
00435 {
00436 public:
00437 const QString &name(void) const
00438 {
00439 static QString name("AlbumArt");
00440 return name;
00441 }
00442
00443 uint plugins(QStringList *list) const
00444 {
00445 *list << name();
00446 return 1;
00447 }
00448
00449 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
00450 {
00451 (void)winid;
00452 (void)pluginName;
00453 return new AlbumArt(parent);
00454 }
00455 }AlbumArtFactory;
00456
00457 Blank::Blank()
00458 : VisualBase(true)
00459 {
00460 fps = 20;
00461 }
00462
00463 Blank::~Blank()
00464 {
00465 }
00466
00467 void Blank::resize(const QSize &newsize)
00468 {
00469 size = newsize;
00470 }
00471
00472
00473 bool Blank::process(VisualNode *node)
00474 {
00475 node = node;
00476 return true;
00477 }
00478
00479 bool Blank::draw(QPainter *p, const QColor &back)
00480 {
00481
00482 p->fillRect(0, 0, size.width(), size.height(), back);
00483 return true;
00484 }
00485
00486 static class BlankFactory : public VisFactory
00487 {
00488 public:
00489 const QString &name(void) const
00490 {
00491 static QString name("Blank");
00492 return name;
00493 }
00494
00495 uint plugins(QStringList *list) const
00496 {
00497 *list << name();
00498 return 1;
00499 }
00500
00501 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
00502 {
00503 (void)parent;
00504 (void)winid;
00505 (void)pluginName;
00506 return new Blank();
00507 }
00508 }BlankFactory;
00509
00510 Squares::Squares()
00511 {
00512 number_of_squares = 16;
00513 fake_height = number_of_squares * analyzerBarWidth;
00514 }
00515
00516 Squares::~Squares()
00517 {
00518 }
00519
00520 void Squares::resize (const QSize &newsize) {
00521
00522 Spectrum::resize (QSize (fake_height, fake_height));
00523
00524 size = newsize;
00525 }
00526
00527 void Squares::drawRect(QPainter *p, QRect *rect, int i, int c, int w, int h)
00528 {
00529 double r, g, b, per;
00530 int correction = (size.width() % rects.size ()) / 2;
00531 int x = ((i / 2) * w) + correction;
00532 int y;
00533
00534 if (i % 2 == 0)
00535 {
00536 y = c - h;
00537 per = double(fake_height - rect->top()) / double(fake_height);
00538 }
00539 else
00540 {
00541 y = c;
00542 per = double(rect->bottom()) / double(fake_height);
00543 }
00544
00545 per = clamp(per, 1.0, 0.0);
00546
00547 r = startColor.red() +
00548 (targetColor.red() - startColor.red()) * (per * per);
00549 g = startColor.green() +
00550 (targetColor.green() - startColor.green()) * (per * per);
00551 b = startColor.blue() +
00552 (targetColor.blue() - startColor.blue()) * (per * per);
00553
00554 r = clamp(r, 255.0, 0.0);
00555 g = clamp(g, 255.0, 0.0);
00556 b = clamp(b, 255.0, 0.0);
00557
00558 p->fillRect (x, y, w, h, QColor (int(r), int(g), int(b)));
00559 }
00560
00561 bool Squares::draw(QPainter *p, const QColor &back)
00562 {
00563 p->fillRect (0, 0, size.width (), size.height (), back);
00564 int w = size.width () / (rects.size () / 2);
00565 int h = w;
00566 int center = size.height () / 2;
00567
00568 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00569 QRect *rectsp = rects.data();
00570 for (uint i = 0; i < rects.count(); i++)
00571 drawRect(p, &(rectsp[i]), i, center, w, h);
00572
00573 #else
00574
00575 drawWarning(p, back, size,
00576 QObject::tr("Visualization requires FFT library") + "\n" +
00577 QObject::tr("Did you run configure?"));
00578 #endif
00579
00580 return true;
00581
00582 for (int x = 0; x < size.width (); x += w) {
00583 p->fillRect (x, center - h / 2, w, h, QColor ("red"));
00584 p->fillRect (x, center + h / 2, w, h, QColor ("blue"));
00585 }
00586 return true;
00587 }
00588
00589 static class SquaresFactory : public VisFactory
00590 {
00591 public:
00592 const QString &name(void) const
00593 {
00594 static QString name("Squares");
00595 return name;
00596 }
00597
00598 uint plugins(QStringList *list) const
00599 {
00600 *list << name();
00601 return 1;
00602 }
00603
00604 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
00605 {
00606 (void)parent;
00607 (void)winid;
00608 (void)pluginName;
00609 return new Squares();
00610 }
00611 }SquaresFactory;
00612
00613 #ifdef OPENGL_SUPPORT
00614
00615
00616 static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
00617 GLint teeth, GLfloat tooth_depth )
00618 {
00619 GLint i;
00620 GLfloat r0, r1, r2;
00621 GLfloat angle, da;
00622 GLfloat u, v, len;
00623
00624 r0 = inner_radius;
00625 r1 = outer_radius - tooth_depth/2.0;
00626 r2 = outer_radius + tooth_depth/2.0;
00627
00628 const double pi = 3.14159264;
00629 da = 2.0*pi / teeth / 4.0;
00630
00631 glShadeModel( GL_FLAT );
00632
00633 glNormal3f( 0.0, 0.0, 1.0 );
00634
00635
00636 glBegin( GL_QUAD_STRIP );
00637 for (i=0;i<=teeth;i++) {
00638 angle = i * 2.0*pi / teeth;
00639 glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
00640 glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
00641 glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
00642 glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
00643 }
00644 glEnd();
00645
00646
00647 glBegin( GL_QUADS );
00648 da = 2.0*pi / teeth / 4.0;
00649 for (i=0;i<teeth;i++) {
00650 angle = i * 2.0*pi / teeth;
00651
00652 glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
00653 glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
00654 glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
00655 glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
00656 }
00657 glEnd();
00658
00659
00660 glNormal3f( 0.0, 0.0, -1.0 );
00661
00662
00663 glBegin( GL_QUAD_STRIP );
00664 for (i=0;i<=teeth;i++) {
00665 angle = i * 2.0*pi / teeth;
00666 glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
00667 glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
00668 glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
00669 glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
00670 }
00671 glEnd();
00672
00673
00674 glBegin( GL_QUADS );
00675 da = 2.0*pi / teeth / 4.0;
00676 for (i=0;i<teeth;i++) {
00677 angle = i * 2.0*pi / teeth;
00678
00679 glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
00680 glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
00681 glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
00682 glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
00683 }
00684 glEnd();
00685
00686
00687
00688 glBegin( GL_QUAD_STRIP );
00689 for (i=0;i<teeth;i++) {
00690 angle = i * 2.0*pi / teeth;
00691
00692 glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
00693 glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
00694 u = r2*cos(angle+da) - r1*cos(angle);
00695 v = r2*sin(angle+da) - r1*sin(angle);
00696 len = sqrt( u*u + v*v );
00697 u /= len;
00698 v /= len;
00699 glNormal3f( v, -u, 0.0 );
00700 glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
00701 glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
00702 glNormal3f( cos(angle), sin(angle), 0.0 );
00703 glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
00704 glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
00705 u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
00706 v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
00707 glNormal3f( v, -u, 0.0 );
00708 glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
00709 glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
00710 glNormal3f( cos(angle), sin(angle), 0.0 );
00711 }
00712
00713 glVertex3f( r1*cos(0.0), r1*sin(0.0), width*0.5 );
00714 glVertex3f( r1*cos(0.0), r1*sin(0.0), -width*0.5 );
00715
00716 glEnd();
00717
00718
00719 glShadeModel( GL_SMOOTH );
00720
00721
00722 glBegin( GL_QUAD_STRIP );
00723 for (i=0;i<=teeth;i++) {
00724 angle = i * 2.0*pi / teeth;
00725 glNormal3f( -cos(angle), -sin(angle), 0.0 );
00726 glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
00727 glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
00728 }
00729 glEnd();
00730
00731 }
00732
00733
00734
00735
00736
00737 static GLfloat view_rotx=20.0, view_rotz=0.0;
00738 static GLint gear1, gear2, gear3;
00739
00740 Gears::Gears(QWidget *parent, const char *name)
00741 : QGLWidget(parent, name)
00742 {
00743 falloff = 4.0;
00744 analyzerBarWidth = 10;
00745 fps = 60;
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 setGeometry(0, 0, parent->width(), parent->height());
00756
00757
00758
00759 angle = 0.0;
00760 view_roty = 30.0;
00761
00762 #ifdef FFTW3_SUPPORT
00763 lin = (myth_fftw_float*) av_malloc(sizeof(myth_fftw_float)*FFTW_N);
00764 rin = (myth_fftw_float*) av_malloc(sizeof(myth_fftw_float)*FFTW_N);
00765 lout = (myth_fftw_complex*)
00766 av_malloc(sizeof(myth_fftw_complex)*(FFTW_N/2+1));
00767 rout = (myth_fftw_complex*)
00768 av_malloc(sizeof(myth_fftw_complex)*(FFTW_N/2+1));
00769
00770 lplan = fftw_plan_dft_r2c_1d(FFTW_N, lin, (myth_fftw_complex_cast*) lout, FFTW_MEASURE);
00771 rplan = fftw_plan_dft_r2c_1d(FFTW_N, rin, (myth_fftw_complex_cast*) rout, FFTW_MEASURE);
00772 #elif FFTW2_SUPPORT
00773 lin = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N);
00774 rin = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N);
00775 lout = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N*2);
00776 rout = (fftw_real*) av_malloc(sizeof(fftw_real)*FFTW_N*2);
00777
00778 plan = rfftw_create_plan(FFTW_N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE);
00779 #endif // FFTW2_SUPPORT
00780
00781
00782 startColor = QColor(0,0,255);
00783 targetColor = QColor(255,0,0);
00784
00785 show();
00786 }
00787
00788 Gears::~Gears()
00789 {
00790 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00791 if (lin)
00792 av_free(lin);
00793 if (rin)
00794 av_free(rin);
00795 if (lout)
00796 av_free(lout);
00797 if (rout)
00798 av_free(rout);
00799 #endif
00800 #ifdef FFTW3_SUPPORT
00801 fftw_destroy_plan(lplan);
00802 fftw_destroy_plan(rplan);
00803 #elif FFTW2_SUPPORT
00804 rfftw_destroy_plan(plan);
00805 #endif
00806 }
00807
00808 void Gears::resize(const QSize &newsize)
00809 {
00810
00811 size = newsize;
00812 scale.setMax(192, size.width() / analyzerBarWidth);
00813
00814 rects.resize( scale.range() );
00815 int i = 0, w = 0;
00816 for (; (unsigned) i < rects.count(); i++, w += analyzerBarWidth)
00817 {
00818 rects[i].setRect(w, size.height() / 2, analyzerBarWidth - 1, 1);
00819 }
00820
00821 int os = magnitudes.size();
00822 magnitudes.resize( scale.range() * 2 );
00823 for (; (unsigned) os < magnitudes.size(); os++)
00824 {
00825 magnitudes[os] = 0.0;
00826 }
00827
00828 scaleFactor = double( size.height() / 2 ) / log( (double)FFTW_N );
00829
00830 setGeometry(0, 0, newsize.width(), newsize.height());
00831 }
00832
00833
00834 bool Gears::process(VisualNode *node)
00835 {
00836 bool allZero = TRUE;
00837 #if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
00838 uint i;
00839 long w = 0, index;
00840 QRect *rectsp = rects.data();
00841 double *magnitudesp = magnitudes.data();
00842 double magL, magR, tmp;
00843
00844 if (node)
00845 {
00846 i = node->length;
00847 fast_real_set_from_short(lin, node->left, node->length);
00848 if (node->right)
00849 {
00850 fast_real_set_from_short(rin, node->right, node->length);
00851 }
00852 }
00853 else
00854 {
00855 i = 0;
00856 }
00857
00858 fast_reals_set(lin + i, rin + i, 0, FFTW_N - i);
00859 #ifdef FFTW3_SUPPORT
00860 fftw_execute(lplan);
00861 fftw_execute(rplan);
00862 #elif FFTW2_SUPPORT
00863 rfftw_one(plan, lin, lout);
00864 rfftw_one(plan, rin, rout);
00865 #endif
00866 index = 1;
00867 for (i = 0; i < rects.count(); i++, w += analyzerBarWidth)
00868 {
00869 #ifdef FFTW3_SUPPORT
00870 magL = (log(sq(real(lout[index])) + sq(real(lout[FFTW_N - index]))) - 22.0) *
00871 scaleFactor;
00872 magR = (log(sq(real(rout[index])) + sq(real(rout[FFTW_N - index]))) - 22.0) *
00873 scaleFactor;
00874 #elif FFTW2_SUPPORT
00875 magL = (log(lout[index] * lout[index] + lout[FFTW_N - index] * lout[FFTW_N - index]) - 22.0) * scaleFactor;
00876 magR = (log(rout[index] * rout[index] + rout[FFTW_N - index] * rout[FFTW_N - index]) - 22.0) * scaleFactor;
00877 #endif
00878
00879 if (magL > size.height() / 2)
00880 {
00881 magL = size.height() / 2;
00882 }
00883 if (magL < magnitudesp[i])
00884 {
00885 tmp = magnitudesp[i] - falloff;
00886 if ( tmp < magL )
00887 {
00888 tmp = magL;
00889 }
00890 magL = tmp;
00891 }
00892 if (magL < 1.)
00893 {
00894 magL = 1.;
00895 }
00896
00897 if (magR > size.height() / 2)
00898 {
00899 magR = size.height() / 2;
00900 }
00901 if (magR < magnitudesp[i + scale.range()])
00902 {
00903 tmp = magnitudesp[i + scale.range()] - falloff;
00904 if ( tmp < magR )
00905 {
00906 tmp = magR;
00907 }
00908 magR = tmp;
00909 }
00910 if (magR < 1.)
00911 {
00912 magR = 1.;
00913 }
00914
00915 if (magR != 1 || magL != 1)
00916 {
00917 allZero = FALSE;
00918 }
00919
00920 magnitudesp[i] = magL;
00921 magnitudesp[i + scale.range()] = magR;
00922
00923 rectsp[i].setTop( size.height() / 2 - int( magL ) );
00924 rectsp[i].setBottom( size.height() / 2 + int( magR ) );
00925
00926 index = scale[i];
00927 }
00928 #else
00929 node = node;
00930 #endif
00931 return allZero;
00932
00933 }
00934
00935 bool Gears::draw(QPainter *p, const QColor &back)
00936 {
00937 updateGL();
00938 p->fillRect(0, 0, 1, 1, back);
00939 return false;
00940 }
00941
00942 void Gears::drawTheGears()
00943 {
00944 angle += 2.0;
00945 view_roty += 1.0;
00946
00947
00948 float spreader = 3.0 - ((rects[2].top() / 255.0) * 3.0);
00949
00950 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00951
00952 glPushMatrix();
00953 glRotatef( view_rotx, 1.0, 0.0, 0.0 );
00954 glRotatef( view_roty, 0.0, 1.0, 0.0 );
00955 glRotatef( view_rotz, 0.0, 0.0, 1.0 );
00956
00957 glTranslatef(0.0, 2.0, 0.0);
00958
00959 glPushMatrix();
00960
00961 glTranslatef(-3.0, -2.0, 0.0 );
00962 glRotatef( angle, 0.0, 0.0, 1.0 );
00963 glCallList(gear1);
00964 glPopMatrix();
00965
00966 glPushMatrix();
00967 glTranslatef( 3.1, -2.0, 0.0 );
00968
00969 glRotatef( -2.0*angle-9.0, 0.0, 0.0, 1.0 );
00970 glCallList(gear2);
00971 glPopMatrix();
00972
00973 glPushMatrix();
00974
00975 glTranslatef( -3.1, 2.2 + spreader, -1.8 );
00976 glRotatef( 90.0, 1.0, 0.0, 0.0 );
00977 glRotatef( 2.0*angle-2.0, 0.0, 0.0, 1.0 );
00978 glCallList(gear3);
00979 glPopMatrix();
00980
00981 glPopMatrix();
00982 }
00983
00984 void Gears::initializeGL()
00985 {
00986 static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0 };
00987 static GLfloat ared[4] = {0.8, 0.1, 0.0, 1.0 };
00988 static GLfloat agreen[4] = {0.0, 0.8, 0.2, 1.0 };
00989 static GLfloat ablue[4] = {0.2, 0.2, 1.0, 1.0 };
00990
00991 glLightfv( GL_LIGHT0, GL_POSITION, pos );
00992 glEnable( GL_CULL_FACE );
00993 glEnable( GL_LIGHTING );
00994 glEnable( GL_LIGHT0 );
00995 glEnable( GL_DEPTH_TEST );
00996
00997
00998 gear1 = glGenLists(1);
00999 glNewList(gear1, GL_COMPILE);
01000 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared );
01001 gear( 1.0, 4.0, 1.0, 20, 0.7 );
01002 glEndList();
01003
01004 gear2 = glGenLists(1);
01005 glNewList(gear2, GL_COMPILE);
01006 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen );
01007 gear( 0.5, 2.0, 2.0, 10, 0.7 );
01008 glEndList();
01009
01010 gear3 = glGenLists(1);
01011 glNewList(gear3, GL_COMPILE);
01012 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue );
01013 gear( 1.3, 2.0, 0.5, 10, 0.7 );
01014 glEndList();
01015
01016 glEnable( GL_NORMALIZE );
01017 }
01018
01019 void Gears::resizeGL( int width, int height )
01020 {
01021 GLfloat w = (float) width / (float) height;
01022 GLfloat h = 1.0;
01023
01024 glViewport( 0, 0, width, height );
01025 glMatrixMode(GL_PROJECTION);
01026 glLoadIdentity();
01027 glFrustum( -w, w, -h, h, 5.0, 60.0 );
01028 glMatrixMode(GL_MODELVIEW);
01029 glLoadIdentity();
01030 glTranslatef( 0.0, 0.0, -40.0 );
01031 }
01032
01033 void Gears::paintGL()
01034 {
01035 drawTheGears();
01036 }
01037
01038 static class GearsFactory : public VisFactory
01039 {
01040 public:
01041 const QString &name(void) const
01042 {
01043 static QString name("Gears");
01044 return name;
01045 }
01046
01047 uint plugins(QStringList *list) const
01048 {
01049 *list << name();
01050 return 1;
01051 }
01052
01053 VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
01054 {
01055 (void)winid;
01056 (void)pluginName;
01057 return new Gears(parent);
01058 }
01059 }GearsFactory;
01060
01061
01062 #endif