Home | History | Annotate | Download | only in android
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    395     private void startTests() {
    396         mThread = new TestThread();
    397         mThread.start();
    398     }
    399 
    400     protected void onPause()
    401     {
    402         Log.v(LOG_TAG, "onPause");
    403         super.onPause();
    404         mThread.quit();
    405         mThread = null;
    406     }
    407 
    408     protected void onResume()
    409     {
    410         Log.v(LOG_TAG, "onResume");
    411         super.onResume();
    412         startTests();
    413     }
    414 
    415     public void onCreate(Bundle icicle)
    416     {
    417         super.onCreate(icicle);
    418         setVolumeControlStream(AudioManager.STREAM_MUSIC);
    419     }
    420 }
    421 
    422