Logo Search packages:      
Sourcecode: qarecord version File versions  Download package

meter.cpp

#include <qpolygon.h>
#include <qwidget.h>
#include <qstring.h>
#include <qpainter.h>
#include <qpaintdevice.h>
#include <qpen.h>
#include <qpixmap.h>
#include <qbrush.h>
#include <qtimer.h>
#include <qsizepolicy.h>
#include <qsize.h>
#include <qboxlayout.h>
#include <math.h>

#include "meter.h"


Meter::Meter(tickType p_tick, RingBuffer *p_ringbuffer, int channelIndex,
int p_sampleSize, int p_minDB, QWidget* parent) : QWidget (parent)
{
    tick = p_tick;
    channel = channelIndex;
    minDB = p_minDB;
    ringBuffer = p_ringbuffer;
    sampleSize = p_sampleSize;
    globalMaxResetCount = 0;
    globalMax = 0;
    setPalette(QPalette(QColor(0, 20, 100), QColor(0, 20, 100)));
    timer = new QTimer(this);
    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(updateMeter()));
    timer->start(200);
}

Meter::~Meter()
{
}

// Paint event handler.
void Meter::paintEvent(QPaintEvent*)
{
    QPainter p(this);
    QPen pen;
    double dB, gdB, len, xscale, overscale, over_dB, meter_over;
    int l1, x, x1, x2, gx, max, ofs;
    int w = width();
    int h = height();

    max = curMax;
    if (max < 0) { // ??
        return;
    }

    p.fillRect(0, 0, w, h, QColor(10, 50, 10));
    p.setFont(QFont("Helvetica", 8));
    pen.setColor(QColor(20, 160, 20));
    pen.setWidth(1);
    p.setPen(pen);
    p.drawRect(0, 0, width()-1, height()-1);

    len = (double)abs(minDB);  
    xscale = (double)(width() - 6 - METER_OVER_WIDTH) / len;  
    meter_over = (sampleSize == 2) ? METER_OVER : METER_OVER32;

    // paint signal level
    if (max > 0) {
        dB = 20.0 * log((double)max/meter_over)/log(10.0);  
        //    printf("max: %d dB: %lf\n", max, dB);
        if (dB < minDB)
            dB = minDB;  
        x = (int)((abs(minDB) + dB) * xscale);
        //  fprintf(stderr, "max: %7d x: %3d dB: %f\n", max, x, dB);

        //green range
        if (tick == TICK_DOWN) {
            p.fillRect(3, 3, x, height() - 3 - METER_TICK_WIDTH,
                    QBrush(QColor(40, 150, 40)));
        } else {
            p.fillRect(3, METER_TICK_WIDTH - 1, x,
                    height() - 3 - METER_TICK_WIDTH,
                    QBrush(QColor(40, 150, 40)));
        }

        //yellow range
        if (dB >= -6) {
            x1 = (int)((abs(minDB) - 6) * xscale);
            x2 = (int)((abs(minDB) + dB) * xscale);
            if (tick == TICK_DOWN) {
                p.fillRect(3 + x1, 3, x2 - x1,
                        height() - 3 - METER_TICK_WIDTH,
                        QBrush(QColor(200, 200, 0)));
            } else {
                p.fillRect(3 + x1, METER_TICK_WIDTH - 1, x2 - x1,
                        height() - 3 - METER_TICK_WIDTH,
                        QBrush(QColor(200, 200, 0)));
            }
        }

        //red range
        if (dB > 0) {
            over_dB = 20.0 * log(32767.0/meter_over)/log(10.0);
            overscale = (double)METER_OVER_WIDTH / over_dB;
            x1 = (int)(abs(minDB) * xscale);
            x2 = (int)(dB * overscale);
            if (tick == TICK_DOWN) {
                p.fillRect(3 + x1, 3, x2, height()-3-METER_TICK_WIDTH,
                        QBrush(QColor(200, 0, 0)));
            } else {
                p.fillRect(3 + x1, METER_TICK_WIDTH - 1, x2,
                        height()-3-METER_TICK_WIDTH,
                        QBrush(QColor(200, 0, 0)));
            } 
        }

        // peak hold
        pen.setWidth(3);
        gdB = (globalMax > 0)
            ?  20.0 * log((double)globalMax/meter_over)/log(10.0)
            : minDB;
        
        if (gdB < minDB)
            gdB = minDB;
        gx = (int)((abs(minDB) + gdB) * xscale);   

        if (gdB > -6) {
            if (gdB > 0) {
                pen.setColor(QColor(250, 0, 0));  //red
                over_dB = 20.0 * log(32767.0/meter_over)/log(10.0);
                overscale = (double)METER_OVER_WIDTH / over_dB;
                gx = (int)(abs(minDB) * xscale + gdB * overscale);
            }
            else
                pen.setColor(QColor(240, 240, 0));  //yellow
        }
        else
            pen.setColor(QColor(60, 180, 60));  //green

        p.setPen(pen); 
        if (tick == TICK_DOWN) {
            p.drawLine(3 + gx, 3, 3 + gx, height()-METER_TICK_WIDTH); 
        } else {
            p.drawLine(3 + gx, METER_TICK_WIDTH - 1, 3 + gx, height()-4);
        }
        pen.setWidth(1);
    }

    //paint scale
    //   large spacing
    for (l1 = 0; l1 < -minDB/10 + 1; l1++) {
        if (!l1) {
            ofs = 2;
            pen.setColor(QColor(250, 0, 0));  //red
        } else {
            ofs = -5;
            pen.setColor(QColor(60, 180, 60));  //green
        }
        p.setPen(pen);
        x = (int)((abs(minDB)-10.0*(double)l1) * xscale);

        if (tick == TICK_DOWN) {
            p.drawLine(4 + x, height() - METER_TICK_WIDTH + 2, 4 + x,
                    height()-16);
            p.drawText(ofs + x, height()-4, QString::number(-10*l1));
        } else {
            p.drawLine(4 + x, 15, 4 + x, METER_TICK_WIDTH-3);
            p.drawText(ofs + x, 12, QString::number(-10*l1));
        }
    }

    //   small spacing
    p.setPen(QColor(240, 240, 0));  //yellow

    if (tick == TICK_DOWN) {
        x = (int)((abs(minDB)-6.0) * xscale);
        p.drawText(x-1, height()-4, QString::number(-6));
        p.drawLine(4 + x, height() - METER_TICK_WIDTH + 2, 4 + x, height()-16);
        x = (int)((abs(minDB)-3.0) * xscale);
        p.drawText(x-1, height()-4, QString::number(-3));
        p.drawLine(4 + x, height() - METER_TICK_WIDTH + 2, 4 + x, height()-16);
        p.setPen(QColor(240, 250, 200));
        p.drawText(width()-18, height()-4, "dB");
    } else {
        x = (int)((abs(minDB)-6.0) * xscale);
        p.drawLine(4 + x, 15, 4 + x, METER_TICK_WIDTH-3);
        p.drawText(x-1, 12, QString::number(-6));
        x = (int)((abs(minDB)-3.0) * xscale);
        p.drawLine(4 + x, 15, 4 + x, METER_TICK_WIDTH-3);
        p.drawText(x-1, 12, QString::number(-3));
        p.setPen(QColor(240, 250, 200));  
        p.drawText(width()-18, 12, "dB");
    }
}

void Meter::updateMeter()
{
    if (globalMaxResetCount > 20) {
        globalMaxResetCount = 0;
        globalMax = 0;
    }

    curMax = ringBuffer->readMax(channel);
    if (curMax > globalMax) {
        globalMax = curMax;
        globalMaxResetCount = 0;
    }

    globalMaxResetCount++;

    Meter::update();
    timer->start(200);
}

QSize Meter::sizeHint() const
{
    return QSize(METER_MINIMUM_WIDTH, METER_MINIMUM_HEIGHT); 
}

QSizePolicy Meter::sizePolicy() const
{
    return QSizePolicy(QSizePolicy::MinimumExpanding,
            QSizePolicy::MinimumExpanding);
}

void Meter::resetGlobalMax()
{
    globalMaxResetCount = 0;
    globalMax = 0;
}

Generated by  Doxygen 1.6.0   Back to index