Explicitly specify API level 8, to permit same .apk be used with multiple platform versions.
In the priority test, use different samples for low and priority sounds,
so it is possible to hear the difference.
Increase sleep times to make it easier to hear.
Only use Log.e for errors.
Add more logs and sleeps.
Pan more slowly.
Fix typos in logs about the test names.
Fix typo in pan comment.
Change-Id: Iebce07ca0cf3d6fa1b04faa8577faa1c6d25f8e6
422 lines
15 KiB
Java
422 lines
15 KiB
Java
/*
|
|
* 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);
|
|
}
|
|
}
|
|
|