bool WOverviewRGB::drawNextPixmapPart() { ScopedTimer t("WOverviewRGB::drawNextPixmapPart"); //qDebug() << "WOverview::drawNextPixmapPart() - m_waveform" << m_waveform; int currentCompletion; ConstWaveformPointer pWaveform = getWaveform(); if (!pWaveform) { return false; } const int dataSize = pWaveform->getDataSize(); if (dataSize == 0) { return false; } if (!m_pWaveformSourceImage) { // Waveform pixmap twice the height of the viewport to be scalable // by total_gain // We keep full range waveform data to scale it on paint m_pWaveformSourceImage = new QImage(dataSize / 2, 2 * 255, QImage::Format_ARGB32_Premultiplied); m_pWaveformSourceImage->fill(QColor(0,0,0,0).value()); } // Always multiple of 2 const int waveformCompletion = pWaveform->getCompletion(); // Test if there is some new to draw (at least of pixel width) const int completionIncrement = waveformCompletion - m_actualCompletion; int visiblePixelIncrement = completionIncrement * width() / dataSize; if (completionIncrement < 2 || visiblePixelIncrement == 0) { return false; } const int nextCompletion = m_actualCompletion + completionIncrement; //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" // << nextCompletion // << "m_actualCompletion:" << m_actualCompletion // << "waveformCompletion:" << waveformCompletion // << "completionIncrement:" << completionIncrement; QPainter painter(m_pWaveformSourceImage); painter.translate(0.0,static_cast<double>(m_pWaveformSourceImage->height())/2.0); QColor color; qreal lowColor_r, lowColor_g, lowColor_b; m_signalColors.getRgbLowColor().getRgbF(&lowColor_r, &lowColor_g, &lowColor_b); qreal midColor_r, midColor_g, midColor_b; m_signalColors.getRgbMidColor().getRgbF(&midColor_r, &midColor_g, &midColor_b); qreal highColor_r, highColor_g, highColor_b; m_signalColors.getRgbHighColor().getRgbF(&highColor_r, &highColor_g, &highColor_b); for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { unsigned char left = pWaveform->getAll(currentCompletion); unsigned char right = pWaveform->getAll(currentCompletion + 1); // Retrieve "raw" LMH values from waveform qreal low = static_cast<qreal>(pWaveform->getLow(currentCompletion)); qreal mid = static_cast<qreal>(pWaveform->getMid(currentCompletion)); qreal high = static_cast<qreal>(pWaveform->getHigh(currentCompletion)); // Do matrix multiplication qreal red = low * lowColor_r + mid * midColor_r + high * highColor_r; qreal green = low * lowColor_g + mid * midColor_g + high * highColor_g; qreal blue = low * lowColor_b + mid * midColor_b + high * highColor_b; // Normalize and draw qreal max = math_max3(red, green, blue); if (max > 0.0) { color.setRgbF(red / max, green / max, blue / max); painter.setPen(color); painter.drawLine(currentCompletion / 2, -left, currentCompletion / 2, 0); } // Retrieve "raw" LMH values from waveform low = static_cast<qreal>(pWaveform->getLow(currentCompletion + 1)); mid = static_cast<qreal>(pWaveform->getMid(currentCompletion + 1)); high = static_cast<qreal>(pWaveform->getHigh(currentCompletion + 1)); // Do matrix multiplication red = low * lowColor_r + mid * midColor_r + high * highColor_r; green = low * lowColor_g + mid * midColor_g + high * highColor_g; blue = low * lowColor_b + mid * midColor_b + high * highColor_b; // Normalize and draw max = math_max3(red, green, blue); if (max > 0.0) { color.setRgbF(red / max, green / max, blue / max); painter.setPen(color); painter.drawLine(currentCompletion / 2, 0, currentCompletion / 2, right); } } // Evaluate waveform ratio peak for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { m_waveformPeak = math_max3( m_waveformPeak, static_cast<float>(pWaveform->getAll(currentCompletion)), static_cast<float>(pWaveform->getAll(currentCompletion + 1))); } m_actualCompletion = nextCompletion; m_waveformImageScaled = QImage(); m_diffGain = 0; // Test if the complete waveform is done if (m_actualCompletion >= dataSize - 2) { m_pixmapDone = true; //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; } return true; }
void GLSLWaveformRendererSignal::draw(QPainter* painter, QPaintEvent* /*event*/) { if (!m_frameBuffersValid || !m_shadersValid) { return; } TrackPointer trackInfo = m_waveformRenderer->getTrackInfo(); if (!trackInfo) { return; } ConstWaveformPointer waveform = trackInfo->getWaveform(); if (waveform.isNull()) { return; } int dataSize = waveform->getDataSize(); if (dataSize <= 1) { return; } const WaveformData* data = waveform->data(); if (data == NULL) { return; } // save the GL state set for QPainter painter->beginNativePainting(); //NOTE: (vRince) completion can change during loadTexture //do not remove currenCompletion temp variable ! const int currentCompletion = waveform->getCompletion(); if (m_loadedWaveform < currentCompletion) { loadTexture(); m_loadedWaveform = currentCompletion; } // Per-band gain from the EQ knobs. float lowGain(1.0), midGain(1.0), highGain(1.0), allGain(1.0); getGains(&allGain, &lowGain, &midGain, &highGain); double firstVisualIndex = m_waveformRenderer->getFirstDisplayedPosition() * dataSize/2.0; double lastVisualIndex = m_waveformRenderer->getLastDisplayedPosition() * dataSize/2.0; // const int firstIndex = int(firstVisualIndex+0.5); // firstVisualIndex = firstIndex - firstIndex%2; // const int lastIndex = int(lastVisualIndex+0.5); // lastVisualIndex = lastIndex + lastIndex%2; //qDebug() << "GAIN" << allGain << lowGain << midGain << highGain; //paint into frame buffer { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(firstVisualIndex, lastVisualIndex, -1.0, 1.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(.0f,.0f,.0f); m_frameShaderProgram->bind(); glViewport(0, 0, m_framebuffer->width(), m_framebuffer->height()); m_frameShaderProgram->setUniformValue("framebufferSize", QVector2D( m_framebuffer->width(), m_framebuffer->height())); m_frameShaderProgram->setUniformValue("waveformLength", dataSize); m_frameShaderProgram->setUniformValue("textureSize", waveform->getTextureSize()); m_frameShaderProgram->setUniformValue("textureStride", waveform->getTextureStride()); m_frameShaderProgram->setUniformValue("firstVisualIndex", (float)firstVisualIndex); m_frameShaderProgram->setUniformValue("lastVisualIndex", (float)lastVisualIndex); m_frameShaderProgram->setUniformValue("allGain", allGain); m_frameShaderProgram->setUniformValue("lowGain", lowGain); m_frameShaderProgram->setUniformValue("midGain", midGain); m_frameShaderProgram->setUniformValue("highGain", highGain); m_frameShaderProgram->setUniformValue("axesColor", QVector4D(m_axesColor_r, m_axesColor_g, m_axesColor_b, m_axesColor_a)); QVector4D lowColor = m_rgbShader ? QVector4D(m_rgbLowColor_r, m_rgbLowColor_g, m_rgbLowColor_b, 1.0) : QVector4D(m_lowColor_r, m_lowColor_g, m_lowColor_b, 1.0); QVector4D midColor = m_rgbShader ? QVector4D(m_rgbMidColor_r, m_rgbMidColor_g, m_rgbMidColor_b, 1.0) : QVector4D(m_midColor_r, m_midColor_g, m_midColor_b, 1.0); QVector4D highColor = m_rgbShader ? QVector4D(m_rgbHighColor_r, m_rgbHighColor_g, m_rgbHighColor_b, 1.0) : QVector4D(m_highColor_r, m_highColor_g, m_highColor_b, 1.0); m_frameShaderProgram->setUniformValue("lowColor", lowColor); m_frameShaderProgram->setUniformValue("midColor", midColor); m_frameShaderProgram->setUniformValue("highColor", highColor); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); m_framebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glCallList(m_unitQuadListId); glBegin(GL_QUADS); { glTexCoord2f(0.0,0.0); glVertex3f(firstVisualIndex, -1.0f, 0.0f); glTexCoord2f(1.0, 0.0); glVertex3f(lastVisualIndex, -1.0f, 0.0f); glTexCoord2f(1.0,1.0); glVertex3f(lastVisualIndex, 1.0f, 0.0f); glTexCoord2f(0.0,1.0); glVertex3f(firstVisualIndex, 1.0f, 0.0f); } glEnd(); m_framebuffer->release(); m_frameShaderProgram->release(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); if (m_bDumpPng) { m_framebuffer->toImage().save("m_framebuffer.png"); m_bDumpPng = false; } } glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(0.0, 0.0, 0.0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); //paint buffer into viewport { glViewport(0, 0, m_waveformRenderer->getWidth(), m_waveformRenderer->getHeight()); glBindTexture(GL_TEXTURE_2D, m_framebuffer->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBegin(GL_QUADS); { glTexCoord2f(0.0, 0.0); glVertex3f(-1.0f, -1.0f, 0.0f); glTexCoord2f(1.0, 0.0); glVertex3f(1.0f, -1.0f, 0.0f); glTexCoord2f(1.0, 1.0); glVertex3f(1.0f, 1.0f, 0.0f); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0f, 1.0f, 0.0f); } glEnd(); } glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); //DEBUG /* glBegin(GL_LINE_LOOP); { glColor4f(0.5,1.0,0.5,0.75); glVertex3f(-1.0f,-1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 0.0f); glVertex3f(1.0f,-1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f); } glEnd(); */ glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); painter->endNativePainting(); }
bool WOverviewHSV::drawNextPixmapPart() { ScopedTimer t("WOverviewHSV::drawNextPixmapPart"); //qDebug() << "WOverview::drawNextPixmapPart() - m_waveform" << m_waveform; int currentCompletion; ConstWaveformPointer pWaveform = getWaveform(); if (!pWaveform) { return false; } const int dataSize = pWaveform->getDataSize(); if (dataSize == 0) { return false; } if (!m_pWaveformSourceImage) { // Waveform pixmap twice the height of the viewport to be scalable // by total_gain // We keep full range waveform data to scale it on paint m_pWaveformSourceImage = new QImage(dataSize / 2, 2 * 255, QImage::Format_ARGB32_Premultiplied); m_pWaveformSourceImage->fill(QColor(0,0,0,0).value()); } // Always multiple of 2 const int waveformCompletion = pWaveform->getCompletion(); // Test if there is some new to draw (at least of pixel width) const int completionIncrement = waveformCompletion - m_actualCompletion; int visiblePixelIncrement = completionIncrement * width() / dataSize; if (completionIncrement < 2 || visiblePixelIncrement == 0) { return false; } const int nextCompletion = m_actualCompletion + completionIncrement; //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" // << nextCompletion // << "m_actualCompletion:" << m_actualCompletion // << "waveformCompletion:" << waveformCompletion // << "completionIncrement:" << completionIncrement; QPainter painter(m_pWaveformSourceImage); painter.translate(0.0,static_cast<double>(m_pWaveformSourceImage->height())/2.0); // Get HSV of low color. NOTE(rryan): On ARM, qreal is float so it's // important we use qreal here and not double or float or else we will get // build failures on ARM. qreal h, s, v; m_signalColors.getLowColor().getHsvF(&h, &s, &v); QColor color; float lo, hi, total; unsigned char maxLow[2] = {0, 0}; unsigned char maxHigh[2] = {0, 0}; unsigned char maxMid[2] = {0, 0}; unsigned char maxAll[2] = {0, 0}; for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { maxAll[0] = pWaveform->getAll(currentCompletion); maxAll[1] = pWaveform->getAll(currentCompletion+1); if (maxAll[0] || maxAll[1]) { maxLow[0] = pWaveform->getLow(currentCompletion); maxLow[1] = pWaveform->getLow(currentCompletion+1); maxMid[0] = pWaveform->getMid(currentCompletion); maxMid[1] = pWaveform->getMid(currentCompletion+1); maxHigh[0] = pWaveform->getHigh(currentCompletion); maxHigh[1] = pWaveform->getHigh(currentCompletion+1); total = (maxLow[0] + maxLow[1] + maxMid[0] + maxMid[1] + maxHigh[0] + maxHigh[1]) * 1.2; // Prevent division by zero if (total > 0) { // Normalize low and high // (mid not need, because it not change the color) lo = (maxLow[0] + maxLow[1]) / total; hi = (maxHigh[0] + maxHigh[1]) / total; } else { lo = hi = 0.0; } // Set color color.setHsvF(h, 1.0-hi, 1.0-lo); painter.setPen(color); painter.drawLine(QPoint(currentCompletion / 2, -maxAll[0]), QPoint(currentCompletion / 2, maxAll[1])); } } // Evaluate waveform ratio peak for (currentCompletion = m_actualCompletion; currentCompletion < nextCompletion; currentCompletion += 2) { m_waveformPeak = math_max3( m_waveformPeak, static_cast<float>(pWaveform->getAll(currentCompletion)), static_cast<float>(pWaveform->getAll(currentCompletion + 1))); } m_actualCompletion = nextCompletion; m_waveformImageScaled = QImage(); m_diffGain = 0; // Test if the complete waveform is done if (m_actualCompletion >= dataSize - 2) { m_pixmapDone = true; //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; } return true; }