SoundPoolTest.java revision 6ed937ebe99088b5671a645060340a558b02fefb
1/* 2 * Copyright (c) 2009, Google Inc. 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.soundpooltest; 18 19import android.app.Activity; 20import android.widget.LinearLayout; 21import android.os.Bundle; 22import android.view.ViewGroup; 23import android.widget.Button; 24import android.view.View; 25import android.view.View.OnClickListener; 26import android.view.KeyEvent; 27import android.media.AudioSystem; 28import android.media.AudioManager; 29import android.media.SoundPool; 30import android.media.SoundPool.OnLoadCompleteListener; 31import android.util.Config; 32import android.util.Log; 33import java.util.HashMap; 34import java.lang.Math; 35 36import com.android.soundpooltest.R; 37 38public class SoundPoolTest extends Activity 39{ 40 private static final String LOG_TAG = "SoundPoolTest"; 41 private static final boolean DEBUG = true; 42 private static final boolean VERBOSE = false; 43 private TestThread mThread; 44 45 private static final int[] mTestFiles = new int[] { 46 R.raw.organ441, 47 R.raw.sine441, 48 R.raw.test1, 49 R.raw.test2, 50 R.raw.test3, 51 R.raw.test4, 52 R.raw.test5 53 }; 54 55 private final static int MAX_STREAMS = 1; 56 private final static float SEMITONE = 1.059463094f; 57 private final static float DEFAULT_VOLUME = 0.707f; 58 private final static float MAX_VOLUME = 1.0f; 59 private final static float MIN_VOLUME = 0.01f; 60 private final static int LOW_PRIORITY = 1000; 61 private final static int NORMAL_PRIORITY = 2000; 62 private final static int HIGH_PRIORITY = 3000; 63 private final static int DEFAULT_LOOP = -1; 64 private final static int DEFAULT_SRC_QUALITY = 0; 65 private final static double PI_OVER_2 = Math.PI / 2.0; 66 67 public SoundPoolTest() {} 68 69 private final class TestThread extends java.lang.Thread { 70 private boolean mRunning; 71 private SoundPool mSoundPool = null; 72 private int mLastSample; 73 private int mLoadStatus; 74 private int[] mSounds; 75 private float mScale[]; 76 77 TestThread() { 78 super("SoundPool.TestThread"); 79 } 80 81 private final class LoadCompleteCallback implements 82 android.media.SoundPool.OnLoadCompleteListener { 83 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 84 synchronized(mSoundPool) { 85 if (DEBUG) Log.d(LOG_TAG, "Sample " + sampleId + " load status = " + status); 86 if (status != 0) { 87 mLoadStatus = status; 88 } 89 if (sampleId == mLastSample) { 90 mSoundPool.notify(); 91 } 92 } 93 } 94 } 95 96 private int loadSound(int resId, int priority) { 97 int id = mSoundPool.load(getApplicationContext(), resId, priority); 98 if (id == 0) { 99 Log.e(LOG_TAG, "Unable to open resource"); 100 } 101 return id; 102 } 103 104 private int initSoundPool() throws java.lang.InterruptedException { 105 106 if (mSoundPool != null) { 107 if (mLoadStatus == 0) return mLoadStatus; 108 mSoundPool.release(); 109 mSoundPool = null; 110 } 111 112 // create sound pool 113 mLoadStatus = 0; 114 mSoundPool = new SoundPool(MAX_STREAMS, AudioSystem.STREAM_MUSIC, 0); 115 mSoundPool.setOnLoadCompleteListener(new LoadCompleteCallback()); 116 int numSounds = mTestFiles.length; 117 mSounds = new int[numSounds]; 118 119 // load sounds 120 synchronized(mSoundPool) { 121 for (int index = 0; index < numSounds; index++) { 122 mSounds[index] = loadSound(mTestFiles[index], NORMAL_PRIORITY); 123 mLastSample = mSounds[index]; 124 } 125 mSoundPool.wait(); 126 } 127 return mLoadStatus; 128 } 129 130 private boolean TestSounds() throws java.lang.InterruptedException { 131 if (DEBUG) Log.d(LOG_TAG, "Begin sounds test"); 132 int count = mSounds.length; 133 for (int index = 0; index < count; index++) { 134 int id = mSoundPool.play(mSounds[index], DEFAULT_VOLUME, DEFAULT_VOLUME, 135 NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f); 136 if (DEBUG) Log.d(LOG_TAG, "Start note " + id); 137 if (id == 0) { 138 Log.e(LOG_TAG, "Error occurred starting note"); 139 return false; 140 } 141 sleep(450); 142 mSoundPool.stop(id); 143 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id); 144 sleep(50); 145 } 146 if (DEBUG) Log.d(LOG_TAG, "End scale test"); 147 return true; 148 } 149 150 private boolean TestScales() throws java.lang.InterruptedException { 151 if (DEBUG) Log.d(LOG_TAG, "Begin scale test"); 152 153 // interate through pitch table 154 int count = mScale.length; 155 for (int step = 0; step < count; step++) { 156 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, 157 NORMAL_PRIORITY, DEFAULT_LOOP, mScale[step]); 158 if (DEBUG) Log.d(LOG_TAG, "Start note " + id); 159 if (id == 0) { 160 Log.e(LOG_TAG, "Error occurred starting note"); 161 return false; 162 } 163 sleep(450); 164 mSoundPool.stop(id); 165 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id); 166 sleep(50); 167 } 168 if (DEBUG) Log.d(LOG_TAG, "End sounds test"); 169 return true; 170 } 171 172 private boolean TestRates() throws java.lang.InterruptedException { 173 if (DEBUG) Log.d(LOG_TAG, "Begin rate test"); 174 175 // start the note 176 int count = mScale.length; 177 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, 178 NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]); 179 if (DEBUG) Log.d(LOG_TAG, "Start note " + id); 180 if (id == 0) { 181 Log.e(LOG_TAG, "Test failed - exiting"); 182 return false; 183 } 184 185 // modify the pitch 186 for (int step = 1; step < count; step++) { 187 sleep(250); 188 mSoundPool.setRate(id, mScale[step]); 189 if (DEBUG) Log.d(LOG_TAG, "Change rate " + mScale[step]); 190 } 191 mSoundPool.stop(id); 192 if (DEBUG) Log.d(LOG_TAG, "End rate test"); 193 return true; 194 } 195 196 private boolean TestPriority() throws java.lang.InterruptedException { 197 if (DEBUG) Log.d(LOG_TAG, "Begin priority test"); 198 boolean result = true; 199 200 // play a normal priority looping sound 201 int normalId = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, 202 NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f); 203 if (DEBUG) Log.d(LOG_TAG, "Start note " + normalId); 204 if (normalId == 0) { 205 Log.e(LOG_TAG, "Error occurred starting note"); 206 return false; 207 } 208 sleep(250); 209 210 // play a low priority sound 211 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, 212 LOW_PRIORITY, DEFAULT_LOOP, 1.0f); 213 if (id > 0) { 214 Log.e(LOG_TAG, "Normal > Low priority test failed"); 215 result = false; 216 mSoundPool.stop(id); 217 } else { 218 Log.e(LOG_TAG, "Normal > Low priority test passed"); 219 } 220 sleep(250); 221 222 // play a high priority sound 223 id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, 224 HIGH_PRIORITY, DEFAULT_LOOP, 1.0f); 225 if (id == 0) { 226 Log.e(LOG_TAG, "High > Normal priority test failed"); 227 result = false; 228 } else { 229 Log.e(LOG_TAG, "High > Normal priority test passed"); 230 } 231 sleep(250); 232 mSoundPool.stop(id); 233 234 // stop normal note 235 mSoundPool.stop(normalId); 236 237 if (DEBUG) Log.d(LOG_TAG, "End priority test"); 238 return result; 239 } 240 241 private boolean TestPauseResume() throws java.lang.InterruptedException { 242 if (DEBUG) Log.d(LOG_TAG, "Begin pause/resume test"); 243 boolean result = true; 244 245 // play a normal priority looping sound 246 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, 247 NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f); 248 if (DEBUG) Log.d(LOG_TAG, "Start note " + id); 249 if (id == 0) { 250 Log.e(LOG_TAG, "Error occurred starting note"); 251 return false; 252 } 253 sleep(250); 254 255 // pause and resume sound a few times 256 for (int count = 0; count < 5; count++) { 257 mSoundPool.pause(id); 258 sleep(250); 259 mSoundPool.resume(id); 260 sleep(250); 261 } 262 263 mSoundPool.stop(id); 264 265 if (DEBUG) Log.d(LOG_TAG, "End pause/resume test"); 266 return result; 267 } 268 269 private boolean TestVolume() throws java.lang.InterruptedException { 270 if (DEBUG) Log.d(LOG_TAG, "Begin volume test"); 271 272 // start the note 273 int id = mSoundPool.play(mSounds[0], 0.0f, 1.0f, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]); 274 if (DEBUG) Log.d(LOG_TAG, "Start note " + id); 275 if (id == 0) { 276 Log.e(LOG_TAG, "Test failed - exiting"); 277 return false; 278 } 279 280 // pan from left to right 281 for (int count = 0; count < 101; count++) { 282 sleep(20); 283 double radians = PI_OVER_2 * count / 100.0; 284 float leftVolume = (float) Math.sin(radians); 285 float rightVolume = (float) Math.cos(radians); 286 mSoundPool.setVolume(id, leftVolume, rightVolume); 287 if (DEBUG) Log.d(LOG_TAG, "Change volume (" + leftVolume + "," + rightVolume + ")"); 288 } 289 290 mSoundPool.stop(id); 291 if (DEBUG) Log.d(LOG_TAG, "End volume test"); 292 return true; 293 } 294 295 public void run() { 296 if (DEBUG) Log.d(LOG_TAG, "Test thread running"); 297 298 // initialize 299 mRunning = true; 300 int failures = 0; 301 302 // initialize pitch table 303 float pitch = 0.5f; 304 mScale = new float[13]; 305 for (int i = 0; i < 13; ++i) { 306 mScale[i] = pitch; 307 pitch *= SEMITONE; 308 } 309 310 try { 311 312 // load sound pool 313 initSoundPool(); 314 315 // do tests 316 if (!TestSounds()) failures = failures + 1; 317 if (!TestScales()) failures = failures + 1; 318 if (!TestRates()) failures = failures + 1; 319 if (!TestPriority()) failures = failures + 1; 320 if (!TestPauseResume()) failures = failures + 1; 321 if (!TestVolume()) failures = failures + 1; 322 323 } catch (java.lang.InterruptedException e) { 324 if (DEBUG) Log.d(LOG_TAG, "Test interrupted"); 325 failures = failures + 1; 326 } finally { 327 mRunning = false; 328 } 329 330 // release sound pool 331 if (mSoundPool != null) { 332 mSoundPool.release(); 333 mSoundPool = null; 334 } 335 336 // output stats 337 if (DEBUG) Log.d(LOG_TAG, "Test thread exit"); 338 if (failures == 0) { 339 Log.i(LOG_TAG, "All tests passed"); 340 } else { 341 Log.i(LOG_TAG, failures + " tests failed"); 342 } 343 } 344 345 public void quit() { 346 if (DEBUG) Log.d(LOG_TAG, "interrupt"); 347 interrupt(); 348 while (mRunning) { 349 try { 350 sleep(20); 351 } catch (java.lang.InterruptedException e) { } 352 } 353 if (DEBUG) Log.d(LOG_TAG, "quit"); 354 } 355 } 356 357 private void startTests() { 358 mThread = new TestThread(); 359 mThread.start(); 360 } 361 362 protected void onPause() 363 { 364 Log.v(LOG_TAG, "onPause"); 365 super.onPause(); 366 mThread.quit(); 367 mThread = null; 368 } 369 370 protected void onResume() 371 { 372 Log.v(LOG_TAG, "onResume"); 373 super.onResume(); 374 startTests(); 375 } 376 377 public void onCreate(Bundle icicle) 378 { 379 super.onCreate(icicle); 380 setVolumeControlStream(AudioManager.STREAM_MUSIC); 381 } 382} 383 384