Home | History | Annotate | Download | only in musicvis
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.musicvis;
     18 
     19 import static android.renderscript.Element.RGB_565;
     20 import static android.renderscript.Sampler.Value.LINEAR;
     21 import static android.renderscript.Sampler.Value.WRAP;
     22 
     23 import android.os.Handler;
     24 import android.os.SystemClock;
     25 import android.renderscript.Mesh.Primitive;
     26 import android.renderscript.*;
     27 import android.renderscript.Element.Builder;
     28 import android.util.Log;
     29 
     30 import java.util.TimeZone;
     31 
     32 public class GenericWaveRS extends RenderScriptScene {
     33 
     34     private final Handler mHandler = new Handler();
     35     private final Runnable mDrawCube = new Runnable() {
     36         public void run() {
     37             updateWave();
     38         }
     39     };
     40     private boolean mVisible;
     41     private int mTexId;
     42 
     43     protected static class WorldState {
     44         public float yRotation;
     45         public int idle;
     46         public int waveCounter;
     47         public int width;
     48     }
     49     protected WorldState mWorldState = new WorldState();
     50 
     51     ScriptC_waveform mScript;
     52 
     53     private ScriptField_Vertex mVertexBuffer;
     54 
     55     private Mesh mCubeMesh;
     56 
     57     protected Allocation mPointAlloc;
     58     // 1024 lines, with 4 points per line (2 space, 2 texture) each consisting of x and y,
     59     // so 8 floats per line.
     60     protected float [] mPointData = new float[1024*8];
     61 
     62     private ProgramVertex mPVBackground;
     63     private ProgramVertexFixedFunction.Constants mPVAlloc;
     64 
     65     protected AudioCapture mAudioCapture = null;
     66     protected int [] mVizData = new int[1024];
     67 
     68     private ProgramFragment mPfBackground;
     69     private Sampler mSampler;
     70     private Allocation mTexture;
     71 
     72     private static final int RSID_STATE = 0;
     73     private static final int RSID_POINTS = 1;
     74     private static final int RSID_LINES = 2;
     75     private static final int RSID_PROGRAMVERTEX = 3;
     76 
     77     protected GenericWaveRS(int width, int height, int texid) {
     78         super(width, height);
     79         mTexId = texid;
     80         mWidth = width;
     81         mHeight = height;
     82         // the x, s and t coordinates don't change, so set those now
     83         int outlen = mPointData.length / 8;
     84         int half = outlen / 2;
     85         for(int i = 0; i < outlen; i++) {
     86             mPointData[i*8]   = i - half;          // start point X (Y set later)
     87             mPointData[i*8+2] = 0;                 // start point S
     88             mPointData[i*8+3] = 0;                 // start point T
     89             mPointData[i*8+4]   = i - half;        // end point X (Y set later)
     90             mPointData[i*8+6] = 1.0f;                 // end point S
     91             mPointData[i*8+7] = 0f;              // end point T
     92         }
     93     }
     94 
     95     @Override
     96     public void resize(int width, int height) {
     97         super.resize(width, height);
     98         mWorldState.width = width;
     99         if (mPVAlloc != null) {
    100             Matrix4f proj = new Matrix4f();
    101             proj.loadProjectionNormalized(mWidth, mHeight);
    102             mPVAlloc.setProjection(proj);
    103         }
    104     }
    105 
    106     @Override
    107     protected ScriptC createScript() {
    108 
    109         mScript = new ScriptC_waveform(mRS, mResources, R.raw.waveform);
    110 
    111         // set our java object as the data for the renderscript allocation
    112         mWorldState.yRotation = 0.0f;
    113         mWorldState.width = mWidth;
    114         updateWorldState();
    115 
    116         //  Now put our model in to a form that renderscript can work with:
    117         //  - create a buffer of floats that are the coordinates for the points that define the cube
    118         //  - create a buffer of integers that are the indices of the points that form lines
    119         //  - combine the two in to a mesh
    120 
    121         // First set up the coordinate system and such
    122         ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
    123         mPVBackground = pvb.create();
    124         mPVAlloc = new ProgramVertexFixedFunction.Constants(mRS);
    125         ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVAlloc);
    126         Matrix4f proj = new Matrix4f();
    127         proj.loadProjectionNormalized(mWidth, mHeight);
    128         mPVAlloc.setProjection(proj);
    129 
    130         mScript.set_gPVBackground(mPVBackground);
    131 
    132         mVertexBuffer = new ScriptField_Vertex(mRS, mPointData.length / 4);
    133 
    134         // Start creating the mesh
    135         final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
    136         meshBuilder.addVertexAllocation(mVertexBuffer.getAllocation());
    137         // This will be a triangle strip mesh
    138         meshBuilder.addIndexSetType(Primitive.TRIANGLE_STRIP);
    139 
    140         // Create the Allocation for the vertices
    141         mCubeMesh = meshBuilder.create();
    142 
    143         mPointAlloc = mVertexBuffer.getAllocation();
    144 
    145         mScript.bind_gPoints(mVertexBuffer);
    146         mScript.set_gPointBuffer(mPointAlloc);
    147         mScript.set_gCubeMesh(mCubeMesh);
    148 
    149         //  upload the vertex data
    150         mPointAlloc.copyFromUnchecked(mPointData);
    151 
    152         // load the texture
    153         mTexture = Allocation.createFromBitmapResource(mRS, mResources, mTexId,
    154                                            Allocation.MipmapControl.MIPMAP_NONE,
    155                                            Allocation.USAGE_GRAPHICS_TEXTURE);
    156 
    157         mScript.set_gTlinetexture(mTexture);
    158 
    159         /*
    160          * create a program fragment to use the texture
    161          */
    162         Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
    163         samplerBuilder.setMinification(LINEAR);
    164         samplerBuilder.setMagnification(LINEAR);
    165         samplerBuilder.setWrapS(WRAP);
    166         samplerBuilder.setWrapT(WRAP);
    167         mSampler = samplerBuilder.create();
    168 
    169         ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
    170         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
    171                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
    172         mPfBackground = builder.create();
    173         mPfBackground.bindSampler(mSampler, 0);
    174 
    175         mScript.set_gPFBackground(mPfBackground);
    176 
    177         return mScript;
    178     }
    179 
    180     @Override
    181     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
    182         mWorldState.yRotation = (xOffset * 4) * 180;
    183         updateWorldState();
    184     }
    185 
    186     @Override
    187     public void start() {
    188         super.start();
    189         mVisible = true;
    190         if (mAudioCapture != null) {
    191             mAudioCapture.start();
    192         }
    193         SystemClock.sleep(200);
    194         updateWave();
    195     }
    196 
    197     @Override
    198     public void stop() {
    199         super.stop();
    200         mVisible = false;
    201         if (mAudioCapture != null) {
    202             mAudioCapture.stop();
    203         }
    204         updateWave();
    205     }
    206 
    207     public void update() {
    208     }
    209 
    210     void updateWave() {
    211         mHandler.removeCallbacks(mDrawCube);
    212         if (!mVisible) {
    213             return;
    214         }
    215         mHandler.postDelayed(mDrawCube, 20);
    216         update();
    217         mWorldState.waveCounter++;
    218         updateWorldState();
    219     }
    220 
    221     protected void updateWorldState() {
    222         mScript.set_gYRotation(mWorldState.yRotation);
    223         mScript.set_gIdle(mWorldState.idle);
    224         mScript.set_gWaveCounter(mWorldState.waveCounter);
    225         mScript.set_gWidth(mWorldState.width);
    226     }
    227 }
    228