• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.soundpooltest;
18 
19 import android.app.Activity;
20 import android.widget.LinearLayout;
21 import android.os.Bundle;
22 import android.view.ViewGroup;
23 import android.widget.Button;
24 import android.view.View;
25 import android.view.View.OnClickListener;
26 import android.view.KeyEvent;
27 import android.media.AudioSystem;
28 import android.media.AudioManager;
29 import android.media.SoundPool;
30 import android.media.SoundPool.OnLoadCompleteListener;
31 import android.util.Log;
32 import java.util.HashMap;
33 import java.lang.Math;
34 
35 import com.android.soundpooltest.R;
36 
37 public 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[] {
45         R.raw.organ441,
46         R.raw.sine441,
47         R.raw.test1,
48         R.raw.test2,
49         R.raw.test3,
50         R.raw.test4,
51         R.raw.test5
52     };
53 
54     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 
SoundPoolTest()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;
71         private int mMaxStreams;
72         private int mLoadStatus;
73         private int[] mSounds;
74         private float mScale[];
75 
TestThread()76         TestThread() {
77             super("SoundPool.TestThread");
78         }
79 
80         private final class LoadCompleteCallback implements
81             android.media.SoundPool.OnLoadCompleteListener {
onLoadComplete(SoundPool soundPool, int sampleId, int status)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 
loadSound(int resId, int priority)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 
initSoundPool(int numStreams)103         private int initSoundPool(int numStreams) throws java.lang.InterruptedException {
104 
105             if (mSoundPool != null) {
106                 if ((mMaxStreams == numStreams) && (mLoadStatus == 0)) return mLoadStatus;
107                 mSoundPool.release();
108                 mSoundPool = null;
109             }
110 
111             // create sound pool
112             mLoadStatus = 0;
113             mMaxStreams = numStreams;
114             mSoundPool = new SoundPool(numStreams, 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 
TestSounds()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 sounds test");
147             return true;
148         }
149 
TestScales()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 scale test");
169             return true;
170         }
171 
TestRates()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, "Stop note " + id);
193             if (DEBUG) Log.d(LOG_TAG, "End rate test");
194             return true;
195         }
196 
TestPriority()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(1000);
210 
211             // play a low priority sound
212             int id = mSoundPool.play(mSounds[1], 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                 sleep(1000);
220                 Log.i(LOG_TAG, "Normal > Low priority test passed");
221             }
222 
223             // play a high priority sound
224             id = mSoundPool.play(mSounds[2], 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                 sleep(1000);
231                 Log.i(LOG_TAG, "Stopping high priority");
232                 mSoundPool.stop(id);
233                 sleep(1000);
234                 Log.i(LOG_TAG, "High > Normal priority test passed");
235             }
236 
237             // stop normal note
238             Log.i(LOG_TAG, "Stopping normal priority");
239             mSoundPool.stop(normalId);
240             sleep(1000);
241 
242             if (DEBUG) Log.d(LOG_TAG, "End priority test");
243             return result;
244         }
245 
TestPauseResume()246         private boolean TestPauseResume() throws java.lang.InterruptedException {
247             if (DEBUG) Log.d(LOG_TAG, "Begin pause/resume test");
248             boolean result = true;
249 
250             // play a normal priority looping sound
251             int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
252                     NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f);
253             if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
254             if (id == 0) {
255                 Log.e(LOG_TAG, "Error occurred starting note");
256                 return false;
257             }
258             sleep(2500);
259 
260             // pause and resume sound a few times
261             for (int count = 0; count < 5; count++) {
262                 if (DEBUG) Log.d(LOG_TAG, "Pause note " + id);
263                 mSoundPool.pause(id);
264                 sleep(1000);
265                 if (DEBUG) Log.d(LOG_TAG, "Resume note " + id);
266                 mSoundPool.resume(id);
267                 sleep(1000);
268             }
269 
270             if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
271             mSoundPool.stop(id);
272             sleep(1000);
273 
274             // play 5 sounds, forces one to be stolen
275             int ids[] = new int[5];
276             for (int i = 0; i < 5; i++) {
277                 ids[i] = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
278                         NORMAL_PRIORITY, DEFAULT_LOOP, mScale[i]);
279                 if (DEBUG) Log.d(LOG_TAG, "Start note " + ids[i]);
280                 if (ids[i] == 0) {
281                     Log.e(LOG_TAG, "Error occurred starting note");
282                     return false;
283                 }
284                 sleep(1000);
285             }
286 
287             // pause and resume sound a few times
288             for (int count = 0; count < 5; count++) {
289                 if (DEBUG) Log.d(LOG_TAG, "autoPause");
290                 mSoundPool.autoPause();
291                 sleep(1000);
292                 if (DEBUG) Log.d(LOG_TAG, "autoResume");
293                 mSoundPool.autoResume();
294                 sleep(1000);
295             }
296 
297             for (int i = 0; i < 5; i++) {
298                 if (DEBUG) Log.d(LOG_TAG, "Stop note " + ids[i]);
299                 mSoundPool.stop(ids[i]);
300             }
301 
302             if (DEBUG) Log.d(LOG_TAG, "End pause/resume test");
303             return result;
304         }
305 
TestVolume()306         private boolean TestVolume() throws java.lang.InterruptedException {
307             if (DEBUG) Log.d(LOG_TAG, "Begin volume test");
308 
309             // start the note
310             int id = mSoundPool.play(mSounds[0], 0.0f, 1.0f, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]);
311             if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
312             if (id == 0) {
313                 Log.e(LOG_TAG, "Test failed - exiting");
314                 return false;
315             }
316 
317             // pan from right to left
318             for (int count = 0; count < 101; count++) {
319                 sleep(50);
320                 double radians = PI_OVER_2 * count / 100.0;
321                 float leftVolume = (float) Math.sin(radians);
322                 float rightVolume = (float) Math.cos(radians);
323                 mSoundPool.setVolume(id, leftVolume, rightVolume);
324                 if (DEBUG) Log.d(LOG_TAG, "Change volume (" + leftVolume + "," + rightVolume + ")");
325             }
326 
327             mSoundPool.stop(id);
328             if (DEBUG) Log.d(LOG_TAG, "End volume test");
329             return true;
330         }
331 
run()332         public void run() {
333             if (DEBUG) Log.d(LOG_TAG, "Test thread running");
334 
335             // initialize
336             mRunning = true;
337             int failures = 0;
338 
339             // initialize pitch table
340             float pitch = 0.5f;
341             mScale = new float[13];
342             for (int i = 0; i < 13; ++i) {
343                 mScale[i] = pitch;
344                 pitch *= SEMITONE;
345             }
346 
347             try {
348 
349                 // do single stream tests
350                 initSoundPool(1);
351                 if (!TestSounds()) failures = failures + 1;
352                 if (!TestScales()) failures = failures + 1;
353                 if (!TestRates()) failures = failures + 1;
354                 if (!TestPriority()) failures = failures + 1;
355                 if (!TestVolume()) failures = failures + 1;
356 
357                 // do multiple stream tests
358                 initSoundPool(4);
359                 if (!TestPauseResume()) failures = failures + 1;
360 
361             } catch (java.lang.InterruptedException e) {
362                 if (DEBUG) Log.d(LOG_TAG, "Test interrupted");
363                 failures = failures + 1;
364             } finally {
365                 mRunning = false;
366             }
367 
368             // release sound pool
369             if (mSoundPool != null) {
370                 mSoundPool.release();
371                 mSoundPool = null;
372             }
373 
374             // output stats
375             if (DEBUG) Log.d(LOG_TAG, "Test thread exit");
376             if (failures == 0) {
377                 Log.i(LOG_TAG, "All tests passed");
378             } else {
379                 Log.i(LOG_TAG, failures + " tests failed");
380             }
381         }
382 
quit()383         public void quit() {
384             if (DEBUG) Log.d(LOG_TAG, "interrupt");
385             interrupt();
386             while (mRunning) {
387                 try {
388                     sleep(20);
389                 } catch (java.lang.InterruptedException e) { }
390             }
391             if (DEBUG) Log.d(LOG_TAG, "quit");
392         }
393     }
394 
startTests()395     private void startTests() {
396         mThread = new TestThread();
397         mThread.start();
398     }
399 
onPause()400     protected void onPause()
401     {
402         Log.v(LOG_TAG, "onPause");
403         super.onPause();
404         mThread.quit();
405         mThread = null;
406     }
407 
onResume()408     protected void onResume()
409     {
410         Log.v(LOG_TAG, "onResume");
411         super.onResume();
412         startTests();
413     }
414 
onCreate(Bundle icicle)415     public void onCreate(Bundle icicle)
416     {
417         super.onCreate(icicle);
418         setVolumeControlStream(AudioManager.STREAM_MUSIC);
419     }
420 }
421 
422