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.Config;
     32 import android.util.Log;
     33 import java.util.HashMap;
     34 import java.lang.Math;
     35 
     36 import com.android.soundpooltest.R;
     37 
     38 public 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 float SEMITONE = 1.059463094f;
     56     private final static float DEFAULT_VOLUME = 0.707f;
     57     private final static float MAX_VOLUME = 1.0f;
     58     private final static float MIN_VOLUME = 0.01f;
     59     private final static int LOW_PRIORITY = 1000;
     60     private final static int NORMAL_PRIORITY = 2000;
     61     private final static int HIGH_PRIORITY = 3000;
     62     private final static int DEFAULT_LOOP = -1;
     63     private final static int DEFAULT_SRC_QUALITY = 0;
     64     private final static double PI_OVER_2 = Math.PI / 2.0;
     65 
     66     public SoundPoolTest() {}
     67 
     68     private final class TestThread extends java.lang.Thread {
     69         private boolean mRunning;
     70         private SoundPool mSoundPool = null;
     71         private int mLastSample;
     72         private int mMaxStreams;
     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(int numStreams) throws java.lang.InterruptedException {
    105 
    106             if (mSoundPool != null) {
    107                 if ((mMaxStreams == numStreams) && (mLoadStatus == 0)) return mLoadStatus;
    108                 mSoundPool.release();
    109                 mSoundPool = null;
    110             }
    111 
    112             // create sound pool
    113             mLoadStatus = 0;
    114             mMaxStreams = numStreams;
    115             mSoundPool = new SoundPool(numStreams, AudioSystem.STREAM_MUSIC, 0);
    116             mSoundPool.setOnLoadCompleteListener(new LoadCompleteCallback());
    117             int numSounds = mTestFiles.length;
    118             mSounds = new int[numSounds];
    119 
    120             // load sounds
    121             synchronized(mSoundPool) {
    122                 for (int index = 0; index < numSounds; index++) {
    123                     mSounds[index] = loadSound(mTestFiles[index], NORMAL_PRIORITY);
    124                     mLastSample = mSounds[index];
    125                 }
    126                 mSoundPool.wait();
    127             }
    128             return mLoadStatus;
    129         }
    130 
    131         private boolean TestSounds() throws java.lang.InterruptedException {
    132             if (DEBUG) Log.d(LOG_TAG, "Begin sounds test");
    133             int count = mSounds.length;
    134             for (int index = 0; index < count; index++) {
    135                 int id = mSoundPool.play(mSounds[index], DEFAULT_VOLUME, DEFAULT_VOLUME,
    136                         NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f);
    137                 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
    138                 if (id == 0) {
    139                     Log.e(LOG_TAG, "Error occurred starting note");
    140                     return false;
    141                 }
    142                 sleep(450);
    143                 mSoundPool.stop(id);
    144                 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
    145                 sleep(50);
    146             }
    147             if (DEBUG) Log.d(LOG_TAG, "End scale test");
    148             return true;
    149         }
    150 
    151         private boolean TestScales() throws java.lang.InterruptedException {
    152             if (DEBUG) Log.d(LOG_TAG, "Begin scale test");
    153 
    154             // interate through pitch table
    155             int count = mScale.length;
    156             for (int step = 0; step < count; step++) {
    157                 int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
    158                         NORMAL_PRIORITY, DEFAULT_LOOP, mScale[step]);
    159                 if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
    160                 if (id == 0) {
    161                     Log.e(LOG_TAG, "Error occurred starting note");
    162                     return false;
    163                 }
    164                 sleep(450);
    165                 mSoundPool.stop(id);
    166                 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
    167                 sleep(50);
    168             }
    169             if (DEBUG) Log.d(LOG_TAG, "End sounds test");
    170             return true;
    171         }
    172 
    173         private boolean TestRates() throws java.lang.InterruptedException {
    174             if (DEBUG) Log.d(LOG_TAG, "Begin rate test");
    175 
    176             // start the note
    177             int count = mScale.length;
    178             int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
    179                     NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]);
    180             if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
    181             if (id == 0) {
    182                 Log.e(LOG_TAG, "Test failed - exiting");
    183                 return false;
    184             }
    185 
    186             // modify the pitch
    187             for (int step = 1; step < count; step++) {
    188                 sleep(250);
    189                 mSoundPool.setRate(id, mScale[step]);
    190                 if (DEBUG) Log.d(LOG_TAG, "Change rate " + mScale[step]);
    191             }
    192             mSoundPool.stop(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(250);
    210 
    211             // play a low priority sound
    212             int id = mSoundPool.play(mSounds[0], 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                 Log.e(LOG_TAG, "Normal > Low priority test passed");
    220             }
    221             sleep(250);
    222 
    223             // play a high priority sound
    224             id = mSoundPool.play(mSounds[0], 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                 Log.e(LOG_TAG, "High > Normal priority test passed");
    231             }
    232             sleep(250);
    233             mSoundPool.stop(id);
    234 
    235             // stop normal note
    236             mSoundPool.stop(normalId);
    237 
    238             if (DEBUG) Log.d(LOG_TAG, "End priority test");
    239             return result;
    240         }
    241 
    242         private boolean TestPauseResume() throws java.lang.InterruptedException {
    243             if (DEBUG) Log.d(LOG_TAG, "Begin pause/resume test");
    244             boolean result = true;
    245 
    246             // play a normal priority looping sound
    247             int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
    248                     NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f);
    249             if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
    250             if (id == 0) {
    251                 Log.e(LOG_TAG, "Error occurred starting note");
    252                 return false;
    253             }
    254             sleep(250);
    255 
    256             // pause and resume sound a few times
    257             for (int count = 0; count < 5; count++) {
    258                 mSoundPool.pause(id);
    259                 sleep(250);
    260                 mSoundPool.resume(id);
    261                 sleep(250);
    262             }
    263 
    264             mSoundPool.stop(id);
    265 
    266             // play 5 sounds, forces one to be stolen
    267             int ids[] = new int[5];
    268             for (int i = 0; i < 5; i++) {
    269                 ids[i] = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
    270                         NORMAL_PRIORITY, DEFAULT_LOOP, mScale[i]);
    271                 if (DEBUG) Log.d(LOG_TAG, "Start note " + ids[i]);
    272                 if (ids[i] == 0) {
    273                     Log.e(LOG_TAG, "Error occurred starting note");
    274                     return false;
    275                 }
    276                 sleep(250);
    277             }
    278 
    279             // pause and resume sound a few times
    280             for (int count = 0; count < 5; count++) {
    281                 mSoundPool.autoPause();
    282                 sleep(250);
    283                 mSoundPool.autoResume();
    284                 sleep(250);
    285             }
    286 
    287             for (int i = 0; i < 5; i++) {
    288                 mSoundPool.stop(ids[i]);
    289             }
    290 
    291             if (DEBUG) Log.d(LOG_TAG, "End pause/resume test");
    292             return result;
    293         }
    294 
    295         private boolean TestVolume() throws java.lang.InterruptedException {
    296             if (DEBUG) Log.d(LOG_TAG, "Begin volume test");
    297 
    298             // start the note
    299             int id = mSoundPool.play(mSounds[0], 0.0f, 1.0f, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]);
    300             if (DEBUG) Log.d(LOG_TAG, "Start note " + id);
    301             if (id == 0) {
    302                 Log.e(LOG_TAG, "Test failed - exiting");
    303                 return false;
    304             }
    305 
    306             // pan from left to right
    307             for (int count = 0; count < 101; count++) {
    308                 sleep(20);
    309                 double radians = PI_OVER_2 * count / 100.0;
    310                 float leftVolume = (float) Math.sin(radians);
    311                 float rightVolume = (float) Math.cos(radians);
    312                 mSoundPool.setVolume(id, leftVolume, rightVolume);
    313                 if (DEBUG) Log.d(LOG_TAG, "Change volume (" + leftVolume + "," + rightVolume + ")");
    314             }
    315 
    316             mSoundPool.stop(id);
    317             if (DEBUG) Log.d(LOG_TAG, "End volume test");
    318             return true;
    319         }
    320 
    321         public void run() {
    322             if (DEBUG) Log.d(LOG_TAG, "Test thread running");
    323 
    324             // initialize
    325             mRunning = true;
    326             int failures = 0;
    327 
    328             // initialize pitch table
    329             float pitch = 0.5f;
    330             mScale = new float[13];
    331             for (int i = 0; i < 13; ++i) {
    332                 mScale[i] = pitch;
    333                 pitch *= SEMITONE;
    334             }
    335 
    336             try {
    337 
    338                 // do single stream tests
    339                 initSoundPool(1);
    340                 if (!TestSounds()) failures = failures + 1;
    341                 if (!TestScales()) failures = failures + 1;
    342                 if (!TestRates()) failures = failures + 1;
    343                 if (!TestPriority()) failures = failures + 1;
    344                 if (!TestVolume()) failures = failures + 1;
    345 
    346                 // do multiple stream tests
    347                 initSoundPool(4);
    348                 if (!TestPauseResume()) failures = failures + 1;
    349 
    350             } catch (java.lang.InterruptedException e) {
    351                 if (DEBUG) Log.d(LOG_TAG, "Test interrupted");
    352                 failures = failures + 1;
    353             } finally {
    354                 mRunning = false;
    355             }
    356 
    357             // release sound pool
    358             if (mSoundPool != null) {
    359                 mSoundPool.release();
    360                 mSoundPool = null;
    361             }
    362 
    363             // output stats
    364             if (DEBUG) Log.d(LOG_TAG, "Test thread exit");
    365             if (failures == 0) {
    366                 Log.i(LOG_TAG, "All tests passed");
    367             } else {
    368                 Log.i(LOG_TAG, failures + " tests failed");
    369             }
    370         }
    371 
    372         public void quit() {
    373             if (DEBUG) Log.d(LOG_TAG, "interrupt");
    374             interrupt();
    375             while (mRunning) {
    376                 try {
    377                     sleep(20);
    378                 } catch (java.lang.InterruptedException e) { }
    379             }
    380             if (DEBUG) Log.d(LOG_TAG, "quit");
    381         }
    382     }
    383 
    384     private void startTests() {
    385         mThread = new TestThread();
    386         mThread.start();
    387     }
    388 
    389     protected void onPause()
    390     {
    391         Log.v(LOG_TAG, "onPause");
    392         super.onPause();
    393         mThread.quit();
    394         mThread = null;
    395     }
    396 
    397     protected void onResume()
    398     {
    399         Log.v(LOG_TAG, "onResume");
    400         super.onResume();
    401         startTests();
    402     }
    403 
    404     public void onCreate(Bundle icicle)
    405     {
    406         super.onCreate(icicle);
    407         setVolumeControlStream(AudioManager.STREAM_MUSIC);
    408     }
    409 }
    410 
    411