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