diff options
author | Eric Laurent <elaurent@google.com> | 2010-08-09 20:00:20 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-08-09 20:00:20 -0700 |
commit | f5c35c84fa629b8cda25f1861d91ec89d7a10f90 (patch) | |
tree | faeb70bed98f261101605341e27ee75811beb459 /media | |
parent | dbe57fcb497c2bcfd594f4fa003e179751bfeebd (diff) | |
parent | 18afcee767694fd1dce1a371769dc898102143ff (diff) | |
download | frameworks_base-f5c35c84fa629b8cda25f1861d91ec89d7a10f90.zip frameworks_base-f5c35c84fa629b8cda25f1861d91ec89d7a10f90.tar.gz frameworks_base-f5c35c84fa629b8cda25f1861d91ec89d7a10f90.tar.bz2 |
am 18afcee7: am 67400d49: Merge "Added tests for audio effects in MediaFrameworkTest" into gingerbread
Merge commit '18afcee767694fd1dce1a371769dc898102143ff'
* commit '18afcee767694fd1dce1a371769dc898102143ff':
Added tests for audio effects in MediaFrameworkTest
Diffstat (limited to 'media')
7 files changed, 3078 insertions, 0 deletions
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java index 3e33951..c7f461e 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java @@ -25,6 +25,11 @@ import com.android.mediaframeworktest.functional.MediaRecorderTest; import com.android.mediaframeworktest.functional.SimTonesTest; import com.android.mediaframeworktest.functional.MediaPlayerInvokeTest; import com.android.mediaframeworktest.functional.MediaAudioManagerTest; +import com.android.mediaframeworktest.functional.MediaAudioEffectTest; +import com.android.mediaframeworktest.functional.MediaBassBoostTest; +import com.android.mediaframeworktest.functional.MediaEqualizerTest; +import com.android.mediaframeworktest.functional.MediaVirtualizerTest; +import com.android.mediaframeworktest.functional.MediaVisualizerTest; import junit.framework.TestSuite; import android.test.InstrumentationTestRunner; @@ -55,6 +60,11 @@ public class MediaFrameworkTestRunner extends InstrumentationTestRunner { suite.addTestSuite(MediaMimeTest.class); suite.addTestSuite(MediaPlayerInvokeTest.class); suite.addTestSuite(MediaAudioManagerTest.class); + suite.addTestSuite(MediaAudioEffectTest.class); + suite.addTestSuite(MediaBassBoostTest.class); + suite.addTestSuite(MediaEqualizerTest.class); + suite.addTestSuite(MediaVirtualizerTest.class); + suite.addTestSuite(MediaVisualizerTest.class); return suite; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java index 9a48c92..ca6e999 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java @@ -35,6 +35,7 @@ public class MediaNames { public static final String WAV = "/sdcard/media_api/music/rings_2ch.wav"; public static final String AMR = "/sdcard/media_api/music/test_amr_ietf.amr"; public static final String OGG = "/sdcard/media_api/music/Revelation.ogg"; + public static final String SINE_200_1000 = "/sdcard/media_api/music/sine_200+1000Hz_44K_mo.wav"; public static final int MP3CBR_LENGTH = 71000; public static final int MP3VBR_LENGTH = 71000; diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java new file mode 100644 index 0000000..fd939ae --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java @@ -0,0 +1,1492 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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.mediaframeworktest.functional; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.MediaNames; +import android.content.res.AssetFileDescriptor; +import android.media.AudioEffect; +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.media.EnvironmentalReverb; +import android.media.Equalizer; +import android.media.MediaPlayer; + +import android.os.Looper; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * Junit / Instrumentation test case for the media AudioTrack api + + */ +public class MediaAudioEffectTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { + private String TAG = "MediaAudioEffectTest"; + + private AudioEffect mEffect = null; + private boolean mHasControl = false; + private boolean mIsEnabled = false; + private int mParameterChanged = -1; + private MediaPlayer mMediaPlayer = null; + private boolean mInitialized = false; + private Looper mLooper = null; + private int mError = 0; + private final Object lock = new Object(); + + public MediaAudioEffectTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + private static void assumeTrue(String message, boolean cond) { + assertTrue("(assume)"+message, cond); + } + + private void log(String testName, String message) { + Log.v(TAG, "["+testName+"] "+message); + } + + private void loge(String testName, String message) { + Log.e(TAG, "["+testName+"] "+message); + } + + //----------------------------------------------------------------- + // AUDIOEFFECT TESTS: + //---------------------------------- + + //----------------------------------------------------------------- + // 0 - static methods + //---------------------------------- + + //Test case 0.0: test queryEffects() and available effects + @LargeTest + public void test0_0QueryEffects() throws Exception { + + AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); + + assertTrue("test0_0QueryEffects: number of effects < 4: "+desc.length, (desc.length >= 4)); + + boolean hasEQ = false; + boolean hasBassBoost = false; + boolean hasVirtualizer = false; + boolean hasEnvReverb = false; + + for (int i = 0; i < desc.length; i++) { + if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) { + hasEQ = true; + } if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) { + hasBassBoost = true; + } else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) { + hasVirtualizer = true; + } + else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) { + hasEnvReverb = true; + } + } + assertTrue("test0_0QueryEffects: equalizer not found", hasEQ); + assertTrue("test0_0QueryEffects: bass boost not found", hasBassBoost); + assertTrue("test0_0QueryEffects: virtualizer not found", hasVirtualizer); + assertTrue("test0_0QueryEffects: environmental reverb not found", hasEnvReverb); + } + + //----------------------------------------------------------------- + // 1 - constructor + //---------------------------------- + + //Test case 1.0: test constructor from effect type and get effect ID + @LargeTest + public void test1_0ConstructorFromType() throws Exception { + boolean result = true; + String msg = "test1_0ConstructorFromType()"; + AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); + assertTrue(msg+": no effects found", (desc.length != 0)); + try { + AudioEffect effect = new AudioEffect(desc[0].mType, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + try { + assertTrue(msg +": invalid effect ID", (effect.getId() != 0)); + } catch (IllegalStateException e) { + msg = msg.concat(": AudioEffect not initialized"); + result = false; + } finally { + effect.release(); + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Effect not found: "+desc[0].mName); + result = false; + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + result = false; + } + assertTrue(msg, result); + } + + //Test case 1.1: test constructor from effect uuid + @LargeTest + public void test1_1ConstructorFromUuid() throws Exception { + boolean result = true; + String msg = "test1_1ConstructorFromUuid()"; + AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); + assertTrue(msg+"no effects found", (desc.length != 0)); + try { + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_NULL, + desc[0].mUuid, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + effect.release(); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Effect not found: "+desc[0].mName); + result = false; + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + result = false; + } + assertTrue(msg, result); + } + + //Test case 1.2: test constructor failure from unknown type + @LargeTest + public void test1_2ConstructorUnknownType() throws Exception { + boolean result = false; + String msg = "test1_2ConstructorUnknownType()"; + + try { + AudioEffect effect = new AudioEffect(UUID.randomUUID(), + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + msg = msg.concat(": could create random AudioEffect"); + if (effect != null) { + effect.release(); + } + } catch (IllegalArgumentException e) { + result = true; + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + } + assertTrue(msg, result); + } + + //Test case 1.3: test getEnabled() failure when called on released effect + @LargeTest + public void test1_3GetEnabledAfterRelease() throws Exception { + boolean result = false; + String msg = "test1_3GetEnabledAfterRelease()"; + + try { + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + effect.release(); + try { + effect.getEnabled(); + } catch (IllegalStateException e) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + } + assertTrue(msg, result); + } + + //Test case 1.4: test contructor on mediaPlayer audio session + @LargeTest + public void test1_4InsertOnMediaPlayer() throws Exception { + boolean result = false; + String msg = "test1_4InsertOnMediaPlayer()"; + + try { + MediaPlayer mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SHORTMP3); + + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + mp.getAudioSessionId()); + assertNotNull(msg + ": could not create AudioEffect", effect); + try { + loge(msg, ": effect.setEnabled"); + effect.setEnabled(true); + } catch (IllegalStateException e) { + msg = msg.concat(": AudioEffect not initialized"); + } + + result = true; + effect.release(); + mp.release(); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } + assertTrue(msg, result); + } + + //Test case 1.5: test auxiliary effect attachement on MediaPlayer + @LargeTest + public void test1_5AuxiliaryOnMediaPlayer() throws Exception { + boolean result = false; + String msg = "test1_5AuxiliaryOnMediaPlayer()"; + + try { + MediaPlayer mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SHORTMP3); + + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + mp.attachAuxEffect(effect.getId()); + mp.setAuxEffectSendLevel(1.0f); + result = true; + effect.release(); + mp.release(); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } + assertTrue(msg, result); + } + + //Test case 1.6: test auxiliary effect attachement failure before setDatasource + @LargeTest + public void test1_6AuxiliaryOnMediaPlayerFailure() throws Exception { + boolean result = false; + String msg = "test1_6AuxiliaryOnMediaPlayerFailure()"; + + try { + createMediaPlayerLooper(); + synchronized(lock) { + try { + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Looper creation: wait was interrupted."); + } + } + assertTrue(mInitialized); // mMediaPlayer has been initialized? + mError = 0; + + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + synchronized(lock) { + try { + mMediaPlayer.attachAuxEffect(effect.getId()); + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Attach effect: wait was interrupted."); + } + } + assertTrue(msg + ": no error on attachAuxEffect", mError != 0); + result = true; + effect.release(); + terminateMediaPlayerLooper(); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } + assertTrue(msg, result); + } + + + //Test case 1.7: test auxiliary effect attachement on AudioTrack + @LargeTest + public void test1_7AuxiliaryOnAudioTrack() throws Exception { + boolean result = false; + String msg = "test1_7AuxiliaryOnAudioTrack()"; + + try { + AudioTrack track = new AudioTrack( + AudioManager.STREAM_MUSIC, + 44100, + AudioFormat.CHANNEL_OUT_MONO, + AudioFormat.ENCODING_PCM_16BIT, + AudioTrack.getMinBufferSize(44100, + AudioFormat.CHANNEL_OUT_MONO, + AudioFormat.ENCODING_PCM_16BIT), + AudioTrack.MODE_STREAM); + assertNotNull(msg + ": could not create AudioTrack", track); + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + + track.attachAuxEffect(effect.getId()); + track.setAuxEffectSendLevel(1.0f); + result = true; + effect.release(); + track.release(); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 2 - enable/ disable + //---------------------------------- + + + //Test case 2.0: test setEnabled() and getEnabled() in valid state + @LargeTest + public void test2_0SetEnabledGetEnabled() throws Exception { + boolean result = false; + String msg = "test2_0SetEnabledGetEnabled()"; + + try { + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + try { + effect.setEnabled(true); + assertTrue(msg + ": invalid state from getEnabled", effect.getEnabled()); + effect.setEnabled(false); + assertFalse(msg + ": invalid state to getEnabled", effect.getEnabled()); + result = true; + } catch (IllegalStateException e) { + msg = msg.concat(": setEnabled() in wrong state"); + } finally { + effect.release(); + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } + assertTrue(msg, result); + } + + //Test case 2.1: test setEnabled() throws exception after release + @LargeTest + public void test2_1SetEnabledAfterRelease() throws Exception { + boolean result = false; + String msg = "test2_1SetEnabledAfterRelease()"; + + try { + AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + effect.release(); + try { + effect.setEnabled(true); + } catch (IllegalStateException e) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 3 - set parameters + //---------------------------------- + + //Test case 3.0: test setParameter(byte[], byte[]) + @LargeTest + public void test3_0SetParameterByteArrayByteArray() throws Exception { + boolean result = false; + String msg = "test3_0SetParameterByteArrayByteArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + byte[] param = intToByteArray(Equalizer.PARAM_CURRENT_PRESET); + byte[] value = shortToByteArray((short)0); + if (effect.setParameter(param, value) == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.1: test setParameter(int, int) + @LargeTest + public void test3_1SetParameterIntInt() throws Exception { + boolean result = false; + String msg = "test3_1SetParameterIntInt()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + if (effect.setParameter(EnvironmentalReverb.PARAM_DECAY_TIME, 0) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.2: test setParameter(int, short) + @LargeTest + public void test3_2SetParameterIntShort() throws Exception { + boolean result = false; + String msg = "test3_2SetParameterIntShort()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + if (effect.setParameter(Equalizer.PARAM_CURRENT_PRESET, (short)0) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.3: test setParameter(int, byte[]) + @LargeTest + public void test3_3SetParameterIntByteArray() throws Exception { + boolean result = false; + String msg = "test3_3SetParameterIntByteArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + byte[] value = shortToByteArray((short)0); + if (effect.setParameter(Equalizer.PARAM_CURRENT_PRESET, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.4: test setParameter(int[], int[]) + @LargeTest + public void test3_4SetParameterIntArrayIntArray() throws Exception { + boolean result = false; + String msg = "test3_4SetParameterIntArrayIntArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] param = new int[1]; + int[] value = new int[1]; + param[0] = EnvironmentalReverb.PARAM_DECAY_TIME; + value[0] = 0; + if (effect.setParameter(param, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.5: test setParameter(int[], short[]) + @LargeTest + public void test3_5SetParameterIntArrayShortArray() throws Exception { + boolean result = false; + String msg = "test3_5SetParameterIntArrayShortArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] param = new int[1]; + short[] value = new short[1]; + param[0] = Equalizer.PARAM_CURRENT_PRESET; + value[0] = (short)0; + if (effect.setParameter(param, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.6: test setParameter(int[], byte[]) + @LargeTest + public void test3_6SetParameterIntArrayByteArray() throws Exception { + boolean result = false; + String msg = "test3_6SetParameterIntArrayByteArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] param = new int[1]; + byte[] value = shortToByteArray((short)0); + param[0] = Equalizer.PARAM_CURRENT_PRESET; + if (effect.setParameter(param, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("setParameter() called in wrong state"); + loge(msg, "setParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 3.7: test setParameter() throws exception after release() + @LargeTest + public void test3_7SetParameterAfterRelease() throws Exception { + boolean result = false; + String msg = "test3_7SetParameterAfterRelease()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + effect.release(); + effect.setParameter(Equalizer.PARAM_CURRENT_PRESET, (short)0); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": setParameter() rejected"); + loge(msg, "setParameter() rejected"); + } catch (IllegalStateException e) { + result = true; + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 4 - get parameters + //---------------------------------- + + //Test case 4.0: test getParameter(byte[], byte[]) + @LargeTest + public void test4_0GetParameterByteArrayByteArray() throws Exception { + boolean result = false; + String msg = "test4_0GetParameterByteArrayByteArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + byte[] param = intToByteArray(Equalizer.PARAM_CURRENT_PRESET); + byte[] value = new byte[2]; + if (effect.getParameter(param, value) == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.1: test getParameter(int, int[]) + @LargeTest + public void test4_1GetParameterIntIntArray() throws Exception { + boolean result = false; + String msg = "test4_1GetParameterIntIntArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] value = new int[1]; + if (effect.getParameter(EnvironmentalReverb.PARAM_DECAY_TIME, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.2: test getParameter(int, short[]) + @LargeTest + public void test4_2GetParameterIntShortArray() throws Exception { + boolean result = false; + String msg = "test4_2GetParameterIntShortArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + short[] value = new short[1]; + if (effect.getParameter(Equalizer.PARAM_CURRENT_PRESET, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.3: test getParameter(int, byte[]) + @LargeTest + public void test4_3GetParameterIntByteArray() throws Exception { + boolean result = false; + String msg = "test4_3GetParameterIntByteArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + byte[] value = new byte[2]; + if (effect.getParameter(Equalizer.PARAM_CURRENT_PRESET, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.4: test getParameter(int[], int[]) + @LargeTest + public void test4_4GetParameterIntArrayIntArray() throws Exception { + boolean result = false; + String msg = "test4_4GetParameterIntArrayIntArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] param = new int[1]; + int[] value = new int[1]; + param[0] = EnvironmentalReverb.PARAM_DECAY_TIME; + if (effect.getParameter(param, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.5: test getParameter(int[], short[]) + @LargeTest + public void test4_5GetParameterIntArrayShortArray() throws Exception { + boolean result = false; + String msg = "test4_5GetParameterIntArrayShortArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] param = new int[1]; + short[] value = new short[1]; + param[0] = Equalizer.PARAM_CURRENT_PRESET; + if (effect.getParameter(param, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.6: test getParameter(int[], byte[]) + @LargeTest + public void test4_6GetParameterIntArrayByteArray() throws Exception { + boolean result = false; + String msg = "test4_6GetParameterIntArrayByteArray()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + int[] param = new int[1]; + byte[] value = new byte[2]; + param[0] = Equalizer.PARAM_CURRENT_PRESET; + if (effect.getParameter(param, value) + == AudioEffect.SUCCESS) { + result = true; + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("getParameter() called in wrong state"); + loge(msg, "getParameter() called in wrong state"); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //Test case 4.7: test getParameter() throws exception after release() + @LargeTest + public void test4_7GetParameterAfterRelease() throws Exception { + boolean result = false; + String msg = "test4_7GetParameterAfterRelease()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + effect.release(); + short[] value = new short[1]; + effect.getParameter(Equalizer.PARAM_CURRENT_PRESET, value); + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": getParameter() rejected"); + loge(msg, "getParameter() rejected"); + } catch (IllegalStateException e) { + result = true; + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 5 priority and listeners + //---------------------------------- + + //Test case 5.0: test control passed to higher priority client + @LargeTest + public void test5_0setEnabledLowerPriority() throws Exception { + boolean result = false; + String msg = "test5_0setEnabledLowerPriority()"; + AudioEffect effect1 = null; + AudioEffect effect2 = null; + try { + effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 1, + 0); + + assertNotNull(msg + ": could not create AudioEffect", effect1); + assertNotNull(msg + ": could not create AudioEffect", effect2); + + assertTrue(msg + ": Effect2 does not have control", effect2.hasControl()); + assertFalse(msg + ": Effect1 has control", effect1.hasControl()); + assertTrue(msg + ": Effect1 can enable", + effect1.setEnabled(true) == AudioEffect.ERROR_INVALID_OPERATION); + assertFalse(msg + ": Effect1 has enabled", effect2.getEnabled()); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Effect not found"); + result = false; + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + result = false; + } finally { + if (effect1 != null) { + effect1.release(); + } + if (effect2 != null) { + effect2.release(); + } + } + assertTrue(msg, result); + } + + //Test case 5.1: test control passed to higher priority client + @LargeTest + public void test5_1setParameterLowerPriority() throws Exception { + boolean result = false; + String msg = "test5_1setParameterLowerPriority()"; + AudioEffect effect1 = null; + AudioEffect effect2 = null; + try { + effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 1, + 0); + + assertNotNull(msg + ": could not create AudioEffect", effect1); + assertNotNull(msg + ": could not create AudioEffect", effect2); + + int status = effect2.setParameter(Equalizer.PARAM_CURRENT_PRESET, (short)0); + assertEquals(msg + ": Effect2 setParameter failed", + AudioEffect.SUCCESS, status); + + status = effect1.setParameter(Equalizer.PARAM_CURRENT_PRESET, (short)1); + assertEquals(msg + ": Effect1 setParameter did not fail", + AudioEffect.ERROR_INVALID_OPERATION, status); + + short[] value = new short[1]; + status = effect2.getParameter(Equalizer.PARAM_CURRENT_PRESET, value); + assertEquals(msg + ": Effect2 getParameter failed", + AudioEffect.SUCCESS, status); + assertEquals(msg + ": Effect1 changed parameter", + (short)0, value[0]); + + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Effect not found"); + result = false; + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + result = false; + } finally { + if (effect1 != null) { + effect1.release(); + } + if (effect2 != null) { + effect2.release(); + } + } + assertTrue(msg, result); + } + + //Test case 5.2: test control status listener + @LargeTest + public void test5_2ControlStatusListener() throws Exception { + boolean result = false; + String msg = "test5_2ControlStatusListener()"; + mEffect = null; + AudioEffect effect2 = null; + try { + mHasControl = true; + createListenerLooper(true, false, false); + synchronized(lock) { + try { + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Looper creation: wait was interrupted."); + } + } + assertTrue(mInitialized); + synchronized(lock) { + try { + effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 1, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect2); + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Create second effect: wait was interrupted."); + } + } + assertFalse(msg + ": effect control not lost by effect1", mHasControl); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } finally { + terminateListenerLooper(); + if (effect2 != null) { + effect2.release(); + } + } + assertTrue(msg, result); + } + + //Test case 5.3: test enable status listener + @LargeTest + public void test5_3EnableStatusListener() throws Exception { + boolean result = false; + String msg = "test5_3EnableStatusListener()"; + mEffect = null; + AudioEffect effect2 = null; + try { + createListenerLooper(false, true, false); + synchronized(lock) { + try { + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Looper creation: wait was interrupted."); + } + } + assertTrue(mInitialized); + mEffect.setEnabled(true); + mIsEnabled = true; + effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 1, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect2); + assertTrue(msg + ": effect not enabled", effect2.getEnabled()); + synchronized(lock) { + try { + effect2.setEnabled(false); + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Create second effect: wait was interrupted."); + } + } + assertFalse(msg + ": enable status not updated", mIsEnabled); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } finally { + terminateListenerLooper(); + if (effect2 != null) { + effect2.release(); + } + } + assertTrue(msg, result); + } + + //Test case 5.4: test parameter changed listener + @LargeTest + public void test5_4ParameterChangedListener() throws Exception { + boolean result = false; + String msg = "test5_4ParameterChangedListener()"; + mEffect = null; + AudioEffect effect2 = null; + try { + createListenerLooper(false, false, true); + synchronized(lock) { + try { + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Looper creation: wait was interrupted."); + } + } + assertTrue(mInitialized); + effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 1, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect2); + synchronized(lock) { + try { + mParameterChanged = -1; + effect2.setParameter(Equalizer.PARAM_CURRENT_PRESET, (short)0); + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Create second effect: wait was interrupted."); + } + } + assertEquals(msg + ": parameter change not received", + Equalizer.PARAM_CURRENT_PRESET, mParameterChanged); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } finally { + terminateListenerLooper(); + if (effect2 != null) { + effect2.release(); + } + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 6 command method + //---------------------------------- + + + //Test case 6.0: test command method + @LargeTest + public void test6_0Command() throws Exception { + boolean result = false; + String msg = "test6_0Command()"; + AudioEffect effect = null; + try { + effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull(msg + ": could not create AudioEffect", effect); + try { + byte[] cmd = new byte[0]; + byte[] reply = new byte[4]; + int status = effect.command(3, cmd, reply); + assertEquals(msg + ": command failed", AudioEffect.SUCCESS, status); + assertTrue(msg + ": effect not enabled", effect.getEnabled()); + result = true; + } catch (IllegalStateException e) { + msg = msg.concat(": command in illegal state"); + } + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + loge(msg, ": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + loge(msg, ": Effect library not loaded"); + } catch (Exception e){ + loge(msg, "Could not create media player:" + e); + } finally { + if (effect != null) { + effect.release(); + } + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // private methods + //---------------------------------- + + /* + * Initializes the message looper so that the MediaPlayer object can + * receive the callback messages. + */ + private void createMediaPlayerLooper() { + new Thread() { + @Override + public void run() { + // Set up a looper to be used by mMediaPlayer. + Looper.prepare(); + + // Save the looper so that we can terminate this thread + // after we are done with it. + mLooper = Looper.myLooper(); + + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { + public boolean onError(MediaPlayer player, int what, int extra) { + synchronized(lock) { + mError = what; + lock.notify(); + } + return true; + } + }); + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + public void onCompletion(MediaPlayer player) { + synchronized(lock) { + lock.notify(); + } + } + }); + synchronized(lock) { + mInitialized = true; + lock.notify(); + } + Looper.loop(); // Blocks forever until Looper.quit() is called. + } + }.start(); + } + /* + * Terminates the message looper thread. + */ + private void terminateMediaPlayerLooper() { + if (mLooper != null) { + mLooper.quit(); + mLooper = null; + } + if (mMediaPlayer != null) { + mMediaPlayer.release(); + } + } + + /* + * Initializes the message looper fro effect listener + */ + class ListenerThread extends Thread { + boolean mControl; + boolean mEnable; + boolean mParameter; + + public ListenerThread(boolean control, boolean enable, boolean parameter) { + super(); + mControl = control; + mEnable = enable; + mParameter = parameter; + } + } + private void createListenerLooper(boolean control, boolean enable, boolean parameter) { + + new ListenerThread(control, enable, parameter) { + @Override + public void run() { + // Set up a looper to be used by mEffect. + Looper.prepare(); + + // Save the looper so that we can terminate this thread + // after we are done with it. + mLooper = Looper.myLooper(); + + mEffect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, + AudioEffect.EFFECT_TYPE_NULL, + 0, + 0); + assertNotNull("could not create AudioEffect", mEffect); + + if (mControl) { + mEffect.setControlStatusListener(new AudioEffect.OnControlStatusChangeListener() { + public void onControlStatusChange(AudioEffect effect, boolean controlGranted) { + synchronized(lock) { + if (effect == mEffect) { + mHasControl = controlGranted; + lock.notify(); + } + } + } + }); + } + if (mEnable) { + mEffect.setEnableStatusListener(new AudioEffect.OnEnableStatusChangeListener() { + public void onEnableStatusChange(AudioEffect effect, boolean enabled) { + synchronized(lock) { + if (effect == mEffect) { + mIsEnabled = enabled; + lock.notify(); + } + } + } + }); + } + if (mParameter) { + mEffect.setParameterListener(new AudioEffect.OnParameterChangeListener() { + public void onParameterChange(AudioEffect effect, int status, byte[] param, + byte[] value) { + synchronized(lock) { + if (effect == mEffect) { + mParameterChanged = byteArrayToInt(param); + lock.notify(); + } + } + } + }); + } + + synchronized(lock) { + mInitialized = true; + lock.notify(); + } + Looper.loop(); // Blocks forever until Looper.quit() is called. + } + }.start(); + } + /* + * Terminates the listener looper thread. + */ + private void terminateListenerLooper() { + if (mEffect != null) { + mEffect.release(); + mEffect = null; + } + if (mLooper != null) { + mLooper.quit(); + mLooper = null; + } + } + + protected int byteArrayToInt(byte[] valueBuf) { + return byteArrayToInt(valueBuf, 0); + + } + + protected int byteArrayToInt(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getInt(offset); + + } + + protected byte[] intToByteArray(int value) { + ByteBuffer converter = ByteBuffer.allocate(4); + converter.order(ByteOrder.nativeOrder()); + converter.putInt(value); + return converter.array(); + } + + protected short byteArrayToShort(byte[] valueBuf) { + return byteArrayToShort(valueBuf, 0); + } + + protected short byteArrayToShort(byte[] valueBuf, int offset) { + ByteBuffer converter = ByteBuffer.wrap(valueBuf); + converter.order(ByteOrder.nativeOrder()); + return converter.getShort(offset); + + } + + protected byte[] shortToByteArray(short value) { + ByteBuffer converter = ByteBuffer.allocate(2); + converter.order(ByteOrder.nativeOrder()); + short sValue = (short) value; + converter.putShort(sValue); + return converter.array(); + } + +} + diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java new file mode 100644 index 0000000..8a68c5e --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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.mediaframeworktest.functional; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.MediaNames; +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.media.AudioEffect; +import android.media.AudioManager; +import android.media.BassBoost; +import android.media.Visualizer; +import android.media.MediaPlayer; + +import android.os.Looper; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * Junit / Instrumentation test case for the media AudioTrack api + + */ +public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { + private String TAG = "MediaBassBoostTest"; + private final static int MIN_ENERGY_RATIO_2 = 4; + private final static short TEST_STRENGTH = 500; + + private BassBoost mBassBoost = null; + private int mSession = -1; + + public MediaBassBoostTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + releaseBassBoost(); + } + + private static void assumeTrue(String message, boolean cond) { + assertTrue("(assume)"+message, cond); + } + + private void log(String testName, String message) { + Log.v(TAG, "["+testName+"] "+message); + } + + private void loge(String testName, String message) { + Log.e(TAG, "["+testName+"] "+message); + } + + //----------------------------------------------------------------- + // BASS BOOST TESTS: + //---------------------------------- + + + //----------------------------------------------------------------- + // 0 - constructor + //---------------------------------- + + //Test case 0.0: test constructor and release + @LargeTest + public void test0_0ConstructorAndRelease() throws Exception { + boolean result = false; + String msg = "test1_0ConstructorAndRelease()"; + BassBoost bb = null; + try { + bb = new BassBoost(0, 0); + assertNotNull(msg + ": could not create BassBoost", bb); + try { + assertTrue(msg +": invalid effect ID", (bb.getId() != 0)); + } catch (IllegalStateException e) { + msg = msg.concat(": BassBoost not initialized"); + } + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": BassBoost not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + } finally { + if (bb != null) { + bb.release(); + } + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 1 - get/set parameters + //---------------------------------- + + //Test case 1.0: test strength + @LargeTest + public void test1_0Strength() throws Exception { + boolean result = false; + String msg = "test1_0Strength()"; + getBassBoost(0); + try { + if (mBassBoost.getStrengthSupported()) { + mBassBoost.setStrength((short)TEST_STRENGTH); + short strength = mBassBoost.getRoundedStrength(); + // allow 10% difference between set strength and rounded strength + assertTrue(msg +": got incorrect strength", + ((float)strength > (float)TEST_STRENGTH * 0.9f) && + ((float)strength < (float)TEST_STRENGTH * 1.1f)); + } else { + short strength = mBassBoost.getRoundedStrength(); + assertTrue(msg +": got incorrect strength", strength >= 0 && strength <= 1000); + } + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseBassBoost(); + } + assertTrue(msg, result); + } + + //Test case 1.1: test properties + @LargeTest + public void test1_1Properties() throws Exception { + boolean result = false; + String msg = "test1_1Properties()"; + getBassBoost(0); + try { + BassBoost.Settings settings = mBassBoost.getProperties(); + String str = settings.toString(); + settings = new BassBoost.Settings(str); + mBassBoost.setProperties(settings); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseBassBoost(); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 2 - Effect action + //---------------------------------- + + //Test case 2.0: test actual bass boost influence on sound + @LargeTest + public void test2_0SoundModification() throws Exception { + boolean result = false; + String msg = "test2_0SoundModification()"; + EnergyProbe probe = null; + AudioEffect vc = null; + MediaPlayer mp = null; + AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); + int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + am.setStreamVolume(AudioManager.STREAM_MUSIC, + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), + 0); + + try { + probe = new EnergyProbe(0); + // creating a volume controller on output mix ensures that ro.audio.silent mutes + // audio after the effects and not before + vc = new AudioEffect( + AudioEffect.EFFECT_TYPE_NULL, + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), + 0, + 0); + vc.setEnabled(true); + + mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SINE_200_1000); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + getBassBoost(mp.getAudioSessionId()); + mp.prepare(); + mp.start(); + Thread.sleep(200); + // measure reference energy around 1kHz + int refEnergy200 = probe.capture(200); + int refEnergy1000 = probe.capture(1000); + mBassBoost.setStrength((short)1000); + mBassBoost.setEnabled(true); + Thread.sleep(500); + // measure energy around 1kHz with band level at min + int energy200 = probe.capture(200); + int energy1000 = probe.capture(1000); + // verify that the energy ration between low and high frequencies is at least + // MIN_ENERGY_RATIO_2 times higher with bassboost on. + assertTrue(msg + ": bass boost has no effect", + ((float)energy200/(float)energy1000) > + (MIN_ENERGY_RATIO_2 * ((float)refEnergy200/(float)refEnergy1000))); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } catch (InterruptedException e) { + loge(msg, "sleep() interrupted"); + } + finally { + releaseBassBoost(); + if (mp != null) { + mp.release(); + } + if (vc != null) { + vc.release(); + } + if (probe != null) { + probe.release(); + } + am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } + assertTrue(msg, result); + } + //----------------------------------------------------------------- + // private methods + //---------------------------------- + + private class EnergyProbe { + Visualizer mVisualizer = null; + private byte[] mFft = new byte[1024]; + + public EnergyProbe(int session) { + mVisualizer = new Visualizer(session); + mVisualizer.setCaptureSize(1024); + } + + public int capture(int freq) throws InterruptedException { + int energy = 0; + int count = 0; + if (mVisualizer != null) { + mVisualizer.setEnabled(true); + for (int i = 0; i < 10; i++) { + if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) { + // TODO: check speex FFT as it seems to return only the number of points + // correspondong to valid part of the spectrum (< Fs). + // e.g., if the number of points is 1024, it covers the frequency range + // 0 to 22050 instead of 0 to 44100 as expected from an FFT. + int bin = freq / (22050 / 1024); + int tmp = 0; + for (int j = bin-2; j < bin+3; j++) { + tmp += (int)mFft[j] * (int)mFft[j]; + } + energy += tmp/5; + count++; + } + Thread.sleep(50); + } + mVisualizer.setEnabled(false); + } + if (count == 0) { + return 0; + } + return energy/count; + } + + public void release() { + if (mVisualizer != null) { + mVisualizer.release(); + mVisualizer = null; + } + } + } + + private void getBassBoost(int session) { + if (mBassBoost == null || session != mSession) { + if (session != mSession && mBassBoost != null) { + mBassBoost.release(); + mBassBoost = null; + } + try { + mBassBoost = new BassBoost(0, session); + mSession = session; + } catch (IllegalArgumentException e) { + Log.e(TAG, "getBassBoost() BassBoost not found exception: "+e); + } catch (UnsupportedOperationException e) { + Log.e(TAG, "getBassBoost() Effect library not loaded exception: "+e); + } + } + assertNotNull("could not create mBassBoost", mBassBoost); + } + + private void releaseBassBoost() { + if (mBassBoost != null) { + mBassBoost.release(); + mBassBoost = null; + } + } + +} + diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java new file mode 100644 index 0000000..e46887b --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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.mediaframeworktest.functional; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.MediaNames; +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.media.AudioEffect; +import android.media.AudioManager; +import android.media.Equalizer; +import android.media.Visualizer; +import android.media.MediaPlayer; + +import android.os.Looper; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * Junit / Instrumentation test case for the media AudioTrack api + + */ +public class MediaEqualizerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { + private String TAG = "MediaEqualizerTest"; + private final static int MIN_NUMBER_OF_BANDS = 4; + private final static int MIN_BAND_LEVEL = -1500; + private final static int MAX_BAND_LEVEL = 1500; + private final static int TEST_FREQUENCY_MILLIHERTZ = 1000000; + private final static int MIN_NUMBER_OF_PRESETS = 4; + private Equalizer mEqualizer = null; + private int mSession = -1; + + public MediaEqualizerTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + releaseEqualizer(); + } + + private static void assumeTrue(String message, boolean cond) { + assertTrue("(assume)"+message, cond); + } + + private void log(String testName, String message) { + Log.v(TAG, "["+testName+"] "+message); + } + + private void loge(String testName, String message) { + Log.e(TAG, "["+testName+"] "+message); + } + + //----------------------------------------------------------------- + // EQUALIZER TESTS: + //---------------------------------- + + + //----------------------------------------------------------------- + // 0 - constructor + //---------------------------------- + + //Test case 0.0: test constructor and release + @LargeTest + public void test0_0ConstructorAndRelease() throws Exception { + boolean result = false; + String msg = "test1_0ConstructorAndRelease()"; + Equalizer eq = null; + try { + eq = new Equalizer(0, 0); + assertNotNull(msg + ": could not create Equalizer", eq); + try { + assertTrue(msg +": invalid effect ID", (eq.getId() != 0)); + } catch (IllegalStateException e) { + msg = msg.concat(": Equalizer not initialized"); + } + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Equalizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + } finally { + if (eq != null) { + eq.release(); + } + } + assertTrue(msg, result); + } + + + //----------------------------------------------------------------- + // 1 - get/set parameters + //---------------------------------- + + //Test case 1.0: test setBandLevel() and getBandLevel() + @LargeTest + public void test1_0BandLevel() throws Exception { + boolean result = false; + String msg = "test1_0BandLevel()"; + getEqualizer(0); + try { + short numBands = mEqualizer.getNumberOfBands(); + assertTrue(msg + ": not enough bands", numBands >= MIN_NUMBER_OF_BANDS); + + short[] levelRange = mEqualizer.getBandLevelRange(); + assertTrue(msg + ": min level too high", levelRange[0] <= MIN_BAND_LEVEL); + assertTrue(msg + ": max level too low", levelRange[1] >= MAX_BAND_LEVEL); + + mEqualizer.setBandLevel((short)0, levelRange[1]); + short level = mEqualizer.getBandLevel((short)0); + // 10% margin on actual level compared to requested level + assertTrue(msg + ": setBandLevel failed", + ((float)level > (float)levelRange[1] * 0.9f) && + ((float)level < (float)levelRange[1] * 1.1f)); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseEqualizer(); + } + assertTrue(msg, result); + } + + //Test case 1.1: test band frequency + @LargeTest + public void test1_1BandFrequency() throws Exception { + boolean result = false; + String msg = "test1_1BandFrequency()"; + getEqualizer(0); + try { + short band = mEqualizer.getBand(TEST_FREQUENCY_MILLIHERTZ); + assertTrue(msg + ": getBand failed", band >= 0); + int[] freqRange = mEqualizer.getBandFreqRange(band); + assertTrue(msg + ": getBandFreqRange failed", + (freqRange[0] <= TEST_FREQUENCY_MILLIHERTZ) && + (freqRange[1] >= TEST_FREQUENCY_MILLIHERTZ)); + int freq = mEqualizer.getCenterFreq(band); + assertTrue(msg + ": getCenterFreq failed", + (freqRange[0] <= freq) && (freqRange[1] >= freq)); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseEqualizer(); + } + assertTrue(msg, result); + } + + //Test case 1.2: test presets + @LargeTest + public void test1_2Presets() throws Exception { + boolean result = false; + String msg = "test1_2Presets()"; + getEqualizer(0); + try { + short numPresets = mEqualizer.getNumberOfPresets(); + assertTrue(msg + ": getNumberOfPresets failed", numPresets >= MIN_NUMBER_OF_PRESETS); + mEqualizer.usePreset((short)(numPresets - 1)); + short preset = mEqualizer.getCurrentPreset(); + assertEquals(msg + ": usePreset failed", preset, (short)(numPresets - 1)); + String name = mEqualizer.getPresetName(preset); + assertNotNull(msg + ": getPresetName failed", name); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseEqualizer(); + } + assertTrue(msg, result); + } + + //Test case 1.3: test properties + @LargeTest + public void test1_3Properties() throws Exception { + boolean result = false; + String msg = "test1_3Properties()"; + getEqualizer(0); + try { + Equalizer.Settings settings = mEqualizer.getProperties(); + String str = settings.toString(); + settings = new Equalizer.Settings(str); + mEqualizer.setProperties(settings); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseEqualizer(); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 2 - Effect action + //---------------------------------- + + //Test case 2.0: test that the equalizer actually alters the sound + @LargeTest + public void test2_0SoundModification() throws Exception { + boolean result = false; + String msg = "test2_0SoundModification()"; + EnergyProbe probe = null; + AudioEffect vc = null; + MediaPlayer mp = null; + AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); + int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + am.setStreamVolume(AudioManager.STREAM_MUSIC, + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), + 0); + try { + probe = new EnergyProbe(0); + // creating a volume controller on output mix ensures that ro.audio.silent mutes + // audio after the effects and not before + vc = new AudioEffect( + AudioEffect.EFFECT_TYPE_NULL, + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), + 0, + 0); + vc.setEnabled(true); + + mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SINE_200_1000); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + getEqualizer(mp.getAudioSessionId()); + mp.prepare(); + mp.start(); + Thread.sleep(500); + // measure reference energy around 1kHz + int refEnergy = probe.capture(1000); + short band = mEqualizer.getBand(1000000); + short[] levelRange = mEqualizer.getBandLevelRange(); + mEqualizer.setBandLevel(band, levelRange[0]); + mEqualizer.setEnabled(true); + Thread.sleep(500); + // measure energy around 1kHz with band level at min + int energy = probe.capture(1000); + assertTrue(msg + ": equalizer has no effect at 1kHz", energy < refEnergy/4); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } catch (InterruptedException e) { + loge(msg, "sleep() interrupted"); + } + finally { + releaseEqualizer(); + if (mp != null) { + mp.release(); + } + if (vc != null) { + vc.release(); + } + if (probe != null) { + probe.release(); + } + am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // private methods + //---------------------------------- + + private class EnergyProbe { + Visualizer mVisualizer = null; + private byte[] mFft = new byte[1024]; + + public EnergyProbe(int session) { + mVisualizer = new Visualizer(session); + mVisualizer.setCaptureSize(1024); + } + + public int capture(int freq) throws InterruptedException { + int energy = 0; + int count = 0; + if (mVisualizer != null) { + mVisualizer.setEnabled(true); + for (int i = 0; i < 10; i++) { + if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) { + // TODO: check speex FFT as it seems to return only the number of points + // correspondong to valid part of the spectrum (< Fs). + // e.g., if the number of points is 1024, it covers the frequency range + // 0 to 22050 instead of 0 to 44100 as expected from an FFT. + int bin = freq / (22050 / 1024); + int tmp = 0; + for (int j = bin-2; j < bin+3; j++) { + tmp += (int)mFft[j] * (int)mFft[j]; + } + energy += tmp/5; + count++; + } + Thread.sleep(50); + } + mVisualizer.setEnabled(false); + } + if (count == 0) { + return 0; + } + return energy/count; + } + + public void release() { + if (mVisualizer != null) { + mVisualizer.release(); + mVisualizer = null; + } + } + } + + private void getEqualizer(int session) { + if (mEqualizer == null || session != mSession) { + if (session != mSession && mEqualizer != null) { + mEqualizer.release(); + mEqualizer = null; + } + try { + mEqualizer = new Equalizer(0, session); + mSession = session; + } catch (IllegalArgumentException e) { + Log.e(TAG, "getEqualizer() Equalizer not found exception: "+e); + } catch (UnsupportedOperationException e) { + Log.e(TAG, "getEqualizer() Effect library not loaded exception: "+e); + } + } + assertNotNull("could not create mEqualizer", mEqualizer); + } + + private void releaseEqualizer() { + if (mEqualizer != null) { + mEqualizer.release(); + mEqualizer = null; + } + } + +} + diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java new file mode 100644 index 0000000..6b8ae44 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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.mediaframeworktest.functional; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.MediaNames; +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.media.AudioEffect; +import android.media.AudioManager; +import android.media.Virtualizer; +import android.media.Visualizer; +import android.media.MediaPlayer; + +import android.os.Looper; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * Junit / Instrumentation test case for the media AudioTrack api + + */ +public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { + private String TAG = "MediaVirtualizerTest"; + private final static int MIN_ENERGY_RATIO_2 = 4; + private final static short TEST_STRENGTH = 500; + + private Virtualizer mVirtualizer = null; + private int mSession = -1; + + public MediaVirtualizerTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + releaseVirtualizer(); + } + + private static void assumeTrue(String message, boolean cond) { + assertTrue("(assume)"+message, cond); + } + + private void log(String testName, String message) { + Log.v(TAG, "["+testName+"] "+message); + } + + private void loge(String testName, String message) { + Log.e(TAG, "["+testName+"] "+message); + } + + //----------------------------------------------------------------- + // VIRTUALIZER TESTS: + //---------------------------------- + + + //----------------------------------------------------------------- + // 0 - constructor + //---------------------------------- + + //Test case 0.0: test constructor and release + @LargeTest + public void test0_0ConstructorAndRelease() throws Exception { + boolean result = false; + String msg = "test1_0ConstructorAndRelease()"; + Virtualizer virtualizer = null; + try { + virtualizer = new Virtualizer(0, 0); + assertNotNull(msg + ": could not create Virtualizer", virtualizer); + try { + assertTrue(msg +": invalid effect ID", (virtualizer.getId() != 0)); + } catch (IllegalStateException e) { + msg = msg.concat(": Virtualizer not initialized"); + } + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Virtualizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + } finally { + if (virtualizer != null) { + virtualizer.release(); + } + } + assertTrue(msg, result); + } + + + //----------------------------------------------------------------- + // 1 - get/set parameters + //---------------------------------- + + //Test case 1.0: test strength + @LargeTest + public void test1_0Strength() throws Exception { + boolean result = false; + String msg = "test1_0Strength()"; + getVirtualizer(0); + try { + if (mVirtualizer.getStrengthSupported()) { + mVirtualizer.setStrength((short)TEST_STRENGTH); + short strength = mVirtualizer.getRoundedStrength(); + // allow 10% difference between set strength and rounded strength + assertTrue(msg +": got incorrect strength", + ((float)strength > (float)TEST_STRENGTH * 0.9f) && + ((float)strength < (float)TEST_STRENGTH * 1.1f)); + } else { + short strength = mVirtualizer.getRoundedStrength(); + assertTrue(msg +": got incorrect strength", strength >= 0 && strength <= 1000); + } + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseVirtualizer(); + } + assertTrue(msg, result); + } + + //Test case 1.1: test properties + @LargeTest + public void test1_1Properties() throws Exception { + boolean result = false; + String msg = "test1_1Properties()"; + getVirtualizer(0); + try { + Virtualizer.Settings settings = mVirtualizer.getProperties(); + String str = settings.toString(); + settings = new Virtualizer.Settings(str); + mVirtualizer.setProperties(settings); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseVirtualizer(); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 2 - Effect action + //---------------------------------- + + //Test case 2.0: test actual virtualizer influence on sound + @LargeTest + public void test2_0SoundModification() throws Exception { + boolean result = false; + String msg = "test2_0SoundModification()"; + EnergyProbe probe = null; + AudioEffect vc = null; + MediaPlayer mp = null; + AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); + int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + am.setStreamVolume(AudioManager.STREAM_MUSIC, + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), + 0); + + try { + probe = new EnergyProbe(0); + // creating a volume controller on output mix ensures that ro.audio.silent mutes + // audio after the effects and not before + vc = new AudioEffect( + AudioEffect.EFFECT_TYPE_NULL, + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), + 0, + 0); + vc.setEnabled(true); + + mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SINE_200_1000); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + getVirtualizer(mp.getAudioSessionId()); + mp.prepare(); + mp.start(); + Thread.sleep(200); + // measure reference energy around 1kHz + int refEnergy200 = probe.capture(200); + int refEnergy1000 = probe.capture(1000); + mVirtualizer.setStrength((short)1000); + mVirtualizer.setEnabled(true); + Thread.sleep(500); + // measure energy around 1kHz with band level at min + int energy200 = probe.capture(200); + int energy1000 = probe.capture(1000); + // verify that the energy ration between low and high frequencies is at least + // four times higher with virtualizer on. + // NOTE: this is what is observed with current virtualizer implementation and the test + // audio file but is not the primary effect of the virtualizer. A better way would + // be to have a stereo PCM capture and check that a strongly paned input is centered + // when output. However, we cannot capture stereo with the visualizer. + assertTrue(msg + ": virtiualizer has no effect", + ((float)energy200/(float)energy1000) > + (MIN_ENERGY_RATIO_2 * ((float)refEnergy200/(float)refEnergy1000))); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } catch (InterruptedException e) { + loge(msg, "sleep() interrupted"); + } + finally { + releaseVirtualizer(); + if (mp != null) { + mp.release(); + } + if (vc != null) { + vc.release(); + } + if (probe != null) { + probe.release(); + } + am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } + assertTrue(msg, result); + } + //----------------------------------------------------------------- + // private methods + //---------------------------------- + + private class EnergyProbe { + Visualizer mVisualizer = null; + private byte[] mFft = new byte[1024]; + + public EnergyProbe(int session) { + mVisualizer = new Visualizer(session); + mVisualizer.setCaptureSize(1024); + } + + public int capture(int freq) throws InterruptedException { + int energy = 0; + int count = 0; + if (mVisualizer != null) { + mVisualizer.setEnabled(true); + for (int i = 0; i < 10; i++) { + if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) { + // TODO: check speex FFT as it seems to return only the number of points + // correspondong to valid part of the spectrum (< Fs). + // e.g., if the number of points is 1024, it covers the frequency range + // 0 to 22050 instead of 0 to 44100 as expected from an FFT. + int bin = freq / (22050 / 1024); + int tmp = 0; + for (int j = bin-2; j < bin+3; j++) { + tmp += (int)mFft[j] * (int)mFft[j]; + } + energy += tmp/5; + count++; + } + Thread.sleep(50); + } + mVisualizer.setEnabled(false); + } + if (count == 0) { + return 0; + } + return energy/count; + } + + public void release() { + if (mVisualizer != null) { + mVisualizer.release(); + mVisualizer = null; + } + } + } + + private void getVirtualizer(int session) { + if (mVirtualizer == null || session != mSession) { + if (session != mSession && mVirtualizer != null) { + mVirtualizer.release(); + mVirtualizer = null; + } + try { + mVirtualizer = new Virtualizer(0, session); + mSession = session; + } catch (IllegalArgumentException e) { + Log.e(TAG, "getVirtualizer() Virtualizer not found exception: "+e); + } catch (UnsupportedOperationException e) { + Log.e(TAG, "getVirtualizer() Effect library not loaded exception: "+e); + } + } + assertNotNull("could not create mVirtualizer", mVirtualizer); + } + + private void releaseVirtualizer() { + if (mVirtualizer != null) { + mVirtualizer.release(); + mVirtualizer = null; + } + } + +} + diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java new file mode 100644 index 0000000..26fdbfe --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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.mediaframeworktest.functional; + +import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.MediaNames; +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.media.AudioEffect; +import android.media.AudioManager; +import android.media.Visualizer; +import android.media.MediaPlayer; + +import android.os.Looper; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.Suppress; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * Junit / Instrumentation test case for the media AudioTrack api + + */ +public class MediaVisualizerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { + private String TAG = "MediaVisualizerTest"; + private final static int MIN_CAPTURE_RATE_MAX = 20000; + private final static int MIN_SAMPLING_RATE = 8000000; + private final static int MAX_SAMPLING_RATE = 48000000; + private final static int MIN_CAPTURE_SIZE_MAX = 1024; + private final static int MAX_CAPTURE_SIZE_MIN = 128; + + private Visualizer mVisualizer = null; + private int mSession = -1; + private boolean mInitialized = false; + private Looper mLooper = null; + private final Object lock = new Object(); + private byte[] mWaveform = null; + private byte[] mFft = null; + private boolean mCaptureWaveform = false; + private boolean mCaptureFft = false; + + public MediaVisualizerTest() { + super("com.android.mediaframeworktest", MediaFrameworkTest.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + releaseVisualizer(); + } + + private static void assumeTrue(String message, boolean cond) { + assertTrue("(assume)"+message, cond); + } + + private void log(String testName, String message) { + Log.v(TAG, "["+testName+"] "+message); + } + + private void loge(String testName, String message) { + Log.e(TAG, "["+testName+"] "+message); + } + + //----------------------------------------------------------------- + // VISUALIZER TESTS: + //---------------------------------- + + + //----------------------------------------------------------------- + // 0 - constructor + //---------------------------------- + + //Test case 0.0: test constructor and release + @LargeTest + public void test0_0ConstructorAndRelease() throws Exception { + boolean result = false; + String msg = "test1_0ConstructorAndRelease()"; + Visualizer visualizer = null; + try { + visualizer = new Visualizer(0); + assertNotNull(msg + ": could not create Visualizer", visualizer); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Visualizer not found"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": Effect library not loaded"); + } finally { + if (visualizer != null) { + visualizer.release(); + } + } + assertTrue(msg, result); + } + + + //----------------------------------------------------------------- + // 1 - get/set parameters + //---------------------------------- + + //Test case 1.0: check capture rate and sampling rate + @LargeTest + public void test1_0CaptureRates() throws Exception { + boolean result = false; + String msg = "test1_0CaptureRates()"; + getVisualizer(0); + try { + int captureRate = mVisualizer.getMaxCaptureRate(); + assertTrue(msg +": insufficient max capture rate", + captureRate >= MIN_CAPTURE_RATE_MAX); + int samplingRate = mVisualizer.getSamplingRate(); + assertTrue(msg +": invalid sampling rate", + samplingRate >= MIN_SAMPLING_RATE && samplingRate <= MAX_SAMPLING_RATE); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseVisualizer(); + } + assertTrue(msg, result); + } + + //Test case 1.1: check capture size + @LargeTest + public void test1_1CaptureSize() throws Exception { + boolean result = false; + String msg = "test1_1CaptureSize()"; + getVisualizer(0); + try { + int[] range = mVisualizer.getCaptureSizeRange(); + assertTrue(msg +": insufficient min capture size", + range[0] <= MAX_CAPTURE_SIZE_MIN); + assertTrue(msg +": insufficient min capture size", + range[1] >= MIN_CAPTURE_SIZE_MAX); + mVisualizer.setCaptureSize(range[0]); + assertEquals(msg +": insufficient min capture size", + range[0], mVisualizer.getCaptureSize()); + mVisualizer.setCaptureSize(range[1]); + assertEquals(msg +": insufficient min capture size", + range[1], mVisualizer.getCaptureSize()); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } finally { + releaseVisualizer(); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // 2 - check capture + //---------------------------------- + + //Test case 2.0: test capture in polling mode + @LargeTest + public void test2_0PollingCapture() throws Exception { + boolean result = false; + String msg = "test2_0PollingCapture()"; + AudioEffect vc = null; + MediaPlayer mp = null; + AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); + int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + am.setStreamVolume(AudioManager.STREAM_MUSIC, + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), + 0); + + try { + // creating a volume controller on output mix ensures that ro.audio.silent mutes + // audio after the effects and not before + vc = new AudioEffect( + AudioEffect.EFFECT_TYPE_NULL, + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), + 0, + 0); + vc.setEnabled(true); + + mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SINE_200_1000); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + getVisualizer(mp.getAudioSessionId()); + mVisualizer.setEnabled(true); + // check capture on silence + byte[] data = new byte[mVisualizer.getCaptureSize()]; + mVisualizer.getWaveForm(data); + int energy = computeEnergy(data, true); + assertEquals(msg +": getWaveForm reports energy for silence", + 0, energy); + mVisualizer.getFft(data); + energy = computeEnergy(data, false); + assertEquals(msg +": getFft reports energy for silence", + 0, energy); + mp.prepare(); + mp.start(); + Thread.sleep(500); + // check capture on sound + mVisualizer.getWaveForm(data); + energy = computeEnergy(data, true); + assertTrue(msg +": getWaveForm reads insufficient level", + energy > 0); + mVisualizer.getFft(data); + energy = computeEnergy(data, false); + assertTrue(msg +": getFft reads insufficient level", + energy > 0); + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } catch (InterruptedException e) { + loge(msg, "sleep() interrupted"); + } + finally { + releaseVisualizer(); + if (mp != null) { + mp.release(); + } + if (vc != null) { + vc.release(); + } + am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } + assertTrue(msg, result); + } + + //Test case 2.1: test capture with listener + @LargeTest + public void test2_1ListenerCapture() throws Exception { + boolean result = false; + String msg = "test2_1ListenerCapture()"; + AudioEffect vc = null; + MediaPlayer mp = null; + AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE); + int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + am.setStreamVolume(AudioManager.STREAM_MUSIC, + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), + 0); + + try { + // creating a volume controller on output mix ensures that ro.audio.silent mutes + // audio after the effects and not before + vc = new AudioEffect( + AudioEffect.EFFECT_TYPE_NULL, + UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"), + 0, + 0); + vc.setEnabled(true); + + mp = new MediaPlayer(); + mp.setDataSource(MediaNames.SINE_200_1000); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + + getVisualizer(mp.getAudioSessionId()); + createListenerLooper(); + synchronized(lock) { + try { + lock.wait(1000); + } catch(Exception e) { + Log.e(TAG, "Looper creation: wait was interrupted."); + } + } + assertTrue(mInitialized); + + mVisualizer.setEnabled(true); + + // check capture on silence + synchronized(lock) { + try { + mCaptureWaveform = true; + lock.wait(1000); + mCaptureWaveform = false; + } catch(Exception e) { + Log.e(TAG, "Capture waveform: wait was interrupted."); + } + } + assertNotNull(msg +": waveform capture failed", mWaveform); + int energy = computeEnergy(mWaveform, true); + assertEquals(msg +": getWaveForm reports energy for silence", + 0, energy); + + synchronized(lock) { + try { + mCaptureFft = true; + lock.wait(1000); + mCaptureFft = false; + } catch(Exception e) { + Log.e(TAG, "Capture FFT: wait was interrupted."); + } + } + assertNotNull(msg +": FFT capture failed", mFft); + energy = computeEnergy(mFft, false); + assertEquals(msg +": getFft reports energy for silence", + 0, energy); + + mp.prepare(); + mp.start(); + Thread.sleep(500); + + // check capture on sound + synchronized(lock) { + try { + mCaptureWaveform = true; + lock.wait(1000); + mCaptureWaveform = false; + } catch(Exception e) { + Log.e(TAG, "Capture waveform: wait was interrupted."); + } + } + assertNotNull(msg +": waveform capture failed", mWaveform); + energy = computeEnergy(mWaveform, true); + assertTrue(msg +": getWaveForm reads insufficient level", + energy > 0); + + synchronized(lock) { + try { + mCaptureFft = true; + lock.wait(1000); + mCaptureFft = false; + } catch(Exception e) { + Log.e(TAG, "Capture FFT: wait was interrupted."); + } + } + assertNotNull(msg +": FFT capture failed", mFft); + energy = computeEnergy(mFft, false); + assertTrue(msg +": getFft reads insufficient level", + energy > 0); + + result = true; + } catch (IllegalArgumentException e) { + msg = msg.concat(": Bad parameter value"); + loge(msg, "Bad parameter value"); + } catch (UnsupportedOperationException e) { + msg = msg.concat(": get parameter() rejected"); + loge(msg, "get parameter() rejected"); + } catch (IllegalStateException e) { + msg = msg.concat("get parameter() called in wrong state"); + loge(msg, "get parameter() called in wrong state"); + } catch (InterruptedException e) { + loge(msg, "sleep() interrupted"); + } + finally { + terminateListenerLooper(); + releaseVisualizer(); + if (mp != null) { + mp.release(); + } + if (vc != null) { + vc.release(); + } + am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } + assertTrue(msg, result); + } + + //----------------------------------------------------------------- + // private methods + //---------------------------------- + + private int computeEnergy(byte[] data, boolean unsigned) { + int energy = 0; + if (data.length != 0) { + for (int i = 0; i < data.length; i++) { + int tmp; + // convert from unsigned 8 bit to signed 16 bit + if (unsigned) { + tmp = ((int)data[i] & 0xFF) - 128; + } else { + tmp = (int)data[i]; + } + energy += tmp*tmp; + } + energy /= data.length; + } + return energy; + } + + private void getVisualizer(int session) { + if (mVisualizer == null || session != mSession) { + if (session != mSession && mVisualizer != null) { + mVisualizer.release(); + mVisualizer = null; + } + try { + mVisualizer = new Visualizer(session); + mSession = session; + } catch (IllegalArgumentException e) { + Log.e(TAG, "getVisualizer() Visualizer not found exception: "+e); + } catch (UnsupportedOperationException e) { + Log.e(TAG, "getVisualizer() Effect library not loaded exception: "+e); + } + } + assertNotNull("could not create mVisualizer", mVisualizer); + } + + private void releaseVisualizer() { + if (mVisualizer != null) { + mVisualizer.release(); + mVisualizer = null; + } + } + + private void createListenerLooper() { + + new Thread() { + @Override + public void run() { + // Set up a looper to be used by mEffect. + Looper.prepare(); + + // Save the looper so that we can terminate this thread + // after we are done with it. + mLooper = Looper.myLooper(); + + if (mVisualizer != null) { + mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() { + public void onWaveFormDataCapture( + Visualizer visualizer, byte[] waveform, int samplingRate) { + synchronized(lock) { + if (visualizer == mVisualizer) { + if (mCaptureWaveform) { + mWaveform = waveform; + lock.notify(); + } + } + } + } + + public void onFftDataCapture( + Visualizer visualizer, byte[] fft, int samplingRate) { + synchronized(lock) { + if (visualizer == mVisualizer) { + if (mCaptureFft) { + mFft = fft; + lock.notify(); + } + } + } + } + }, + 10000, + true, + true); + } + + synchronized(lock) { + mInitialized = true; + lock.notify(); + } + Looper.loop(); // Blocks forever until Looper.quit() is called. + } + }.start(); + } + /* + * Terminates the listener looper thread. + */ + private void terminateListenerLooper() { + if (mLooper != null) { + mLooper.quit(); + mLooper = null; + } + } + +} + |