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 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             // 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 
    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 
    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 
    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 
    410