![]() |
Mixxx
|
00001 #include <QDebug> 00002 #include <QColor> 00003 #include <QDomNode> 00004 #include <QPaintEvent> 00005 #include <QPainter> 00006 #include <QObject> 00007 #include <QVector> 00008 #include <QLine> 00009 #include <qgl.h> 00010 00011 #include "waveformrendersignal.h" 00012 #include "waveformrenderer.h" 00013 #include "controlobjectthreadmain.h" 00014 #include "controlobject.h" 00015 #include "widget/wskincolor.h" 00016 #include "widget/wwidget.h" 00017 #include "trackinfoobject.h" 00018 00019 WaveformRenderSignal::WaveformRenderSignal(const char* group, WaveformRenderer *parent) 00020 : m_pParent(parent), 00021 m_iWidth(0), 00022 m_iHeight(0), 00023 m_fGain(1), 00024 m_lines(0), 00025 m_pTrack(NULL), 00026 signalColor(255,255,255) { 00027 m_pGain = new ControlObjectThreadMain( 00028 ControlObject::getControl(ConfigKey(group, "total_gain"))); 00029 if (m_pGain != NULL) { 00030 connect(m_pGain, SIGNAL(valueChanged(double)), 00031 this, SLOT(slotUpdateGain(double))); 00032 } 00033 } 00034 00035 WaveformRenderSignal::~WaveformRenderSignal() { 00036 qDebug() << this << "~WaveformRenderSignal()"; 00037 delete m_pGain; 00038 } 00039 00040 void WaveformRenderSignal::resize(int w, int h) { 00041 m_iWidth = w; 00042 m_iHeight = h; 00043 } 00044 00045 void WaveformRenderSignal::newTrack(TrackPointer pTrack) { 00046 m_pTrack = pTrack; 00047 } 00048 00049 void WaveformRenderSignal::slotUpdateGain(double v) { 00050 m_fGain = v; 00051 } 00052 00053 void WaveformRenderSignal::setup(QDomNode node) { 00054 signalColor.setNamedColor(WWidget::selectNodeQString(node, "SignalColor")); 00055 signalColor = WSkinColor::getCorrectColor(signalColor); 00056 } 00057 00058 00059 void WaveformRenderSignal::draw(QPainter *pPainter, QPaintEvent *event, 00060 QVector<float> *buffer, double dPlayPos, 00061 double rateAdjust) { 00062 if (buffer == NULL) { 00063 return; 00064 } 00065 00066 const float* baseBuffer = buffer->constData(); 00067 00068 int numBufferSamples = buffer->size(); 00069 int iCurPos = 0; 00070 iCurPos = (int)(dPlayPos*numBufferSamples); 00071 00072 if ((iCurPos % 2) != 0) 00073 iCurPos--; 00074 00075 pPainter->save(); 00076 00077 pPainter->setPen(signalColor); 00078 00079 const double subpixelsPerPixel = m_pParent->getSubpixelsPerPixel() * (1.0 + rateAdjust); 00080 00081 int subpixelWidth = int(m_iWidth * subpixelsPerPixel); 00082 00083 // If the array is not large enough, expand it. 00084 // Amortize the cost of this by requesting a factor of 2 more. 00085 if(m_lines.size() < subpixelWidth) { 00086 m_lines.resize(2*subpixelWidth); 00087 } 00088 00089 // Use the pointer to the QVector internal data to avoid range 00090 // checks. QVector<QLineF>::operator[] profiled very high. const_cast is 00091 // naughty but we just want Qt to leave us alone here. WARNING: calling 00092 // m_lines.data() will copy the entire vector in memory by calling 00093 // QVector<T>::detach(). QVector<T>::constData() does not do this. 00094 QLineF* lineData = const_cast<QLineF*>(m_lines.constData()); 00095 int halfw = subpixelWidth/2; 00096 for(int i=0;i<subpixelWidth;i++) { 00097 // Start at curPos minus half the waveform viewer 00098 int thisIndex = iCurPos+2*(i-halfw); 00099 if(thisIndex >= 0 && (thisIndex+1) < numBufferSamples) { 00100 float sampl = baseBuffer[thisIndex] * m_fGain * m_iHeight * 0.5f; 00101 float sampr = -baseBuffer[thisIndex+1] * m_fGain * m_iHeight * 0.5f; 00102 const qreal xPos = i/subpixelsPerPixel; 00103 lineData[i].setLine(xPos, sampr, xPos, sampl); 00104 } else { 00105 lineData[i].setLine(0,0,0,0); 00106 } 00107 } 00108 00109 // Only draw lines that we have provided 00110 pPainter->drawLines(lineData, subpixelWidth); 00111 00112 // Some of the pre-roll is on screen. Draw little triangles to indicate 00113 // where the pre-roll is located. 00114 if (iCurPos < 2*halfw) { 00115 double start_index = 0; 00116 int end_index = (halfw - iCurPos/2); 00117 QPolygonF polygon; 00118 const int polyWidth = 80; 00119 polygon << QPointF(0, 0) 00120 << QPointF(-polyWidth/subpixelsPerPixel, -m_iHeight/5) 00121 << QPointF(-polyWidth/subpixelsPerPixel, m_iHeight/5); 00122 polygon.translate(end_index/subpixelsPerPixel, 0); 00123 00124 int index = end_index; 00125 while (index > start_index) { 00126 pPainter->drawPolygon(polygon); 00127 polygon.translate(-polyWidth/subpixelsPerPixel, 0); 00128 index -= polyWidth; 00129 } 00130 } 00131 pPainter->restore(); 00132 }