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