1838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen/*
2838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * Copyright (C) 2009 The Android Open Source Project
3838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen *
4838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
5838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * you may not use this file except in compliance with the License.
6838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * You may obtain a copy of the License at
7838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen *
8838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
9838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen *
10838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * Unless required by applicable law or agreed to in writing, software
11838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
12838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * See the License for the specific language governing permissions and
14838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen * limitations under the License.
15838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen */
16838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
17838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenpackage com.android.musicvis.vis5;
18838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
19838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport com.android.musicvis.R;
20838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport com.android.musicvis.RenderScriptScene;
217eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchoukimport com.android.musicvis.ScriptField_Vertex;
22f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentimport com.android.musicvis.AudioCapture;
23838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
24838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport android.os.Handler;
254341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchoukimport android.renderscript.*;
26838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport android.renderscript.Element.Builder;
27838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport android.renderscript.ProgramStore.BlendDstFunc;
28838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport android.renderscript.ProgramStore.BlendSrcFunc;
2924c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissenimport android.renderscript.Sampler.Value;
30838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport android.util.Log;
31838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport android.view.MotionEvent;
32838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
33838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenimport java.util.TimeZone;
34838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
35838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissenclass Visualization5RS extends RenderScriptScene {
36838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
37838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private final Handler mHandler = new Handler();
38838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private final Runnable mDrawCube = new Runnable() {
39838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public void run() {
40838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            updateWave();
41838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
42838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    };
43838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private boolean mVisible;
44838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
45838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private int mNeedlePos = 0;
46838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private int mNeedleSpeed = 0;
47838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    // tweak this to get quicker/slower response
48838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private int mNeedleMass = 10;
49838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private int mSpringForceAtOrigin = 200;
5027b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
51838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    static class WorldState {
52838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public float mAngle;
53838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public int   mPeak;
54838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public float mRotate;
55838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public float mTilt;
56838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public int   mIdle;
57838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        public int   mWaveCounter;
58838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
59838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    WorldState mWorldState = new WorldState();
607eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk
61e04dd5b72d1200dd3f344a94fdea3ca876089b94Stephen Hines    ScriptC_many mScript;
62359640d9ca565aaeb75710de9802cd5ae93cc3dbShih-wei Liao    private com.android.musicvis.vis5.ScriptField_Vertex mVertexBuffer;
63838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
64838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private ProgramStore mPfsBackground;
6524c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen    private ProgramFragment mPfBackgroundMip;
6624c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen    private ProgramFragment mPfBackgroundNoMip;
67afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen    private ProgramRaster mPr;
6824c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen    private Sampler mSamplerMip;
6924c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen    private Sampler mSamplerNoMip;
70838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private Allocation[] mTextures;
7127b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
72838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private ProgramVertex mPVBackground;
734341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk    private ProgramVertexFixedFunction.Constants mPVAlloc;
74838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
75af04b9bc843d3d1de3d2349a0c4a581d53df6398Alex Sakhartchouk    private Mesh mCubeMesh;
76838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
77838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    protected Allocation mPointAlloc;
78838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    // 256 lines, with 4 points per line (2 space, 2 texture) each consisting of x and y,
79838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    // so 8 floats per line.
80838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    protected float [] mPointData = new float[256*8];
81838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
82838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private Allocation mLineIdxAlloc;
83838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    // 2 indices per line
84838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private short [] mIndexData = new short[256*2];
8527b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
86f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent    private AudioCapture mAudioCapture = null;
87f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent    private int [] mVizData = new int[1024];
88838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
89838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private static final int RSID_STATE = 0;
90838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private static final int RSID_POINTS = 1;
91838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private static final int RSID_LINES = 2;
92838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private static final int RSID_PROGRAMVERTEX = 3;
93838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
94838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    private float mTouchY;
9527b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
96838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    Visualization5RS(int width, int height) {
97838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        super(width, height);
98838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mWidth = width;
99838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mHeight = height;
100838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // the x, s and t coordinates don't change, so set those now
101838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        int outlen = mPointData.length / 8;
102838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        int half = outlen / 2;
103838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        for(int i = 0; i < outlen; i++) {
104838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPointData[i*8]   = i - half;          // start point X (Y set later)
105838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPointData[i*8+2] = 0;                 // start point S
106838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPointData[i*8+3] = 0;                 // start point T
107838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPointData[i*8+4] = i - half;          // end point X (Y set later)
108838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPointData[i*8+6] = 1.0f;              // end point S
109838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPointData[i*8+7] = 0f;                // end point T
110838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
111838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
112838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
113838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    @Override
114838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    public void resize(int width, int height) {
115838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        super.resize(width, height);
116838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        if (mPVAlloc != null) {
1174341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            Matrix4f proj = new Matrix4f();
1184341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            proj.loadProjectionNormalized(width, height);
1194341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            mPVAlloc.setProjection(proj);
120838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
121838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mWorldState.mTilt = -20;
122838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
123838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
1247eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk    /*@Override
125838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    public void onTouchEvent(MotionEvent event) {
126838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        switch(event.getAction()) {
127838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            case MotionEvent.ACTION_DOWN:
128838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mTouchY = event.getY();
129838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                break;
130838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            case MotionEvent.ACTION_MOVE:
131838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                float dy = event.getY() - mTouchY;
132838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mTouchY += dy;
133838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                dy /= 10;
134838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                dy += mWorldState.mTilt;
135838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                if (dy > 0) {
136838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                    dy = 0;
137838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                } else if (dy < -45) {
138838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                    dy = -45;
139838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                }
140838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mWorldState.mTilt = dy;
141838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mState.data(mWorldState);
1427eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk                //updateWorldState();
143838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
1447eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk    }*/
14527b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
146838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    @Override
1477eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk    public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
148838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // update our state, then push it to the renderscript
149838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mWorldState.mRotate = (xOffset - 0.5f) * 90;
1507eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        updateWorldState();
151838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
152838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
153838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    @Override
154838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    protected ScriptC createScript() {
155570b7a66c0b415fcb534facbc04bb31987788ea1Jason Sams        mScript = new ScriptC_many(mRS, mResources, R.raw.many);
156838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
157838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // First set up the coordinate system and such
1584341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
159838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mPVBackground = pvb.create();
1604341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        mPVAlloc = new ProgramVertexFixedFunction.Constants(mRS);
1614341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVAlloc);
1624341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        Matrix4f proj = new Matrix4f();
1634341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        proj.loadProjectionNormalized(mWidth, mHeight);
1644341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        mPVAlloc.setProjection(proj);
165838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
1667eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gPVBackground(mPVBackground);
1677eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk
168838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mTextures = new Allocation[8];
169169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[0] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.background,
170169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
171169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1727eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_background(mTextures[0]);
173169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[1] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.frame,
174169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
175169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1767eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_frame(mTextures[1]);
177169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[2] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.peak_on,
178169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
179169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1807eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_peak_on(mTextures[2]);
181169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[3] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.peak_off,
182169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
183169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1847eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_peak_off(mTextures[3]);
185169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[4] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.needle,
186169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
187169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1887eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_needle(mTextures[4]);
189169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[5] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.black,
190169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
191169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1927eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_black(mTextures[5]);
193169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[6] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.albumart,
194169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
195169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
1967eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTvumeter_album(mTextures[6]);
197169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams        mTextures[7] = Allocation.createFromBitmapResource(mRS, mResources, R.drawable.fire,
198169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
199169d6c34b7a4df1eee57469bbc6da14851cadfe2Jason Sams                                                           Allocation.USAGE_GRAPHICS_TEXTURE);
2007eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTlinetexture(mTextures[7]);
201838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
202838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        {
20324c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            Sampler.Builder builder = new Sampler.Builder(mRS);
2044341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setMinification(Value.LINEAR);
2054341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setMagnification(Value.LINEAR);
20624c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            builder.setWrapS(Value.WRAP);
20724c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            builder.setWrapT(Value.WRAP);
20824c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            mSamplerNoMip = builder.create();
20924c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen        }
21024c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen
21124c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen        {
21224c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            Sampler.Builder builder = new Sampler.Builder(mRS);
2134341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setMinification(Value.LINEAR_MIP_LINEAR);
2144341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setMagnification(Value.LINEAR);
21524c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            builder.setWrapS(Value.WRAP);
21624c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            builder.setWrapT(Value.WRAP);
21724c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            mSamplerMip = builder.create();
21824c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen        }
21924c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen
22024c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen        {
2214341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
2224341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
2234341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk                               ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
22424c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            mPfBackgroundNoMip = builder.create();
22524c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            mPfBackgroundNoMip.bindSampler(mSamplerNoMip, 0);
2267eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk            mScript.set_gPFBackgroundNoMip(mPfBackgroundNoMip);
22724c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen        }
22827b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
22924c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen        {
2304341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
2314341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
2324341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk                               ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
23324c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            mPfBackgroundMip = builder.create();
23424c4457ac15bc93bb34f9d9e4aebdd6d730cb3beMarco Nelissen            mPfBackgroundMip.bindSampler(mSamplerMip, 0);
2357eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk            mScript.set_gPFBackgroundMip(mPfBackgroundMip);
236838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
237838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
238838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        {
239afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen            ProgramRaster.Builder builder = new ProgramRaster.Builder(mRS);
240afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen            builder.setCullMode(ProgramRaster.CullMode.NONE);
241afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen            mPr = builder.create();
242afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen            mScript.set_gPR(mPr);
243afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen        }
244afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen
245afe48dfc857488291998a8aaa5a9540d01e5a5c8Marco Nelissen        {
2464341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
247838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            builder.setDepthFunc(ProgramStore.DepthFunc.EQUAL);
248838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            //builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
249838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
2504341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setDitherEnabled(true); // without dithering there is severe banding
2514341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk            builder.setDepthMaskEnabled(false);
252838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mPfsBackground = builder.create();
2537eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk
2547eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk            mScript.set_gPFSBackground(mPfsBackground);
255838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
25627b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
257838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // Start creating the mesh
258359640d9ca565aaeb75710de9802cd5ae93cc3dbShih-wei Liao        mVertexBuffer = new com.android.musicvis.vis5.ScriptField_Vertex(mRS, mPointData.length / 4);
2597eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk
260af04b9bc843d3d1de3d2349a0c4a581d53df6398Alex Sakhartchouk        final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
261af04b9bc843d3d1de3d2349a0c4a581d53df6398Alex Sakhartchouk        meshBuilder.addVertexAllocation(mVertexBuffer.getAllocation());
262af04b9bc843d3d1de3d2349a0c4a581d53df6398Alex Sakhartchouk        // Create the Allocation for the indices
26390469ff5b56927860902774af1e6e784c887e50bJason Sams        mLineIdxAlloc = Allocation.createSized(mRS, Element.U16(mRS), mIndexData.length,
26490469ff5b56927860902774af1e6e784c887e50bJason Sams                                               Allocation.USAGE_SCRIPT |
26590469ff5b56927860902774af1e6e784c887e50bJason Sams                                               Allocation.USAGE_GRAPHICS_VERTEX);
266838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // This will be a line mesh
2674341cb656df71c56ea15d17d0119cbb4407a6858Alex Sakhartchouk        meshBuilder.addIndexSetAllocation(mLineIdxAlloc, Mesh.Primitive.LINE);
268838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
269838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // Create the Allocation for the vertices
270838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mCubeMesh = meshBuilder.create();
2717eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk
2727eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mPointAlloc = mVertexBuffer.getAllocation();
2737eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk
2746e3b811bf4fc3045304a62621fbb0fc8ebaa925dShih-wei Liao        mScript.bind_gPoints(mVertexBuffer);
2757eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gPointBuffer(mPointAlloc);
2767eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gCubeMesh(mCubeMesh);
277838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
278a811c2147ed62535efd5685002dc315aae5a5eacJason Sams        // put the vertex and index data in their respective buffers
279838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        updateWave();
280838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        for(int i = 0; i < mIndexData.length; i ++) {
281838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mIndexData[i] = (short) i;
282838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
283838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
284a811c2147ed62535efd5685002dc315aae5a5eacJason Sams        //  upload the vertex and index data
28531744cfc0a2c73b2120f24b0df9527c5923e0205Marco Nelissen        mPointAlloc.copyFromUnchecked(mPointData);
286570b7a66c0b415fcb534facbc04bb31987788ea1Jason Sams        mLineIdxAlloc.copyFrom(mIndexData);
28790469ff5b56927860902774af1e6e784c887e50bJason Sams        mLineIdxAlloc.syncAll(Allocation.USAGE_SCRIPT);
288838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
2897eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        return mScript;
290838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
291838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
292838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    @Override
293838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    public void start() {
294838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        super.start();
295838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mVisible = true;
296f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        if (mAudioCapture == null) {
297f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent            mAudioCapture = new AudioCapture(AudioCapture.TYPE_PCM, 1024);
298f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        }
299f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        mAudioCapture.start();
300838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        updateWave();
301838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
302838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
303838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    @Override
304838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    public void stop() {
305838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        super.stop();
306838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mVisible = false;
307f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        if (mAudioCapture != null) {
308f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent            mAudioCapture.stop();
309f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent            mAudioCapture.release();
310f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent            mAudioCapture = null;
311f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        }
312838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
313838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
314838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    void updateWave() {
315838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mHandler.removeCallbacks(mDrawCube);
316d760ff3f6c6ef0276457027945f829e14b7ed4acMarco Nelissen        if (!mVisible) {
317d760ff3f6c6ef0276457027945f829e14b7ed4acMarco Nelissen            return;
318838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
319d760ff3f6c6ef0276457027945f829e14b7ed4acMarco Nelissen        mHandler.postDelayed(mDrawCube, 20);
320838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
321f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        int len = 0;
322f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        if (mAudioCapture != null) {
323e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent            // arbitrary scalar to get better range: 512 = 2 * 256 (256 for 8 to 16 bit)
324e024bb9ab683bfb161ac11acb4df30fd8c9efe9cEric Laurent            mVizData = mAudioCapture.getFormattedData(512, 1);
325f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent            len = mVizData.length;
326f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent        }
32727b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
328838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // Simulate running the signal through a rectifier by
329838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // taking the average of the absolute sample values.
330838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        int volt = 0;
331838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        if (len > 0) {
332838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            for (int i = 0; i < len; i++) {
333838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                int val = mVizData[i];
334838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                if (val < 0) {
335838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                    val = -val;
336838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                }
337838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                volt += val;
338838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            }
339f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent            volt = volt / len;
340838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
341838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
342838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // There are several forces working on the needle: a force applied by the
343838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // electromagnet, a force applied by the spring,  and friction.
344838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // The force from the magnet is proportional to the current flowing
345838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // through its coil. We have to take in to account that the coil is an
346838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // inductive load, which means that an immediate change in applied voltage
347838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // will result in a gradual change in current, but also that current will
348838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // be induced by the movement of the needle.
349838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // The force from the spring is proportional to the position of the needle.
350838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // The friction force is a function of the speed of the needle, but so is
351838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // the current induced by the movement of the needle, so we can combine
352838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // them.
35327b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
35427b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
355838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // Add up the various forces, with some multipliers to make the movement
356838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // of the needle more realistic
357838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // 'volt' is for the applied voltage, which causes a current to flow through the coil
358838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // mNeedleSpeed * 3 is for the movement of the needle, which induces an opposite current
359838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // in the coil, and is also proportional to the friction
360838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // mNeedlePos + mSpringForceAtOrigin is for the force of the spring pushing the needle back
361838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        int netforce = volt - mNeedleSpeed * 3 - (mNeedlePos + mSpringForceAtOrigin) ;
362838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        int acceleration = netforce / mNeedleMass;
363838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mNeedleSpeed += acceleration;
364838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mNeedlePos += mNeedleSpeed;
365838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        if (mNeedlePos < 0) {
366838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mNeedlePos = 0;
367838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mNeedleSpeed = 0;
368838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        } else if (mNeedlePos > 32767) {
369838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            if (mNeedlePos > 33333) {
370838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                 mWorldState.mPeak = 10;
371838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            }
372838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mNeedlePos = 32767;
373838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mNeedleSpeed = 0;
374838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
375838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        if (mWorldState.mPeak > 0) {
376838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mWorldState.mPeak--;
377838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
378838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
379838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        mWorldState.mAngle = 131f - (mNeedlePos / 410f); // ~80 degree range
38027b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
381838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        // downsample 1024 samples in to 256
38227b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
383838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        if (len == 0) {
384838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            if (mWorldState.mIdle == 0) {
385838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mWorldState.mIdle = 1;
386838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            }
387838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        } else {
388838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            if (mWorldState.mIdle != 0) {
389838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mWorldState.mIdle = 0;
390838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            }
391838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            // TODO: might be more efficient to push this in to renderscript
392838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            int outlen = mPointData.length / 8;
393838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            len /= 4;
394838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            if (len > outlen) len = outlen;
395838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            for(int i = 0; i < len; i++) {
396838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                int amp = (mVizData[i*4]  + mVizData[i*4+1] + mVizData[i*4+2] + mVizData[i*4+3]);
397838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mPointData[i*8+1] = amp;
398838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen                mPointData[i*8+5] = -amp;
399838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            }
40031744cfc0a2c73b2120f24b0df9527c5923e0205Marco Nelissen            mPointAlloc.copyFromUnchecked(mPointData);
401838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen            mWorldState.mWaveCounter++;
402838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen        }
40327b89e7e0538fc01e374c4c5882172aec8d58351Jason Sams
4047eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        updateWorldState();
405838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen    }
406838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen
4077eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk    protected void updateWorldState() {
4087eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gAngle(mWorldState.mAngle);
4097eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gPeak(mWorldState.mPeak);
4107eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gRotate(mWorldState.mRotate);
4117eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gTilt(mWorldState.mTilt);
4127eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gIdle(mWorldState.mIdle);
4137eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk        mScript.set_gWaveCounter(mWorldState.mWaveCounter);
4147eb6bcc2cbc062abea4f3c9d3e542215697c7b66Alex Sakhartchouk    }
415838dedb90f8a53e0cb4c3c8fe86a1f807ee8d784Marco Nelissen}
416