File indexing completed on 2025-01-05 04:25:41
0001 /**************************************************************************************** 0002 * Copyright (c) 2004 Enrico Ros <eros.kde@email.it> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #include "DiscoAnalyzer.h" 0018 0019 #include <QImage> 0020 #include <QStandardPaths> 0021 0022 #include <cmath> 0023 #include <cstdlib> 0024 #include <sys/time.h> 0025 0026 0027 DiscoAnalyzer::DiscoAnalyzer( QWidget *parent ): 0028 Analyzer::Base( parent ) 0029 { 0030 setObjectName( "Disco" ); 0031 0032 m_dotTexture = bindTexture( QImage( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/dot.png" ) ) ); 0033 m_w1Texture = bindTexture( QImage( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/wirl1.png" ) ) ); 0034 m_w2Texture = bindTexture( QImage( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/wirl2.png" ) ) ); 0035 0036 m_show.paused = true; 0037 m_show.pauseTimer = 0.0; 0038 m_show.rotDegrees = 0.0; 0039 m_frame.rotDegrees = 0.0; 0040 } 0041 0042 DiscoAnalyzer::~DiscoAnalyzer() 0043 { 0044 deleteTexture( m_dotTexture ); 0045 deleteTexture( m_w1Texture ); 0046 deleteTexture( m_w2Texture ); 0047 } 0048 0049 void DiscoAnalyzer::demo() 0050 { 0051 static int t = 0; 0052 static bool forward = true; 0053 0054 QVector<float> s( 200 ); 0055 const double dt = double( t ) / 200; 0056 0057 for( int i = 0; i < s.size(); ++i ) 0058 s[i] = dt * ( sin( M_PI + ( i * M_PI ) / s.size() ) + 1.0 ); 0059 0060 analyze( s ); 0061 0062 if( t == 0 ) 0063 forward = true; 0064 if( t == 200 ) 0065 forward = false; 0066 0067 t = forward ? t + 2 : t - 2; 0068 } 0069 0070 void DiscoAnalyzer::initializeGL() 0071 { 0072 // Set a smooth shade model 0073 glShadeModel( GL_SMOOTH ); 0074 0075 // Disable depth test (all is drawn on a 2d plane) 0076 glDisable( GL_DEPTH_TEST ); 0077 0078 // Set blend parameters for 'composting alpha' 0079 glBlendFunc( GL_SRC_ALPHA, GL_ONE ); //superpose 0080 //glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); //fade 0081 glEnable( GL_BLEND ); 0082 0083 // Clear frame with a black background 0084 glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); 0085 glClear( GL_COLOR_BUFFER_BIT ); 0086 } 0087 0088 void DiscoAnalyzer::resizeGL( int w, int h ) 0089 { 0090 // Setup screen. We're going to manually do the perspective projection 0091 glViewport( 0, 0, ( GLint )w, ( GLint )h ); 0092 glMatrixMode( GL_PROJECTION ); 0093 glLoadIdentity(); 0094 glOrtho( -10.0f, 10.0f, -10.0f, 10.0f, -5.0f, 5.0f ); 0095 0096 // Get the aspect ratio of the screen to draw 'cicular' particles 0097 const float ratio = ( float )w / ( float )h, 0098 eqPixH = 60, 0099 eqPixW = 80; 0100 if( ratio >= ( 4.0 / 3.0 ) ) 0101 { 0102 m_unitX = 10.0 / ( eqPixH * ratio ); 0103 m_unitY = 10.0 / eqPixH; 0104 } 0105 else 0106 { 0107 m_unitX = 10.0 / eqPixW; 0108 m_unitY = 10.0 / ( eqPixW / ratio ); 0109 } 0110 0111 // Get current timestamp. 0112 timeval tv; 0113 gettimeofday( &tv, NULL ); 0114 m_show.timeStamp = ( double )tv.tv_sec + ( double )tv.tv_usec / 1000000.0; 0115 } 0116 0117 void DiscoAnalyzer::analyze( const QVector<float> &s ) 0118 { 0119 bool haveNoData = s.empty(); 0120 0121 // if we're going into pause mode, clear timers. 0122 if( !m_show.paused && haveNoData ) 0123 m_show.pauseTimer = 0.0; 0124 0125 // if we have got data, interpolate it (asking myself why I'm doing it here..) 0126 if( !( m_show.paused = haveNoData ) ) 0127 { 0128 int bands = s.size(), 0129 lowbands = bands / 4, 0130 hibands = bands / 3, 0131 midbands = bands - lowbands - hibands; Q_UNUSED( midbands ); 0132 float currentEnergy = 0, 0133 currentMeanBand = 0, 0134 maxValue = 0; 0135 for( int i = 0; i < bands; i++ ) 0136 { 0137 float value = s[i]; 0138 currentEnergy += value; 0139 currentMeanBand += ( float )i * value; 0140 if( value > maxValue ) 0141 maxValue = value; 0142 } 0143 m_frame.silence = currentEnergy < 0.001; 0144 if( !m_frame.silence ) 0145 { 0146 m_frame.meanBand = 100.0 * currentMeanBand / ( currentEnergy * bands ); 0147 currentEnergy = 100.0 * currentEnergy / ( float )bands; 0148 m_frame.dEnergy = currentEnergy - m_frame.energy; 0149 m_frame.energy = currentEnergy; 0150 // printf( "%d [%f :: %f ]\t%f \n", bands, frame.energy, frame.meanBand, maxValue ); 0151 } 0152 else 0153 m_frame.energy = 0.0; 0154 } 0155 } 0156 0157 void DiscoAnalyzer::paintGL() 0158 { 0159 0160 } 0161 0162 void DiscoAnalyzer::drawDot( float x, float y, float size ) 0163 { 0164 float sizeX = size * m_unitX, 0165 sizeY = size * m_unitY, 0166 pLeft = x - sizeX, 0167 pTop = y + sizeY, 0168 pRight = x + sizeX, 0169 pBottom = y - sizeY; 0170 glTexCoord2f( 0, 0 ); // Bottom Left 0171 glVertex2f( pLeft, pBottom ); 0172 glTexCoord2f( 0, 1 ); // Top Left 0173 glVertex2f( pLeft, pTop ); 0174 glTexCoord2f( 1, 1 ); // Top Right 0175 glVertex2f( pRight, pTop ); 0176 glTexCoord2f( 1, 0 ); // Bottom Right 0177 glVertex2f( pRight, pBottom ); 0178 } 0179 0180 void DiscoAnalyzer::drawFullDot( float r, float g, float b, float a ) 0181 { 0182 glBindTexture( GL_TEXTURE_2D, m_dotTexture ); 0183 glEnable( GL_TEXTURE_2D ); 0184 glColor4f( r, g, b, a ); 0185 glBegin( GL_TRIANGLE_STRIP ); 0186 glTexCoord2f( 1.0, 1.0 ); 0187 glVertex2f( 10.0f, 10.0f ); 0188 glTexCoord2f( 0.0, 1.0 ); 0189 glVertex2f( -10.0f, 10.0f ); 0190 glTexCoord2f( 1.0, 0.0 ); 0191 glVertex2f( 10.0f, -10.0f ); 0192 glTexCoord2f( 0.0 , 0.0 ); 0193 glVertex2f( -10.0f, -10.0f ); 0194 glEnd(); 0195 glDisable( GL_TEXTURE_2D ); 0196 } 0197 0198 0199 void DiscoAnalyzer::setTextureMatrix( float rot, float scale ) 0200 { 0201 glMatrixMode( GL_TEXTURE ); 0202 glLoadIdentity(); 0203 if( rot != 0.0 || scale != 0.0 ) 0204 { 0205 glTranslatef( 0.5f, 0.5f, 0.0f ); 0206 glRotatef( rot, 0.0f, 0.0f, 1.0f ); 0207 glScalef( scale, scale, 1.0f ); 0208 glTranslatef( -0.5f, -0.5f, 0.0f ); 0209 } 0210 glMatrixMode( GL_MODELVIEW ); 0211 } 0212