• 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 scale 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 sounds 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, "End rate test");
193             return true;
194         }
195 
TestPriority()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 
TestPauseResume()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             // 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 
290             if (DEBUG) Log.d(LOG_TAG, "End pause/resume test");
291             return result;
292         }
293 
TestVolume()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 
run()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 
337                 // do single stream tests
338                 initSoundPool(1);
339                 if (!TestSounds()) failures = failures + 1;
340                 if (!TestScales()) failures = failures + 1;
341                 if (!TestRates()) failures = failures + 1;
342                 if (!TestPriority()) failures = failures + 1;
343                 if (!TestVolume()) failures = failures + 1;
344 
345                 // do multiple stream tests
346                 initSoundPool(4);
347                 if (!TestPauseResume()) failures = failures + 1;
348 
349             } 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 
quit()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 
startTests()383     private void startTests() {
384         mThread = new TestThread();
385         mThread.start();
386     }
387 
onPause()388     protected void onPause()
389     {
390         Log.v(LOG_TAG, "onPause");
391         super.onPause();
392         mThread.quit();
393         mThread = null;
394     }
395 
onResume()396     protected void onResume()
397     {
398         Log.v(LOG_TAG, "onResume");
399         super.onResume();
400         startTests();
401     }
402 
onCreate(Bundle icicle)403     public void onCreate(Bundle icicle)
404     {
405         super.onCreate(icicle);
406         setVolumeControlStream(AudioManager.STREAM_MUSIC);
407     }
408 }
409 
410