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 
    155         mScript.set_gTlinetexture(mTexture);
    156 
    157         /*
    158          * create a program fragment to use the texture
    159          */
    160         Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
    161         samplerBuilder.setMinification(LINEAR);
    162         samplerBuilder.setMagnification(LINEAR);
    163         samplerBuilder.setWrapS(WRAP);
    164         samplerBuilder.setWrapT(WRAP);
    165         mSampler = samplerBuilder.create();
    166 
    167         ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
    168         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
    169                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
    170         mPfBackground = builder.create();
    171         mPfBackground.bindSampler(mSampler, 0);
    172 
    173         mScript.set_gPFBackground(mPfBackground);
    174 
    175         return mScript;
    176     }
    177 
    178     @Override
    179     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
    180         mWorldState.yRotation = (xOffset * 4) * 180;
    181         updateWorldState();
    182     }
    183 
    184     @Override
    185     public void start() {
    186         super.start();
    187         mVisible = true;
    188         if (mAudioCapture != null) {
    189             mAudioCapture.start();
    190         }
    191         SystemClock.sleep(200);
    192         updateWave();
    193     }
    194 
    195     @Override
    196     public void stop() {
    197         super.stop();
    198         mVisible = false;
    199         if (mAudioCapture != null) {
    200             mAudioCapture.stop();
    201         }
    202         updateWave();
    203     }
    204 
    205     public void update() {
    206     }
    207 
    208     void updateWave() {
    209         mHandler.removeCallbacks(mDrawCube);
    210         if (!mVisible) {
    211             return;
    212         }
    213         mHandler.postDelayed(mDrawCube, 20);
    214         update();
    215         mWorldState.waveCounter++;
    216         updateWorldState();
    217     }
    218 
    219     protected void updateWorldState() {
    220         mScript.set_gYRotation(mWorldState.yRotation);
    221         mScript.set_gIdle(mWorldState.idle);
    222         mScript.set_gWaveCounter(mWorldState.waveCounter);
    223         mScript.set_gWidth(mWorldState.width);
    224     }
    225 }
    226