Mixxx

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

Go to the documentation of this file.
00001 
00007 #include <QDebug>
00008 #include <QDomNode>
00009 #include <QImage>
00010 #include <QObject>
00011 #include <qgl.h>
00012 
00013 #include "glwaveformrenderer.h"
00014 #include "waveformrenderbeat.h"
00015 #include "trackinfoobject.h"
00016 #include "soundsourceproxy.h"
00017 #include "controlobjectthreadmain.h"
00018 #include "controlobject.h"
00019 #include "widget/wwidget.h"
00020 #include "widget/wskincolor.h"
00021 
00022 #define DEFAULT_SECONDS_TO_DISPLAY 4
00023 #define SCALE_TEST 4
00024 
00025 GLWaveformRenderer::GLWaveformRenderer(const char* group) :
00026 m_iWidth(0),
00027 m_iHeight(0),
00028 m_iMax(0),
00029 m_iMin(0),
00030 m_iNumSamples(0),
00031 bgColor(0,0,0),
00032 signalColor(255,255,255),
00033 colorMarker(255,255,255),
00034 colorBeat(255,255,255),
00035 colorCue(255,255,255),
00036 m_iDesiredSecondsToDisplay(DEFAULT_SECONDS_TO_DISPLAY),
00037 m_pSampleBuffer(NULL),
00038 m_pInternalBuffer(NULL),
00039 m_iInternalBufferSize(0)
00040 {
00041     m_pPlayPos = new ControlObjectThreadMain(ControlObject::getControl(ConfigKey(group,"playposition")));
00042     connect(m_pPlayPos, SIGNAL(valueChanged(double)), this, SLOT(slotUpdatePlayPos(double)));
00043 
00044     m_pCOVisualResample = new ControlObject(ConfigKey(group,"VisualResample"));
00045     m_pCOVerticalScale = new ControlObject(ConfigKey(group, "VisualVerticalScale"));
00046 }
00047 
00048 
00049 GLWaveformRenderer::~GLWaveformRenderer() {
00050     if(m_pCOVisualResample)
00051         delete m_pCOVisualResample;
00052     m_pCOVisualResample = NULL;
00053 
00054     if(m_pCOVerticalScale)
00055         delete m_pCOVerticalScale;
00056     m_pCOVerticalScale = NULL;
00057 
00058     if(m_pPlayPos)
00059         delete m_pPlayPos;
00060     m_pPlayPos = NULL;
00061 
00062 }
00063 
00064 void GLWaveformRenderer::slotUpdatePlayPos(double v) {
00065     m_dPlayPos = v;
00066 }
00067 
00068 
00069 void GLWaveformRenderer::resize(int w, int h) {
00070     m_iWidth = w;
00071     m_iHeight = h;
00072 
00073     m_pInternalBuffer = new GLfloat[w*3*5];
00074     m_iInternalBufferSize = w*5;
00075 
00076     for(int i=0; i<w*5; i++) {
00077         m_pInternalBuffer[i*3+0] = i-10;
00078         m_pInternalBuffer[i*3+1] = 0.5;
00079         m_pInternalBuffer[i*3+2] = 1.0;
00080 
00081 
00082     }
00083 
00084     glMatrixMode(GL_PROJECTION);
00085     glLoadIdentity();
00086     gluPerspective(60.0, 1.0, 1.0, 1000.0);
00087     glViewport(0,0,w,h);
00088 
00089     gluLookAt(0,0,15.0, // look along z-axis
00090               0,0,0,  // from the origin
00091               0,1.0,0); // with y being 'up'
00092 
00093     setupControlObjects();
00094 }
00095 
00096 void GLWaveformRenderer::setupControlObjects() {
00097 
00098     // the max positive value of a sample is 32767, (2**15-1)
00099     // we want the waveforms normalized so that 0-32767 maps to 0-m_iHeight/2
00100     // (m_iHeight/2) = (32767) / x  =>  x = 32767/(m_iHeight/2)
00101     int verticalScale = ((1<<15)-1)*2/ m_iHeight;
00102     m_pCOVerticalScale->set(verticalScale);
00103 
00104 
00105     // the resample rate is the number of seconds that correspond to one pixel
00106     // on the visual waveform display.
00107 
00108     // the reason for using seconds is that we do not know the
00109     // sample rate of the song that will be loaded.
00110 
00111     // we calculate this as follows:
00112 
00113     // secondsPerPixel = desiredSecondsToDisplay / m_iWidth
00114 
00115     // for now just send the width.. meh
00116     double secondsPerPixel = double(m_iDesiredSecondsToDisplay)/m_iWidth;
00117     //m_pCOVisualResample->set(secondsPerPixel);
00118 
00119     m_pCOVisualResample->set(m_iWidth);
00120 
00121     qDebug() << "GLWaveformRenderer::setupControlObjects - VisualResample: " << secondsPerPixel << " VerticalScale: " << verticalScale;
00122 
00123 }
00124 
00125 void GLWaveformRenderer::setup(QDomNode node) {
00126 
00127     bgColor.setNamedColor(WWidget::selectNodeQString(node, "BgColor"));
00128     bgColor = WSkinColor::getCorrectColor(bgColor);
00129 
00130     qDebug() << "Got bgColor " << bgColor;
00131 
00132     signalColor.setNamedColor(WWidget::selectNodeQString(node, "SignalColor"));
00133     signalColor = WSkinColor::getCorrectColor(signalColor);
00134 
00135     qDebug() << "Got signalColor " << signalColor;
00136 
00137     colorMarker.setNamedColor(WWidget::selectNodeQString(node, "MarkerColor"));
00138     colorMarker = WSkinColor::getCorrectColor(colorMarker);
00139 
00140     colorBeat.setNamedColor(WWidget::selectNodeQString(node, "BeatColor"));
00141     colorBeat = WSkinColor::getCorrectColor(colorBeat);
00142 
00143     colorCue.setNamedColor(WWidget::selectNodeQString(node, "CueColor"));
00144     colorCue = WSkinColor::getCorrectColor(colorCue);
00145 
00146 }
00147 
00148 
00149 void GLWaveformRenderer::precomputePixmap() {
00150 
00151 }
00152 
00153 bool GLWaveformRenderer::fetchWaveformFromTrack() {
00154 
00155     if(!m_pTrack)
00156         return false;
00157 
00158     QVector<float> *buffer = m_pTrack->getVisualWaveform();
00159 
00160     if(buffer == NULL)
00161         return false;
00162 
00163     m_pSampleBuffer = buffer;
00164     m_iNumSamples = buffer->size();
00165 
00166     return true;
00167 }
00168 
00169 
00170 
00171 void GLWaveformRenderer::drawSignalLines() {
00172 
00173     if(m_pSampleBuffer == NULL) {
00174             return;
00175     }
00176 
00177     int iCurPos = 0;
00178     if(m_dPlayPos != -1) {
00179         iCurPos = (int)(m_dPlayPos*m_iNumSamples);
00180     }
00181 
00182     if((iCurPos % 2) != 0)
00183         iCurPos--;
00184 
00185 
00186     int halfw = m_iInternalBufferSize/2;
00187 
00188     for(int i=0;i<m_iInternalBufferSize;i++) {
00189         int thisIndex = iCurPos+2*(i-halfw);
00190         if(thisIndex >= 0 && (thisIndex+1) < m_iNumSamples) {
00191             float sampl = (*m_pSampleBuffer)[thisIndex];
00192             float sampr = (*m_pSampleBuffer)[thisIndex+1];
00193 
00194             m_pInternalBuffer[i*3+1] = sampl;
00195         }
00196 
00197 
00198     }
00199 
00200     /*
00201     pPainter->scale(1.0/float(SCALE_TEST),m_iHeight*0.40);
00202     int halfw = m_iWidth*SCALE_TEST/2;
00203     for(int i=0;i<m_iWidth*SCALE_TEST;i++) {
00204         //pPainter->drawLine(QPoint(i,0), QPoint(i, i/sca));
00205         int thisIndex = iCurPos+2*(i-halfw);
00206         if(thisIndex >= 0 && (thisIndex+1) < m_iNumSamples) {
00207             float sampl = (*m_pSampleBuffer)[thisIndex];
00208             float sampr = (*m_pSampleBuffer)[thisIndex+1];
00209 
00210             // Old cruft
00211             //pPainter->drawLine(QPoint(i,m_iHeight/4), QPoint(i,m_iHeight/4+sampl/scaley2));
00212             //pPainter->drawLine(QPoint(i,-m_iHeight/4), QPoint(i,-m_iHeight/4+sampr/scaley2));
00213 
00214             // These are decent
00215             //pPainter->drawLine(QPoint(i,0), QPoint(i, sampl/scaley));
00216             //pPainter->drawLine(QPoint(i,0), QPoint(i, -sampr/scaley));
00217 
00218             //m_lines[i] = QLineF(i,-sampr,i,sampl);
00219         } else {
00220             //m_lines[i] = QLineF(0,0,0,0);
00221         }
00222     }
00223 
00224     //pPainter->drawLines(m_lines);
00225 
00226     pPainter->restore();
00227     */
00228 }
00229 
00230 void GLWaveformRenderer::drawSignalPixmap(QPainter *pPainter) {
00231 
00232 }
00233 
00234 void GLWaveformRenderer::glDraw() {
00235 
00236     if(m_iWidth == 0 || m_iHeight == 0)
00237         return;
00238 
00239     if(m_pSampleBuffer == NULL) {
00240         fetchWaveformFromTrack();
00241         if(m_pSampleBuffer != NULL)
00242             qDebug() << "Received waveform from track";
00243     }
00244 
00245     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00246     glMatrixMode(GL_MODELVIEW);
00247     glLoadIdentity();
00248 
00249     gluLookAt(0,0,15,
00250               0,0,0,
00251               0,1,0);
00252 
00253     glDrawBuffer(GL_BACK);
00254 
00255 
00256     glPushMatrix();
00257 
00258     glScalef(1.0/5.0,m_iHeight/2, 1.0);
00259 
00260     drawSignalLines();
00261 
00262     glBegin(GL_LINES);
00263 
00264     glVertex3f(0,0,1.0);
00265     glVertex3f(0,1.0,1.0);
00266 
00267 
00268     glEnd();
00269 
00270     glEnableClientState(GL_VERTEX_ARRAY);
00271     glVertexPointer(3, GL_FLOAT, 0, m_pInternalBuffer);
00272     glDrawArrays(GL_LINE_LOOP,0,m_iInternalBufferSize);
00273 
00274     glPopMatrix();
00275 
00276 
00277 
00278     glFlush();
00279 }
00280 
00281 void GLWaveformRenderer::draw(QPainter* pPainter, QPaintEvent *pEvent) {
00282     pPainter->fillRect(pEvent->rect(), QBrush(bgColor));
00283     pPainter->setPen(signalColor);
00284 
00285     if(m_iWidth == 0 || m_iHeight == 0)
00286         return;
00287 
00288     //int scaley = 32767*2/ m_iHeight;
00289     //int scaley2 = 32767*4/ m_iHeight;
00290     //int sca = m_iWidth*2/ m_iHeight;
00291 
00292 
00293     if(m_pSampleBuffer == NULL) {
00294         fetchWaveformFromTrack();
00295         if(m_pSampleBuffer != NULL)
00296             qDebug() << "Received waveform from track";
00297     }
00298 
00299 
00300 
00301     //drawSignalPixmap(pPainter);
00302 
00303 
00304 
00305     pPainter->translate(0,m_iHeight/2);
00306     pPainter->scale(1.0,-1.0);
00307     //drawSignalLines(pPainter);
00308 
00309 
00310     // Draw various markers.
00311     pPainter->setPen(colorMarker);
00312 
00313     pPainter->drawLine(QLine(0,0,m_iWidth,0));
00314     pPainter->drawLine(QLine(m_iWidth/2,m_iHeight/2,m_iWidth/2,-m_iHeight/2));
00315     //pPainter->drawLine(QPoint(-h,0), QPoint(h,0));
00316     //pPainter->drawLine(QPoint(h,m_iHeight/2), QPoint(h,-m_iHeight/2));
00317 
00318 
00319 }
00320 
00321 void GLWaveformRenderer::newTrack(TrackPointer pTrack) {
00322     m_pTrack = pTrack;
00323     m_pSampleBuffer = 0;
00324     m_iNumSamples = 0;
00325 
00326 }
00327 
00328 int GLWaveformRenderer::getDesiredSecondsToDisplay() {
00329     return m_iDesiredSecondsToDisplay;
00330 }
00331 
00332 void GLWaveformRenderer::setDesiredSecondsToDisplay(int secondsToDisplay) {
00333     m_iDesiredSecondsToDisplay = secondsToDisplay;
00334 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines