1df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent/*
2df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * Copyright (C) 2010 The Android Open Source Project
3df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *
4df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * you may not use this file except in compliance with the License.
6df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * You may obtain a copy of the License at
7df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *
8df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *
10df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * Unless required by applicable law or agreed to in writing, software
11df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * See the License for the specific language governing permissions and
14df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * limitations under the License.
15df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent */
16df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
171a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurentpackage android.media.audiofx;
18df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
19df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentimport android.util.Log;
20df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentimport java.lang.ref.WeakReference;
21df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentimport android.os.Handler;
22df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentimport android.os.Looper;
23df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentimport android.os.Message;
24df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
25df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent/**
26df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * The Visualizer class enables application to retrieve part of the currently playing audio for
27df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * visualization purpose. It is not an audio recording interface and only returns partial and low
28df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
29df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * of the visualizer requires the permission android.permission.RECORD_AUDIO.
30df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <p>The audio session ID passed to the constructor indicates which audio content should be
31df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * visualized:<br>
32df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <ul>
33df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *   <li>If the session is 0, the audio output mix is visualized</li>
341a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent *   <li>If the session is not 0, the audio from a particular {@link android.media.MediaPlayer} or
351a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent *   {@link android.media.AudioTrack}
36df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *   using this audio session is visualized </li>
37df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * </ul>
38df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <p>Two types of representation of audio content can be captured: <br>
39df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <ul>
40df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *   <li>Waveform data: consecutive 8-bit (unsigned) mono samples by using the
41df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *   {@link #getWaveForm(byte[])} method</li>
42df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *   <li>Frequency data: 8-bit magnitude FFT by using the {@link #getFft(byte[])} method</li>
43df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * </ul>
44df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <p>The length of the capture can be retrieved or specified by calling respectively
4503a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent * {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. The capture size must be a
4603a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent * power of 2 in the range returned by {@link #getCaptureSizeRange()}.
47df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <p>In addition to the polling capture mode described above with {@link #getWaveForm(byte[])} and
48df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *  {@link #getFft(byte[])} methods, a callback mode is also available by installing a listener by
49df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *  use of the {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
50df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *  The rate at which the listener capture method is called as well as the type of data returned is
51df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *  specified.
52df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <p>Before capturing data, the Visualizer must be enabled by calling the
53df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * {@link #setEnabled(boolean)} method.
54df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * When data capture is not needed any more, the Visualizer should be disabled.
55df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * <p>It is good practice to call the {@link #release()} method when the Visualizer is not used
56df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * anymore to free up native resources associated to the Visualizer instance.
571a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * <p>Creating a Visualizer on the output mix (audio session 0) requires permission
581a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
5901b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi * <p>The Visualizer class can also be used to perform measurements on the audio being played back.
6001b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi * The measurements to perform are defined by setting a mask of the requested measurement modes with
6101b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi * {@link #setMeasurementMode(int)}. Supported values are {@link #MEASUREMENT_MODE_NONE} to cancel
6201b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi * any measurement, and {@link #MEASUREMENT_MODE_PEAK_RMS} for peak and RMS monitoring.
6301b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi * Measurements can be retrieved through {@link #getMeasurementPeakRms(MeasurementPeakRms)}.
64df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent */
65df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
66df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentpublic class Visualizer {
67df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
68df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    static {
69df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        System.loadLibrary("audioeffect_jni");
70df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        native_init();
71df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
72df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
73df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private final static String TAG = "Visualizer-JAVA";
74df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
75df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
76df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * State of a Visualizer object that was not successfully initialized upon creation
77df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
78df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public static final int STATE_UNINITIALIZED = 0;
79df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
80df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * State of a Visualizer object that is ready to be used.
81df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
82df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public static final int STATE_INITIALIZED   = 1;
83df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
84df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * State of a Visualizer object that is active.
85df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
86df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public static final int STATE_ENABLED   = 2;
87df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
88e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    // to keep in sync with system/media/audio_effects/include/audio_effects/effect_visualizer.h
89e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    /**
90e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * Defines a capture mode where amplification is applied based on the content of the captured
91e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * data. This is the default Visualizer mode, and is suitable for music visualization.
92e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     */
93e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    public static final int SCALING_MODE_NORMALIZED = 0;
94e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    /**
95e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * Defines a capture mode where the playback volume will affect (scale) the range of the
96e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * captured data. A low playback volume will lead to low sample and fft values, and vice-versa.
97e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     */
98e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    public static final int SCALING_MODE_AS_PLAYED = 1;
99e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi
100badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    /**
10101b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi     * Defines a measurement mode in which no measurements are performed.
102badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     */
103badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    public static final int MEASUREMENT_MODE_NONE = 0;
104badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
105badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    /**
106badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * Defines a measurement mode which computes the peak and RMS value in mB, where 0mB is the
107badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * maximum sample value, and -9600mB is the minimum value.
10801b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi     * Values for peak and RMS can be retrieved with
10901b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi     * {@link #getMeasurementPeakRms(MeasurementPeakRms)}.
110badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     */
111badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    public static final int MEASUREMENT_MODE_PEAK_RMS = 1 << 0;
112badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
113df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // to keep in sync with frameworks/base/media/jni/audioeffect/android_media_Visualizer.cpp
11417cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private static final int NATIVE_EVENT_PCM_CAPTURE = 0;
11517cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private static final int NATIVE_EVENT_FFT_CAPTURE = 1;
1163540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    private static final int NATIVE_EVENT_SERVER_DIED = 2;
117df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
118df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Error codes:
119df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
120df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Successful operation.
121df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
122df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int SUCCESS              = 0;
123df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
124df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Unspecified error.
125df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
126df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ERROR                = -1;
127df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
128ed6eae420fd60dcb7d90f54c3116959b75bd6276Glenn Kasten     * Internal operation status. Not returned by any method.
129df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
130df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ALREADY_EXISTS       = -2;
131df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
132df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Operation failed due to bad object initialization.
133df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
134df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ERROR_NO_INIT              = -3;
135df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
136df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Operation failed due to bad parameter value.
137df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
138df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ERROR_BAD_VALUE            = -4;
139df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
140df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Operation failed because it was requested in wrong state.
141df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
142df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ERROR_INVALID_OPERATION    = -5;
143df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
144df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Operation failed due to lack of memory.
145df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
146df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ERROR_NO_MEMORY            = -6;
147df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
148df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Operation failed due to dead remote object.
149df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
150df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public  static final int ERROR_DEAD_OBJECT          = -7;
151df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
152df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------------------------------------------------------------
153df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Member variables
154df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------
155df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
156df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Indicates the state of the Visualizer instance
157df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
15817cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private int mState = STATE_UNINITIALIZED;
159df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
160df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Lock to synchronize access to mState
161df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
16217cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private final Object mStateLock = new Object();
163df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
164df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * System wide unique Identifier of the visualizer engine used by this Visualizer instance
165df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
16617cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private int mId;
167df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
168df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
169df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Lock to protect listeners updates against event notifications
170df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
17117cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private final Object mListenerLock = new Object();
172df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
173df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Handler for events coming from the native code
174df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
17517cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private NativeEventHandler mNativeEventHandler = null;
176df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
177df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     *  PCM and FFT capture listener registered by client
178df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
17917cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent    private OnDataCaptureListener mCaptureListener = null;
1803540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    /**
1813540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     *  Server Died listener registered by client
1823540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     */
1833540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    private OnServerDiedListener mServerDiedListener = null;
184df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
185df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // accessed by native methods
186ea7861c918567d17d40a762b38f97c053d88b839Ashok Bhat    private long mNativeVisualizer;
187ea7861c918567d17d40a762b38f97c053d88b839Ashok Bhat    private long mJniData;
188df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
189df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------------------------------------------------------------
190df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Constructor, Finalize
191df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------
192df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
193df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Class constructor.
19417cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent     * @param audioSession system wide unique audio session identifier. If audioSession
195df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     *  is not 0, the visualizer will be attached to the MediaPlayer or AudioTrack in the
196df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     *  same audio session. Otherwise, the Visualizer will apply to the output mix.
197df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     *
198df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @throws java.lang.UnsupportedOperationException
199df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @throws java.lang.RuntimeException
200df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
201df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
202df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public Visualizer(int audioSession)
203df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws UnsupportedOperationException, RuntimeException {
204df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        int[] id = new int[1];
205df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
206df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
207df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            mState = STATE_UNINITIALIZED;
208df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            // native initialization
209df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id);
210df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (result != SUCCESS && result != ALREADY_EXISTS) {
211df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                Log.e(TAG, "Error code "+result+" when initializing Visualizer.");
212df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                switch (result) {
213df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                case ERROR_INVALID_OPERATION:
214df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    throw (new UnsupportedOperationException("Effect library not loaded"));
215df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                default:
216df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    throw (new RuntimeException("Cannot initialize Visualizer engine, error: "
217df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                            +result));
218df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                }
219df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
220df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            mId = id[0];
221df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (native_getEnabled()) {
222df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                mState = STATE_ENABLED;
223df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            } else {
224df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                mState = STATE_INITIALIZED;
225df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
226df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
227df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
228df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
229df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
230df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Releases the native Visualizer resources. It is a good practice to release the
231df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * visualization engine when not in use.
232df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
233df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public void release() {
234df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
235df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            native_release();
236df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            mState = STATE_UNINITIALIZED;
237df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
238df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
239df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
240df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    @Override
241df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    protected void finalize() {
242df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        native_finalize();
243df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
244df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
245df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
246df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Enable or disable the visualization engine.
247df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param enabled requested enable state
248df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return {@link #SUCCESS} in case of success,
249df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} in case of failure.
250df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @throws IllegalStateException
251df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
252df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int setEnabled(boolean enabled)
253df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws IllegalStateException {
254df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
255672c0dc3a04cb149691603342c319994e21235cbEric Laurent            if (mState == STATE_UNINITIALIZED) {
256df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("setEnabled() called in wrong state: "+mState));
257df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
258672c0dc3a04cb149691603342c319994e21235cbEric Laurent            int status = SUCCESS;
259672c0dc3a04cb149691603342c319994e21235cbEric Laurent            if ((enabled && (mState == STATE_INITIALIZED)) ||
260672c0dc3a04cb149691603342c319994e21235cbEric Laurent                    (!enabled && (mState == STATE_ENABLED))) {
261672c0dc3a04cb149691603342c319994e21235cbEric Laurent                status = native_setEnabled(enabled);
262672c0dc3a04cb149691603342c319994e21235cbEric Laurent                if (status == SUCCESS) {
263672c0dc3a04cb149691603342c319994e21235cbEric Laurent                    mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
264672c0dc3a04cb149691603342c319994e21235cbEric Laurent                }
265df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
266df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return status;
267df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
268df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
269df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
270df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
271df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Get current activation state of the visualizer.
272df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return true if the visualizer is active, false otherwise
273df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
274df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public boolean getEnabled()
275df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {
276df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
277df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (mState == STATE_UNINITIALIZED) {
278df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("getEnabled() called in wrong state: "+mState));
279df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
280df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return native_getEnabled();
281df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
282df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
283df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
284df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
285df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Returns the capture size range.
286df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return the mininum capture size is returned in first array element and the maximum in second
287df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * array element.
288df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
289df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public static native int[] getCaptureSizeRange();
290df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
291df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
292df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Returns the maximum capture rate for the callback capture method. This is the maximum value
293df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * for the rate parameter of the
294df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
295df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return the maximum capture rate expressed in milliHertz
296df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
297df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public static native int getMaxCaptureRate();
298df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
299df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
300df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Sets the capture size, i.e. the number of bytes returned by {@link #getWaveForm(byte[])} and
301df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #getFft(byte[])} methods. The capture size must be a power of 2 in the range returned
302df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * by {@link #getCaptureSizeRange()}.
303df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * This method must not be called when the Visualizer is enabled.
304df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param size requested capture size
305df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return {@link #SUCCESS} in case of success,
306df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #ERROR_BAD_VALUE} in case of failure.
307df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @throws IllegalStateException
308df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
309df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int setCaptureSize(int size)
310df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws IllegalStateException {
311df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
312df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (mState != STATE_INITIALIZED) {
313df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("setCaptureSize() called in wrong state: "+mState));
314df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
315df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return native_setCaptureSize(size);
316df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
317df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
318df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
319df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
320df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Returns current capture size.
321df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return the capture size in bytes.
322df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
323df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int getCaptureSize()
324df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws IllegalStateException {
325df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
326df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (mState == STATE_UNINITIALIZED) {
327df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("getCaptureSize() called in wrong state: "+mState));
328df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
329df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return native_getCaptureSize();
330df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
331df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
332df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
333df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
334e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * Set the type of scaling applied on the captured visualization data.
335e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * @param mode see {@link #SCALING_MODE_NORMALIZED}
336e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     *     and {@link #SCALING_MODE_AS_PLAYED}
337e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * @return {@link #SUCCESS} in case of success,
338e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     *     {@link #ERROR_BAD_VALUE} in case of failure.
339e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * @throws IllegalStateException
340e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     */
341e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    public int setScalingMode(int mode)
342e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    throws IllegalStateException {
343e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi        synchronized (mStateLock) {
344e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi            if (mState == STATE_UNINITIALIZED) {
345e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi                throw(new IllegalStateException("setScalingMode() called in wrong state: "
346e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi                        + mState));
347e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi            }
348e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi            return native_setScalingMode(mode);
349e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi        }
350e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    }
351e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi
352e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    /**
353e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * Returns the current scaling mode on the captured visualization data.
354e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * @return the scaling mode, see {@link #SCALING_MODE_NORMALIZED}
355e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     *     and {@link #SCALING_MODE_AS_PLAYED}.
356e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     * @throws IllegalStateException
357e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi     */
358e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    public int getScalingMode()
359e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    throws IllegalStateException {
360e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi        synchronized (mStateLock) {
361e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi            if (mState == STATE_UNINITIALIZED) {
362e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi                throw(new IllegalStateException("getScalingMode() called in wrong state: "
363e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi                        + mState));
364e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi            }
365e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi            return native_getScalingMode();
366e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi        }
367e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    }
368e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi
369e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    /**
370badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * Sets the combination of measurement modes to be performed by this audio effect.
371badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @param mode a mask of the measurements to perform. The valid values are
372badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *     {@link #MEASUREMENT_MODE_NONE} (to cancel any measurement)
373badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *     or {@link #MEASUREMENT_MODE_PEAK_RMS}.
374badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE} in case of failure.
375badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @throws IllegalStateException
376badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     */
377badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    public int setMeasurementMode(int mode)
378badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            throws IllegalStateException {
379badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        synchronized (mStateLock) {
380badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            if (mState == STATE_UNINITIALIZED) {
381badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi                throw(new IllegalStateException("setMeasurementMode() called in wrong state: "
382badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi                        + mState));
383badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            }
384badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            return native_setMeasurementMode(mode);
385badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        }
386badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    }
387badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
388badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    /**
389badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * Returns the current measurement modes performed by this audio effect
390badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @return the mask of the measurements,
391badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *     {@link #MEASUREMENT_MODE_NONE} (when no measurements are performed)
392badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *     or {@link #MEASUREMENT_MODE_PEAK_RMS}.
393badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @throws IllegalStateException
394badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     */
395badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    public int getMeasurementMode()
396badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            throws IllegalStateException {
397badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        synchronized (mStateLock) {
398badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            if (mState == STATE_UNINITIALIZED) {
399badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi                throw(new IllegalStateException("getMeasurementMode() called in wrong state: "
400badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi                        + mState));
401badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            }
402badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            return native_getMeasurementMode();
403badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        }
404badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    }
405badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
406badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    /**
407df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Returns the sampling rate of the captured audio.
408df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return the sampling rate in milliHertz.
409df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
410df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int getSamplingRate()
411df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws IllegalStateException {
412df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
413df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (mState == STATE_UNINITIALIZED) {
414df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("getSamplingRate() called in wrong state: "+mState));
415df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
416df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return native_getSamplingRate();
417df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
418df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
419df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
420df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
421df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Returns a waveform capture of currently playing audio content. The capture consists in
422df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * a number of consecutive 8-bit (unsigned) mono PCM samples equal to the capture size returned
423df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * by {@link #getCaptureSize()}.
424df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * <p>This method must be called when the Visualizer is enabled.
425df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param waveform array of bytes where the waveform should be returned
426df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return {@link #SUCCESS} in case of success,
427df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
428df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * in case of failure.
429df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @throws IllegalStateException
430df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
431df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int getWaveForm(byte[] waveform)
432df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws IllegalStateException {
433df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
434df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (mState != STATE_ENABLED) {
435df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("getWaveForm() called in wrong state: "+mState));
436df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
437df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return native_getWaveForm(waveform);
438df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
439df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
440df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
44103a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * Returns a frequency capture of currently playing audio content.
442df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * <p>This method must be called when the Visualizer is enabled.
44303a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <p>The capture is an 8-bit magnitude FFT, the frequency range covered being 0 (DC) to half of
44403a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * the sampling rate returned by {@link #getSamplingRate()}. The capture returns the real and
44503a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * imaginary parts of a number of frequency points equal to half of the capture size plus one.
44603a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <p>Note: only the real part is returned for the first point (DC) and the last point
44703a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * (sampling frequency / 2).
44803a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <p>The layout in the returned byte array is as follows:
44903a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <ul>
45003a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *   <li> n is the capture size returned by getCaptureSize()</li>
45103a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *   <li> Rfk, Ifk are respectively  the real and imaginary parts of the kth frequency
45203a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *   component</li>
45303a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *   <li> If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is:
45403a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *   (k*Fs)/(n/2) </li>
45503a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * </ul>
45603a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <table border="0" cellspacing="0" cellpadding="0">
45703a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <tr><td>Index </p></td>
45803a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>0 </p></td>
45903a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>1 </p></td>
46003a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>2 </p></td>
46103a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>3 </p></td>
46203a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>4 </p></td>
46303a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>5 </p></td>
46403a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>... </p></td>
46503a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>n - 2 </p></td>
46603a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>n - 1 </p></td></tr>
46703a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * <tr><td>Data </p></td>
46803a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>Rf0 </p></td>
46903a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>Rf(n/2) </p></td>
47003a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>Rf1 </p></td>
47103a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>If1 </p></td>
47203a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>Rf2 </p></td>
47303a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>If2 </p></td>
47403a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>... </p></td>
47503a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>Rf(n-1)/2 </p></td>
47603a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     *     <td>If(n-1)/2 </p></td></tr>
47703a4090b4d5965ff01cbb03dcf6d96b30d634fa3Eric Laurent     * </table>
478df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param fft array of bytes where the FFT should be returned
479df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return {@link #SUCCESS} in case of success,
480df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
481df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * in case of failure.
482df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @throws IllegalStateException
483df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
484df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int getFft(byte[] fft)
485df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    throws IllegalStateException {
486df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mStateLock) {
487df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (mState != STATE_ENABLED) {
488df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                throw(new IllegalStateException("getFft() called in wrong state: "+mState));
489df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
490df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return native_getFft(fft);
491df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
492df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
493df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
494badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    /**
495badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * A class to store peak and RMS values.
496badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * Peak and RMS are expressed in mB, as described in the
497badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * {@link Visualizer#MEASUREMENT_MODE_PEAK_RMS} measurement mode.
498badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     */
499badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    public static final class MeasurementPeakRms {
500badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        /**
50101b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi         * The peak value in mB.
502badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi         */
503badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        public int mPeak;
504badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        /**
50501b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi         * The RMS value in mB.
506badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi         */
507badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        public int mRms;
508badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    }
509badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
510badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    /**
511badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * Retrieves the latest peak and RMS measurement.
51201b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi     * Sets the peak and RMS fields of the supplied {@link Visualizer.MeasurementPeakRms} to the
51301b5743aee4473c3bdbcb0decde47952a4cb739dJean-Michel Trivi     * latest measured values.
514badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @param measurement a non-null {@link Visualizer.MeasurementPeakRms} instance to store
515badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *    the measurement values.
516badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE},
517badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *    {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
518badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     *    in case of failure.
519badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi     */
520badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    public int getMeasurementPeakRms(MeasurementPeakRms measurement) {
521badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        if (measurement == null) {
522badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            Log.e(TAG, "Cannot store measurements in a null object");
523badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            return ERROR_BAD_VALUE;
524badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        }
525badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        synchronized (mStateLock) {
526badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            if (mState != STATE_ENABLED) {
527badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi                throw (new IllegalStateException("getMeasurementPeakRms() called in wrong state: "
528badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi                        + mState));
529badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            }
530badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi            return native_getPeakRms(measurement);
531badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi        }
532badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    }
533badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
534df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //---------------------------------------------------------
535df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Interface definitions
536df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------
537df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
538df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * The OnDataCaptureListener interface defines methods called by the Visualizer to periodically
539df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * update the audio visualization capture.
540df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * The client application can implement this interface and register the listener with the
541df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
542df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
543df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public interface OnDataCaptureListener  {
544df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        /**
545df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * Method called when a new waveform capture is available.
546449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman         * <p>Data in the waveform buffer is valid only within the scope of the callback.
547449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman         * Applications which needs access to the waveform data after returning from the callback
548449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman         * should make a copy of the data instead of holding a reference.
549df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * @param visualizer Visualizer object on which the listener is registered.
550df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * @param waveform array of bytes containing the waveform representation.
551df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * @param samplingRate sampling rate of the audio visualized.
552df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         */
553df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate);
554df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
555df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        /**
556df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * Method called when a new frequency capture is available.
557449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman         * <p>Data in the fft buffer is valid only within the scope of the callback.
558449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman         * Applications which needs access to the fft data after returning from the callback
559449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman         * should make a copy of the data instead of holding a reference.
560df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * @param visualizer Visualizer object on which the listener is registered.
561df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * @param fft array of bytes containing the frequency representation.
562df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         * @param samplingRate sampling rate of the audio visualized.
563df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent         */
564df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate);
565df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
566df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
567df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
568df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Registers an OnDataCaptureListener interface and specifies the rate at which the capture
569df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * should be updated as well as the type of capture requested.
570df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * <p>Call this method with a null listener to stop receiving the capture updates.
571df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param listener OnDataCaptureListener registered
572df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param rate rate in milliHertz at which the capture should be updated
573df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param waveform true if a waveform capture is requested: the onWaveFormDataCapture()
574df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * method will be called on the OnDataCaptureListener interface.
575df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @param fft true if a frequency capture is requested: the onFftDataCapture() method will be
576df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * called on the OnDataCaptureListener interface.
577df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * @return {@link #SUCCESS} in case of success,
578df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * {@link #ERROR_NO_INIT} or {@link #ERROR_BAD_VALUE} in case of failure.
579df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
580df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public int setDataCaptureListener(OnDataCaptureListener listener,
581df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            int rate, boolean waveform, boolean fft) {
582df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        synchronized (mListenerLock) {
583df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            mCaptureListener = listener;
584df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
585df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        if (listener == null) {
586df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            // make sure capture callback is stopped in native code
587df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            waveform = false;
588df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            fft = false;
589df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
590df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        int status = native_setPeriodicCapture(rate, waveform, fft);
591df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        if (status == SUCCESS) {
592df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if ((listener != null) && (mNativeEventHandler == null)) {
593df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                Looper looper;
594df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                if ((looper = Looper.myLooper()) != null) {
595df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    mNativeEventHandler = new NativeEventHandler(this, looper);
596df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                } else if ((looper = Looper.getMainLooper()) != null) {
597df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    mNativeEventHandler = new NativeEventHandler(this, looper);
598df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                } else {
599df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    mNativeEventHandler = null;
600df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    status = ERROR_NO_INIT;
601df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                }
602df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
603df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
604df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return status;
605df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
606df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
607df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    /**
6083540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * @hide
6093540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     *
6103540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * The OnServerDiedListener interface defines a method called by the Visualizer to indicate that
6113540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * the connection to the native media server has been broken and that the Visualizer object will
6123540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * need to be released and re-created.
6133540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * The client application can implement this interface and register the listener with the
6143540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * {@link #setServerDiedListener(OnServerDiedListener)} method.
6153540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     */
6163540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    public interface OnServerDiedListener  {
6173540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        /**
6183540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * @hide
6193540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         *
6203540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * Method called when the native media server has died.
6213540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * <p>If the native media server encounters a fatal error and needs to restart, the binder
6223540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * connection from the {@link #Visualizer} to the media server will be broken.  Data capture
6233540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * callbacks will stop happening, and client initiated calls to the {@link #Visualizer}
6243540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * instance will fail with the error code {@link #DEAD_OBJECT}.  To restore functionality,
6253540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         * clients should {@link #release()} their old visualizer and create a new instance.
6263540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman         */
6273540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        void onServerDied();
6283540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    }
6293540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
6303540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    /**
6313540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * @hide
6323540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     *
6333540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * Registers an OnServerDiedListener interface.
6343540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * <p>Call this method with a null listener to stop receiving server death notifications.
6353540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     * @return {@link #SUCCESS} in case of success,
6363540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman     */
6373540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    public int setServerDiedListener(OnServerDiedListener listener) {
6383540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        synchronized (mListenerLock) {
6393540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            mServerDiedListener = listener;
6403540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        }
6413540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        return SUCCESS;
6423540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    }
6433540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
6443540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    /**
645df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     * Helper class to handle the forwarding of native events to the appropriate listeners
646df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent     */
647df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private class NativeEventHandler extends Handler
648df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {
649df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        private Visualizer mVisualizer;
650df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
651df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        public NativeEventHandler(Visualizer v, Looper looper) {
652df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            super(looper);
653df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            mVisualizer = v;
654df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
655df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
6563540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        private void handleCaptureMessage(Message msg) {
657df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            OnDataCaptureListener l = null;
658df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            synchronized (mListenerLock) {
659df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                l = mVisualizer.mCaptureListener;
660df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
661df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
662df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            if (l != null) {
663df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                byte[] data = (byte[])msg.obj;
664df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                int samplingRate = msg.arg1;
6653540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
666df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                switch(msg.what) {
667df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                case NATIVE_EVENT_PCM_CAPTURE:
668df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    l.onWaveFormDataCapture(mVisualizer, data, samplingRate);
669df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    break;
670df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                case NATIVE_EVENT_FFT_CAPTURE:
671df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    l.onFftDataCapture(mVisualizer, data, samplingRate);
672df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    break;
673df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                default:
6743540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                    Log.e(TAG,"Unknown native event in handleCaptureMessge: "+msg.what);
675df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                    break;
676df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                }
677df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            }
678df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
6793540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
6803540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        private void handleServerDiedMessage(Message msg) {
6813540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            OnServerDiedListener l = null;
6823540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            synchronized (mListenerLock) {
6833540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                l = mVisualizer.mServerDiedListener;
6843540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            }
6853540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
6863540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            if (l != null)
6873540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                l.onServerDied();
6883540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        }
6893540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
6903540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        @Override
6913540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        public void handleMessage(Message msg) {
6923540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            if (mVisualizer == null) {
6933540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                return;
6943540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            }
6953540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
6963540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            switch(msg.what) {
6973540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            case NATIVE_EVENT_PCM_CAPTURE:
6983540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            case NATIVE_EVENT_FFT_CAPTURE:
6993540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                handleCaptureMessage(msg);
7003540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                break;
7013540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            case NATIVE_EVENT_SERVER_DIED:
7023540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                handleServerDiedMessage(msg);
7033540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                break;
7043540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            default:
7053540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                Log.e(TAG,"Unknown native event: "+msg.what);
7063540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                break;
7073540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            }
7083540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        }
709df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
710df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
711df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //---------------------------------------------------------
712df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Interface definitions
713df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------
714df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
715df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private static native final void native_init();
716df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
717df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_setup(Object audioeffect_this,
718df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                          int audioSession,
719df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                          int[] id);
720df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
721df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final void native_finalize();
722df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
723df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final void native_release();
724df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
725df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_setEnabled(boolean enabled);
726df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
727df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final boolean native_getEnabled();
728df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
729df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_setCaptureSize(int size);
730df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
731df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_getCaptureSize();
732df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
733e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    private native final int native_setScalingMode(int mode);
734e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi
735e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi    private native final int native_getScalingMode();
736e1123e7f36723a8b888501c9a22a589297849ca2Jean-Michel Trivi
737badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    private native final int native_setMeasurementMode(int mode);
738badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
739badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    private native final int native_getMeasurementMode();
740badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
741df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_getSamplingRate();
742df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
743df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_getWaveForm(byte[] waveform);
744df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
745df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_getFft(byte[] fft);
746df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
747badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi    private native final int native_getPeakRms(MeasurementPeakRms measurement);
748badca26cb218852d32862dada36ee52fce865ad2Jean-Michel Trivi
749df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private native final int native_setPeriodicCapture(int rate, boolean waveForm, boolean fft);
750df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
751df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //---------------------------------------------------------
752df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Java methods called from the native side
753df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //--------------------
754df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    @SuppressWarnings("unused")
755df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    private static void postEventFromNative(Object effect_ref,
756df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            int what, int arg1, int arg2, Object obj) {
757df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        Visualizer visu = (Visualizer)((WeakReference)effect_ref).get();
758df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        if (visu == null) {
759df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            return;
760df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
761df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
762df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        if (visu.mNativeEventHandler != null) {
763df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            Message m = visu.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
764df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            visu.mNativeEventHandler.sendMessage(m);
765df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
766df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
767df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
768df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
769df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
770df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
771