blob: ed3b7922f57add07573b0c0a5941d7523f28f99c [file] [log] [blame]
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma version(1)
#pragma rs java_package_name(com.android.musicvis.vis5)
#include "rs_graphics.rsh"
float gAngle;
int gPeak;
float gRotate;
float gTilt;
int gIdle;
int gWaveCounter;
rs_program_vertex gPVBackground;
rs_program_fragment gPFBackgroundMip;
rs_program_fragment gPFBackgroundNoMip;
rs_program_raster gPR;
rs_allocation gTvumeter_background;
rs_allocation gTvumeter_peak_on;
rs_allocation gTvumeter_peak_off;
rs_allocation gTvumeter_needle;
rs_allocation gTvumeter_black;
rs_allocation gTvumeter_frame;
rs_allocation gTvumeter_album;
rs_program_store gPFSBackground;
typedef struct Vertex {
float2 position;
float2 texture0;
} Vertex_t;
Vertex_t *gPoints;
rs_allocation gPointBuffer;
rs_allocation gTlinetexture;
rs_mesh gCubeMesh;
#define RSID_POINTS 1
static void drawVU(rs_matrix4x4 *ident) {
rs_matrix4x4 mat1;
float scale = 0.0041;
rsMatrixLoad(&mat1,ident);
rsMatrixRotate(&mat1, 0.f, 0.f, 0.f, 1.f);
rsMatrixScale(&mat1, scale, scale, scale);
rsgProgramVertexLoadModelMatrix(&mat1);
rsgBindProgramFragment(gPFBackgroundMip);
rsgBindProgramStore(gPFSBackground);
// draw the background image (416x233)
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_background);
rsgDrawQuadTexCoords(
-208.0f, -33.0f, 600.0f, // space
0.0f, 1.0f, // texture
208, -33.0f, 600.0f, // space
1.0f, 1.0f, // texture
208, 200.0f, 600.0f, // space
1.0f, 0.0f, // texture
-208.0f, 200.0f, 600.0f, // space
0.0f, 0.0f); // texture
// draw the peak indicator light (56x58)
if (gPeak > 0) {
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_peak_on);
} else {
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_peak_off);
}
rsgDrawQuadTexCoords(
140.0f, 70.0f, 600.0f, // space
0.0f, 1.0f, // texture
196, 70.0f, 600.0f, // space
1.0f, 1.0f, // texture
196, 128.0f, 600.0f, // space
1.0f, 0.0f, // texture
140.0f, 128.0f, 600.0f, // space
0.0f, 0.0f); // texture
// Draw the needle (88x262, center of rotation at 44,217 from top left)
// set matrix so point of rotation becomes origin
rsMatrixLoad(&mat1,ident);
rsMatrixTranslate(&mat1, 0.f, -57.0f * scale, 0.f);
rsMatrixRotate(&mat1, gAngle - 90.f, 0.f, 0.f, 1.f);
rsMatrixScale(&mat1, scale, scale, scale);
rsgProgramVertexLoadModelMatrix(&mat1);
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_needle);
rsgDrawQuadTexCoords(
-44.0f, -102.0f+57.f, 600.0f, // space
0.0f, 1.0f, // texture
44.0f, -102.0f+57.f, 600.0f, // space
1.0f, 1.0f, // texture
44.0f, 160.0f+57.f, 600.0f, // space
1.0f, 0.0f, // texture
-44.0f, 160.0f+57.f, 600.0f, // space
0.0f, 0.0f); // texture
// restore matrix
rsMatrixLoad(&mat1,ident);
rsMatrixRotate(&mat1, 0.f, 0.f, 0.f, 1.f);
rsMatrixScale(&mat1, scale, scale, scale);
rsgProgramVertexLoadModelMatrix(&mat1);
// erase the part of the needle we don't want to show
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_black);
rsgDrawQuad(-100.f, -55.f, 600.f,
-100.f, -105.f, 600.f,
100.f, -105.f, 600.f,
100.f, -55.f, 600.f);
// draw the frame (472x290)
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_frame);
rsgDrawQuadTexCoords(
-236.0f, -60.0f, 600.0f, // space
0.0f, 1.0f, // texture
236, -60.0f, 600.0f, // space
1.0f, 1.0f, // texture
236, 230.0f, 600.0f, // space
1.0f, 0.0f, // texture
-236.0f, 230.0f, 600.0f, // space
0.0f, 0.0f); // texture
}
int fadeoutcounter = 0;
int fadeincounter = 0;
int wave1pos = 0;
int wave1amp = 0;
int wave2pos = 0;
int wave2amp= 0;
int wave3pos = 0;
int wave3amp= 0;
int wave4pos = 0;
int wave4amp= 0;
float idle[4096];
int waveCounter = 0;
int lastuptime = 0;
float autorotation = 0;
#define FADEOUT_LENGTH 100
#define FADEOUT_FACTOR 0.95f
#define FADEIN_LENGTH 15
static void makeIdleWave(float *points) {
int i;
// show a number of superimposed moving sinewaves
float amp1 = sin(0.007f * wave1amp) * 120 * 1024;
float amp2 = sin(0.023f * wave2amp) * 80 * 1024;
float amp3 = sin(0.011f * wave3amp) * 40 * 1024;
float amp4 = sin(0.031f * wave4amp) * 20 * 1024;
for (i = 0; i < 256; i++) {
float val = sin(0.013f * (wave1pos + i * 4)) * amp1
+ sin(0.029f * (wave2pos + i * 4)) * amp2;
float off = sin(0.005f * (wave3pos + i * 4)) * amp3
+ sin(0.017f * (wave4pos + i * 4)) * amp4;
if (val < 2.f && val > -2.f) val = 2.f;
points[i*8+1] = val + off;
points[i*8+5] = -val + off;
}
}
static void drawWave(rs_matrix4x4 *ident) {
float scale = .008f;
rs_matrix4x4 mat1;
rsMatrixLoad(&mat1, ident);
rsMatrixScale(&mat1, scale, scale / 2048.f, scale);
rsMatrixTranslate(&mat1, 0.f, 81920.f, 350.f);
rsgProgramVertexLoadModelMatrix(&mat1);
int i;
if (gIdle) {
// idle state animation
float *points = (float*)gPoints;
if (fadeoutcounter > 0) {
// fade waveform to 0
for (i = 0; i < 256; i++) {
float val = fabs(points[i*8+1]);
val = val * FADEOUT_FACTOR;
if (val < 2.f) val = 2.f;
points[i*8+1] = val;
points[i*8+5] = -val;
}
fadeoutcounter--;
if (fadeoutcounter == 0) {
wave1amp = 0;
wave2amp = 0;
wave3amp = 0;
wave4amp = 0;
}
} else {
// idle animation
makeIdleWave(points);
}
fadeincounter = FADEIN_LENGTH;
} else {
if (fadeincounter > 0 && fadeoutcounter == 0) {
// morph from idle animation back to waveform
makeIdleWave(idle);
if (waveCounter != gWaveCounter) {
waveCounter = gWaveCounter;
float *points = (float*)gPoints;
for (i = 0; i < 256; i++) {
float val = fabs(points[i*8+1]);
points[i*8+1] = (val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+1] * fadeincounter) / FADEIN_LENGTH;
points[i*8+5] = (-val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+5] * fadeincounter) / FADEIN_LENGTH;
}
}
fadeincounter--;
if (fadeincounter == 0) {
fadeoutcounter = FADEOUT_LENGTH;
}
} else {
fadeoutcounter = FADEOUT_LENGTH;
}
}
rsgBindProgramRaster(gPR);
rsgBindProgramFragment(gPFBackgroundNoMip);
rsgBindTexture(gPFBackgroundNoMip, 0, gTlinetexture);
rsgDrawMesh(gCubeMesh);
}
static void drawVizLayer(rs_matrix4x4 *ident) {
for (int i = 0; i < 6; i++) {
if (i & 1) {
drawVU(ident);
} else {
drawWave(ident);
}
rsMatrixRotate(ident, 60.f, 0.f, 1.f, 0.f);
}
}
int root(void) {
rsgClearColor(0.f, 0.f, 0.f, 1.f);
rsgBindProgramVertex(gPVBackground);
int i;
rs_matrix4x4 ident;
int now = (int)rsUptimeMillis();
int delta = now - lastuptime;
lastuptime = now;
if (delta > 80) {
// Limit the delta to avoid jumps when coming back from sleep.
// A value of 80 will make the rotation keep the same speed
// until the frame rate drops to 12.5 fps, at which point it
// will start slowing down.
delta = 80;
}
autorotation += .3 * delta / 35;
while (autorotation > 360.f) autorotation -= 360.f;
rsMatrixLoadIdentity(&ident);
rsMatrixRotate(&ident, gTilt, 1.f, 0.f, 0.f);
rsMatrixRotate(&ident, autorotation + gRotate, 0.f, 1.f, 0.f);
// draw the reflections
rsMatrixTranslate(&ident, 0.f, -1.f, 0.f);
rsMatrixScale(&ident, 1.f, -1.f, 1.f);
drawVizLayer(&ident);
// draw the reflecting plane
rsgBindProgramFragment(gPFBackgroundMip);
rsgBindTexture(gPFBackgroundMip, 0, gTvumeter_album);
rsgDrawQuadTexCoords(
-1500.0f, -60.0f, 1500.0f, // space
0.f, 1.f, // texture
1500, -60.0f, 1500.0f, // space
1.f, 1.f, // texture
1500, -60.0f, -1500.0f, // space
1.f, 0.f, // texture
-1500.0f, -60.0f, -1500.0f, // space
0.f, 0.f); // texture
// draw the visualizer
rsMatrixScale(&ident, 1.f, -1.f, 1.f);
rsMatrixTranslate(&ident, 0.f, 1.f, 0.f);
drawVizLayer(&ident);
wave1pos++;
wave1amp++;
wave2pos--;
wave2amp++;
wave3pos++;
wave3amp++;
wave4pos++;
wave4amp++;
return 1;
}