Clementine-audio-player-Mac.../src/analyzers/glanalyzer.cpp

319 lines
7.4 KiB
C++

/* This file is part of Clementine.
Copyright 2004, Adam Pigg <adam@piggz.co.uk>
Copyright 2009, David Sansome <davidsansome@gmail.com>
Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
Copyright 2014, John Maguire <john.maguire@gmail.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
/* Original Author: Adam Pigg <adam@piggz.co.uk> 2004
*/
#include <config.h>
#ifdef HAVE_QGLWIDGET
#include <kdebug.h>
#include <cmath>
#include "glanalyzer.h"
GLAnalyzer::GLAnalyzer(QWidget* parent)
: Analyzer::Base3D(parent, 15), m_oldy(32, -10.0f), m_peaks(32) {}
GLAnalyzer::~GLAnalyzer() {}
void GLAnalyzer::analyze(const Scope& s) {
// kdDebug() << "Scope Size: " << s.size() << endl;
/* Scope t(32);
if (s.size() != 32)
{
Analyzer::interpolate(s, t);
}
else
{
t = s;
}*/
uint offset = 0;
static float peak;
float mfactor = 0.0;
static int drawcount;
if (s.size() == 64) {
offset = 8;
}
glRotatef(0.25f, 0.0f, 1.0f, 0.5f); // Rotate the scene
drawFloor();
drawcount++;
if (drawcount > 25) {
drawcount = 0;
peak = 0.0;
}
for (uint i = 0; i < 32; i++) {
if (s[i] > peak) {
peak = s[i];
}
}
mfactor = 20 / peak;
for (uint i = 0; i < 32; i++) {
// Calculate new horizontal position (x) depending on number of samples
x = -16.0f + i;
// Calculating new vertical position (y) depending on the data passed by
// amarok
y = static_cast<float>(s[i + offset] *
mfactor); // This make it kinda dynamically
// resize depending on the data
// Some basic bounds checking
if (y > 30)
y = 30;
else if (y < 0)
y = 0;
if ((y - m_oldy[i]) < -0.6f) {
y = m_oldy[i] - 0.7f;
}
if (y < 0.0f) {
y = 0.0f;
}
m_oldy[i] = y; // Save value as last value
// Peak Code
if (m_oldy[i] > m_peaks[i].level) {
m_peaks[i].level = m_oldy[i];
m_peaks[i].delay = 30;
}
if (m_peaks[i].delay > 0) {
m_peaks[i].delay--;
}
if (m_peaks[i].level > 1.0f) {
if (m_peaks[i].delay <= 0) {
m_peaks[i].level -= 0.4f;
}
}
// Draw the bar
drawBar(x, y);
drawPeak(x, m_peaks[i].level);
}
updateGL();
}
void GLAnalyzer::initializeGL() {
// Clear frame (next fading will be preferred to clearing)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color to black
glClear(GL_COLOR_BUFFER_BIT);
// Set the shading model
glShadeModel(GL_SMOOTH);
// Set the polygon mode to fill
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Enable depth testing for hidden line removal
glEnable(GL_DEPTH_TEST);
// Set blend parameters for 'composting alpha'
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void GLAnalyzer::resizeGL(int w, int h) {
glViewport(0, 0, (GLint)w, (GLint)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-16.0f, 16.0f, -10.0f, 10.0f, -50.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void GLAnalyzer::paintGL() {
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glPushMatrix();
glLoadIdentity();
glBegin(GL_TRIANGLE_STRIP);
glColor4f(0.0f, 0.0f, 0.1f, 0.08f);
glVertex2f(20.0f, 10.0f);
glVertex2f(-20.0f, 10.0f);
glVertex2f(20.0f, -10.0f);
glVertex2f(-20.0f, -10.0f);
glEnd();
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
#endif
// swapBuffers();
glFlush();
}
void GLAnalyzer::drawBar(float xPos, float height) {
glPushMatrix();
// Sets color to blue
// Set the colour depending on the height of the bar
glColor3f((height / 40) + 0.5f, (height / 40) + 0.625f, 1.0f);
glTranslatef(xPos, -10.0f, 0.0f);
glScalef(1.0f, height, 3.0f);
drawCube();
// Set colour to full blue
// glColor3f(0.0f, 0.0f, 1.0f);
// drawFrame();
glPopMatrix();
}
void GLAnalyzer::drawFloor() {
glPushMatrix();
// Sets color to amarok blue
glColor3f(0.5f, 0.625f, 1.0f);
glTranslatef(-16.0f, -11.0f, -4.0f);
glScalef(32.0f, 1.0f, 10.0f);
drawCube();
// Set colour to full blue
glColor3f(0.0f, 0.0f, 1.0f);
drawFrame();
glPopMatrix();
}
void GLAnalyzer::drawPeak(float xPos, float ypos) {
glPushMatrix();
// Set the colour to red
glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef(xPos, ypos - 10.0f, 0.0f);
glScalef(1.0f, 1.0f, 3.0f);
drawCube();
glPopMatrix();
}
void GLAnalyzer::drawCube() {
glPushMatrix();
glBegin(GL_POLYGON);
// This is the top face
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// This is the front face
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// This is the right face
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
// This is the left face
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// This is the bottom face
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// This is the back face
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
glPopMatrix();
}
void GLAnalyzer::drawFrame() {
glPushMatrix();
glBegin(GL_LINES);
// This is the top face
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// This is the front face
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// This is the right face
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
// This is the left face
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// This is the bottom face
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// This is the back face
glVertex3f(0.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
glPopMatrix();
}
#endif