view edwaveform.cpp @ 392:fc9b476c46de

Pass parameters to sub-processes of make.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 19 Oct 2012 05:26:34 +0300
parents 28a74940f2b6
children 5137db55f00b
line wrap: on
line source

#include <QtGui>
#include <SDL_audio.h>
#include "edwaveform.h"


WaveTrackDisplay::WaveTrackDisplay(QWidget *parent) : QWidget(parent)
{
    data      = NULL;
    size      = 0;
    format    = AUDIO_S16SYS;
    channels  = 1;
    freq      = 1;
    scale     = 1.0f;
    time      = offs = 0;
    duration  = 0;

    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
}


void WaveTrackDisplay::setWaveform(void *mdata, int msize, int mformat, int mchannels, int mfreq)
{
    data     = mdata;
    size     = msize;
    format   = mformat;
    channels = mchannels;
    freq     = mfreq;

    int bps = getBps();
    if (bps != 0)
        duration = ((float) (size / bps) / (float) freq) * 1000.0f;
    else
        duration = 0;

    update();
}


int WaveTrackDisplay::getBps()
{
    int bps = channels;
    switch (format)
    {
        case AUDIO_S16SYS:
        case AUDIO_U16SYS:
            bps *= sizeof(quint16);
            break;
        case AUDIO_S8:
        case AUDIO_U8:
            bps *= sizeof(quint8);
            break;
    }
    return bps;
}


float WaveTrackDisplay::getDuration()
{
    return duration;
}


float WaveTrackDisplay::getTimeScale(float value)
{
    return (value * scale * (float) freq) / 1000.0f;
}


float WaveTrackDisplay::getTimeFromCoord(float value)
{
    return value * scale;
}


void WaveTrackDisplay::setTime(const float mtime)
{
    fprintf(stderr, "setTime(%1.5f)\n", mtime);
    if (time != mtime && mtime >= 0 && mtime < duration)
    {
        time = mtime;
        update();
        emit timeChanged(time);
    }
}


void WaveTrackDisplay::setOffset(const float moffs)
{
    if (offs != moffs && moffs >= 0 && moffs < getDuration())
    {
        offs = moffs;
        update();
        emit offsetChanged(offs);
    }
}


void WaveTrackDisplay::setScale(const float mscale)
{
    if (mscale > 0.05)
        scale = mscale;
    update();
}


float WaveTrackDisplay::getScaledWidth()
{
    return getTimeScale(width());
}


float WaveTrackDisplay::getTime()
{
    return time;
}


float WaveTrackDisplay::getOffset()
{
    return offs;
}


void WaveTrackDisplay::paintEvent(QPaintEvent *)
{
    QColor waveColor(0, 150, 0);
    QColor waveCenterLine(0, 0, 0);
    QColor markerColor(255,255,255);
    QColor bgColor(0, 0, 0);//255, 255, 255);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.fillRect(QRect(0, 0, width(), height()), bgColor);

    if (data != NULL)
    {
        int voffs = 0;

        painter.save();
        painter.translate(0, height() / 2);

        painter.setPen(waveCenterLine);
        painter.drawLine(0, 0, width(), 0);

        switch (format)
        {
            case AUDIO_S16SYS:
                painter.scale(1.0f, (float) height() / 32768.0f);
                break;
            case AUDIO_U16SYS:
                voffs = -32768;
                painter.scale(1.0f, height() / 32768.0f);
                break;

            case AUDIO_S8:
                painter.scale(1.0f, height() / 128.0f);
                break;
            case AUDIO_U8:
                voffs = -128;
                painter.scale(1.0f, height() / 128.0f);
                break;
        }

        painter.scale(1.0f, 0.5f);
        painter.setPen(waveColor);

        float mscale = (scale * (float)freq) / 1000.0f;
        int prevY = 0, prevX = 0;
        if (format == AUDIO_S16SYS || format == AUDIO_U16SYS)
        {
            qint16 *buf = (qint16 *) data;
            for (int xc = 0; xc < width(); xc++)
            {
                int value = buf[(int) (((offs + xc) * mscale)) * channels] + voffs;
                painter.drawLine(prevX, prevY, xc, value);
                prevY = value;
                prevX = xc;
            }
        }
        else
        if (format == AUDIO_S8 || format == AUDIO_U8)
        {
            qint8 *buf = (qint8 *) data;
            for (int xc = 0; xc < width(); xc++)
            {
                int value = buf[((int) ((offs + xc) * mscale)) * channels] + voffs;
                painter.drawLine(prevX, prevY, xc, value);
                prevY = value;
                prevX = xc;
            }
        }
        
        painter.restore();
    }
    
    float xc = getTimeScale(time - offs), wd = getTimeScale(width());
    if (xc >= 0 && xc <= wd)
    {
        xc = time - offs;
        painter.scale(scale, 1.0f);
        painter.setPen(markerColor);
        painter.drawLine(xc, 0, xc, height());
    }
}


