// // // C++ Implementation: $MODULE$ // // Description: // // // Author: Mark Kretschmann , (C) 2003 // // Copyright: See COPYING file that comes with this distribution // // #include "baranalyzer.h" #include //log10(), etc. #include "debug.h" #include BarAnalyzer::BarAnalyzer( TQWidget *tqparent ) : Analyzer::Base2D( tqparent, 12, 8 ) //, m_bands( BAND_COUNT ) //, barVector( BAND_COUNT, 0 ) //, roofVector( BAND_COUNT, 50 ) //, roofVelocityVector( BAND_COUNT, ROOF_VELOCITY_REDUCTION_FACTOR ) { //roof pixmaps don't depend on size() so we do in the ctor m_bg = tqparent->paletteBackgroundColor(); TQColor fg( 0xff, 0x50, 0x70 ); #define m_bg backgroundColor() double dr = double(m_bg.red() - fg.red()) / (NUM_ROOFS-1); //-1 because we start loop below at 0 double dg = double(m_bg.green() - fg.green()) / (NUM_ROOFS-1); double db = double(m_bg.blue() - fg.blue()) / (NUM_ROOFS-1); for ( uint i = 0; i < NUM_ROOFS; ++i ) { m_pixRoof[i].resize( COLUMN_WIDTH, 1 ); m_pixRoof[i].fill( TQColor( fg.red()+int(dr*i), fg.green()+int(dg*i), fg.blue()+int(db*i) ) ); } #undef m_bg } void BarAnalyzer::resizeEvent( TQResizeEvent * e ) { debug() << "Baranalyzer Resized(" << width() << "x" << height() << ")" << endl; Analyzer::Base2D::resizeEvent( e ); init(); } // METHODS ===================================================== void BarAnalyzer::init() { const double MAX_AMPLITUDE = 1.0; const double F = double(height() - 2) / (log10( 255 ) * MAX_AMPLITUDE ); setPaletteBackgroundColor(m_bg); BAND_COUNT = width() / 5; MAX_DOWN = int(0 -((height() / 50))); MAX_UP = int((height() / 25)); debug() << "BAND_COUNT = " << BAND_COUNT << " MAX_UP = " << MAX_UP << "MAX_DOWN = " << MAX_DOWN << endl; barVector.resize( BAND_COUNT, 0 ); roofVector.resize( BAND_COUNT, height() -5 ); roofVelocityVector.resize( BAND_COUNT, ROOF_VELOCITY_REDUCTION_FACTOR ); m_roofMem.resize(BAND_COUNT); m_scope.resize(BAND_COUNT); //generate a list of values that express amplitudes in range 0-MAX_AMP as ints from 0-height() on log scale for ( uint x = 0; x < 256; ++x ) { m_lvlMapper[x] = uint( F * log10( x+1 ) ); } m_pixBarGradient.resize( height()*COLUMN_WIDTH, height() ); m_pixCompose.resize( size() ); TQPainter p( &m_pixBarGradient ); for ( int x=0, r=0x40, g=0x30, b=0xff, r2=255-r; x < height(); ++x ) { for ( int y = x; y > 0; --y ) { const double fraction = (double)y / height(); // p.setPen( TQColor( r + (int)(r2 * fraction), g, b - (int)(255 * fraction) ) ); p.setPen( TQColor( r + (int)(r2 * fraction), g, b ) ); p.drawLine( x*COLUMN_WIDTH, height() - y, (x+1)*COLUMN_WIDTH, height() - y ); } } setMinimumSize( TQSize( BAND_COUNT * COLUMN_WIDTH, 10 ) ); } void BarAnalyzer::analyze( const Scope &s ) { //start with a blank canvas eraseCanvas(); //Analyzer::interpolate( s, m_bands ); Scope &v = m_scope; Analyzer::interpolate( s, v ); for ( uint i = 0, x = 0, y2; i < v.size(); ++i, x+=COLUMN_WIDTH+1 ) { //assign pre[log10]'d value y2 = uint(v[i] * 256); //256 will be optimised to a bitshift //no, it's a float y2 = m_lvlMapper[ (y2 > 255) ? 255 : y2 ]; //lvlMapper is array of ints with values 0 to height() int change = y2 - barVector[i]; //using the best of Markey's, piggz and Max's ideas on the way to shift the bars //we have the following: // 1. don't adjust shift when doing small up movements // 2. shift large upwards with a bias towards last value // 3. fall downwards at a constant pace /*if ( change > MAX_UP ) //anything too much greater than 2 gives "jitter" //add some dynamics - makes the value slightly closer to what it was last time y2 = ( barVector[i] + MAX_UP ); //y2 = ( barVector[i] * 2 + y2 ) / 3; else*/ if ( change < MAX_DOWN ) y2 = barVector[i] + MAX_DOWN; if ( (int)y2 > roofVector[i] ) { roofVector[i] = (int)y2; roofVelocityVector[i] = 1; } //remember where we are barVector[i] = y2; if ( m_roofMem[i].size() > NUM_ROOFS ) m_roofMem[i].erase( m_roofMem[i].begin() ); //blt last n roofs, a.k.a motion blur for ( uint c = 0; c < m_roofMem[i].size(); ++c ) //bitBlt( m_pComposePixmap, x, m_roofMem[i]->at( c ), m_roofPixmaps[ c ] ); bitBlt( canvas(), x, m_roofMem[i][c], &m_pixRoof[ NUM_ROOFS - 1 - c ] ); //blt the bar bitBlt( canvas(), x, height() - y2, gradient(), y2 * COLUMN_WIDTH, height() - y2, COLUMN_WIDTH, y2, TQt::CopyROP ); m_roofMem[i].push_back( height() - roofVector[i] - 2 ); //set roof parameters for the NEXT draw if ( roofVelocityVector[i] != 0 ) { if ( roofVelocityVector[i] > 32 ) //no reason to do == 32 roofVector[i] -= (roofVelocityVector[i] - 32) / 20; //trivial calculation if ( roofVector[i] < 0 ) { roofVector[i] = 0; //not strictly necessary roofVelocityVector[i] = 0; } else ++roofVelocityVector[i]; } } }