Example #1
0
AbstractScopeWidget::AbstractScopeWidget(bool trackMouse, QWidget *parent) :
        QWidget(parent)
        , m_mousePos(0, 0)
        , m_mouseWithinWidget(false)
        , offset(5)
        , m_accelFactorHUD(1)
        , m_accelFactorScope(1)
        , m_accelFactorBackground(1)
        , m_semaphoreHUD(1)
        , m_semaphoreScope(1)
        , m_semaphoreBackground(1)
        , initialDimensionUpdateDone(false)
        , m_requestForcedUpdate(false)
        , m_rescaleMinDist(4)
        , m_rescaleVerticalThreshold(2.0f)
        , m_rescaleActive(false)
	, m_rescalePropertiesLocked(false)
	, m_rescaleFirstRescaleDone(true)
	, m_rescaleDirection(North)

{
    m_scopePalette = QPalette();
    m_scopePalette.setBrush(QPalette::Window, QBrush(dark2));
    m_scopePalette.setBrush(QPalette::Base, QBrush(dark));
    m_scopePalette.setBrush(QPalette::Button, QBrush(dark));
    m_scopePalette.setBrush(QPalette::Text, QBrush(light));
    m_scopePalette.setBrush(QPalette::WindowText, QBrush(light));
    m_scopePalette.setBrush(QPalette::ButtonText, QBrush(light));
    this->setPalette(m_scopePalette);
    this->setAutoFillBackground(true);

    m_aAutoRefresh = new QAction(i18n("Auto Refresh"), this);
    m_aAutoRefresh->setCheckable(true);
    m_aRealtime = new QAction(i18n("Realtime (with precision loss)"), this);
    m_aRealtime->setCheckable(true);

    m_menu = new QMenu(this);
    // Disabled dark palette on menus since it breaks up with some themes: kdenlive issue #2950
    //m_menu->setPalette(m_scopePalette);
    m_menu->addAction(m_aAutoRefresh);
    m_menu->addAction(m_aRealtime);

    this->setContextMenuPolicy(Qt::CustomContextMenu);

    bool b = true;
    b &= connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint)));

    b &= connect(this, SIGNAL(signalHUDRenderingFinished(uint, uint)), this, SLOT(slotHUDRenderingFinished(uint, uint)));
    b &= connect(this, SIGNAL(signalScopeRenderingFinished(uint, uint)), this, SLOT(slotScopeRenderingFinished(uint, uint)));
    b &= connect(this, SIGNAL(signalBackgroundRenderingFinished(uint, uint)), this, SLOT(slotBackgroundRenderingFinished(uint, uint)));
    b &= connect(m_aRealtime, SIGNAL(toggled(bool)), this, SLOT(slotResetRealtimeFactor(bool)));
    b &= connect(m_aAutoRefresh, SIGNAL(toggled(bool)), this, SLOT(slotAutoRefreshToggled(bool)));
    Q_ASSERT(b);

    // Enable mouse tracking if desired.
    // Causes the mouseMoved signal to be emitted when the mouse moves inside the
    // widget, even when no mouse button is pressed.
    this->setMouseTracking(trackMouse);
}
Example #2
0
QImage Waveform::renderGfxScope(uint accelFactor, const QImage &qimage)
{
    QTime start = QTime::currentTime();
    start.start();

    const int paintmode = ui->paintMode->itemData(ui->paintMode->currentIndex()).toInt();
    WaveformGenerator::Rec rec = m_aRec601->isChecked() ? WaveformGenerator::Rec_601 : WaveformGenerator::Rec_709;
    QImage wave = m_waveformGenerator->calculateWaveform(scopeRect().size() - m_textWidth - QSize(0,m_paddingBottom), qimage,
                                                         (WaveformGenerator::PaintMode) paintmode, true, rec, accelFactor);

    emit signalScopeRenderingFinished(start.elapsed(), 1);
    return wave;
}
Example #3
0
QImage Histogram::renderGfxScope(uint accelFactor, const QImage qimage)
{
    QTime start = QTime::currentTime();
    start.start();

    const int componentFlags =   (ui->cbY->isChecked() ? 1 : 0) * HistogramGenerator::ComponentY
                               | (ui->cbS->isChecked() ? 1 : 0) * HistogramGenerator::ComponentSum
                               | (ui->cbR->isChecked() ? 1 : 0) * HistogramGenerator::ComponentR
                               | (ui->cbG->isChecked() ? 1 : 0) * HistogramGenerator::ComponentG
                               | (ui->cbB->isChecked() ? 1 : 0) * HistogramGenerator::ComponentB;

    HistogramGenerator::Rec rec = m_aRec601->isChecked() ? HistogramGenerator::Rec_601 : HistogramGenerator::Rec_709;

    QImage histogram = m_histogramGenerator->calculateHistogram(m_scopeRect.size(), qimage, componentFlags,
                                                                rec, m_aUnscaled->isChecked(), accelFactor);

    emit signalScopeRenderingFinished(start.elapsed(), accelFactor);
    return histogram;
}
Example #4
0
QImage AudioSpectrum::renderAudioScope(uint, const QVector<int16_t> audioFrame, const int freq, const int num_channels,
                                       const int num_samples, const int)
{
    if (
            audioFrame.size() > 63
            && m_innerScopeRect.width() > 0 && m_innerScopeRect.height() > 0    // <= 0 if widget is too small (resized by user)
    ) {
        if (!m_customFreq) {
            m_freqMax = freq / 2;
        }

        QTime start = QTime::currentTime();


#ifdef DETECT_OVERMODULATION
        bool overmodulated = false;
        int overmodulateCount = 0;

        for (int i = 0; i < audioFrame.size(); i++) {
            if (
                    audioFrame[i] == std::numeric_limits<int16_t>::max()
                    || audioFrame[i] == std::numeric_limits<int16_t>::min()) {
                overmodulateCount++;
                if (overmodulateCount > 3) {
                    overmodulated = true;
                    break;
                }
            }
        }
        if (overmodulated) {
            colorizeFactor = 1;
        } else {
            if (colorizeFactor > 0) {
                colorizeFactor -= .08;
                if (colorizeFactor < 0) {
                    colorizeFactor = 0;
                }
            }
        }
#endif


        // Determine the window size to use. It should be
        // * not bigger than the number of samples actually available
        // * divisible by 2
        int fftWindow = ui->windowSize->itemData(ui->windowSize->currentIndex()).toInt();
        if (fftWindow > num_samples) {
            fftWindow = num_samples;
        }
        if ((fftWindow & 1) == 1) {
            fftWindow--;
        }

        // Show the window size used, for information
        ui->labelFFTSizeNumber->setText(QVariant(fftWindow).toString());


        // Get the spectral power distribution of the input samples,
        // using the given window size and function
        float freqSpectrum[fftWindow/2];
        FFTTools::WindowType windowType = (FFTTools::WindowType) ui->windowFunction->itemData(ui->windowFunction->currentIndex()).toInt();
        m_fftTools.fftNormalized(audioFrame, 0, num_channels, freqSpectrum, windowType, fftWindow, 0);


        // Store the current FFT window (for the HUD) and run the interpolation
        // for easy pixel-based dB value access
        QVector<float> dbMap;
        m_lastFFTLock.acquire();
        m_lastFFT = QVector<float>(fftWindow/2);
        memcpy(m_lastFFT.data(), &(freqSpectrum[0]), fftWindow/2 * sizeof(float));

        uint right = ((float) m_freqMax)/(m_freq/2) * (m_lastFFT.size() - 1);
        dbMap = FFTTools::interpolatePeakPreserving(m_lastFFT, m_innerScopeRect.width(), 0, right, -180);
        m_lastFFTLock.release();


#ifdef DEBUG_AUDIOSPEC
        QTime drawTime = QTime::currentTime();
#endif

        // Draw the spectrum
        QImage spectrum(m_scopeRect.size(), QImage::Format_ARGB32);
        spectrum.fill(qRgba(0,0,0,0));
        const uint w = m_innerScopeRect.width();
        const uint h = m_innerScopeRect.height();
        const uint leftDist = m_innerScopeRect.left() - m_scopeRect.left();
        const uint topDist = m_innerScopeRect.top() - m_scopeRect.top();
        QColor spectrumColor(AbstractScopeWidget::colDarkWhite);
        int yMax;

#ifdef DETECT_OVERMODULATION
        if (colorizeFactor > 0) {
            QColor col = AbstractScopeWidget::colHighlightDark;
            QColor spec = spectrumColor;
            float f = std::sin(M_PI_2 * colorizeFactor);
            spectrumColor = QColor(
                        (int) (f * col.red() + (1-f) * spec.red()),
                        (int) (f * col.green() + (1-f) * spec.green()),
                        (int) (f * col.blue() + (1-f) * spec.blue()),
                        spec.alpha()
                        );
            // Limit the maximum colorization for non-overmodulated frames to better
            // recognize consecutively overmodulated frames
            if (colorizeFactor > MAX_OVM_COLOR) {
                colorizeFactor = MAX_OVM_COLOR;
            }
        }
#endif

#ifdef AUDIOSPEC_LINES
        QPainter davinci(&spectrum);
        davinci.setPen(QPen(QBrush(spectrumColor.rgba()), 1, Qt::SolidLine));
#endif

        for (uint i = 0; i < w; i++) {
            yMax = (dbMap[i] - m_dBmin) / (m_dBmax-m_dBmin) * (h-1);
            if (yMax < 0) {
                yMax = 0;
            } else if (yMax >= (int)h) {
                yMax = h-1;
            }
#ifdef AUDIOSPEC_LINES
            davinci.drawLine(leftDist + i, topDist + h-1, leftDist + i, topDist + h-1 - yMax);
#else
            for (int y = 0; y < yMax && y < (int)h; y++) {
                spectrum.setPixel(leftDist + i, topDist + h-y-1, spectrumColor.rgba());
            }
#endif
        }

        // Calculate the peak values. Use the new value if it is bigger, otherwise adapt to lower
        // values using the Moving Average formula
        if (m_aShowMax->isChecked()) {
            davinci.setPen(QPen(QBrush(AbstractScopeWidget::colHighlightLight), 2));
            if (m_peaks.size() != fftWindow/2) {
                m_peaks = QVector<float>(m_lastFFT);
            } else {
                for (int i = 0; i < fftWindow/2; i++) {
                    if (m_lastFFT[i] > m_peaks[i]) {
                        m_peaks[i] = m_lastFFT[i];
                    } else {
                        m_peaks[i] = ALPHA_MOVING_AVG * m_lastFFT[i] + (1-ALPHA_MOVING_AVG) * m_peaks[i];
                    }
                }
            }
            int prev = 0;
            m_peakMap = FFTTools::interpolatePeakPreserving(m_peaks, m_innerScopeRect.width(), 0, right, -180);
            for (uint i = 0; i < w; i++) {
                yMax = (m_peakMap[i] - m_dBmin) / (m_dBmax-m_dBmin) * (h-1);
                if (yMax < 0) {
                    yMax = 0;
                } else if (yMax >= (int)h) {
                    yMax = h-1;
                }

                davinci.drawLine(leftDist + i-1, topDist + h-prev-1, leftDist + i, topDist + h-yMax-1);
                spectrum.setPixel(leftDist + i, topDist + h-yMax-1, AbstractScopeWidget::colHighlightLight.rgba());
                prev = yMax;
            }
        }

#ifdef DEBUG_AUDIOSPEC
        m_showTotal++;
        m_timeTotal += drawTime.elapsed();
        qDebug() << widgetName() << " took " << drawTime.elapsed() << " ms for drawing. Average: " << ((float)m_timeTotal/m_showTotal) ;
#endif

        emit signalScopeRenderingFinished(start.elapsed(), 1);


        return spectrum;
    } else {
        emit signalScopeRenderingFinished(0, 1);
        return QImage();
    }
}
Example #5
0
QImage AudioSignal::renderAudioScope(uint, const QVector<int16_t> audioFrame,
                                     const int, const int num_channels, const int samples, const int)
{
    QTime start = QTime::currentTime();

    int num_samples = samples > 200 ? 200 : samples;

    QByteArray channels;
    for (int i = 0; i < num_channels; i++) {
        long val = 0;
        for (int s = 0; s < num_samples; s ++) {
            val += abs(audioFrame[i+s*num_channels] / 128);
        }
        channels.append(val / num_samples);
    }

    if (peeks.count()!=channels.count()){
        peeks=QByteArray(channels.count(),0);
        peekage=QByteArray(channels.count(),0);
    }
    for (int chan=0;chan<peeks.count();chan++)
    {
        peekage[chan] = peekage[chan]+1;
        if (  peeks.at(chan)<channels.at(chan) ||  peekage.at(chan)>50 )
        {
            peekage[chan]=0;
            peeks[chan]=channels[chan];
        }
    }

    QImage image(m_scopeRect.size(), QImage::Format_ARGB32);
    image.fill(Qt::transparent);
    QPainter p(&image);
    p.setPen(Qt::white);
    p.setRenderHint(QPainter::TextAntialiasing, false);
    p.setRenderHint(QPainter::Antialiasing, false);
    
    int numchan = channels.size();
    bool horiz=width() > height();
    int dbsize=20;
    bool showdb=width()>(dbsize+40);
    //valpixel=1.0 for 127, 1.0+(1/40) for 1 short oversample, 1.0+(2/40) for longer oversample
    for (int i = 0; i < numchan; i++) {
        //int maxx= (unsigned char)channels[i] * (horiz ? width() : height() ) / 127;
        double valpixel=valueToPixel((double)(unsigned char)channels[i]/127.0);
        int maxx=  height()  * valpixel;
        int xdelta= height()   /42 ;
        int _y2= (showdb?width()-dbsize:width () ) / numchan - 1  ;
        int _y1= (showdb?width()-dbsize:width() ) *i/numchan;
        int _x2= maxx >  xdelta ? xdelta - 3 : maxx - 3 ;
        if (horiz){
            dbsize=9;
            showdb=height()>(dbsize);
            maxx=width()*valpixel;
            xdelta = width() / 42;
            _y2=( showdb?height()-dbsize:height() ) / numchan - 1 ;
            _y1= (showdb?height()-dbsize:height() ) * i/numchan;
            _x2= maxx >  xdelta ? xdelta - 1 : maxx - 1;
        }

        for (int x = 0; x <= 42; x++) {
            int _x1= x *xdelta;
            QColor sig=Qt::green;
            //value of actual painted digit
            double ival=(double)_x1/(double)xdelta/42.0;
            if (ival > 40.0/42.0){
                sig=Qt::red;
            }else if ( ival > 37.0/42.0){
                sig=Qt::darkYellow;
            }else if ( ival >30.0/42.0){
                sig=Qt::yellow;
            }
            if (maxx > 0) {
                if (horiz){
                    p.fillRect(_x1, _y1, _x2, _y2, QBrush(sig, Qt::SolidPattern) );
                }else{
                    p.fillRect(_y1, height()-_x1, _y2,-_x2, QBrush(sig, Qt::SolidPattern) );
                }
                maxx -= xdelta;
            }
        }
        int xp=valueToPixel((double)peeks.at(i)/127.0)*(horiz?width():height())-2;
        p.fillRect(horiz?xp:_y1,horiz?_y1:height()-xdelta-xp,horiz?3:_y2,horiz?_y2:3,QBrush(Qt::gray,Qt::SolidPattern));

    }
    if (showdb){
        //draw db value at related pixel
        for (int l=0;l<dbscale.size();l++){
            if (!horiz){
                double xf=pow(10.0,(double)dbscale.at(l) / 20.0 )*(double)height();
                p.drawText(width()-20,height()-xf*40.0/42.0+20, QString().sprintf("%d",dbscale.at(l)));
            }else{
                double xf=pow(10.0,(double)dbscale.at(l) / 20.0 )*(double)width();
                p.drawText(xf*40/42-10,height()-2, QString().sprintf("%d",dbscale.at(l)));
            }
        }
    }
    p.end();
    emit signalScopeRenderingFinished((uint) start.elapsed(), 1);
    return image;
}