void WaveTrackDisplay::mousePressEvent(QMouseEvent *ev)
{
    if (ev->button() == Qt::LeftButton)
    {
        dragPoint = ev->pos();
        dragOffs = offs;
        dragging = false;
    }
}


void WaveTrackDisplay::mouseMoveEvent(QMouseEvent *ev)
{
    if ((ev->buttons() & Qt::LeftButton) && ev->pos().x() != dragPoint.x())
    {
        dragging = true;
        setOffset(dragOffs - (ev->pos().x() - dragPoint.x()) / scale);
    }
}


void WaveTrackDisplay::mouseReleaseEvent(QMouseEvent *ev)
{
    if (ev->button() == Qt::LeftButton)
    {
        dragging = false;
    }
    else
    if (ev->button() == Qt::RightButton && !dragging)
    {
        setTime(offs + getTimeFromCoord(ev->pos().x()));
    }
}


WaveTrackView::WaveTrackView(QWidget *parent) : QWidget(parent)
{
    QHBoxLayout *mainLayout = new QHBoxLayout(this);
    mainLayout->setMargin(0);
    wave = new WaveTrackDisplay(this);

    QFrame *infoLayoutContainer = new QFrame(this);
    infoLayoutContainer->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
    infoLayoutContainer->setLineWidth(2);
//    infoLayoutContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
//    infoLayoutContainer->resize(250, 60);

    QVBoxLayout *infoLayout = new QVBoxLayout(infoLayoutContainer);
    infoLayout->setMargin(0);
//    QVBoxLayout *infoLayout = new QVBoxLayout();
    infoName = new QLabel("Audio");
    infoName->setStyleSheet("QLabel { background-color: black; color: white; padding: 2px; }");
    infoLayout->addWidget(infoName);

    infoData = new QLabel();
    infoData->setStyleSheet("QLabel { padding: 2px; }");
    infoLayout->addWidget(infoData);

    mainLayout->addWidget(infoLayoutContainer);
//    mainLayout->addLayout(infoLayout);
    mainLayout->addWidget(wave);

    connect(wave, SIGNAL(timeChanged(float)), this, SLOT(slotTimeChanged(float)));
    connect(wave, SIGNAL(offsetChanged(float)), this, SLOT(slotOffsetChanged(float)));
}


void WaveTrackView::setWaveform(void *mdata, int msize, int mformat, int mchannels, int mfreq)
{
    QString fmt;
    switch (mformat)
    {
        case AUDIO_S16SYS: fmt = "16bit (S)"; break;
        case AUDIO_U16SYS: fmt = "16bit (U)"; break;
        case AUDIO_S8:     fmt = "8bit (S)"; break;
        case AUDIO_U8:     fmt = "8bit (U)"; break;
        default:           fmt = "?"; break;
    }
    infoData->setText(QString("<b>%1</b>, <b>%2</b> ch, <b>%3</b> Hz").arg(fmt).arg(mchannels).arg(mfreq));
    wave->setWaveform(mdata, msize, mformat, mchannels, mfreq);
    update();
}


void WaveTrackView::setName(QString name)
{
    infoName->setText(name);
    update();
}


void WaveTrackView::setTime(const float mtime)
{
    wave->setTime(mtime);
}


void WaveTrackView::setOffset(const float moffs)
{
    wave->setOffset(moffs);
}


void WaveTrackView::setScale(const float mscale)
{
    wave->setScale(mscale);
}


float WaveTrackView::getTime()
{
    return wave->getTime();
}


float WaveTrackView::getOffset()
{
    return wave->getOffset();
}


float WaveTrackView::getScaledWidth()
{
    return wave->getScaledWidth();
}


void WaveTrackView::slotTimeChanged(float value)
{
    emit timeChanged(value);
}


void WaveTrackView::slotOffsetChanged(float value)
{
    emit offsetChanged(value);
}


float WaveTrackView::getDuration()
{
    return wave->getDuration();
}