1 #include "waveform/renderers/glwaveformrendererrgb.h"
2 #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
3 
4 #include "track/track.h"
5 #include "util/math.h"
6 #include "waveform/waveform.h"
7 #include "waveform/waveformwidgetfactory.h"
8 #include "waveformwidgetrenderer.h"
9 #include "widget/wskincolor.h"
10 #include "widget/wwidget.h"
11 
12 namespace {
13 const float kHeightScaleFactor = 255.0f / sqrtf(255 * 255 * 3);
14 } // namespace
15 
GLWaveformRendererRGB(WaveformWidgetRenderer * waveformWidgetRenderer)16 GLWaveformRendererRGB::GLWaveformRendererRGB(
17         WaveformWidgetRenderer* waveformWidgetRenderer)
18         : WaveformRendererSignalBase(waveformWidgetRenderer) {
19 }
20 
~GLWaveformRendererRGB()21 GLWaveformRendererRGB::~GLWaveformRendererRGB() {
22 }
23 
onSetup(const QDomNode &)24 void GLWaveformRendererRGB::onSetup(const QDomNode& /* node */) {
25 }
26 
draw(QPainter * painter,QPaintEvent *)27 void GLWaveformRendererRGB::draw(QPainter* painter, QPaintEvent* /*event*/) {
28     maybeInitializeGL();
29 
30     TrackPointer pTrack = m_waveformRenderer->getTrackInfo();
31     if (!pTrack) {
32         return;
33     }
34 
35     ConstWaveformPointer waveform = pTrack->getWaveform();
36     if (waveform.isNull()) {
37         return;
38     }
39 
40     const int dataSize = waveform->getDataSize();
41     if (dataSize <= 1) {
42         return;
43     }
44 
45     const WaveformData* data = waveform->data();
46     if (data == nullptr) {
47         return;
48     }
49 
50     auto firstVisualIndex = static_cast<GLfloat>(
51             m_waveformRenderer->getFirstDisplayedPosition() * dataSize);
52     auto lastVisualIndex = static_cast<GLfloat>(
53             m_waveformRenderer->getLastDisplayedPosition() * dataSize);
54     const auto lineWidth = static_cast<GLfloat>(
55             (1.0 / m_waveformRenderer->getVisualSamplePerPixel()) + 1.5);
56 
57     const auto firstIndex = static_cast<int>(firstVisualIndex + 0.5);
58     firstVisualIndex = firstIndex - firstIndex % 2;
59 
60     const auto lastIndex = static_cast<int>(lastVisualIndex + 0.5);
61     lastVisualIndex = lastIndex + lastIndex % 2;
62 
63     // Reset device for native painting
64     painter->beginNativePainting();
65 
66     glEnable(GL_BLEND);
67     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
68 
69     // Per-band gain from the EQ knobs.
70     float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
71     getGains(&allGain, &lowGain, &midGain, &highGain);
72 
73     if (m_alignment == Qt::AlignCenter) {
74         glMatrixMode(GL_PROJECTION);
75         glPushMatrix();
76         glLoadIdentity();
77         if (m_orientation == Qt::Vertical) {
78             glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
79             glScalef(-1.0f, 1.0f, 1.0f);
80         }
81         glOrtho(firstVisualIndex, lastVisualIndex, -255.0, 255.0, -10.0, 10.0);
82 
83         glMatrixMode(GL_MODELVIEW);
84         glPushMatrix();
85         glLoadIdentity();
86 
87         glScalef(1.0f, allGain, 1.0f);
88 
89         glLineWidth(1.2f);
90         glDisable(GL_LINE_SMOOTH);
91 
92         // Draw reference line
93         glBegin(GL_LINES); {
94             glColor4f(static_cast<GLfloat>(m_axesColor_r),
95                     static_cast<GLfloat>(m_axesColor_g),
96                     static_cast<GLfloat>(m_axesColor_b),
97                     static_cast<GLfloat>(m_axesColor_a));
98             glVertex2f(firstVisualIndex, 0);
99             glVertex2f(lastVisualIndex,  0);
100         }
101         glEnd();
102 
103         glLineWidth(lineWidth);
104         glEnable(GL_LINE_SMOOTH);
105 
106         glBegin(GL_LINES); {
107 
108             int firstIndex = math_max(static_cast<int>(firstVisualIndex), 0);
109             int lastIndex = math_min(static_cast<int>(lastVisualIndex), dataSize);
110 
111             for (int visualIndex = firstIndex;
112                     visualIndex < lastIndex;
113                     visualIndex += 2) {
114                 const float left_low = lowGain * static_cast<float>(data[visualIndex].filtered.low);
115                 const float left_mid = midGain * static_cast<float>(data[visualIndex].filtered.mid);
116                 const float left_high = highGain *
117                         static_cast<float>(data[visualIndex].filtered.high);
118                 const float left_all =
119                         sqrtf(left_low * left_low + left_mid * left_mid +
120                                 left_high * left_high) *
121                         kHeightScaleFactor;
122                 float left_red =
123                         left_low * static_cast<float>(m_rgbLowColor_r) +
124                         left_mid * static_cast<float>(m_rgbMidColor_r) +
125                         left_high * static_cast<float>(m_rgbHighColor_r);
126                 float left_green =
127                         left_low * static_cast<float>(m_rgbLowColor_g) +
128                         left_mid * static_cast<float>(m_rgbMidColor_g) +
129                         left_high * static_cast<float>(m_rgbHighColor_g);
130                 float left_blue =
131                         left_low * static_cast<float>(m_rgbLowColor_b) +
132                         left_mid * static_cast<float>(m_rgbMidColor_b) +
133                         left_high * static_cast<float>(m_rgbHighColor_b);
134                 float left_max    = math_max3(left_red, left_green, left_blue);
135                 if (left_max > 0.0f) {  // Prevent division by zero
136                     glColor4f(left_red / left_max, left_green / left_max, left_blue / left_max, 0.8f);
137                     glVertex2f(visualIndex, 0.0f);
138                     glVertex2f(visualIndex, left_all);
139                 }
140 
141                 float right_low = lowGain * static_cast<float>(data[visualIndex + 1].filtered.low);
142                 float right_mid = midGain * static_cast<float>(data[visualIndex + 1].filtered.mid);
143                 float right_high = highGain *
144                         static_cast<float>(data[visualIndex + 1].filtered.high);
145                 float right_all   = sqrtf(right_low * right_low + right_mid * right_mid + right_high * right_high) * kHeightScaleFactor;
146                 float right_red =
147                         right_low * static_cast<float>(m_rgbLowColor_r) +
148                         right_mid * static_cast<float>(m_rgbMidColor_r) +
149                         right_high * static_cast<float>(m_rgbHighColor_r);
150                 float right_green =
151                         right_low * static_cast<float>(m_rgbLowColor_g) +
152                         right_mid * static_cast<float>(m_rgbMidColor_g) +
153                         right_high * static_cast<float>(m_rgbHighColor_g);
154                 float right_blue =
155                         right_low * static_cast<float>(m_rgbLowColor_b) +
156                         right_mid * static_cast<float>(m_rgbMidColor_b) +
157                         right_high * static_cast<float>(m_rgbHighColor_b);
158                 float right_max   = math_max3(right_red, right_green, right_blue);
159                 if (right_max > 0.0f) {  // Prevent division by zero
160                     glColor4f(right_red / right_max, right_green / right_max, right_blue / right_max, 0.8f);
161                     glVertex2f(visualIndex, 0.0f);
162                     glVertex2f(visualIndex, -1.0f * right_all);
163                 }
164             }
165         }
166 
167         glEnd();
168 
169     } else {  // top || bottom
170         glMatrixMode(GL_PROJECTION);
171         glPushMatrix();
172         glLoadIdentity();
173         if (m_orientation == Qt::Vertical) {
174             glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
175             glScalef(-1.0f, 1.0f, 1.0f);
176         }
177         if (m_alignment == Qt::AlignBottom || m_alignment == Qt::AlignRight) {
178             glOrtho(firstVisualIndex, lastVisualIndex, 0.0, 255.0, -10.0, 10.0);
179         } else {
180             glOrtho(firstVisualIndex, lastVisualIndex, 255.0, 0.0, -10.0, 10.0);
181         }
182 
183         glMatrixMode(GL_MODELVIEW);
184         glPushMatrix();
185         glLoadIdentity();
186 
187         glScalef(1.0f, allGain, 1.0f);
188 
189         glLineWidth(lineWidth);
190         glEnable(GL_LINE_SMOOTH);
191 
192         glBegin(GL_LINES); {
193 
194             int firstIndex = math_max(static_cast<int>(firstVisualIndex), 0);
195             int lastIndex = math_min(static_cast<int>(lastVisualIndex), dataSize);
196 
197             for (int visualIndex = firstIndex;
198                     visualIndex < lastIndex;
199                     visualIndex += 2) {
200                 float low = lowGain *
201                         static_cast<float>(
202                                 math_max(data[visualIndex].filtered.low,
203                                         data[visualIndex + 1].filtered.low));
204                 float mid = midGain *
205                         static_cast<float>(
206                                 math_max(data[visualIndex].filtered.mid,
207                                         data[visualIndex + 1].filtered.mid));
208                 float high = highGain *
209                         static_cast<float>(
210                                 math_max(data[visualIndex].filtered.high,
211                                         data[visualIndex + 1].filtered.high));
212 
213                 float all = sqrtf(low * low + mid * mid + high * high) * kHeightScaleFactor;
214 
215                 float red = low * static_cast<float>(m_rgbLowColor_r) +
216                         mid * static_cast<float>(m_rgbMidColor_r) +
217                         high * static_cast<float>(m_rgbHighColor_r);
218                 float green = low * static_cast<float>(m_rgbLowColor_g) +
219                         mid * static_cast<float>(m_rgbMidColor_g) +
220                         high * static_cast<float>(m_rgbHighColor_g);
221                 float blue = low * static_cast<float>(m_rgbLowColor_b) +
222                         mid * static_cast<float>(m_rgbMidColor_b) +
223                         high * static_cast<float>(m_rgbHighColor_b);
224 
225                 float max = math_max3(red, green, blue);
226                 if (max > 0.0f) {  // Prevent division by zero
227                     glColor4f(red / max, green / max, blue / max, 0.9f);
228                     glVertex2f(float(visualIndex), 0.0f);
229                     glVertex2f(float(visualIndex), all);
230                 }
231             }
232         }
233 
234         glEnd();
235     }
236 
237     glPopMatrix();
238     glMatrixMode(GL_PROJECTION);
239     glPopMatrix();
240 
241     painter->endNativePainting();
242 }
243 
244 #endif // !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
245