blob: 33db2ddb900fe01f58a3b3011ac8fafc424b2fbf [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;
Dave Sparksd94466c2009-12-15 10:05:53 -080031import android.util.Log;
32import java.util.HashMap;
33import java.lang.Math;
34
35import com.android.soundpooltest.R;
36
37public class SoundPoolTest extends Activity
38{
39 private static final String LOG_TAG = "SoundPoolTest";
40 private static final boolean DEBUG = true;
41 private static final boolean VERBOSE = false;
42 private TestThread mThread;
43
44 private static final int[] mTestFiles = new int[] {
Dave Sparks19055302009-12-23 09:55:21 -080045 R.raw.organ441,
Dave Sparksd94466c2009-12-15 10:05:53 -080046 R.raw.sine441,
Andreas Huber6ed937e2010-02-09 16:59:18 -080047 R.raw.test1,
Dave Sparksd94466c2009-12-15 10:05:53 -080048 R.raw.test2,
49 R.raw.test3,
50 R.raw.test4,
51 R.raw.test5
52 };
53
Dave Sparksd94466c2009-12-15 10:05:53 -080054 private final static float SEMITONE = 1.059463094f;
55 private final static float DEFAULT_VOLUME = 0.707f;
56 private final static float MAX_VOLUME = 1.0f;
57 private final static float MIN_VOLUME = 0.01f;
58 private final static int LOW_PRIORITY = 1000;
59 private final static int NORMAL_PRIORITY = 2000;
60 private final static int HIGH_PRIORITY = 3000;
61 private final static int DEFAULT_LOOP = -1;
62 private final static int DEFAULT_SRC_QUALITY = 0;
63 private final static double PI_OVER_2 = Math.PI / 2.0;
64
65 public SoundPoolTest() {}
66
67 private final class TestThread extends java.lang.Thread {
68 private boolean mRunning;
69 private SoundPool mSoundPool = null;
70 private int mLastSample;
Dave Sparksf992cbb2010-02-09 13:00:09 -080071 private int mMaxStreams;
Dave Sparksd94466c2009-12-15 10:05:53 -080072 private int mLoadStatus;
73 private int[] mSounds;
74 private float mScale[];
75
76 TestThread() {
77 super("SoundPool.TestThread");
78 }
79
80 private final class LoadCompleteCallback implements
81 android.media.SoundPool.OnLoadCompleteListener {
82 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
83 synchronized(mSoundPool) {
84 if (DEBUG) Log.d(LOG_TAG, "Sample " + sampleId + " load status = " + status);
85 if (status != 0) {
86 mLoadStatus = status;
87 }
88 if (sampleId == mLastSample) {
89 mSoundPool.notify();
90 }
91 }
92 }
93 }
94
95 private int loadSound(int resId, int priority) {
96 int id = mSoundPool.load(getApplicationContext(), resId, priority);
97 if (id == 0) {
98 Log.e(LOG_TAG, "Unable to open resource");
99 }
100 return id;
101 }
102
Dave Sparksf992cbb2010-02-09 13:00:09 -0800103 private int initSoundPool(int numStreams) throws java.lang.InterruptedException {
Dave Sparksd94466c2009-12-15 10:05:53 -0800104
105 if (mSoundPool != null) {
Dave Sparksf992cbb2010-02-09 13:00:09 -0800106 if ((mMaxStreams == numStreams) && (mLoadStatus == 0)) return mLoadStatus;
Dave Sparksd94466c2009-12-15 10:05:53 -0800107 mSoundPool.release();
108 mSoundPool = null;
109 }
110
111 // create sound pool
112 mLoadStatus = 0;
Dave Sparksf992cbb2010-02-09 13:00:09 -0800113 mMaxStreams = numStreams;
114 mSoundPool = new SoundPool(numStreams, AudioSystem.STREAM_MUSIC, 0);
Dave Sparksd94466c2009-12-15 10:05:53 -0800115 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
Dave Sparksf992cbb2010-02-09 13:00:09 -0800265 // play 5 sounds, forces one to be stolen
266 int ids[] = new int[5];
267 for (int i = 0; i < 5; i++) {
268 ids[i] = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
269 NORMAL_PRIORITY, DEFAULT_LOOP, mScale[i]);
270 if (DEBUG) Log.d(LOG_TAG, "Start note " + ids[i]);
271 if (ids[i] == 0) {
272 Log.e(LOG_TAG, "Error occurred starting note");
273 return false;
274 }
275 sleep(250);
276 }
277
278 // pause and resume sound a few times
279 for (int count = 0; count < 5; count++) {
280 mSoundPool.autoPause();
281 sleep(250);
282 mSoundPool.autoResume();
283 sleep(250);
284 }
285
286 for (int i = 0; i < 5; i++) {
287 mSoundPool.stop(ids[i]);
288 }
289
Dave Sparksd94466c2009-12-15 10:05:53 -0800290 if (DEBUG) Log.d(LOG_TAG, "End pause/resume test");
291 return result;
292 }
293
294 private boolean TestVolume() throws java.lang.InterruptedException {
295 if (DEBUG) Log.d(LOG_TAG, "Begin volume test");
296
297 // start the note
298 int id = mSoundPool.play(mSounds[0], 0.0f, 1.0f, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]);
299 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
300 if (id == 0) {
301 Log.e(LOG_TAG, "Test failed - exiting");
302 return false;
303 }
304
305 // pan from left to right
306 for (int count = 0; count < 101; count++) {
307 sleep(20);
308 double radians = PI_OVER_2 * count / 100.0;
309 float leftVolume = (float) Math.sin(radians);
310 float rightVolume = (float) Math.cos(radians);
311 mSoundPool.setVolume(id, leftVolume, rightVolume);
312 if (DEBUG) Log.d(LOG_TAG, "Change volume (" + leftVolume + "," + rightVolume + ")");
313 }
314
315 mSoundPool.stop(id);
316 if (DEBUG) Log.d(LOG_TAG, "End volume test");
317 return true;
318 }
319
320 public void run() {
321 if (DEBUG) Log.d(LOG_TAG, "Test thread running");
322
323 // initialize
324 mRunning = true;
325 int failures = 0;
326
327 // initialize pitch table
328 float pitch = 0.5f;
329 mScale = new float[13];
330 for (int i = 0; i < 13; ++i) {
331 mScale[i] = pitch;
332 pitch *= SEMITONE;
333 }
334
335 try {
336
Dave Sparksf992cbb2010-02-09 13:00:09 -0800337 // do single stream tests
338 initSoundPool(1);
Dave Sparksd94466c2009-12-15 10:05:53 -0800339 if (!TestSounds()) failures = failures + 1;
340 if (!TestScales()) failures = failures + 1;
341 if (!TestRates()) failures = failures + 1;
342 if (!TestPriority()) failures = failures + 1;
Dave Sparksd94466c2009-12-15 10:05:53 -0800343 if (!TestVolume()) failures = failures + 1;
344
Dave Sparksf992cbb2010-02-09 13:00:09 -0800345 // do multiple stream tests
346 initSoundPool(4);
347 if (!TestPauseResume()) failures = failures + 1;
348
Dave Sparksd94466c2009-12-15 10:05:53 -0800349 } catch (java.lang.InterruptedException e) {
350 if (DEBUG) Log.d(LOG_TAG, "Test interrupted");
351 failures = failures + 1;
352 } finally {
353 mRunning = false;
354 }
355
356 // release sound pool
357 if (mSoundPool != null) {
358 mSoundPool.release();
359 mSoundPool = null;
360 }
361
362 // output stats
363 if (DEBUG) Log.d(LOG_TAG, "Test thread exit");
364 if (failures == 0) {
365 Log.i(LOG_TAG, "All tests passed");
366 } else {
367 Log.i(LOG_TAG, failures + " tests failed");
368 }
369 }
370
371 public void quit() {
372 if (DEBUG) Log.d(LOG_TAG, "interrupt");
373 interrupt();
374 while (mRunning) {
375 try {
376 sleep(20);
377 } catch (java.lang.InterruptedException e) { }
378 }
379 if (DEBUG) Log.d(LOG_TAG, "quit");
380 }
381 }
382
383 private void startTests() {
384 mThread = new TestThread();
385 mThread.start();
386 }
387
388 protected void onPause()
389 {
390 Log.v(LOG_TAG, "onPause");
391 super.onPause();
392 mThread.quit();
393 mThread = null;
394 }
395
396 protected void onResume()
397 {
398 Log.v(LOG_TAG, "onResume");
399 super.onResume();
400 startTests();
401 }
402
403 public void onCreate(Bundle icicle)
404 {
405 super.onCreate(icicle);
406 setVolumeControlStream(AudioManager.STREAM_MUSIC);
407 }
408}
409