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 volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
202        am.setStreamVolume(AudioManager.STREAM_MUSIC,
203                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
204                           0);
205        getReverb(0);
206        try {
207            probe = new EnergyProbe(0);
208            // creating a volume controller on output mix ensures that ro.audio.silent mutes
209            // audio after the effects and not before
210            vc = new AudioEffect(
211                                AudioEffect.EFFECT_TYPE_NULL,
212                                VOLUME_EFFECT_UUID,
213                                0,
214                                0);
215            vc.setEnabled(true);
216
217            mp = new MediaPlayer();
218            mp.setDataSource(MediaNames.SINE_200_1000);
219            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
220            mp.attachAuxEffect(mReverb.getId());
221            mp.setAuxEffectSendLevel(1.0f);
222            mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
223            mReverb.setEnabled(true);
224            mp.prepare();
225            mp.start();
226            Thread.sleep(1000);
227            mp.stop();
228            Thread.sleep(200);
229            // measure energy around 1kHz after media player was stopped for 200 ms
230            int energy1000 = probe.capture(1000);
231            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
232            result = true;
233        } catch (IllegalArgumentException e) {
234            msg = msg.concat(": Bad parameter value");
235            loge(msg, "Bad parameter value");
236        } catch (UnsupportedOperationException e) {
237            msg = msg.concat(": get parameter() rejected");
238            loge(msg, "get parameter() rejected");
239        } catch (IllegalStateException e) {
240            msg = msg.concat("get parameter() called in wrong state");
241            loge(msg, "get parameter() called in wrong state");
242        } catch (InterruptedException e) {
243            loge(msg, "sleep() interrupted");
244        }
245        finally {
246            releaseReverb();
247            if (mp != null) {
248                mp.release();
249            }
250            if (vc != null) {
251                vc.release();
252            }
253            if (probe != null) {
254                probe.release();
255            }
256            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
257        }
258        assertTrue(msg, result);
259    }
260
261    //Test case 2.1: test actual insert reverb influence on sound
262    @LargeTest
263    public void test2_1InsertSoundModification() throws Exception {
264        boolean result = false;
265        String msg = "test2_1InsertSoundModification()";
266        EnergyProbe probe = null;
267        AudioEffect vc = null;
268        MediaPlayer mp = null;
269        AudioEffect rvb = null;
270        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
271        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
272        am.setStreamVolume(AudioManager.STREAM_MUSIC,
273                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
274                           0);
275        try {
276            // creating a volume controller on output mix ensures that ro.audio.silent mutes
277            // audio after the effects and not before
278            vc = new AudioEffect(
279                                AudioEffect.EFFECT_TYPE_NULL,
280                                VOLUME_EFFECT_UUID,
281                                0,
282                                0);
283            vc.setEnabled(true);
284
285            mp = new MediaPlayer();
286            mp.setDataSource(MediaNames.SINE_200_1000);
287            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
288
289            // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary
290            // reverb will be chosen by the effect framework as we are on session 0
291            rvb = new AudioEffect(
292                        AudioEffect.EFFECT_TYPE_NULL,
293                        PRESET_REVERB_EFFECT_UUID,
294                        0,
295                        0);
296
297            rvb.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_PLATE);
298            rvb.setEnabled(true);
299
300            // create probe after reverb so that it is chained behind the reverb in the
301            // effect chain
302            probe = new EnergyProbe(0);
303
304            mp.prepare();
305            mp.start();
306            Thread.sleep(1000);
307            mp.stop();
308            Thread.sleep(200);
309            // measure energy around 1kHz after media player was stopped for 200 ms
310            int energy1000 = probe.capture(1000);
311            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
312            result = true;
313        } catch (IllegalArgumentException e) {
314            msg = msg.concat(": Bad parameter value");
315            loge(msg, "Bad parameter value");
316        } catch (UnsupportedOperationException e) {
317            msg = msg.concat(": get parameter() rejected");
318            loge(msg, "get parameter() rejected");
319        } catch (IllegalStateException e) {
320            msg = msg.concat("get parameter() called in wrong state");
321            loge(msg, "get parameter() called in wrong state");
322        } catch (InterruptedException e) {
323            loge(msg, "sleep() interrupted");
324        }
325        finally {
326            if (mp != null) {
327                mp.release();
328            }
329            if (vc != null) {
330                vc.release();
331            }
332            if (rvb != null) {
333                rvb.release();
334            }
335            if (probe != null) {
336                probe.release();
337            }
338            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
339        }
340        assertTrue(msg, result);
341    }
342
343    //-----------------------------------------------------------------
344    // private methods
345    //----------------------------------
346
347    private void getReverb(int session) {
348         if (mReverb == null || session != mSession) {
349             if (session != mSession && mReverb != null) {
350                 mReverb.release();
351                 mReverb = null;
352             }
353             try {
354                mReverb = new PresetReverb(0, session);
355                mSession = session;
356            } catch (IllegalArgumentException e) {
357                Log.e(TAG, "getReverb() PresetReverb not found exception: "+e);
358            } catch (UnsupportedOperationException e) {
359                Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
360            }
361         }
362         assertNotNull("could not create mReverb", mReverb);
363    }
364
365    private void releaseReverb() {
366        if (mReverb != null) {
367            mReverb.release();
368            mReverb = null;
369        }
370   }
371
372}
373