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 Allocation mLineIdxAlloc; 63 // 2 indices per line 64 private short [] mIndexData = new short[1024*2]; 65 66 private ProgramVertex mPVBackground; 67 private ProgramVertexFixedFunction.Constants mPVAlloc; 68 69 protected AudioCapture mAudioCapture = null; 70 protected int [] mVizData = new int[1024]; 71 72 private ProgramFragment mPfBackground; 73 private Sampler mSampler; 74 private Allocation mTexture; 75 76 private static final int RSID_STATE = 0; 77 private static final int RSID_POINTS = 1; 78 private static final int RSID_LINES = 2; 79 private static final int RSID_PROGRAMVERTEX = 3; 80 GenericWaveRS(int width, int height, int texid)81 protected GenericWaveRS(int width, int height, int texid) { 82 super(width, height); 83 mTexId = texid; 84 mWidth = width; 85 mHeight = height; 86 // the x, s and t coordinates don't change, so set those now 87 int outlen = mPointData.length / 8; 88 int half = outlen / 2; 89 for(int i = 0; i < outlen; i++) { 90 mPointData[i*8] = i - half; // start point X (Y set later) 91 mPointData[i*8+2] = 0; // start point S 92 mPointData[i*8+3] = 0; // start point T 93 mPointData[i*8+4] = i - half; // end point X (Y set later) 94 mPointData[i*8+6] = 1.0f; // end point S 95 mPointData[i*8+7] = 0f; // end point T 96 } 97 } 98 99 @Override resize(int width, int height)100 public void resize(int width, int height) { 101 super.resize(width, height); 102 mWorldState.width = width; 103 if (mPVAlloc != null) { 104 Matrix4f proj = new Matrix4f(); 105 proj.loadProjectionNormalized(mWidth, mHeight); 106 mPVAlloc.setProjection(proj); 107 } 108 } 109 110 @Override createScript()111 protected ScriptC createScript() { 112 113 mScript = new ScriptC_waveform(mRS, mResources, R.raw.waveform); 114 115 // set our java object as the data for the renderscript allocation 116 mWorldState.yRotation = 0.0f; 117 mWorldState.width = mWidth; 118 updateWorldState(); 119 120 // Now put our model in to a form that renderscript can work with: 121 // - create a buffer of floats that are the coordinates for the points that define the cube 122 // - create a buffer of integers that are the indices of the points that form lines 123 // - combine the two in to a mesh 124 125 // First set up the coordinate system and such 126 ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); 127 mPVBackground = pvb.create(); 128 mPVAlloc = new ProgramVertexFixedFunction.Constants(mRS); 129 ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVAlloc); 130 Matrix4f proj = new Matrix4f(); 131 proj.loadProjectionNormalized(mWidth, mHeight); 132 mPVAlloc.setProjection(proj); 133 134 mScript.set_gPVBackground(mPVBackground); 135 136 mVertexBuffer = new ScriptField_Vertex(mRS, mPointData.length / 4); 137 138 // Start creating the mesh 139 final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS); 140 meshBuilder.addVertexAllocation(mVertexBuffer.getAllocation()); 141 // Create the Allocation for the indices 142 mLineIdxAlloc = Allocation.createSized(mRS, Element.U16(mRS), mIndexData.length, 143 Allocation.USAGE_GRAPHICS_VERTEX | 144 Allocation.USAGE_SCRIPT); 145 // This will be a line mesh 146 meshBuilder.addIndexSetAllocation(mLineIdxAlloc, Primitive.LINE); 147 148 // Create the Allocation for the vertices 149 mCubeMesh = meshBuilder.create(); 150 151 mPointAlloc = mVertexBuffer.getAllocation(); 152 153 mScript.bind_gPoints(mVertexBuffer); 154 mScript.set_gPointBuffer(mPointAlloc); 155 mScript.set_gCubeMesh(mCubeMesh); 156 157 // put the vertex and index data in their respective buffers 158 updateWave(); 159 for(int i = 0; i < mIndexData.length; i ++) { 160 mIndexData[i] = (short) i; 161 } 162 163 // upload the vertex and index data 164 mPointAlloc.copyFromUnchecked(mPointData); 165 mLineIdxAlloc.copyFrom(mIndexData); 166 mLineIdxAlloc.syncAll(Allocation.USAGE_SCRIPT); 167 168 // load the texture 169 mTexture = Allocation.createFromBitmapResource(mRS, mResources, mTexId); 170 171 mScript.set_gTlinetexture(mTexture); 172 173 /* 174 * create a program fragment to use the texture 175 */ 176 Sampler.Builder samplerBuilder = new Sampler.Builder(mRS); 177 samplerBuilder.setMinification(LINEAR); 178 samplerBuilder.setMagnification(LINEAR); 179 samplerBuilder.setWrapS(WRAP); 180 samplerBuilder.setWrapT(WRAP); 181 mSampler = samplerBuilder.create(); 182 183 ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS); 184 builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, 185 ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); 186 mPfBackground = builder.create(); 187 mPfBackground.bindSampler(mSampler, 0); 188 189 mScript.set_gPFBackground(mPfBackground); 190 191 return mScript; 192 } 193 194 @Override setOffset(float xOffset, float yOffset, int xPixels, int yPixels)195 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { 196 mWorldState.yRotation = (xOffset * 4) * 180; 197 updateWorldState(); 198 } 199 200 @Override start()201 public void start() { 202 super.start(); 203 mVisible = true; 204 if (mAudioCapture != null) { 205 mAudioCapture.start(); 206 } 207 SystemClock.sleep(200); 208 updateWave(); 209 } 210 211 @Override stop()212 public void stop() { 213 super.stop(); 214 mVisible = false; 215 if (mAudioCapture != null) { 216 mAudioCapture.stop(); 217 } 218 updateWave(); 219 } 220 update()221 public void update() { 222 } 223 updateWave()224 void updateWave() { 225 mHandler.removeCallbacks(mDrawCube); 226 if (!mVisible) { 227 return; 228 } 229 mHandler.postDelayed(mDrawCube, 20); 230 update(); 231 mWorldState.waveCounter++; 232 updateWorldState(); 233 } 234 updateWorldState()235 protected void updateWorldState() { 236 mScript.set_gYRotation(mWorldState.yRotation); 237 mScript.set_gIdle(mWorldState.idle); 238 mScript.set_gWaveCounter(mWorldState.waveCounter); 239 mScript.set_gWidth(mWorldState.width); 240 } 241 } 242