• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.media.cts;
18 
19 import android.media.audiofx.AudioEffect;
20 import android.media.AudioFormat;
21 import android.media.AudioManager;
22 import android.media.audiofx.Visualizer;
23 import android.os.Looper;
24 import android.test.AndroidTestCase;
25 import android.util.Log;
26 
27 public class VisualizerTest extends AndroidTestCase {
28 
29     private String TAG = "VisualizerTest";
30     private final static int MIN_CAPTURE_RATE_MAX = 10000; // 10Hz
31     private final static int MIN_CAPTURE_SIZE_MAX = 1024;
32     private final static int MAX_CAPTURE_SIZE_MIN = 512;
33     private final static int MAX_LOOPER_WAIT_COUNT = 10;
34 
35     private Visualizer mVisualizer = null;
36     private int mSession = -1;
37     private boolean mInitialized = false;
38     private Looper mLooper = null;
39     private final Object mLock = new Object();
40     private byte[] mWaveform = null;
41     private byte[] mFft = null;
42     private boolean mCaptureWaveform = false;
43     private boolean mCaptureFft = false;
44     private Thread mListenerThread;
45 
46     //-----------------------------------------------------------------
47     // VISUALIZER TESTS:
48     //----------------------------------
49 
50     //-----------------------------------------------------------------
51     // 0 - constructor
52     //----------------------------------
53 
54     //Test case 0.0: test constructor and release
test0_0ConstructorAndRelease()55     public void test0_0ConstructorAndRelease() throws Exception {
56         Visualizer visualizer = null;
57          try {
58             visualizer = new Visualizer(0);
59             assertNotNull("could not create Visualizer", visualizer);
60         } catch (IllegalArgumentException e) {
61             fail("Visualizer not found");
62         } catch (UnsupportedOperationException e) {
63             fail("Effect library not loaded");
64         } finally {
65             if (visualizer != null) {
66                 visualizer.release();
67             }
68         }
69     }
70 
71 
72     //-----------------------------------------------------------------
73     // 1 - get/set parameters
74     //----------------------------------
75 
76     //Test case 1.0: capture rates
test1_0CaptureRates()77     public void test1_0CaptureRates() throws Exception {
78         getVisualizer(0);
79         try {
80             int captureRate = mVisualizer.getMaxCaptureRate();
81             assertTrue("insufficient max capture rate",
82                     captureRate >= MIN_CAPTURE_RATE_MAX);
83             int samplingRate = mVisualizer.getSamplingRate();
84         } catch (IllegalArgumentException e) {
85             fail("Bad parameter value");
86         } catch (UnsupportedOperationException e) {
87             fail("get parameter() rejected");
88         } catch (IllegalStateException e) {
89             fail("get parameter() called in wrong state");
90         } finally {
91             releaseVisualizer();
92         }
93     }
94 
95     //Test case 1.1: test capture size
test1_1CaptureSize()96     public void test1_1CaptureSize() throws Exception {
97         getVisualizer(0);
98         try {
99             int[] range = mVisualizer.getCaptureSizeRange();
100             assertTrue("insufficient min capture size",
101                     range[0] <= MAX_CAPTURE_SIZE_MIN);
102             assertTrue("insufficient min capture size",
103                     range[1] >= MIN_CAPTURE_SIZE_MAX);
104             mVisualizer.setCaptureSize(range[0]);
105             assertEquals("insufficient min capture size",
106                     range[0], mVisualizer.getCaptureSize());
107             mVisualizer.setCaptureSize(range[1]);
108             assertEquals("insufficient min capture size",
109                     range[1], mVisualizer.getCaptureSize());
110         } catch (IllegalArgumentException e) {
111             fail("Bad parameter value");
112         } catch (UnsupportedOperationException e) {
113             fail("get parameter() rejected");
114         } catch (IllegalStateException e) {
115             fail("get parameter() called in wrong state");
116         } finally {
117             releaseVisualizer();
118         }
119     }
120 
121     //-----------------------------------------------------------------
122     // 2 - check capture
123     //----------------------------------
124 
125     //Test case 2.0: test cature in polling mode
test2_0PollingCapture()126     public void test2_0PollingCapture() throws Exception {
127         try {
128             getVisualizer(0);
129             mVisualizer.setEnabled(true);
130             assertTrue("visualizer not enabled", mVisualizer.getEnabled());
131             Thread.sleep(100);
132             // check capture on silence
133             byte[] data = new byte[mVisualizer.getCaptureSize()];
134             mVisualizer.getWaveForm(data);
135             int energy = computeEnergy(data, true);
136             assertEquals("getWaveForm reports energy for silence",
137                     0, energy);
138             mVisualizer.getFft(data);
139             energy = computeEnergy(data, false);
140             assertEquals("getFft reports energy for silence",
141                     0, energy);
142 
143         } catch (IllegalStateException e) {
144             fail("method called in wrong state");
145         } catch (InterruptedException e) {
146             fail("sleep() interrupted");
147         } finally {
148             releaseVisualizer();
149         }
150     }
151 
152     //Test case 2.1: test capture with listener
test2_1ListenerCapture()153     public void test2_1ListenerCapture() throws Exception {
154         try {
155             getVisualizer(0);
156             synchronized(mLock) {
157                 mInitialized = false;
158                 createListenerLooper();
159                 waitForLooperInitialization_l();
160             }
161             mVisualizer.setEnabled(true);
162             assertTrue("visualizer not enabled", mVisualizer.getEnabled());
163 
164             Thread.sleep(100);
165 
166             // check capture on silence
167             synchronized(mLock) {
168                 mCaptureWaveform = true;
169                 int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
170                 while ((mWaveform == null) && (looperWaitCount-- > 0)) {
171                     try {
172                         mLock.wait();
173                     } catch(Exception e) {
174                     }
175                 }
176                 mCaptureWaveform = false;
177             }
178             assertNotNull("waveform capture failed", mWaveform);
179             int energy = computeEnergy(mWaveform, true);
180             assertEquals("getWaveForm reports energy for silence",
181                     0, energy);
182 
183             synchronized(mLock) {
184                 mCaptureFft = true;
185                 int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
186                 while ((mFft == null) && (looperWaitCount-- > 0)) {
187                     try {
188                         mLock.wait();
189                     } catch(Exception e) {
190                     }
191                 }
192                 mCaptureFft = false;
193             }
194             assertNotNull("FFT capture failed", mFft);
195             energy = computeEnergy(mFft, false);
196             assertEquals("getFft reports energy for silence",
197                     0, energy);
198 
199         } catch (IllegalStateException e) {
200             fail("method called in wrong state");
201         } catch (InterruptedException e) {
202             fail("sleep() interrupted");
203         } finally {
204             terminateListenerLooper();
205             releaseVisualizer();
206         }
207     }
208 
209     //-----------------------------------------------------------------
210     // private methods
211     //----------------------------------
212 
computeEnergy(byte[] data, boolean pcm)213     private int computeEnergy(byte[] data, boolean pcm) {
214         int energy = 0;
215         if (data.length != 0) {
216             if (pcm) {
217                 for (int i = 0; i < data.length; i++) {
218                     int tmp = ((int)data[i] & 0xFF) - 128;
219                     energy += tmp*tmp;
220                 }
221             } else {
222                 energy = (int)data[0] * (int)data[0];
223                 for (int i = 2; i < data.length; i += 2) {
224                     int real = (int)data[i];
225                     int img = (int)data[i + 1];
226                     energy += real * real + img * img;
227                 }
228             }
229         }
230         return energy;
231     }
232 
getVisualizer(int session)233     private void getVisualizer(int session) {
234          if (mVisualizer == null || session != mSession) {
235              if (session != mSession && mVisualizer != null) {
236                  mVisualizer.release();
237                  mVisualizer = null;
238              }
239              try {
240                 mVisualizer = new Visualizer(session);
241                 mSession = session;
242             } catch (IllegalArgumentException e) {
243                 Log.e(TAG, "getVisualizer() Visualizer not found exception: "+e);
244             } catch (UnsupportedOperationException e) {
245                 Log.e(TAG, "getVisualizer() Effect library not loaded exception: "+e);
246             }
247          }
248          assertNotNull("could not create mVisualizer", mVisualizer);
249     }
250 
releaseVisualizer()251     private void releaseVisualizer() {
252         if (mVisualizer != null) {
253             mVisualizer.release();
254             mVisualizer = null;
255         }
256     }
257 
waitForLooperInitialization_l()258     private void waitForLooperInitialization_l() {
259         int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
260         while (!mInitialized && (looperWaitCount-- > 0)) {
261             try {
262                 mLock.wait();
263             } catch(Exception e) {
264             }
265         }
266         assertTrue(mInitialized);
267     }
268 
createListenerLooper()269     private void createListenerLooper() {
270         mListenerThread = new Thread() {
271             @Override
272             public void run() {
273                 // Set up a looper to be used by mEffect.
274                 Looper.prepare();
275 
276                 // Save the looper so that we can terminate this thread
277                 // after we are done with it.
278                 mLooper = Looper.myLooper();
279 
280                 synchronized(mLock) {
281                     if (mVisualizer != null) {
282                         mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
283                             public void onWaveFormDataCapture(
284                                     Visualizer visualizer, byte[] waveform, int samplingRate) {
285                                 synchronized(mLock) {
286                                     if (visualizer == mVisualizer) {
287                                         if (mCaptureWaveform) {
288                                             mWaveform = waveform;
289                                             mLock.notify();
290                                         }
291                                     }
292                                 }
293                             }
294 
295                             public void onFftDataCapture(
296                                     Visualizer visualizer, byte[] fft, int samplingRate) {
297                                 synchronized(mLock) {
298                                     Log.e(TAG, "onFftDataCapture 2 mCaptureFft: "+mCaptureFft);
299                                     if (visualizer == mVisualizer) {
300                                         if (mCaptureFft) {
301                                             mFft = fft;
302                                             mLock.notify();
303                                         }
304                                     }
305                                 }
306                             }
307                         },
308                         10000,
309                         true,
310                         true);
311                     }
312                     mInitialized = true;
313                     mLock.notify();
314                 }
315                 Looper.loop();  // Blocks forever until Looper.quit() is called.
316             }
317         };
318         mListenerThread.start();
319     }
320     /*
321      * Terminates the listener looper thread.
322      */
terminateListenerLooper()323     private void terminateListenerLooper() {
324         if (mListenerThread != null) {
325             if (mLooper != null) {
326                 mLooper.quit();
327                 mLooper = null;
328             }
329             try {
330                 mListenerThread.join();
331             } catch(InterruptedException e) {
332             }
333             mListenerThread = null;
334         }
335     }
336 }
337