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.vis3; 18 19 import com.android.musicvis.GenericWaveRS; 20 import com.android.musicvis.R; 21 import com.android.musicvis.RenderScriptScene; 22 import com.android.musicvis.AudioCapture; 23 24 import android.graphics.Canvas; 25 import android.graphics.Rect; 26 import android.os.Handler; 27 import android.renderscript.Allocation; 28 import android.renderscript.Element; 29 import android.renderscript.Mesh.Primitive; 30 import android.renderscript.ProgramVertex; 31 import android.renderscript.ScriptC; 32 import android.renderscript.Type; 33 import android.renderscript.Element.Builder; 34 import android.util.Log; 35 import android.view.SurfaceHolder; 36 37 import java.util.TimeZone; 38 39 class Visualization3RS extends GenericWaveRS { 40 41 private short [] mAnalyzer = new short[512]; 42 43 float lastOffset; 44 45 Visualization3RS(int width, int height) { 46 super(width, height, R.drawable.ice); 47 lastOffset = 0; 48 } 49 50 @Override 51 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { 52 mWorldState.yRotation = (xOffset * 4) * 360; 53 updateWorldState(); 54 } 55 56 @Override 57 public void start() { 58 if (mAudioCapture == null) { 59 mAudioCapture = new AudioCapture(AudioCapture.TYPE_FFT, 512); 60 } 61 super.start(); 62 } 63 64 @Override 65 public void stop() { 66 super.stop(); 67 if (mAudioCapture != null) { 68 mAudioCapture.release(); 69 mAudioCapture = null; 70 } 71 } 72 73 @Override 74 public void update() { 75 76 int len = 0; 77 if (mAudioCapture != null) { 78 mVizData = mAudioCapture.getFormattedData(1, 1); 79 // the really high frequencies aren't that interesting for music, 80 // so just chop those off and use only the lower half of the spectrum 81 len = mVizData.length / 2; 82 } 83 if (len == 0) { 84 if (mWorldState.idle == 0) { 85 mWorldState.idle = 1; 86 updateWorldState(); 87 } 88 return; 89 } 90 91 len /= 2; // the bins are comprised of 2 values each 92 93 if (len > mAnalyzer.length) len = mAnalyzer.length; 94 95 if (mWorldState.idle != 0) { 96 mWorldState.idle = 0; 97 updateWorldState(); 98 } 99 100 for (int i = 1; i < len - 1; i++) { 101 int val1 = mVizData[i * 2]; 102 int val2 = mVizData[i * 2 + 1]; 103 int val = val1 * val1 + val2 * val2; 104 short newval = (short)(val * (i/16+1)); 105 short oldval = mAnalyzer[i]; 106 if (newval >= oldval - 800) { 107 // use new high value 108 } else { 109 newval = (short)(oldval - 800); 110 } 111 mAnalyzer[i] = newval; 112 } 113 114 // distribute the data over mWidth samples in the middle of the mPointData array 115 final int outlen = mPointData.length / 8; 116 final int width = mWidth > outlen ? outlen : mWidth; 117 final int skip = (outlen - width) / 2; 118 119 int srcidx = 0; 120 int cnt = 0; 121 for (int i = 0; i < width; i++) { 122 float val = mAnalyzer[srcidx] / 8; 123 if (val < 1f && val > -1f) val = 1; 124 mPointData[(i + skip) * 8 + 1] = val; 125 mPointData[(i + skip) * 8 + 5] = -val; 126 cnt += len; 127 if (cnt > width) { 128 srcidx++; 129 cnt -= width; 130 } 131 } 132 mPointAlloc.copyFromUnchecked(mPointData); 133 } 134 135 } 136