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)
18 
19 #include "rs_graphics.rsh"
20 
21 float gYRotation;
22 int gIdle;
23 int gWaveCounter;
24 int gWidth;
25 
26 rs_program_vertex gPVBackground;
27 rs_program_fragment gPFBackground;
28 
29 typedef struct Vertex {
30     float2 position;
31     float2 texture0;
32 } Vertex_t;
33 Vertex_t *gPoints;
34 
35 rs_allocation gPointBuffer;
36 rs_allocation gTlinetexture;
37 rs_mesh gCubeMesh;
38 
39 #define RSID_POINTS 1
40 
41 #define FADEOUT_LENGTH 100
42 #define FADEOUT_FACTOR 0.95f
43 #define FADEIN_LENGTH 15
44 
45 static int fadeoutcounter = 0;
46 static int fadeincounter = 0;
47 static int wave1pos = 0;
48 static int wave1amp = 0;
49 static int wave2pos = 0;
50 static int wave2amp= 0;
51 static int wave3pos = 0;
52 static int wave3amp= 0;
53 static int wave4pos = 0;
54 static int wave4amp= 0;
55 static float idle[8192];
56 static int waveCounter = 0;
57 
58 static void makeIdleWave(float *points) {
59     // show a number of superimposed moving sinewaves
60     float amp1 = sin(0.007f * wave1amp) * 120;
61     float amp2 = sin(0.023f * wave2amp) * 80;
62     float amp3 = sin(0.011f * wave3amp) * 40;
63     float amp4 = sin(0.031f * wave4amp) * 20;
64     for (int i = 0; i < 1024; i++) {
65         float val = fabs(sin(0.013f * (wave1pos + i)) * amp1
66                   + sin(0.029f * (wave2pos + i)) * amp2);
67         float off = sin(0.005f * (wave3pos + i)) * amp3
68                   + sin(0.017f * (wave4pos + i)) * amp4;
69         if (val < 2.f && val > -2.f) val = 2.f;
70         points[i*8+1] = val + off;
71         points[i*8+5] = -val + off;
72     }
73     wave1pos++;
74     wave1amp++;
75     wave2pos--;
76     wave2amp++;
77     wave3pos++;
78     wave3amp++;
79     wave4pos++;
80     wave4amp++;
81 }
82 
83 int root(void) {
84     rsgClearColor(0.f, 0.f, 0.f, 1.f);
85 
86     int i;
87 
88     if (gIdle) {
89 
90         // idle state animation
91         float *points = (float*)gPoints;
92         if (fadeoutcounter > 0) {
93             // fade waveform to 0
94             for (i = 0; i < 1024; i++) {
95                 float val = fabs(points[i*8+1]);
96                 val = val * FADEOUT_FACTOR;
97                 if (val < 2.f) val = 2.f;
98                 points[i*8+1] = val;
99                 points[i*8+5] = -val;
100             }
101             fadeoutcounter--;
102             if (fadeoutcounter == 0) {
103                 wave1amp = 0;
104                 wave2amp = 0;
105                 wave3amp = 0;
106                 wave4amp = 0;
107             }
108         } else {
109             // idle animation
110             makeIdleWave(points);
111         }
112         fadeincounter = FADEIN_LENGTH;
113     } else {
114         if (fadeincounter > 0 && fadeoutcounter == 0) {
115             // morph from idle animation back to waveform
116             makeIdleWave(idle);
117             if (waveCounter != gWaveCounter) {
118                 waveCounter = gWaveCounter;
119                 float *points = (float*)gPoints;
120                 for (i = 0; i < 1024; i++) {
121                     float val = fabs(points[i*8+1]);
122                     points[i*8+1] = (val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+1] * fadeincounter) / FADEIN_LENGTH;
123                     points[i*8+5] = (-val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+5] * fadeincounter) / FADEIN_LENGTH;
124                 }
125             }
126             fadeincounter--;
127             if (fadeincounter == 0) {
128                 fadeoutcounter = FADEOUT_LENGTH;
129             }
130         } else {
131             fadeoutcounter = FADEOUT_LENGTH;
132         }
133     }
134 
135     rs_matrix4x4 mat1;
136     float yrot = gYRotation;
137     float scale = 0.004165f * (1.0f + 2.f * fabs(sin(radians(yrot))));
138 
139     // Draw the visualizer.
140     rsgBindProgramVertex(gPVBackground);
141     rsgBindProgramFragment(gPFBackground);
142     rsgBindTexture(gPFBackground, 0, gTlinetexture);
143 
144     // Change the model matrix to account for the large model
145     // and to do the necessary rotations.
146     rsMatrixLoadIdentity(&mat1);
147     rsMatrixRotate(&mat1, yrot, 0.f, 0.f, 1.f);
148     rsMatrixScale(&mat1, scale, scale, scale);
149     rsgProgramVertexLoadModelMatrix(&mat1);
150 
151     rsgDrawMesh(gCubeMesh);
152 
153     return 1;
154 }
155 
156