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 17package com.android.effectstest; 18 19import android.app.Activity; 20import android.content.Context; 21import android.content.Intent; 22import android.media.audiofx.Visualizer; 23import android.os.Bundle; 24import android.os.Handler; 25import android.os.Looper; 26import android.os.Message; 27import android.util.Log; 28import android.view.KeyEvent; 29import android.view.Menu; 30import android.view.View; 31import android.view.View.OnClickListener; 32import android.view.ViewGroup; 33import android.widget.Button; 34import android.widget.CompoundButton; 35import android.widget.CompoundButton.OnCheckedChangeListener; 36import android.widget.EditText; 37import android.widget.TextView; 38import android.widget.ToggleButton; 39import android.widget.SeekBar; 40 41import java.nio.ByteOrder; 42import java.nio.ByteBuffer; 43import java.util.HashMap; 44import java.util.Map; 45 46public class VisualizerTest extends Activity implements OnCheckedChangeListener { 47 48 private final static String TAG = "Visualizer Test"; 49 50 private Visualizer mVisualizer; 51 ToggleButton mOnOffButton; 52 ToggleButton mReleaseButton; 53 boolean mEnabled; 54 EditText mSessionText; 55 static int sSession = 0; 56 int mCaptureSize; 57 ToggleButton mCallbackButton; 58 boolean mCallbackOn; 59 VisualizerListener mVisualizerListener; 60 private static HashMap<Integer, Visualizer> sInstances = new HashMap<Integer, Visualizer>(10); 61 private VisualizerTestHandler mVisualizerTestHandler = null; 62 63 public VisualizerTest() { 64 Log.d(TAG, "contructor"); 65 } 66 67 @Override 68 public void onCreate(Bundle icicle) { 69 super.onCreate(icicle); 70 71 TextView textView; 72 73 setContentView(R.layout.visualizertest); 74 75 mSessionText = (EditText) findViewById(R.id.sessionEdit); 76 mSessionText.setOnKeyListener(mSessionKeyListener); 77 mSessionText.setText(Integer.toString(sSession)); 78 79 mReleaseButton = (ToggleButton)findViewById(R.id.visuReleaseButton); 80 mOnOffButton = (ToggleButton)findViewById(R.id.visualizerOnOff); 81 mCallbackButton = (ToggleButton)findViewById(R.id.visuCallbackOnOff); 82 mCallbackOn = false; 83 mCallbackButton.setChecked(mCallbackOn); 84 85 mVisualizerTestHandler = new VisualizerTestHandler(); 86 mVisualizerListener = new VisualizerListener(); 87 88 getEffect(sSession); 89 90 if (mVisualizer != null) { 91 mReleaseButton.setOnCheckedChangeListener(this); 92 mOnOffButton.setOnCheckedChangeListener(this); 93 mCallbackButton.setOnCheckedChangeListener(this); 94 } 95 } 96 97 private static final int MSG_START_CAPTURE = 0; 98 private static final int MSG_STOP_CAPTURE = 1; 99 private static final int MSG_NEW_CAPTURE = 2; 100 private static final int CAPTURE_PERIOD_MS = 100; 101 102 private class VisualizerTestHandler extends Handler { 103 boolean mActive = false; 104 @Override 105 public void handleMessage(Message msg) { 106 switch (msg.what) { 107 case MSG_START_CAPTURE: 108 if (!mActive) { 109 Log.d(TAG, "Start capture"); 110 mActive = true; 111 sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE, 0, 0, null), CAPTURE_PERIOD_MS); 112 } 113 break; 114 case MSG_STOP_CAPTURE: 115 if (mActive) { 116 Log.d(TAG, "Stop capture"); 117 mActive = false; 118 } 119 break; 120 case MSG_NEW_CAPTURE: 121 if (mActive && mVisualizer != null) { 122 if (mCaptureSize > 0) { 123 byte[] data = new byte[mCaptureSize]; 124 if (mVisualizer.getWaveForm(data) == Visualizer.SUCCESS) { 125 int len = data.length < mCaptureSize ? data.length : mCaptureSize; 126 displayVal(R.id.waveformMin, data[0]); 127 displayVal(R.id.waveformMax, data[len-1]); 128 displayVal(R.id.waveformCenter, data[len/2]); 129 }; 130 if (mVisualizer.getFft(data) == Visualizer.SUCCESS) { 131 int len = data.length < mCaptureSize ? data.length : mCaptureSize; 132 displayVal(R.id.fftMin, data[0]); 133 displayVal(R.id.fftMax, data[len-1]); 134 displayVal(R.id.fftCenter, data[len/2]); 135 }; 136 } 137 sendMessageDelayed(obtainMessage(MSG_NEW_CAPTURE, 0, 0, null), CAPTURE_PERIOD_MS); 138 } 139 break; 140 } 141 } 142 } 143 144 private class VisualizerListener implements Visualizer.OnDataCaptureListener { 145 146 public VisualizerListener() { 147 } 148 public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) { 149 if (visualizer == mVisualizer) { 150 if (waveform.length > 0) { 151 Log.d(TAG, "onWaveFormDataCapture(): "+waveform[0]+" smp rate: "+samplingRate/1000); 152 displayVal(R.id.waveformMin, waveform[0]); 153 displayVal(R.id.waveformMax, waveform[waveform.length - 1]); 154 displayVal(R.id.waveformCenter, waveform[waveform.length/2]); 155 } 156 } 157 } 158 public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) { 159 if (visualizer == mVisualizer) { 160 if (fft.length > 0) { 161 Log.d(TAG, "onFftDataCapture(): "+fft[0]); 162 displayVal(R.id.fftMin, fft[0]); 163 displayVal(R.id.fftMax, fft[fft.length - 1]); 164 displayVal(R.id.fftCenter, fft[fft.length/2]); 165 } 166 } 167 } 168 } 169 170 @Override 171 public void onResume() { 172 super.onResume(); 173 } 174 175 @Override 176 public void onPause() { 177 super.onPause(); 178 } 179 180 private View.OnKeyListener mSessionKeyListener 181 = new View.OnKeyListener() { 182 public boolean onKey(View v, int keyCode, KeyEvent event) { 183 if (event.getAction() == KeyEvent.ACTION_DOWN) { 184 switch (keyCode) { 185 case KeyEvent.KEYCODE_DPAD_CENTER: 186 case KeyEvent.KEYCODE_ENTER: 187 try { 188 sSession = Integer.parseInt(mSessionText.getText().toString()); 189 getEffect(sSession); 190 } catch (NumberFormatException e) { 191 Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString()); 192 } 193 194 return true; 195 } 196 } 197 return false; 198 } 199 }; 200 201 // OnCheckedChangeListener 202 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 203 if (buttonView.getId() == R.id.visualizerOnOff) { 204 if (mVisualizer != null) { 205 mEnabled = isChecked; 206 mCallbackButton.setEnabled(!mEnabled); 207 if (mCallbackOn && mEnabled) { 208 mVisualizer.setDataCaptureListener(mVisualizerListener, 209 10000, 210 true, 211 true); 212 } 213 mVisualizer.setEnabled(mEnabled); 214 if (mCallbackOn) { 215 if (!mEnabled) { 216 mVisualizer.setDataCaptureListener(null, 217 10000, 218 false, 219 false); 220 } 221 } else { 222 int msg = isChecked ? MSG_START_CAPTURE : MSG_STOP_CAPTURE; 223 mVisualizerTestHandler.sendMessage( 224 mVisualizerTestHandler.obtainMessage(msg, 0, 0, null)); 225 } 226 } 227 } 228 if (buttonView.getId() == R.id.visuReleaseButton) { 229 if (isChecked) { 230 if (mVisualizer == null) { 231 getEffect(sSession); 232 } 233 } else { 234 if (mVisualizer != null) { 235 putEffect(sSession); 236 } 237 } 238 } 239 if (buttonView.getId() == R.id.visuCallbackOnOff) { 240 mCallbackOn = isChecked; 241 } 242 } 243 244 private void displayVal(int viewId, int val) { 245 TextView textView = (TextView)findViewById(viewId); 246 String text = Integer.toString(val); 247 textView.setText(text); 248 } 249 250 251 private void getEffect(int session) { 252 synchronized (sInstances) { 253 if (sInstances.containsKey(session)) { 254 mVisualizer = sInstances.get(session); 255 } else { 256 try{ 257 mVisualizer = new Visualizer(session); 258 } catch (UnsupportedOperationException e) { 259 Log.e(TAG,"Visualizer library not loaded"); 260 throw (new RuntimeException("Cannot initialize effect")); 261 } catch (RuntimeException e) { 262 throw e; 263 } 264 sInstances.put(session, mVisualizer); 265 } 266 } 267 mReleaseButton.setEnabled(false); 268 mOnOffButton.setEnabled(false); 269 if (mVisualizer != null) { 270 mCaptureSize = mVisualizer.getCaptureSize(); 271 272 mReleaseButton.setChecked(true); 273 mReleaseButton.setEnabled(true); 274 275 mEnabled = mVisualizer.getEnabled(); 276 mOnOffButton.setChecked(mEnabled); 277 mOnOffButton.setEnabled(true); 278 279 mCallbackButton.setEnabled(!mEnabled); 280 } 281 } 282 283 private void putEffect(int session) { 284 mOnOffButton.setChecked(false); 285 mOnOffButton.setEnabled(false); 286 synchronized (sInstances) { 287 if (mVisualizer != null) { 288 mVisualizer.release(); 289 Log.d(TAG,"Visualizer released"); 290 mVisualizer = null; 291 sInstances.remove(session); 292 } 293 } 294 } 295 296} 297