1 // Copyright (C) 2009 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma version(1)
16 
17 #pragma rs java_package_name(com.android.musicvis.vis5)
18 
19 #include "rs_graphics.rsh"
20 
21 float gAngle;
22 int   gPeak;
23 float gRotate;
24 float gTilt;
25 int   gIdle;
26 int   gWaveCounter;
27 
28 rs_program_vertex gPVBackground;
29 rs_program_fragment gPFBackgroundMip;
30 rs_program_fragment gPFBackgroundNoMip;
31 rs_program_raster gPR;
32 
33 rs_allocation gTvumeter_background;
34 rs_allocation gTvumeter_peak_on;
35 rs_allocation gTvumeter_peak_off;
36 rs_allocation gTvumeter_needle;
37 rs_allocation gTvumeter_black;
38 rs_allocation gTvumeter_frame;
39 rs_allocation gTvumeter_album;
40 
41 rs_program_store gPFSBackground;
42 
43 typedef struct Vertex {
44     float2 position;
45     float2 texture0;
46 } Vertex_t;
47 Vertex_t *gPoints;
48 
49 
50 rs_allocation gPointBuffer;
51 rs_allocation gTlinetexture;
52 rs_mesh gCubeMesh;
53 
54 #define RSID_POINTS 1
55 
56 static void drawVU(rs_matrix4x4 *ident) {
57     rs_matrix4x4 mat1;
58     float scale = 0.0041;
59 
60     rsMatrixLoad(&mat1,ident);
61     rsMatrixRotate(&mat1, 0.f, 0.f, 0.f, 1.f);
62     rsMatrixScale(&mat1, scale, scale, scale);
63     rsgProgramVertexLoadModelMatrix(&mat1);
64 
65     rsgBindProgramFragment(gPFBackgroundMip);
66     rsgBindProgramStore(gPFSBackground);
67 
68     // draw the background image (416x233)
69     rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_background);
70     rsgDrawQuadTexCoords(
71             -208.0f, -33.0f, 600.0f,       // space
72                 0.0f, 1.0f,               // texture
73             208, -33.0f, 600.0f,           // space
74                 1.0f, 1.0f,               // texture
75             208, 200.0f, 600.0f,           // space
76                 1.0f, 0.0f,               // texture
77             -208.0f, 200.0f, 600.0f,       // space
78                 0.0f, 0.0f);              // texture
79 
80     // draw the peak indicator light (56x58)
81     if (gPeak > 0) {
82         rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_peak_on);
83     } else {
84         rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_peak_off);
85     }
86     rsgDrawQuadTexCoords(
87             140.0f, 70.0f, 600.0f,         // space
88                 0.0f, 1.0f,               // texture
89             196, 70.0f, 600.0f,            // space
90                 1.0f, 1.0f,               // texture
91             196, 128.0f, 600.0f,           // space
92                 1.0f, 0.0f,               // texture
93             140.0f, 128.0f, 600.0f,        // space
94                 0.0f, 0.0f);              // texture
95 
96 
97 
98     // Draw the needle (88x262, center of rotation at 44,217 from top left)
99 
100     // set matrix so point of rotation becomes origin
101     rsMatrixLoad(&mat1,ident);
102     rsMatrixTranslate(&mat1, 0.f, -57.0f * scale, 0.f);
103     rsMatrixRotate(&mat1, gAngle - 90.f, 0.f, 0.f, 1.f);
104     rsMatrixScale(&mat1, scale, scale, scale);
105     rsgProgramVertexLoadModelMatrix(&mat1);
106     rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_needle);
107     rsgDrawQuadTexCoords(
108             -44.0f, -102.0f+57.f, 600.0f,         // space
109                 0.0f, 1.0f,             // texture
110             44.0f, -102.0f+57.f, 600.0f,             // space
111                 1.0f, 1.0f,              // texture
112             44.0f, 160.0f+57.f, 600.0f,             // space
113                 1.0f, 0.0f,              // texture
114             -44.0f, 160.0f+57.f, 600.0f,         // space
115                 0.0f, 0.0f);             // texture
116 
117 
118     // restore matrix
119     rsMatrixLoad(&mat1,ident);
120     rsMatrixRotate(&mat1, 0.f, 0.f, 0.f, 1.f);
121     rsMatrixScale(&mat1, scale, scale, scale);
122     rsgProgramVertexLoadModelMatrix(&mat1);
123 
124     // erase the part of the needle we don't want to show
125     rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_black);
126     rsgDrawQuad(-100.f, -55.f, 600.f,
127              -100.f, -105.f, 600.f,
128               100.f, -105.f, 600.f,
129               100.f, -55.f, 600.f);
130 
131 
132     // draw the frame (472x290)
133     rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_frame);
134     rsgDrawQuadTexCoords(
135             -236.0f, -60.0f, 600.0f,           // space
136                 0.0f, 1.0f,                  // texture
137             236, -60.0f, 600.0f,               // space
138                 1.0f, 1.0f,                  // texture
139             236, 230.0f, 600.0f,               // space
140                 1.0f, 0.0f,                  // texture
141             -236.0f, 230.0f, 600.0f,           // space
142                 0.0f, 0.0f);                 // texture
143 
144 
145 }
146 
147 int fadeoutcounter = 0;
148 int fadeincounter = 0;
149 int wave1pos = 0;
150 int wave1amp = 0;
151 int wave2pos = 0;
152 int wave2amp= 0;
153 int wave3pos = 0;
154 int wave3amp= 0;
155 int wave4pos = 0;
156 int wave4amp= 0;
157 float idle[4096];
158 int waveCounter = 0;
159 int lastuptime = 0;
160 float autorotation = 0;
161 
162 #define FADEOUT_LENGTH 100
163 #define FADEOUT_FACTOR 0.95f
164 #define FADEIN_LENGTH 15
165 
166 static void makeIdleWave(float *points) {
167     int i;
168     // show a number of superimposed moving sinewaves
169     float amp1 = sin(0.007f * wave1amp) * 120 * 1024;
170     float amp2 = sin(0.023f * wave2amp) * 80 * 1024;
171     float amp3 = sin(0.011f * wave3amp) * 40 * 1024;
172     float amp4 = sin(0.031f * wave4amp) * 20 * 1024;
173     for (i = 0; i < 256; i++) {
174         float val = sin(0.013f * (wave1pos + i * 4)) * amp1
175                   + sin(0.029f * (wave2pos + i * 4)) * amp2;
176         float off = sin(0.005f * (wave3pos + i * 4)) * amp3
177                   + sin(0.017f * (wave4pos + i * 4)) * amp4;
178         if (val < 2.f && val > -2.f) val = 2.f;
179         points[i*8+1] = val + off;
180         points[i*8+5] = -val + off;
181     }
182 }
183 
184 
185 static void drawWave(rs_matrix4x4 *ident) {
186     float scale = .008f;
187     rs_matrix4x4 mat1;
188     rsMatrixLoad(&mat1, ident);
189     rsMatrixScale(&mat1, scale, scale / 2048.f, scale);
190     rsMatrixTranslate(&mat1, 0.f, 81920.f, 350.f);
191     rsgProgramVertexLoadModelMatrix(&mat1);
192     int i;
193 
194     if (gIdle) {
195 
196         // idle state animation
197         float *points = (float*)gPoints;
198         if (fadeoutcounter > 0) {
199             // fade waveform to 0
200             for (i = 0; i < 256; i++) {
201                 float val = fabs(points[i*8+1]);
202                 val = val * FADEOUT_FACTOR;
203                 if (val < 2.f) val = 2.f;
204                 points[i*8+1] = val;
205                 points[i*8+5] = -val;
206             }
207             fadeoutcounter--;
208             if (fadeoutcounter == 0) {
209                 wave1amp = 0;
210                 wave2amp = 0;
211                 wave3amp = 0;
212                 wave4amp = 0;
213             }
214         } else {
215             // idle animation
216             makeIdleWave(points);
217         }
218         fadeincounter = FADEIN_LENGTH;
219     } else {
220         if (fadeincounter > 0 && fadeoutcounter == 0) {
221             // morph from idle animation back to waveform
222             makeIdleWave(idle);
223             if (waveCounter != gWaveCounter) {
224                 waveCounter = gWaveCounter;
225                 float *points = (float*)gPoints;
226                 for (i = 0; i < 256; i++) {
227                     float val = fabs(points[i*8+1]);
228                     points[i*8+1] = (val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+1] * fadeincounter) / FADEIN_LENGTH;
229                     points[i*8+5] = (-val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+5] * fadeincounter) / FADEIN_LENGTH;
230                 }
231             }
232             fadeincounter--;
233             if (fadeincounter == 0) {
234                 fadeoutcounter = FADEOUT_LENGTH;
235             }
236         } else {
237             fadeoutcounter = FADEOUT_LENGTH;
238         }
239     }
240 
241     rsgBindProgramRaster(gPR);
242     rsgBindProgramFragment(gPFBackgroundNoMip);
243     rsgBindTexture(gPFBackgroundNoMip, 0, gTlinetexture);
244     rsgDrawMesh(gCubeMesh);
245 }
246 
247 
248 static void drawVizLayer(rs_matrix4x4 *ident) {
249     for (int i = 0; i < 6; i++) {
250         if (i & 1) {
251             drawVU(ident);
252         } else {
253             drawWave(ident);
254         }
255 
256         rsMatrixRotate(ident, 60.f, 0.f, 1.f, 0.f);
257     }
258 }
259 
260 
261 int root(void) {
262     rsgClearColor(0.f, 0.f, 0.f, 1.f);
263 
264     rsgBindProgramVertex(gPVBackground);
265 
266     int i;
267     rs_matrix4x4 ident;
268     int now = (int)rsUptimeMillis();
269     int delta = now - lastuptime;
270     lastuptime = now;
271     if (delta > 80) {
272         // Limit the delta to avoid jumps when coming back from sleep.
273         // A value of 80 will make the rotation keep the same speed
274         // until the frame rate drops to 12.5 fps, at which point it
275         // will start slowing down.
276         delta = 80;
277     }
278     autorotation += .3 * delta / 35;
279     while (autorotation > 360.f) autorotation -= 360.f;
280 
281     rsMatrixLoadIdentity(&ident);
282     rsMatrixRotate(&ident, gTilt, 1.f, 0.f, 0.f);
283     rsMatrixRotate(&ident, autorotation + gRotate, 0.f, 1.f, 0.f);
284 
285     // draw the reflections
286     rsMatrixTranslate(&ident, 0.f, -1.f, 0.f);
287     rsMatrixScale(&ident, 1.f, -1.f, 1.f);
288     drawVizLayer(&ident);
289 
290     // draw the reflecting plane
291     rsgBindProgramFragment(gPFBackgroundMip);
292     rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_album);
293     rsgDrawQuadTexCoords(
294             -1500.0f, -60.0f, 1500.0f,           // space
295                 0.f, 1.f,    // texture
296             1500, -60.0f, 1500.0f,               // space
297                 1.f, 1.f,    // texture
298             1500, -60.0f, -1500.0f,               // space
299                 1.f, 0.f,    // texture
300             -1500.0f, -60.0f, -1500.0f,           // space
301                 0.f, 0.f);   // texture
302 
303     // draw the visualizer
304     rsMatrixScale(&ident, 1.f, -1.f, 1.f);
305     rsMatrixTranslate(&ident, 0.f, 1.f, 0.f);
306 
307     drawVizLayer(&ident);
308 
309     wave1pos++;
310     wave1amp++;
311     wave2pos--;
312     wave2amp++;
313     wave3pos++;
314     wave3amp++;
315     wave4pos++;
316     wave4amp++;
317 
318     return 1;
319 }
320