blob: df1b37599052351fe8617b4bdd55485dcb01ec5d [file] [log] [blame]
Dave Sparksd94466c2009-12-15 10:05:53 -08001/*
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[] {
Dave Sparks19055302009-12-23 09:55:21 -080046 R.raw.organ441,
Dave Sparksd94466c2009-12-15 10:05:53 -080047 R.raw.sine441,
Andreas Huber6ed937e2010-02-09 16:59:18 -080048 R.raw.test1,
Dave Sparksd94466c2009-12-15 10:05:53 -080049 R.raw.test2,
50 R.raw.test3,
51 R.raw.test4,
52 R.raw.test5
53 };
54
Dave Sparksd94466c2009-12-15 10:05:53 -080055 private final static float SEMITONE = 1.059463094f;
56 private final static float DEFAULT_VOLUME = 0.707f;
57 private final static float MAX_VOLUME = 1.0f;
58 private final static float MIN_VOLUME = 0.01f;
59 private final static int LOW_PRIORITY = 1000;
60 private final static int NORMAL_PRIORITY = 2000;
61 private final static int HIGH_PRIORITY = 3000;
62 private final static int DEFAULT_LOOP = -1;
63 private final static int DEFAULT_SRC_QUALITY = 0;
64 private final static double PI_OVER_2 = Math.PI / 2.0;
65
66 public SoundPoolTest() {}
67
68 private final class TestThread extends java.lang.Thread {
69 private boolean mRunning;
70 private SoundPool mSoundPool = null;
71 private int mLastSample;
Dave Sparksf992cbb2010-02-09 13:00:09 -080072 private int mMaxStreams;
Dave Sparksd94466c2009-12-15 10:05:53 -080073 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
Dave Sparksf992cbb2010-02-09 13:00:09 -0800104 private int initSoundPool(int numStreams) throws java.lang.InterruptedException {
Dave Sparksd94466c2009-12-15 10:05:53 -0800105
106 if (mSoundPool != null) {
Dave Sparksf992cbb2010-02-09 13:00:09 -0800107 if ((mMaxStreams == numStreams) && (mLoadStatus == 0)) return mLoadStatus;
Dave Sparksd94466c2009-12-15 10:05:53 -0800108 mSoundPool.release();
109 mSoundPool = null;
110 }
111
112 // create sound pool
113 mLoadStatus = 0;
Dave Sparksf992cbb2010-02-09 13:00:09 -0800114 mMaxStreams = numStreams;
115 mSoundPool = new SoundPool(numStreams, AudioSystem.STREAM_MUSIC, 0);
Dave Sparksd94466c2009-12-15 10:05:53 -0800116 mSoundPool.setOnLoadCompleteListener(new LoadCompleteCallback());
117 int numSounds = mTestFiles.length;
118 mSounds = new int[numSounds];
119
120 // load sounds
121 synchronized(mSoundPool) {
122 for (int index = 0; index < numSounds; index++) {
123 mSounds[index] = loadSound(mTestFiles[index], NORMAL_PRIORITY);
124 mLastSample = mSounds[index];
125 }
126 mSoundPool.wait();
127 }
128 return mLoadStatus;
129 }
130
131 private boolean TestSounds() throws java.lang.InterruptedException {
132 if (DEBUG) Log.d(LOG_TAG, "Begin sounds test");
133 int count = mSounds.length;
134 for (int index = 0; index < count; index++) {
135 int id = mSoundPool.play(mSounds[index], DEFAULT_VOLUME, DEFAULT_VOLUME,
136 NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f);
137 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
138 if (id == 0) {
139 Log.e(LOG_TAG, "Error occurred starting note");
140 return false;
141 }
142 sleep(450);
143 mSoundPool.stop(id);
144 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
145 sleep(50);
146 }
147 if (DEBUG) Log.d(LOG_TAG, "End scale test");
148 return true;
149 }
150
151 private boolean TestScales() throws java.lang.InterruptedException {
152 if (DEBUG) Log.d(LOG_TAG, "Begin scale test");
153
154 // interate through pitch table
155 int count = mScale.length;
156 for (int step = 0; step < count; step++) {
157 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
158 NORMAL_PRIORITY, DEFAULT_LOOP, mScale[step]);
159 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
160 if (id == 0) {
161 Log.e(LOG_TAG, "Error occurred starting note");
162 return false;
163 }
164 sleep(450);
165 mSoundPool.stop(id);
166 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
167 sleep(50);
168 }
169 if (DEBUG) Log.d(LOG_TAG, "End sounds test");
170 return true;
171 }
172
173 private boolean TestRates() throws java.lang.InterruptedException {
174 if (DEBUG) Log.d(LOG_TAG, "Begin rate test");
175
176 // start the note
177 int count = mScale.length;
178 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
179 NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]);
180 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
181 if (id == 0) {
182 Log.e(LOG_TAG, "Test failed - exiting");
183 return false;
184 }
185
186 // modify the pitch
187 for (int step = 1; step < count; step++) {
188 sleep(250);
189 mSoundPool.setRate(id, mScale[step]);
190 if (DEBUG) Log.d(LOG_TAG, "Change rate " + mScale[step]);
191 }
192 mSoundPool.stop(id);
193 if (DEBUG) Log.d(LOG_TAG, "End rate test");
194 return true;
195 }
196
197 private boolean TestPriority() throws java.lang.InterruptedException {
198 if (DEBUG) Log.d(LOG_TAG, "Begin priority test");
199 boolean result = true;
200
201 // play a normal priority looping sound
202 int normalId = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
203 NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f);
204 if (DEBUG) Log.d(LOG_TAG, "Start note " + normalId);
205 if (normalId == 0) {
206 Log.e(LOG_TAG, "Error occurred starting note");
207 return false;
208 }
209 sleep(250);
210
211 // play a low priority sound
212 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
213 LOW_PRIORITY, DEFAULT_LOOP, 1.0f);
214 if (id > 0) {
215 Log.e(LOG_TAG, "Normal > Low priority test failed");
216 result = false;
217 mSoundPool.stop(id);
218 } else {
219 Log.e(LOG_TAG, "Normal > Low priority test passed");
220 }
221 sleep(250);
222
223 // play a high priority sound
224 id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
225 HIGH_PRIORITY, DEFAULT_LOOP, 1.0f);
226 if (id == 0) {
227 Log.e(LOG_TAG, "High > Normal priority test failed");
228 result = false;
229 } else {
230 Log.e(LOG_TAG, "High > Normal priority test passed");
231 }
232 sleep(250);
233 mSoundPool.stop(id);
234
235 // stop normal note
236 mSoundPool.stop(normalId);
237
238 if (DEBUG) Log.d(LOG_TAG, "End priority test");
239 return result;
240 }
241
242 private boolean TestPauseResume() throws java.lang.InterruptedException {
243 if (DEBUG) Log.d(LOG_TAG, "Begin pause/resume test");
244 boolean result = true;
245
246 // play a normal priority looping sound
247 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
248 NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f);
249 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
250 if (id == 0) {
251 Log.e(LOG_TAG, "Error occurred starting note");
252 return false;
253 }
254 sleep(250);
255
256 // pause and resume sound a few times
257 for (int count = 0; count < 5; count++) {
258 mSoundPool.pause(id);
259 sleep(250);
260 mSoundPool.resume(id);
261 sleep(250);
262 }
263
264 mSoundPool.stop(id);
265
Dave Sparksf992cbb2010-02-09 13:00:09 -0800266 // play 5 sounds, forces one to be stolen
267 int ids[] = new int[5];
268 for (int i = 0; i < 5; i++) {
269 ids[i] = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
270 NORMAL_PRIORITY, DEFAULT_LOOP, mScale[i]);
271 if (DEBUG) Log.d(LOG_TAG, "Start note " + ids[i]);
272 if (ids[i] == 0) {
273 Log.e(LOG_TAG, "Error occurred starting note");
274 return false;
275 }
276 sleep(250);
277 }
278
279 // pause and resume sound a few times
280 for (int count = 0; count < 5; count++) {
281 mSoundPool.autoPause();
282 sleep(250);
283 mSoundPool.autoResume();
284 sleep(250);
285 }
286
287 for (int i = 0; i < 5; i++) {
288 mSoundPool.stop(ids[i]);
289 }
290
Dave Sparksd94466c2009-12-15 10:05:53 -0800291 if (DEBUG) Log.d(LOG_TAG, "End pause/resume test");
292 return result;
293 }
294
295 private boolean TestVolume() throws java.lang.InterruptedException {
296 if (DEBUG) Log.d(LOG_TAG, "Begin volume test");
297
298 // start the note
299 int id = mSoundPool.play(mSounds[0], 0.0f, 1.0f, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]);
300 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
301 if (id == 0) {
302 Log.e(LOG_TAG, "Test failed - exiting");
303 return false;
304 }
305
306 // pan from left to right
307 for (int count = 0; count < 101; count++) {
308 sleep(20);
309 double radians = PI_OVER_2 * count / 100.0;
310 float leftVolume = (float) Math.sin(radians);
311 float rightVolume = (float) Math.cos(radians);
312 mSoundPool.setVolume(id, leftVolume, rightVolume);
313 if (DEBUG) Log.d(LOG_TAG, "Change volume (" + leftVolume + "," + rightVolume + ")");
314 }
315
316 mSoundPool.stop(id);
317 if (DEBUG) Log.d(LOG_TAG, "End volume test");
318 return true;
319 }
320
321 public void run() {
322 if (DEBUG) Log.d(LOG_TAG, "Test thread running");
323
324 // initialize
325 mRunning = true;
326 int failures = 0;
327
328 // initialize pitch table
329 float pitch = 0.5f;
330 mScale = new float[13];
331 for (int i = 0; i < 13; ++i) {
332 mScale[i] = pitch;
333 pitch *= SEMITONE;
334 }
335
336 try {
337
Dave Sparksf992cbb2010-02-09 13:00:09 -0800338 // do single stream tests
339 initSoundPool(1);
Dave Sparksd94466c2009-12-15 10:05:53 -0800340 if (!TestSounds()) failures = failures + 1;
341 if (!TestScales()) failures = failures + 1;
342 if (!TestRates()) failures = failures + 1;
343 if (!TestPriority()) failures = failures + 1;
Dave Sparksd94466c2009-12-15 10:05:53 -0800344 if (!TestVolume()) failures = failures + 1;
345
Dave Sparksf992cbb2010-02-09 13:00:09 -0800346 // do multiple stream tests
347 initSoundPool(4);
348 if (!TestPauseResume()) failures = failures + 1;
349
Dave Sparksd94466c2009-12-15 10:05:53 -0800350 } catch (java.lang.InterruptedException e) {
351 if (DEBUG) Log.d(LOG_TAG, "Test interrupted");
352 failures = failures + 1;
353 } finally {
354 mRunning = false;
355 }
356
357 // release sound pool
358 if (mSoundPool != null) {
359 mSoundPool.release();
360 mSoundPool = null;
361 }
362
363 // output stats
364 if (DEBUG) Log.d(LOG_TAG, "Test thread exit");
365 if (failures == 0) {
366 Log.i(LOG_TAG, "All tests passed");
367 } else {
368 Log.i(LOG_TAG, failures + " tests failed");
369 }
370 }
371
372 public void quit() {
373 if (DEBUG) Log.d(LOG_TAG, "interrupt");
374 interrupt();
375 while (mRunning) {
376 try {
377 sleep(20);
378 } catch (java.lang.InterruptedException e) { }
379 }
380 if (DEBUG) Log.d(LOG_TAG, "quit");
381 }
382 }
383
384 private void startTests() {
385 mThread = new TestThread();
386 mThread.start();
387 }
388
389 protected void onPause()
390 {
391 Log.v(LOG_TAG, "onPause");
392 super.onPause();
393 mThread.quit();
394 mThread = null;
395 }
396
397 protected void onResume()
398 {
399 Log.v(LOG_TAG, "onResume");
400 super.onResume();
401 startTests();
402 }
403
404 public void onCreate(Bundle icicle)
405 {
406 super.onCreate(icicle);
407 setVolumeControlStream(AudioManager.STREAM_MUSIC);
408 }
409}
410