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