MediaPresetReverbTest.java revision c81e0ad9bd438575389623f523a28e2e6ca69236
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mediaframeworktest.functional.audio;
18
19import com.android.mediaframeworktest.MediaFrameworkTest;
20import com.android.mediaframeworktest.MediaNames;
21import com.android.mediaframeworktest.functional.EnergyProbe;
22import android.content.Context;
23import android.content.res.AssetFileDescriptor;
24import android.media.audiofx.AudioEffect;
25import android.media.AudioManager;
26import android.media.audiofx.PresetReverb;
27import android.media.audiofx.Visualizer;
28import android.media.MediaPlayer;
29
30import android.os.Looper;
31import android.test.suitebuilder.annotation.LargeTest;
32import android.test.suitebuilder.annotation.MediumTest;
33import android.test.suitebuilder.annotation.Suppress;
34import android.test.ActivityInstrumentationTestCase2;
35import android.util.Log;
36
37import java.nio.ByteOrder;
38import java.nio.ByteBuffer;
39import java.util.UUID;
40
41/**
42 * Junit / Instrumentation test case for the media AudioTrack api
43
44 */
45public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
46    private String TAG = "MediaPresetReverbTest";
47    // Implementor UUID for volume controller effect defined in
48    // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
49    private final static UUID VOLUME_EFFECT_UUID =
50        UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b");
51    // Implementor UUID for preset reverb effect defined in
52    // frameworks/base/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
53    private final static UUID PRESET_REVERB_EFFECT_UUID =
54        UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b");
55
56    private PresetReverb mReverb = null;
57    private int mSession = -1;
58
59    public MediaPresetReverbTest() {
60        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
61    }
62
63    @Override
64    protected void setUp() throws Exception {
65      super.setUp();
66    }
67
68    @Override
69    protected void tearDown() throws Exception {
70        super.tearDown();
71        releaseReverb();
72    }
73
74    private static void assumeTrue(String message, boolean cond) {
75        assertTrue("(assume)"+message, cond);
76    }
77
78    private void log(String testName, String message) {
79        Log.v(TAG, "["+testName+"] "+message);
80    }
81
82    private void loge(String testName, String message) {
83        Log.e(TAG, "["+testName+"] "+message);
84    }
85
86    //-----------------------------------------------------------------
87    // PRESET REVEB TESTS:
88    //----------------------------------
89
90
91    //-----------------------------------------------------------------
92    // 0 - constructor
93    //----------------------------------
94
95    //Test case 0.0: test constructor and release
96    @LargeTest
97    public void test0_0ConstructorAndRelease() throws Exception {
98        boolean result = false;
99        String msg = "test1_0ConstructorAndRelease()";
100        PresetReverb reverb = null;
101         try {
102            reverb = new PresetReverb(0, 0);
103            assertNotNull(msg + ": could not create PresetReverb", reverb);
104            try {
105                assertTrue(msg +": invalid effect ID", (reverb.getId() != 0));
106            } catch (IllegalStateException e) {
107                msg = msg.concat(": PresetReverb not initialized");
108            }
109            result = true;
110        } catch (IllegalArgumentException e) {
111            msg = msg.concat(": PresetReverb not found");
112        } catch (UnsupportedOperationException e) {
113            msg = msg.concat(": Effect library not loaded");
114        } finally {
115            if (reverb != null) {
116                reverb.release();
117            }
118        }
119        assertTrue(msg, result);
120    }
121
122    //-----------------------------------------------------------------
123    // 1 - get/set parameters
124    //----------------------------------
125
126    //Test case 1.0: test preset
127    @LargeTest
128    public void test1_0Preset() throws Exception {
129        boolean result = false;
130        String msg = "test1_0Preset()";
131        getReverb(0);
132        try {
133            mReverb.setPreset((short)PresetReverb.PRESET_LARGEROOM);
134            short preset = mReverb.getPreset();
135            assertEquals(msg +": got incorrect preset",
136                         (short)PresetReverb.PRESET_LARGEROOM,
137                         preset);
138            result = true;
139        } catch (IllegalArgumentException e) {
140            msg = msg.concat(": Bad parameter value");
141            loge(msg, "Bad parameter value");
142        } catch (UnsupportedOperationException e) {
143            msg = msg.concat(": get parameter() rejected");
144            loge(msg, "get parameter() rejected");
145        } catch (IllegalStateException e) {
146            msg = msg.concat("get parameter() called in wrong state");
147            loge(msg, "get parameter() called in wrong state");
148        } finally {
149            releaseReverb();
150        }
151        assertTrue(msg, result);
152    }
153
154    //Test case 1.1: test properties
155    @LargeTest
156    public void test1_1Properties() throws Exception {
157        boolean result = false;
158        String msg = "test1_1Properties()";
159        getReverb(0);
160        try {
161            PresetReverb.Settings settings = mReverb.getProperties();
162            short newPreset = (short)PresetReverb.PRESET_LARGEROOM;
163            if (settings.preset == (short)PresetReverb.PRESET_LARGEROOM) {
164                newPreset = (short)PresetReverb.PRESET_SMALLROOM;
165            }
166            String str = settings.toString();
167            settings = new PresetReverb.Settings(str);
168            settings.preset = newPreset;
169            mReverb.setProperties(settings);
170            settings = mReverb.getProperties();
171            assertEquals(msg +": setProperties failed", newPreset, settings.preset);
172            result = true;
173        } catch (IllegalArgumentException e) {
174            msg = msg.concat(": Bad parameter value");
175            loge(msg, "Bad parameter value");
176        } catch (UnsupportedOperationException e) {
177            msg = msg.concat(": get parameter() rejected");
178            loge(msg, "get parameter() rejected");
179        } catch (IllegalStateException e) {
180            msg = msg.concat("get parameter() called in wrong state");
181            loge(msg, "get parameter() called in wrong state");
182        } finally {
183            releaseReverb();
184        }
185        assertTrue(msg, result);
186    }
187
188    //-----------------------------------------------------------------
189    // 2 - Effect action
190    //----------------------------------
191
192    //Test case 2.0: test actual auxiliary reverb influence on sound
193    @LargeTest
194    public void test2_0AuxiliarySoundModification() throws Exception {
195        boolean result = false;
196        String msg = "test2_0AuxiliarySoundModification()";
197        EnergyProbe probe = null;
198        AudioEffect vc = null;
199        MediaPlayer mp = null;
200        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
201        int ringerMode = am.getRingerMode();
202        am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
203        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
204        am.setStreamVolume(AudioManager.STREAM_MUSIC,
205                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
206                           0);
207        getReverb(0);
208        try {
209            probe = new EnergyProbe(0);
210            // creating a volume controller on output mix ensures that ro.audio.silent mutes
211            // audio after the effects and not before
212            vc = new AudioEffect(
213                                AudioEffect.EFFECT_TYPE_NULL,
214                                VOLUME_EFFECT_UUID,
215                                0,
216                                0);
217            vc.setEnabled(true);
218
219            mp = new MediaPlayer();
220            mp.setDataSource(MediaNames.SINE_200_1000);
221            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
222            mp.attachAuxEffect(mReverb.getId());
223            mp.setAuxEffectSendLevel(1.0f);
224            mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
225            mReverb.setEnabled(true);
226            mp.prepare();
227            mp.start();
228            Thread.sleep(1000);
229            mp.stop();
230            Thread.sleep(200);
231            // measure energy around 1kHz after media player was stopped for 200 ms
232            int energy1000 = probe.capture(1000);
233            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
234            result = true;
235        } catch (IllegalArgumentException e) {
236            msg = msg.concat(": Bad parameter value");
237            loge(msg, "Bad parameter value");
238        } catch (UnsupportedOperationException e) {
239            msg = msg.concat(": get parameter() rejected");
240            loge(msg, "get parameter() rejected");
241        } catch (IllegalStateException e) {
242            msg = msg.concat("get parameter() called in wrong state");
243            loge(msg, "get parameter() called in wrong state");
244        } catch (InterruptedException e) {
245            loge(msg, "sleep() interrupted");
246        }
247        finally {
248            releaseReverb();
249            if (mp != null) {
250                mp.release();
251            }
252            if (vc != null) {
253                vc.release();
254            }
255            if (probe != null) {
256                probe.release();
257            }
258            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
259            am.setRingerMode(ringerMode);
260        }
261        assertTrue(msg, result);
262    }
263
264    //Test case 2.1: test actual insert reverb influence on sound
265    @LargeTest
266    public void test2_1InsertSoundModification() throws Exception {
267        boolean result = false;
268        String msg = "test2_1InsertSoundModification()";
269        EnergyProbe probe = null;
270        AudioEffect vc = null;
271        MediaPlayer mp = null;
272        AudioEffect rvb = null;
273        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
274        int ringerMode = am.getRingerMode();
275        am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
276        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
277        am.setStreamVolume(AudioManager.STREAM_MUSIC,
278                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
279                           0);
280        try {
281            // creating a volume controller on output mix ensures that ro.audio.silent mutes
282            // audio after the effects and not before
283            vc = new AudioEffect(
284                                AudioEffect.EFFECT_TYPE_NULL,
285                                VOLUME_EFFECT_UUID,
286                                0,
287                                0);
288            vc.setEnabled(true);
289
290            mp = new MediaPlayer();
291            mp.setDataSource(MediaNames.SINE_200_1000);
292            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
293
294            // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary
295            // reverb will be chosen by the effect framework as we are on session 0
296            rvb = new AudioEffect(
297                        AudioEffect.EFFECT_TYPE_NULL,
298                        PRESET_REVERB_EFFECT_UUID,
299                        0,
300                        0);
301
302            rvb.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_PLATE);
303            rvb.setEnabled(true);
304
305            // create probe after reverb so that it is chained behind the reverb in the
306            // effect chain
307            probe = new EnergyProbe(0);
308
309            mp.prepare();
310            mp.start();
311            Thread.sleep(1000);
312            mp.stop();
313            Thread.sleep(200);
314            // measure energy around 1kHz after media player was stopped for 200 ms
315            int energy1000 = probe.capture(1000);
316            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
317            result = true;
318        } catch (IllegalArgumentException e) {
319            msg = msg.concat(": Bad parameter value");
320            loge(msg, "Bad parameter value");
321        } catch (UnsupportedOperationException e) {
322            msg = msg.concat(": get parameter() rejected");
323            loge(msg, "get parameter() rejected");
324        } catch (IllegalStateException e) {
325            msg = msg.concat("get parameter() called in wrong state");
326            loge(msg, "get parameter() called in wrong state");
327        } catch (InterruptedException e) {
328            loge(msg, "sleep() interrupted");
329        }
330        finally {
331            if (mp != null) {
332                mp.release();
333            }
334            if (vc != null) {
335                vc.release();
336            }
337            if (rvb != null) {
338                rvb.release();
339            }
340            if (probe != null) {
341                probe.release();
342            }
343            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
344            am.setRingerMode(ringerMode);
345        }
346        assertTrue(msg, result);
347    }
348
349    //-----------------------------------------------------------------
350    // private methods
351    //----------------------------------
352
353    private void getReverb(int session) {
354         if (mReverb == null || session != mSession) {
355             if (session != mSession && mReverb != null) {
356                 mReverb.release();
357                 mReverb = null;
358             }
359             try {
360                mReverb = new PresetReverb(0, session);
361                mSession = session;
362            } catch (IllegalArgumentException e) {
363                Log.e(TAG, "getReverb() PresetReverb not found exception: "+e);
364            } catch (UnsupportedOperationException e) {
365                Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
366            }
367         }
368         assertNotNull("could not create mReverb", mReverb);
369    }
370
371    private void releaseReverb() {
372        if (mReverb != null) {
373            mReverb.release();
374            mReverb = null;
375        }
376   }
377
378}
379