/* * Copyright (c) 2009, Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.soundpooltest; import android.app.Activity; import android.widget.LinearLayout; import android.os.Bundle; import android.view.ViewGroup; import android.widget.Button; import android.view.View; import android.view.View.OnClickListener; import android.view.KeyEvent; import android.media.AudioSystem; import android.media.AudioManager; import android.media.SoundPool; import android.media.SoundPool.OnLoadCompleteListener; import android.util.Log; import java.util.HashMap; import java.lang.Math; import com.android.soundpooltest.R; public class SoundPoolTest extends Activity { private static final String LOG_TAG = "SoundPoolTest"; private static final boolean DEBUG = true; private static final boolean VERBOSE = false; private TestThread mThread; private static final int[] mTestFiles = new int[] { R.raw.organ441, R.raw.sine441, R.raw.test1, R.raw.test2, R.raw.test3, R.raw.test4, R.raw.test5 }; private final static float SEMITONE = 1.059463094f; private final static float DEFAULT_VOLUME = 0.707f; private final static float MAX_VOLUME = 1.0f; private final static float MIN_VOLUME = 0.01f; private final static int LOW_PRIORITY = 1000; private final static int NORMAL_PRIORITY = 2000; private final static int HIGH_PRIORITY = 3000; private final static int DEFAULT_LOOP = -1; private final static int DEFAULT_SRC_QUALITY = 0; private final static double PI_OVER_2 = Math.PI / 2.0; public SoundPoolTest() {} private final class TestThread extends java.lang.Thread { private boolean mRunning; private SoundPool mSoundPool = null; private int mLastSample; private int mMaxStreams; private int mLoadStatus; private int[] mSounds; private float mScale[]; TestThread() { super("SoundPool.TestThread"); } private final class LoadCompleteCallback implements android.media.SoundPool.OnLoadCompleteListener { public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { synchronized(mSoundPool) { if (DEBUG) Log.d(LOG_TAG, "Sample " + sampleId + " load status = " + status); if (status != 0) { mLoadStatus = status; } if (sampleId == mLastSample) { mSoundPool.notify(); } } } } private int loadSound(int resId, int priority) { int id = mSoundPool.load(getApplicationContext(), resId, priority); if (id == 0) { Log.e(LOG_TAG, "Unable to open resource"); } return id; } private int initSoundPool(int numStreams) throws java.lang.InterruptedException { if (mSoundPool != null) { if ((mMaxStreams == numStreams) && (mLoadStatus == 0)) return mLoadStatus; mSoundPool.release(); mSoundPool = null; } // create sound pool mLoadStatus = 0; mMaxStreams = numStreams; mSoundPool = new SoundPool(numStreams, AudioSystem.STREAM_MUSIC, 0); mSoundPool.setOnLoadCompleteListener(new LoadCompleteCallback()); int numSounds = mTestFiles.length; mSounds = new int[numSounds]; // load sounds synchronized(mSoundPool) { for (int index = 0; index < numSounds; index++) { mSounds[index] = loadSound(mTestFiles[index], NORMAL_PRIORITY); mLastSample = mSounds[index]; } mSoundPool.wait(); } return mLoadStatus; } private boolean TestSounds() throws java.lang.InterruptedException { if (DEBUG) Log.d(LOG_TAG, "Begin sounds test"); int count = mSounds.length; for (int index = 0; index < count; index++) { int id = mSoundPool.play(mSounds[index], DEFAULT_VOLUME, DEFAULT_VOLUME, NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f); if (DEBUG) Log.d(LOG_TAG, "Start note " + id); if (id == 0) { Log.e(LOG_TAG, "Error occurred starting note"); return false; } sleep(450); mSoundPool.stop(id); if (DEBUG) Log.d(LOG_TAG, "Stop note " + id); sleep(50); } if (DEBUG) Log.d(LOG_TAG, "End sounds test"); return true; } private boolean TestScales() throws java.lang.InterruptedException { if (DEBUG) Log.d(LOG_TAG, "Begin scale test"); // interate through pitch table int count = mScale.length; for (int step = 0; step < count; step++) { int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[step]); if (DEBUG) Log.d(LOG_TAG, "Start note " + id); if (id == 0) { Log.e(LOG_TAG, "Error occurred starting note"); return false; } sleep(450); mSoundPool.stop(id); if (DEBUG) Log.d(LOG_TAG, "Stop note " + id); sleep(50); } if (DEBUG) Log.d(LOG_TAG, "End scale test"); return true; } private boolean TestRates() throws java.lang.InterruptedException { if (DEBUG) Log.d(LOG_TAG, "Begin rate test"); // start the note int count = mScale.length; int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]); if (DEBUG) Log.d(LOG_TAG, "Start note " + id); if (id == 0) { Log.e(LOG_TAG, "Test failed - exiting"); return false; } // modify the pitch for (int step = 1; step < count; step++) { sleep(250); mSoundPool.setRate(id, mScale[step]); if (DEBUG) Log.d(LOG_TAG, "Change rate " + mScale[step]); } mSoundPool.stop(id); if (DEBUG) Log.d(LOG_TAG, "Stop note " + id); if (DEBUG) Log.d(LOG_TAG, "End rate test"); return true; } private boolean TestPriority() throws java.lang.InterruptedException { if (DEBUG) Log.d(LOG_TAG, "Begin priority test"); boolean result = true; // play a normal priority looping sound int normalId = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f); if (DEBUG) Log.d(LOG_TAG, "Start note " + normalId); if (normalId == 0) { Log.e(LOG_TAG, "Error occurred starting note"); return false; } sleep(1000); // play a low priority sound int id = mSoundPool.play(mSounds[1], DEFAULT_VOLUME, DEFAULT_VOLUME, LOW_PRIORITY, DEFAULT_LOOP, 1.0f); if (id != 0) { Log.e(LOG_TAG, "Normal > Low priority test failed"); result = false; mSoundPool.stop(id); } else { sleep(1000); Log.i(LOG_TAG, "Normal > Low priority test passed"); } // play a high priority sound id = mSoundPool.play(mSounds[2], DEFAULT_VOLUME, DEFAULT_VOLUME, HIGH_PRIORITY, DEFAULT_LOOP, 1.0f); if (id == 0) { Log.e(LOG_TAG, "High > Normal priority test failed"); result = false; } else { sleep(1000); Log.i(LOG_TAG, "Stopping high priority"); mSoundPool.stop(id); sleep(1000); Log.i(LOG_TAG, "High > Normal priority test passed"); } // stop normal note Log.i(LOG_TAG, "Stopping normal priority"); mSoundPool.stop(normalId); sleep(1000); if (DEBUG) Log.d(LOG_TAG, "End priority test"); return result; } private boolean TestPauseResume() throws java.lang.InterruptedException { if (DEBUG) Log.d(LOG_TAG, "Begin pause/resume test"); boolean result = true; // play a normal priority looping sound int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, NORMAL_PRIORITY, DEFAULT_LOOP, 1.0f); if (DEBUG) Log.d(LOG_TAG, "Start note " + id); if (id == 0) { Log.e(LOG_TAG, "Error occurred starting note"); return false; } sleep(2500); // pause and resume sound a few times for (int count = 0; count < 5; count++) { if (DEBUG) Log.d(LOG_TAG, "Pause note " + id); mSoundPool.pause(id); sleep(1000); if (DEBUG) Log.d(LOG_TAG, "Resume note " + id); mSoundPool.resume(id); sleep(1000); } if (DEBUG) Log.d(LOG_TAG, "Stop note " + id); mSoundPool.stop(id); sleep(1000); // play 5 sounds, forces one to be stolen int ids[] = new int[5]; for (int i = 0; i < 5; i++) { ids[i] = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[i]); if (DEBUG) Log.d(LOG_TAG, "Start note " + ids[i]); if (ids[i] == 0) { Log.e(LOG_TAG, "Error occurred starting note"); return false; } sleep(1000); } // pause and resume sound a few times for (int count = 0; count < 5; count++) { if (DEBUG) Log.d(LOG_TAG, "autoPause"); mSoundPool.autoPause(); sleep(1000); if (DEBUG) Log.d(LOG_TAG, "autoResume"); mSoundPool.autoResume(); sleep(1000); } for (int i = 0; i < 5; i++) { if (DEBUG) Log.d(LOG_TAG, "Stop note " + ids[i]); mSoundPool.stop(ids[i]); } if (DEBUG) Log.d(LOG_TAG, "End pause/resume test"); return result; } private boolean TestVolume() throws java.lang.InterruptedException { if (DEBUG) Log.d(LOG_TAG, "Begin volume test"); // start the note int id = mSoundPool.play(mSounds[0], 0.0f, 1.0f, NORMAL_PRIORITY, DEFAULT_LOOP, mScale[0]); if (DEBUG) Log.d(LOG_TAG, "Start note " + id); if (id == 0) { Log.e(LOG_TAG, "Test failed - exiting"); return false; } // pan from right to left for (int count = 0; count < 101; count++) { sleep(50); double radians = PI_OVER_2 * count / 100.0; float leftVolume = (float) Math.sin(radians); float rightVolume = (float) Math.cos(radians); mSoundPool.setVolume(id, leftVolume, rightVolume); if (DEBUG) Log.d(LOG_TAG, "Change volume (" + leftVolume + "," + rightVolume + ")"); } mSoundPool.stop(id); if (DEBUG) Log.d(LOG_TAG, "End volume test"); return true; } public void run() { if (DEBUG) Log.d(LOG_TAG, "Test thread running"); // initialize mRunning = true; int failures = 0; // initialize pitch table float pitch = 0.5f; mScale = new float[13]; for (int i = 0; i < 13; ++i) { mScale[i] = pitch; pitch *= SEMITONE; } try { // do single stream tests initSoundPool(1); if (!TestSounds()) failures = failures + 1; if (!TestScales()) failures = failures + 1; if (!TestRates()) failures = failures + 1; if (!TestPriority()) failures = failures + 1; if (!TestVolume()) failures = failures + 1; // do multiple stream tests initSoundPool(4); if (!TestPauseResume()) failures = failures + 1; } catch (java.lang.InterruptedException e) { if (DEBUG) Log.d(LOG_TAG, "Test interrupted"); failures = failures + 1; } finally { mRunning = false; } // release sound pool if (mSoundPool != null) { mSoundPool.release(); mSoundPool = null; } // output stats if (DEBUG) Log.d(LOG_TAG, "Test thread exit"); if (failures == 0) { Log.i(LOG_TAG, "All tests passed"); } else { Log.i(LOG_TAG, failures + " tests failed"); } } public void quit() { if (DEBUG) Log.d(LOG_TAG, "interrupt"); interrupt(); while (mRunning) { try { sleep(20); } catch (java.lang.InterruptedException e) { } } if (DEBUG) Log.d(LOG_TAG, "quit"); } } private void startTests() { mThread = new TestThread(); mThread.start(); } protected void onPause() { Log.v(LOG_TAG, "onPause"); super.onPause(); mThread.quit(); mThread = null; } protected void onResume() { Log.v(LOG_TAG, "onResume"); super.onResume(); startTests(); } public void onCreate(Bundle icicle) { super.onCreate(icicle); setVolumeControlStream(AudioManager.STREAM_MUSIC); } }