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