1 /*
2  * DISTRHO glBars Plugin based on XMMS/XBMC "GL Bars"
3  * Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
4  * Copyright (C) 2000 Christian Zander <phoenix@minion.de>
5  * Copyright (C) 2015 Nedko Arnaudov
6  * Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * For a full copy of the license see the LICENSE file.
18  */
19 
20 #ifndef GLBARS_STATE_HPP_INCLUDED
21 #define GLBARS_STATE_HPP_INCLUDED
22 
23 #include "OpenGL.hpp"
24 
25 static inline
draw_rectangle(GLfloat x1,GLfloat y1,GLfloat z1,GLfloat x2,GLfloat y2,GLfloat z2)26 void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
27 {
28     if (y1 == y2)
29     {
30         glVertex3f(x1, y1, z1);
31         glVertex3f(x2, y1, z1);
32         glVertex3f(x2, y2, z2);
33 
34         glVertex3f(x2, y2, z2);
35         glVertex3f(x1, y2, z2);
36         glVertex3f(x1, y1, z1);
37     }
38     else
39     {
40         glVertex3f(x1, y1, z1);
41         glVertex3f(x2, y1, z2);
42         glVertex3f(x2, y2, z2);
43 
44         glVertex3f(x2, y2, z2);
45         glVertex3f(x1, y2, z1);
46         glVertex3f(x1, y1, z1);
47     }
48 }
49 
50 static inline
draw_bar(GLenum mode,GLfloat x_offset,GLfloat z_offset,GLfloat height,GLfloat red,GLfloat green,GLfloat blue)51 void draw_bar(GLenum mode, GLfloat x_offset, GLfloat z_offset, GLfloat height, GLfloat red, GLfloat green, GLfloat blue)
52 {
53     const GLfloat width = 0.1;
54 
55     if (mode == GL_POINT)
56         glColor3f(0.2, 1.0, 0.2);
57 
58     if (mode != GL_POINT)
59     {
60         glColor3f(red,green,blue);
61         draw_rectangle(x_offset, height, z_offset, x_offset + width, height, z_offset + 0.1);
62     }
63     draw_rectangle(x_offset, 0, z_offset, x_offset + width, 0, z_offset + 0.1);
64 
65     if (mode != GL_POINT)
66     {
67         glColor3f(0.5 * red, 0.5 * green, 0.5 * blue);
68         draw_rectangle(x_offset, 0.0, z_offset + 0.1, x_offset + width, height, z_offset + 0.1);
69     }
70     draw_rectangle(x_offset, 0.0, z_offset, x_offset + width, height, z_offset );
71 
72     if (mode != GL_POINT)
73     {
74         glColor3f(0.25 * red, 0.25 * green, 0.25 * blue);
75         draw_rectangle(x_offset, 0.0, z_offset , x_offset, height, z_offset + 0.1);
76     }
77     draw_rectangle(x_offset + width, 0.0, z_offset , x_offset + width, height, z_offset + 0.1);
78 }
79 
80 struct glBarsState {
81     GLenum g_mode;
82     GLfloat x_angle, x_speed;
83     GLfloat y_angle, y_speed;
84     GLfloat z_angle, z_speed;
85     GLfloat heights[16][16], cHeights[16][16], scale;
86     GLfloat hSpeed;
87 
glBarsStateglBarsState88     glBarsState()
89     {
90         g_mode = GL_FILL;
91         x_angle = 20.0;
92         x_speed = 0.0;
93         y_angle = 15.0; // was 45
94         y_speed = 0.5;
95         z_angle = 0.0;
96         z_speed = 0.0;
97 
98         // Set "Bar Height"
99         scale = 1.f   / log(256.f); // "Default" / standard
100         //scale = 2.f   / log(256.f); // "Big"
101         //scale = 3.f   / log(256.f); // "Very Big" / real big
102         //scale = 0.33f / log(256.f); // unused
103         //scale = 0.5f  / log(256.f); // "Small"
104 
105         // Set "Speed"
106         //hSpeed = 0.025f;          // "Slow"
107         hSpeed = 0.0125f;         // "Default"
108         //hSpeed = 0.1f;            // "Fast"
109         //hSpeed = 0.2f;            // "Very Fast"
110         //hSpeed = 0.05f;           // "Very Slow"
111 
112         for (int x = 0; x < 16; x++)
113         {
114             for (int y = 0; y < 16; y++)
115                 cHeights[y][x] = heights[y][x] = 0;
116         }
117     }
118 
drawBarsglBarsState119     void drawBars()
120     {
121         GLfloat x_offset, z_offset, r_base, b_base;
122 
123         glClear(GL_DEPTH_BUFFER_BIT);
124         glPushMatrix();
125         glTranslatef(0.0,-0.5,-5.0);
126         glRotatef(x_angle,1.0,0.0,0.0);
127         glRotatef(y_angle,0.0,1.0,0.0);
128         glRotatef(z_angle,0.0,0.0,1.0);
129 
130         glPolygonMode(GL_FRONT_AND_BACK, g_mode);
131         glBegin(GL_TRIANGLES);
132 
133         for (int y = 0; y < 16; y++)
134         {
135             z_offset = -1.6 + ((15 - y) * 0.2);
136 
137             b_base = y * (1.0 / 15);
138             r_base = 1.0 - b_base;
139 
140             for (int x = 0; x < 16; x++)
141             {
142                 x_offset = -1.6 + ((float)x * 0.2);
143                 if (::fabs(cHeights[y][x]-heights[y][x])>hSpeed)
144                 {
145                   if (cHeights[y][x]<heights[y][x])
146                       cHeights[y][x] += hSpeed;
147                   else
148                       cHeights[y][x] -= hSpeed;
149                 }
150                 draw_bar(g_mode, x_offset, z_offset,
151                          cHeights[y][x], r_base - (float(x) * (r_base / 15.0)),
152                          (float)x * (1.0 / 15), b_base /*, 16*y+x*/);
153             }
154         }
155 
156         glEnd();
157         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
158         glPopMatrix();
159     }
160 
RenderglBarsState161     void Render()
162     {
163         glDisable(GL_BLEND);
164         glMatrixMode(GL_PROJECTION);
165         glPushMatrix();
166         glLoadIdentity();
167         glFrustum(-1, 1, -1, 1, 1.5, 10);
168         glMatrixMode(GL_MODELVIEW);
169         glPushMatrix();
170         glLoadIdentity();
171         glEnable(GL_DEPTH_TEST);
172         glDepthFunc(GL_LESS);
173         glPolygonMode(GL_FRONT, GL_FILL);
174         //glPolygonMode(GL_BACK, GL_FILL);
175 
176         x_angle += x_speed;
177         if (x_angle >= 360.0)
178             x_angle -= 360.0;
179 
180         y_angle += y_speed;
181         if (y_angle >= 360.0)
182             y_angle -= 360.0;
183 
184         z_angle += z_speed;
185         if (z_angle >= 360.0)
186             z_angle -= 360.0;
187 
188         drawBars();
189 
190         glPopMatrix();
191         glMatrixMode(GL_PROJECTION);
192         glPopMatrix();
193         glDisable(GL_DEPTH_TEST);
194         glEnable(GL_BLEND);
195     }
196 
AudioDataglBarsState197     void AudioData(const float* pAudioData, int iAudioDataLength)
198     {
199         const int xscale[] = {0, 1, 2, 3, 5, 7, 10, 14, 20, 28, 40, 54, 74, 101, 137, 187, 255};
200 
201         GLfloat val;
202 
203         for (int y = 15; y > 0; y--)
204         {
205             for (int i = 0; i < 16; i++)
206                 heights[y][i] = heights[y - 1][i];
207         }
208 
209         for (int i = 0; i < 16; i++)
210         {
211             int y = 0;
212             for (int c = xscale[i]; c < xscale[i + 1]; c++)
213             {
214                 if (c<iAudioDataLength)
215                 {
216                     if ((int)(pAudioData[c] * (INT16_MAX)) > y)
217                         y = (int)(pAudioData[c] * (INT16_MAX));
218                 }
219                 else
220                 {
221                     continue;
222                 }
223             }
224             y >>= 7;
225             if (y > 0)
226                 val = (logf(y) * scale);
227             else
228                 val = 0;
229             heights[0][i] = val;
230         }
231     }
232 };
233 
234 #endif // GLBARS_STATE_HPP_INCLUDED
235