Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/waveform/waveformrenderbeat.cpp

Go to the documentation of this file.
00001 
00002 #include <QDebug>
00003 #include <QColor>
00004 #include <QDomNode>
00005 #include <QPaintEvent>
00006 #include <QPainter>
00007 #include <QObject>
00008 #include <QVector>
00009 
00010 #include "waveformrenderbeat.h"
00011 #include "waveformrenderer.h"
00012 #include "controlobjectthreadmain.h"
00013 #include "controlobject.h"
00014 #include "widget/wskincolor.h"
00015 #include "widget/wwidget.h"
00016 #include "trackinfoobject.h"
00017 #include "track/beats.h"
00018 
00019 
00020 WaveformRenderBeat::WaveformRenderBeat(const char* group, WaveformRenderer *parent)
00021         : m_pParent(parent),
00022           m_pTrackSamples(NULL),
00023           m_pTrack(),
00024           m_iWidth(0),
00025           m_iHeight(0),
00026           m_dSamplesPerPixel(-1),
00027           m_dSamplesPerDownsample(-1),
00028           m_iNumSamples(0),
00029           m_iSampleRate(0),
00030           m_bBeatActive(false) {
00031     m_pTrackSamples = new ControlObjectThreadMain(
00032         ControlObject::getControl(ConfigKey(group,"track_samples")));
00033     slotUpdateTrackSamples(m_pTrackSamples->get());
00034     connect(m_pTrackSamples, SIGNAL(valueChanged(double)),
00035             this, SLOT(slotUpdateTrackSamples(double)));
00036 
00037     m_pTrackSampleRate = new ControlObjectThreadMain(
00038         ControlObject::getControl(ConfigKey(group,"track_samplerate")));
00039     slotUpdateTrackSampleRate(m_pTrackSampleRate->get());
00040     connect(m_pTrackSampleRate, SIGNAL(valueChanged(double)),
00041             this, SLOT(slotUpdateTrackSampleRate(double)));
00042 
00043     m_pBeatActive = new ControlObjectThreadMain(
00044         ControlObject::getControl(ConfigKey(group,"beat_active")));
00045     slotUpdateBeatActive(m_pBeatActive->get());
00046     connect(m_pBeatActive, SIGNAL(valueChanged(double)),
00047             this, SLOT(slotUpdateBeatActive(double)));
00048 }
00049 
00050 WaveformRenderBeat::~WaveformRenderBeat() {
00051    delete m_pTrackSamples;
00052    delete m_pBeatActive;
00053     qDebug() << this << "~WaveformRenderBeat()";
00054 }
00055 
00056 void WaveformRenderBeat::slotUpdateTrackSamples(double samples) {
00057     //qDebug() << "WaveformRenderBeat :: samples = " << int(samples);
00058     m_iNumSamples = static_cast<int>(samples);
00059 }
00060 
00061 void WaveformRenderBeat::slotUpdateTrackSampleRate(double sampleRate) {
00062 
00063 
00064     // f = z * m * n
00065     double m = m_pParent->getSubpixelsPerPixel();
00066     double f = sampleRate;
00067     double z = m_pParent->getPixelsPerSecond();
00068     double n = f / (m*z);
00069 
00070     m_iSampleRate = static_cast<int>(sampleRate);
00071     m_dSamplesPerDownsample = n;
00072     m_dSamplesPerPixel = f/z;
00073 
00074     //qDebug() << "WaveformRenderBeat :: sampleRate = " << int(sampleRate)
00075     //         << "samplesPerDownsample" << m_dSamplesPerDownsample
00076     //         << "samplesPerPixel" << m_dSamplesPerPixel;
00077 }
00078 
00079 void WaveformRenderBeat::slotUpdateBeatActive(double beatActive) {
00080     m_bBeatActive = beatActive > 0;
00081 }
00082 
00083 void WaveformRenderBeat::resize(int w, int h) {
00084     m_iWidth = w;
00085     m_iHeight = h;
00086 }
00087 
00088 void WaveformRenderBeat::newTrack(TrackPointer pTrack) {
00089     m_pTrack = pTrack;
00090 }
00091 
00092 void WaveformRenderBeat::setup(QDomNode node) {
00093     colorMarks.setNamedColor(WWidget::selectNodeQString(node, "BeatColor"));
00094     colorMarks = WSkinColor::getCorrectColor(colorMarks);
00095 
00096     colorHighlight = Qt::black;
00097     QString highlight = WWidget::selectNodeQString(node, "BeatHighlightColor");
00098     if (highlight != "") {
00099         colorHighlight.setNamedColor(highlight);
00100     }
00101     colorHighlight = WSkinColor::getCorrectColor(colorHighlight);
00102 }
00103 
00104 void WaveformRenderBeat::draw(QPainter *pPainter, QPaintEvent *event,
00105                               QVector<float> *buffer, double dPlayPos, double rateAdjust) {
00106     slotUpdateTrackSamples(m_pTrackSamples->get());
00107 
00108     if(m_iSampleRate <= 0 || m_iNumSamples == 0)
00109         return;
00110 
00111     if(buffer == NULL)
00112         return;
00113 
00114     BeatsPointer pBeats = m_pTrack->getBeats();
00115     if (!pBeats)
00116         return;
00117 
00118     int iCurPos = (int)(dPlayPos * m_iNumSamples);
00119     if(iCurPos % 2 != 0)
00120         iCurPos--;
00121 
00122     // iCurPos is the current sample being processed the current pixel
00123     // p, with respect to iCurPos is in the screen if it is less than
00124     // halfw from iCurPos. A sample is a beat if it satisifes the following:
00125 
00126     // for b beats per minute, that means b/60 beats per seconds, or 60/b seconds per beat.
00127     // with a sample rate of f (generally 44khz),
00128     //   60f/b = samples per beat
00129 
00130     // Therefore, sample s is a beat if it satisfies  s % 60f/b == 0.
00131     // where s is a /mono/ sample
00132 
00133     double subpixelsPerPixel = m_pParent->getSubpixelsPerPixel()*(1.0+rateAdjust);
00134 
00135     QPen marksPen(colorMarks);
00136     marksPen.setWidth(subpixelsPerPixel*1.5);
00137     QPen highlightPen(colorHighlight);
00138     highlightPen.setWidth(subpixelsPerPixel*1.5);
00139 
00140     pPainter->save();
00141     pPainter->scale(1.0/subpixelsPerPixel,1.0);
00142 
00143     pPainter->setPen(marksPen);
00144 
00145     double subpixelWidth = m_iWidth * subpixelsPerPixel;
00146     double subpixelHalfWidth = subpixelWidth / 2.0;
00147     double halfh = m_iHeight/2;
00148 
00149     // basePos and endPos are in samples
00150     double basePos = iCurPos - m_dSamplesPerPixel * m_iWidth * (1.0+rateAdjust);
00151     double endPos = basePos + (2 * m_iWidth) * m_dSamplesPerPixel * (1.0+rateAdjust);
00152 
00153 
00154     m_beatList.clear();
00155     pBeats->findBeats(basePos, endPos, &m_beatList);
00156 
00157     bool reset = false;
00158     foreach (double curPos, m_beatList) {
00159         if (curPos < 0)
00160             continue;
00161 
00162         // i relative to the current play position in subpixels
00163         double i = (((curPos) - iCurPos)/2)/m_dSamplesPerDownsample;
00164 
00165         // If a beat is active, highlight the marker.
00166         if(m_bBeatActive && abs(i) < 20) {
00167             pPainter->setPen(highlightPen);
00168             reset = true;
00169         }
00170 
00171         // Translate from -subpixelHalfWidth..subpixelHalfwidth to 0..subpixelWidth
00172         i += subpixelHalfWidth;
00173 
00174         pPainter->drawLine(QLineF(i,halfh,i,-halfh));
00175 
00176         if(reset) {
00177             pPainter->setPen(marksPen);
00178             reset = false;
00179         }
00180     }
00181 
00182     pPainter->restore();
00183 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines