/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.audiofx;

import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.util.UUID;

AudioEffect is the base class for controlling audio effects provided by the android audio framework.

Applications should not use the AudioEffect class directly but one of its derived classes to control specific effects:

To apply the audio effect to a specific AudioTrack or MediaPlayer instance, the application must specify the audio session ID of that instance when creating the AudioEffect. (see MediaPlayer.getAudioSessionId() for details on audio sessions).

NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output mix by use of session 0 is deprecated.

Creating an AudioEffect object will create the corresponding effect engine in the audio framework if no instance of the same effect type exists in the specified audio session. If one exists, this instance will be used.

The application creating the AudioEffect object (or a derived class) will either receive control of the effect engine or not depending on the priority parameter. If priority is higher than the priority used by the current effect engine owner, the control will be transfered to the new object. Otherwise control will remain with the previous object. In this case, the new application will be notified of changes in effect engine state or control ownership by the appropriate listener.

/** * AudioEffect is the base class for controlling audio effects provided by the android audio * framework. * <p>Applications should not use the AudioEffect class directly but one of its derived classes to * control specific effects: * <ul> * <li> {@link android.media.audiofx.Equalizer}</li> * <li> {@link android.media.audiofx.Virtualizer}</li> * <li> {@link android.media.audiofx.BassBoost}</li> * <li> {@link android.media.audiofx.PresetReverb}</li> * <li> {@link android.media.audiofx.EnvironmentalReverb}</li> * <li> {@link android.media.audiofx.DynamicsProcessing}</li> * </ul> * <p>To apply the audio effect to a specific AudioTrack or MediaPlayer instance, * the application must specify the audio session ID of that instance when creating the AudioEffect. * (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions). * <p>NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output * mix by use of session 0 is deprecated. * <p>Creating an AudioEffect object will create the corresponding effect engine in the audio * framework if no instance of the same effect type exists in the specified audio session. * If one exists, this instance will be used. * <p>The application creating the AudioEffect object (or a derived class) will either receive * control of the effect engine or not depending on the priority parameter. If priority is higher * than the priority used by the current effect engine owner, the control will be transfered to the * new object. Otherwise control will remain with the previous object. In this case, the new * application will be notified of changes in effect engine state or control ownership by the * appropriate listener. */
public class AudioEffect { static { System.loadLibrary("audioeffect_jni"); native_init(); } private final static String TAG = "AudioEffect-JAVA"; // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h /** * The following UUIDs define effect types corresponding to standard audio * effects whose implementation and interface conform to the OpenSL ES * specification. The definitions match the corresponding interface IDs in * OpenSLES_IID.h */
UUID for environmental reverberation effect
/** * UUID for environmental reverberation effect */
public static final UUID EFFECT_TYPE_ENV_REVERB = UUID .fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e");
UUID for preset reverberation effect
/** * UUID for preset reverberation effect */
public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID .fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");
UUID for equalizer effect
/** * UUID for equalizer effect */
public static final UUID EFFECT_TYPE_EQUALIZER = UUID .fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b");
UUID for bass boost effect
/** * UUID for bass boost effect */
public static final UUID EFFECT_TYPE_BASS_BOOST = UUID .fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
UUID for virtualizer effect
/** * UUID for virtualizer effect */
public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b"); /** * UUIDs for effect types not covered by OpenSL ES. */
UUID for Automatic Gain Control (AGC)
/** * UUID for Automatic Gain Control (AGC) */
public static final UUID EFFECT_TYPE_AGC = UUID .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");
UUID for Acoustic Echo Canceler (AEC)
/** * UUID for Acoustic Echo Canceler (AEC) */
public static final UUID EFFECT_TYPE_AEC = UUID .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");
UUID for Noise Suppressor (NS)
/** * UUID for Noise Suppressor (NS) */
public static final UUID EFFECT_TYPE_NS = UUID .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
UUID for Loudness Enhancer
/** * UUID for Loudness Enhancer */
public static final UUID EFFECT_TYPE_LOUDNESS_ENHANCER = UUID .fromString("fe3199be-aed0-413f-87bb-11260eb63cf1");
UUID for Dynamics Processing
/** * UUID for Dynamics Processing */
public static final UUID EFFECT_TYPE_DYNAMICS_PROCESSING = UUID .fromString("7261676f-6d75-7369-6364-28e2fd3ac39e");
Null effect UUID. See AudioEffect(UUID, UUID, int, int) for use.
@hide
/** * Null effect UUID. See {@link AudioEffect(UUID, UUID, int, int)} for use. * @hide */
@TestApi public static final UUID EFFECT_TYPE_NULL = UUID .fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");
State of an AudioEffect object that was not successfully initialized upon creation
@hide
/** * State of an AudioEffect object that was not successfully initialized upon * creation * @hide */
public static final int STATE_UNINITIALIZED = 0;
State of an AudioEffect object that is ready to be used.
@hide
/** * State of an AudioEffect object that is ready to be used. * @hide */
public static final int STATE_INITIALIZED = 1; // to keep in sync with // frameworks/base/include/media/AudioEffect.h
Event id for engine control ownership change notification.
@hide
/** * Event id for engine control ownership change notification. * @hide */
public static final int NATIVE_EVENT_CONTROL_STATUS = 0;
Event id for engine state change notification.
@hide
/** * Event id for engine state change notification. * @hide */
public static final int NATIVE_EVENT_ENABLED_STATUS = 1;
Event id for engine parameter change notification.
@hide
/** * Event id for engine parameter change notification. * @hide */
public static final int NATIVE_EVENT_PARAMETER_CHANGED = 2;
Successful operation.
/** * Successful operation. */
public static final int SUCCESS = 0;
Unspecified error.
/** * Unspecified error. */
public static final int ERROR = -1;
Internal operation status. Not returned by any method.
/** * Internal operation status. Not returned by any method. */
public static final int ALREADY_EXISTS = -2;
Operation failed due to bad object initialization.
/** * Operation failed due to bad object initialization. */
public static final int ERROR_NO_INIT = -3;
Operation failed due to bad parameter value.
/** * Operation failed due to bad parameter value. */
public static final int ERROR_BAD_VALUE = -4;
Operation failed because it was requested in wrong state.
/** * Operation failed because it was requested in wrong state. */
public static final int ERROR_INVALID_OPERATION = -5;
Operation failed due to lack of memory.
/** * Operation failed due to lack of memory. */
public static final int ERROR_NO_MEMORY = -6;
Operation failed due to dead remote object.
/** * Operation failed due to dead remote object. */
public static final int ERROR_DEAD_OBJECT = -7;
The effect descriptor contains information on a particular effect implemented in the audio framework:
The method AudioEffect.queryEffects() returns an array of Descriptors to facilitate effects enumeration.
/** * The effect descriptor contains information on a particular effect implemented in the * audio framework:<br> * <ul> * <li>type: UUID identifying the effect type. May be one of: * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC}, * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS}, * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}, {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}, * {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}. * </li> * <li>uuid: UUID for this particular implementation</li> * <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li> * <li>name: human readable effect name</li> * <li>implementor: human readable effect implementor name</li> * </ul> * The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects * enumeration. */
public static class Descriptor { public Descriptor() { }
Params:
/** * @param type UUID identifying the effect type. May be one of: * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC}, * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS}, * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}, * {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}, * {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}. * @param uuid UUID for this particular implementation * @param connectMode {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY} * @param name human readable effect name * @param implementor human readable effect implementor name * */
public Descriptor(String type, String uuid, String connectMode, String name, String implementor) { this.type = UUID.fromString(type); this.uuid = UUID.fromString(uuid); this.connectMode = connectMode; this.name = name; this.implementor = implementor; }
Indicates the generic type of the effect (Equalizer, Bass boost ...). One of AudioEffect.EFFECT_TYPE_AEC, AudioEffect.EFFECT_TYPE_AGC, AudioEffect.EFFECT_TYPE_BASS_BOOST, AudioEffect.EFFECT_TYPE_ENV_REVERB, AudioEffect.EFFECT_TYPE_EQUALIZER, AudioEffect.EFFECT_TYPE_NS, AudioEffect.EFFECT_TYPE_PRESET_REVERB AudioEffect.EFFECT_TYPE_VIRTUALIZER or AudioEffect.EFFECT_TYPE_DYNAMICS_PROCESSING.
For reverberation, bass boost, EQ and virtualizer, the UUID corresponds to the OpenSL ES Interface ID.
/** * Indicates the generic type of the effect (Equalizer, Bass boost ...). * One of {@link AudioEffect#EFFECT_TYPE_AEC}, * {@link AudioEffect#EFFECT_TYPE_AGC}, {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, * {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, * {@link AudioEffect#EFFECT_TYPE_NS}, {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB} * {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER} * or {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}.<br> * For reverberation, bass boost, EQ and virtualizer, the UUID * corresponds to the OpenSL ES Interface ID. */
public UUID type;
Indicates the particular implementation of the effect in that type. Several effects can have the same type but this uuid is unique to a given implementation.
/** * Indicates the particular implementation of the effect in that type. Several effects * can have the same type but this uuid is unique to a given implementation. */
public UUID uuid;
Indicates if the effect is of insert category AudioEffect.EFFECT_INSERT or auxiliary category AudioEffect.EFFECT_AUXILIARY. Insert effects (typically an Equalizer) are applied to the entire audio source and usually not shared by several sources. Auxiliary effects (typically a reverberator) are applied to part of the signal (wet) and the effect output is added to the original signal (dry). Audio pre processing are applied to audio captured on a particular AudioRecord.
/** * Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary * category {@link #EFFECT_AUXILIARY}. * Insert effects (typically an {@link Equalizer}) are applied * to the entire audio source and usually not shared by several sources. Auxiliary effects * (typically a reverberator) are applied to part of the signal (wet) and the effect output * is added to the original signal (dry). * Audio pre processing are applied to audio captured on a particular * {@link android.media.AudioRecord}. */
public String connectMode;
Human readable effect name
/** * Human readable effect name */
public String name;
Human readable effect implementor name
/** * Human readable effect implementor name */
public String implementor; };
Effect connection mode is insert. Specifying an audio session ID when creating the effect will insert this effect after all players in the same audio session.
/** * Effect connection mode is insert. Specifying an audio session ID when creating the effect * will insert this effect after all players in the same audio session. */
public static final String EFFECT_INSERT = "Insert";
Effect connection mode is auxiliary.

Auxiliary effects must be created on session 0 (global output mix). In order for a MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to this effect and a send level must be specified.

Use the effect ID returned by getId() to designate this particular effect when attaching it to the MediaPlayer or AudioTrack.

/** * Effect connection mode is auxiliary. * <p>Auxiliary effects must be created on session 0 (global output mix). In order for a * MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to * this effect and a send level must be specified. * <p>Use the effect ID returned by {@link #getId()} to designate this particular effect when * attaching it to the MediaPlayer or AudioTrack. */
public static final String EFFECT_AUXILIARY = "Auxiliary";
Effect connection mode is pre processing. The audio pre processing effects are attached to an audio input (AudioRecord).
@hide
/** * Effect connection mode is pre processing. * The audio pre processing effects are attached to an audio input (AudioRecord). * @hide */
public static final String EFFECT_PRE_PROCESSING = "Pre Processing"; // -------------------------------------------------------------------------- // Member variables // --------------------
Indicates the state of the AudioEffect instance
/** * Indicates the state of the AudioEffect instance */
private int mState = STATE_UNINITIALIZED;
Lock to synchronize access to mState
/** * Lock to synchronize access to mState */
private final Object mStateLock = new Object();
System wide unique effect ID
/** * System wide unique effect ID */
private int mId; // accessed by native methods private long mNativeAudioEffect; private long mJniData;
Effect descriptor
/** * Effect descriptor */
private Descriptor mDescriptor;
Listener for effect engine state change notifications.
See Also:
  • setEnableStatusListener(OnEnableStatusChangeListener)
/** * Listener for effect engine state change notifications. * * @see #setEnableStatusListener(OnEnableStatusChangeListener) */
private OnEnableStatusChangeListener mEnableStatusChangeListener = null;
Listener for effect engine control ownership change notifications.
See Also:
  • setControlStatusListener(OnControlStatusChangeListener)
/** * Listener for effect engine control ownership change notifications. * * @see #setControlStatusListener(OnControlStatusChangeListener) */
private OnControlStatusChangeListener mControlChangeStatusListener = null;
Listener for effect engine control ownership change notifications.
See Also:
  • setParameterListener(OnParameterChangeListener)
/** * Listener for effect engine control ownership change notifications. * * @see #setParameterListener(OnParameterChangeListener) */
private OnParameterChangeListener mParameterChangeListener = null;
Lock to protect listeners updates against event notifications
@hide
/** * Lock to protect listeners updates against event notifications * @hide */
public final Object mListenerLock = new Object();
Handler for events coming from the native code
@hide
/** * Handler for events coming from the native code * @hide */
public NativeEventHandler mNativeEventHandler = null; // -------------------------------------------------------------------------- // Constructor, Finalize // --------------------
Class constructor.
Params:
  • type – type of effect engine created. See EFFECT_TYPE_ENV_REVERB, EFFECT_TYPE_EQUALIZER ... Types corresponding to built-in effects are defined by AudioEffect class. Other types can be specified provided they correspond an existing OpenSL ES interface ID and the corresponsing effect is available on the platform. If an unspecified effect type is requested, the constructor with throw the IllegalArgumentException. This parameter can be set to EFFECT_TYPE_NULL in which case only the uuid will be used to select the effect.
  • uuid – unique identifier of a particular effect implementation. Must be specified if the caller wants to use a particular implementation of an effect type. This parameter can be set to EFFECT_TYPE_NULL in which case only the type will be used to select the effect.
  • priority – the priority level requested by the application for controlling the effect engine. As the same effect engine can be shared by several applications, this parameter indicates how much the requesting application needs control of effect parameters. The normal priority is 0, above normal is a positive number, below normal a negative number.
  • audioSession – system wide unique audio session identifier. The effect will be attached to the MediaPlayer or AudioTrack in the same audio session.
Throws:
@hide
/** * Class constructor. * * @param type type of effect engine created. See {@link #EFFECT_TYPE_ENV_REVERB}, * {@link #EFFECT_TYPE_EQUALIZER} ... Types corresponding to * built-in effects are defined by AudioEffect class. Other types * can be specified provided they correspond an existing OpenSL * ES interface ID and the corresponsing effect is available on * the platform. If an unspecified effect type is requested, the * constructor with throw the IllegalArgumentException. This * parameter can be set to {@link #EFFECT_TYPE_NULL} in which * case only the uuid will be used to select the effect. * @param uuid unique identifier of a particular effect implementation. * Must be specified if the caller wants to use a particular * implementation of an effect type. This parameter can be set to * {@link #EFFECT_TYPE_NULL} in which case only the type will * be used to select the effect. * @param priority the priority level requested by the application for * controlling the effect engine. As the same effect engine can * be shared by several applications, this parameter indicates * how much the requesting application needs control of effect * parameters. The normal priority is 0, above normal is a * positive number, below normal a negative number. * @param audioSession system wide unique audio session identifier. * The effect will be attached to the MediaPlayer or AudioTrack in * the same audio session. * * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException * @hide */
public AudioEffect(UUID type, UUID uuid, int priority, int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { int[] id = new int[1]; Descriptor[] desc = new Descriptor[1]; // native initialization int initResult = native_setup(new WeakReference<AudioEffect>(this), type.toString(), uuid.toString(), priority, audioSession, id, desc, ActivityThread.currentOpPackageName()); if (initResult != SUCCESS && initResult != ALREADY_EXISTS) { Log.e(TAG, "Error code " + initResult + " when initializing AudioEffect."); switch (initResult) { case ERROR_BAD_VALUE: throw (new IllegalArgumentException("Effect type: " + type + " not supported.")); case ERROR_INVALID_OPERATION: throw (new UnsupportedOperationException( "Effect library not loaded")); default: throw (new RuntimeException( "Cannot initialize effect engine for type: " + type + " Error: " + initResult)); } } mId = id[0]; mDescriptor = desc[0]; synchronized (mStateLock) { mState = STATE_INITIALIZED; } }
Releases the native AudioEffect resources. It is a good practice to release the effect engine when not in use as control can be returned to other applications or the native resources released.
/** * Releases the native AudioEffect resources. It is a good practice to * release the effect engine when not in use as control can be returned to * other applications or the native resources released. */
public void release() { synchronized (mStateLock) { native_release(); mState = STATE_UNINITIALIZED; } } @Override protected void finalize() { native_finalize(); }
Get the effect descriptor.
Throws:
See Also:
  • Descriptor
/** * Get the effect descriptor. * * @see android.media.audiofx.AudioEffect.Descriptor * @throws IllegalStateException */
public Descriptor getDescriptor() throws IllegalStateException { checkState("getDescriptor()"); return mDescriptor; } // -------------------------------------------------------------------------- // Effects Enumeration // --------------------
Query all effects available on the platform. Returns an array of Descriptor objects
Throws:
/** * Query all effects available on the platform. Returns an array of * {@link android.media.audiofx.AudioEffect.Descriptor} objects * * @throws IllegalStateException */
static public Descriptor[] queryEffects() { return (Descriptor[]) native_query_effects(); }
Query all audio pre-processing effects applied to the AudioRecord with the supplied audio session ID. Returns an array of Descriptor objects.
Params:
  • audioSession – system wide unique audio session identifier.
Throws:
@hide
/** * Query all audio pre-processing effects applied to the AudioRecord with the supplied * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor} * objects. * @param audioSession system wide unique audio session identifier. * @throws IllegalStateException * @hide */
static public Descriptor[] queryPreProcessings(int audioSession) { return (Descriptor[]) native_query_pre_processing(audioSession); }
Checks if the device implements the specified effect type.
Params:
  • type – the requested effect type.
Returns:true if the device implements the specified effect type, false otherwise.
@hide
/** * Checks if the device implements the specified effect type. * @param type the requested effect type. * @return true if the device implements the specified effect type, false otherwise. * @hide */
@TestApi public static boolean isEffectTypeAvailable(UUID type) { AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); if (desc == null) { return false; } for (int i = 0; i < desc.length; i++) { if (desc[i].type.equals(type)) { return true; } } return false; } // -------------------------------------------------------------------------- // Control methods // --------------------
Enable or disable the effect. Creating an audio effect does not automatically apply this effect on the audio source. It creates the resources necessary to process this effect but the audio signal is still bypassed through the effect engine. Calling this method will make that the effect is actually applied or not to the audio content being played in the corresponding audio session.
Params:
  • enabled – the requested enable state
Throws:
Returns:SUCCESS in case of success, ERROR_INVALID_OPERATION or ERROR_DEAD_OBJECT in case of failure.
/** * Enable or disable the effect. * Creating an audio effect does not automatically apply this effect on the audio source. It * creates the resources necessary to process this effect but the audio signal is still bypassed * through the effect engine. Calling this method will make that the effect is actually applied * or not to the audio content being played in the corresponding audio session. * * @param enabled the requested enable state * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION} * or {@link #ERROR_DEAD_OBJECT} in case of failure. * @throws IllegalStateException */
public int setEnabled(boolean enabled) throws IllegalStateException { checkState("setEnabled()"); return native_setEnabled(enabled); }
Set effect parameter. The setParameter method is provided in several forms addressing most common parameter formats. This form is the most generic one where the parameter and its value are both specified as an array of bytes. The parameter and value type and length are therefore totally free. For standard effect defined by OpenSL ES, the parameter format and values must match the definitions in the corresponding OpenSL ES interface.
Params:
  • param – the identifier of the parameter to set
  • value – the new value for the specified parameter
Throws:
Returns:SUCCESS in case of success, ERROR_BAD_VALUE, ERROR_NO_MEMORY, ERROR_INVALID_OPERATION or ERROR_DEAD_OBJECT in case of failure
@hide
/** * Set effect parameter. The setParameter method is provided in several * forms addressing most common parameter formats. This form is the most * generic one where the parameter and its value are both specified as an * array of bytes. The parameter and value type and length are therefore * totally free. For standard effect defined by OpenSL ES, the parameter * format and values must match the definitions in the corresponding OpenSL * ES interface. * * @param param the identifier of the parameter to set * @param value the new value for the specified parameter * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE}, * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or * {@link #ERROR_DEAD_OBJECT} in case of failure * @throws IllegalStateException * @hide */
@TestApi public int setParameter(byte[] param, byte[] value) throws IllegalStateException { checkState("setParameter()"); return native_setParameter(param.length, param, value.length, value); }
Set effect parameter. The parameter and its value are integers.
See Also:
  • setParameter(byte[], byte[])
@hide
/** * Set effect parameter. The parameter and its value are integers. * * @see #setParameter(byte[], byte[]) * @hide */
@TestApi public int setParameter(int param, int value) throws IllegalStateException { byte[] p = intToByteArray(param); byte[] v = intToByteArray(value); return setParameter(p, v); }
Set effect parameter. The parameter is an integer and the value is a short integer.
See Also:
  • setParameter(byte[], byte[])
@hide
/** * Set effect parameter. The parameter is an integer and the value is a * short integer. * * @see #setParameter(byte[], byte[]) * @hide */
@TestApi public int setParameter(int param, short value) throws IllegalStateException { byte[] p = intToByteArray(param); byte[] v = shortToByteArray(value); return setParameter(p, v); }
Set effect parameter. The parameter is an integer and the value is an array of bytes.
See Also:
  • setParameter(byte[], byte[])
@hide
/** * Set effect parameter. The parameter is an integer and the value is an * array of bytes. * * @see #setParameter(byte[], byte[]) * @hide */
@TestApi public int setParameter(int param, byte[] value) throws IllegalStateException { byte[] p = intToByteArray(param); return setParameter(p, value); }
Set effect parameter. The parameter is an array of 1 or 2 integers and the value is also an array of 1 or 2 integers
See Also:
  • setParameter(byte[], byte[])
@hide
/** * Set effect parameter. The parameter is an array of 1 or 2 integers and * the value is also an array of 1 or 2 integers * * @see #setParameter(byte[], byte[]) * @hide */
@TestApi public int setParameter(int[] param, int[] value) throws IllegalStateException { if (param.length > 2 || value.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param[0]); if (param.length > 1) { byte[] p2 = intToByteArray(param[1]); p = concatArrays(p, p2); } byte[] v = intToByteArray(value[0]); if (value.length > 1) { byte[] v2 = intToByteArray(value[1]); v = concatArrays(v, v2); } return setParameter(p, v); }
Set effect parameter. The parameter is an array of 1 or 2 integers and the value is an array of 1 or 2 short integers
See Also:
  • setParameter(byte[], byte[])
@hide
/** * Set effect parameter. The parameter is an array of 1 or 2 integers and * the value is an array of 1 or 2 short integers * * @see #setParameter(byte[], byte[]) * @hide */
public int setParameter(int[] param, short[] value) throws IllegalStateException { if (param.length > 2 || value.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param[0]); if (param.length > 1) { byte[] p2 = intToByteArray(param[1]); p = concatArrays(p, p2); } byte[] v = shortToByteArray(value[0]); if (value.length > 1) { byte[] v2 = shortToByteArray(value[1]); v = concatArrays(v, v2); } return setParameter(p, v); }
Set effect parameter. The parameter is an array of 1 or 2 integers and the value is an array of bytes
See Also:
  • setParameter(byte[], byte[])
@hide
/** * Set effect parameter. The parameter is an array of 1 or 2 integers and * the value is an array of bytes * * @see #setParameter(byte[], byte[]) * @hide */
@TestApi public int setParameter(int[] param, byte[] value) throws IllegalStateException { if (param.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param[0]); if (param.length > 1) { byte[] p2 = intToByteArray(param[1]); p = concatArrays(p, p2); } return setParameter(p, value); }
Get effect parameter. The getParameter method is provided in several forms addressing most common parameter formats. This form is the most generic one where the parameter and its value are both specified as an array of bytes. The parameter and value type and length are therefore totally free.
Params:
  • param – the identifier of the parameter to set
  • value – the new value for the specified parameter
Throws:
Returns:the number of meaningful bytes in value array in case of success or ERROR_BAD_VALUE, ERROR_NO_MEMORY, ERROR_INVALID_OPERATION or ERROR_DEAD_OBJECT in case of failure.
@hide
/** * Get effect parameter. The getParameter method is provided in several * forms addressing most common parameter formats. This form is the most * generic one where the parameter and its value are both specified as an * array of bytes. The parameter and value type and length are therefore * totally free. * * @param param the identifier of the parameter to set * @param value the new value for the specified parameter * @return the number of meaningful bytes in value array in case of success or * {@link #ERROR_BAD_VALUE}, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} * or {@link #ERROR_DEAD_OBJECT} in case of failure. * @throws IllegalStateException * @hide */
@TestApi public int getParameter(byte[] param, byte[] value) throws IllegalStateException { checkState("getParameter()"); return native_getParameter(param.length, param, value.length, value); }
Get effect parameter. The parameter is an integer and the value is an array of bytes.
See Also:
  • getParameter(byte[], byte[])
@hide
/** * Get effect parameter. The parameter is an integer and the value is an * array of bytes. * * @see #getParameter(byte[], byte[]) * @hide */
@TestApi public int getParameter(int param, byte[] value) throws IllegalStateException { byte[] p = intToByteArray(param); return getParameter(p, value); }
Get effect parameter. The parameter is an integer and the value is an array of 1 or 2 integers
See Also:
  • In case of success, returns the number of meaningful integers in value array.
@hide
/** * Get effect parameter. The parameter is an integer and the value is an * array of 1 or 2 integers * * @see #getParameter(byte[], byte[]) * In case of success, returns the number of meaningful integers in value array. * @hide */
@TestApi public int getParameter(int param, int[] value) throws IllegalStateException { if (value.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param); byte[] v = new byte[value.length * 4]; int status = getParameter(p, v); if (status == 4 || status == 8) { value[0] = byteArrayToInt(v); if (status == 8) { value[1] = byteArrayToInt(v, 4); } status /= 4; } else { status = ERROR; } return status; }
Get effect parameter. The parameter is an integer and the value is an array of 1 or 2 short integers
See Also:
  • In case of success, returns the number of meaningful short integers in value array.
@hide
/** * Get effect parameter. The parameter is an integer and the value is an * array of 1 or 2 short integers * * @see #getParameter(byte[], byte[]) * In case of success, returns the number of meaningful short integers in value array. * @hide */
@TestApi public int getParameter(int param, short[] value) throws IllegalStateException { if (value.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param); byte[] v = new byte[value.length * 2]; int status = getParameter(p, v); if (status == 2 || status == 4) { value[0] = byteArrayToShort(v); if (status == 4) { value[1] = byteArrayToShort(v, 2); } status /= 2; } else { status = ERROR; } return status; }
Get effect parameter. The parameter is an array of 1 or 2 integers and the value is also an array of 1 or 2 integers
See Also:
  • In case of success, the returns the number of meaningful integers in value array.
@hide
/** * Get effect parameter. The parameter is an array of 1 or 2 integers and * the value is also an array of 1 or 2 integers * * @see #getParameter(byte[], byte[]) * In case of success, the returns the number of meaningful integers in value array. * @hide */
public int getParameter(int[] param, int[] value) throws IllegalStateException { if (param.length > 2 || value.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param[0]); if (param.length > 1) { byte[] p2 = intToByteArray(param[1]); p = concatArrays(p, p2); } byte[] v = new byte[value.length * 4]; int status = getParameter(p, v); if (status == 4 || status == 8) { value[0] = byteArrayToInt(v); if (status == 8) { value[1] = byteArrayToInt(v, 4); } status /= 4; } else { status = ERROR; } return status; }
Get effect parameter. The parameter is an array of 1 or 2 integers and the value is an array of 1 or 2 short integers
See Also:
  • In case of success, returns the number of meaningful short integers in value array.
@hide
/** * Get effect parameter. The parameter is an array of 1 or 2 integers and * the value is an array of 1 or 2 short integers * * @see #getParameter(byte[], byte[]) * In case of success, returns the number of meaningful short integers in value array. * @hide */
@TestApi public int getParameter(int[] param, short[] value) throws IllegalStateException { if (param.length > 2 || value.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param[0]); if (param.length > 1) { byte[] p2 = intToByteArray(param[1]); p = concatArrays(p, p2); } byte[] v = new byte[value.length * 2]; int status = getParameter(p, v); if (status == 2 || status == 4) { value[0] = byteArrayToShort(v); if (status == 4) { value[1] = byteArrayToShort(v, 2); } status /= 2; } else { status = ERROR; } return status; }
Get effect parameter. The parameter is an array of 1 or 2 integers and the value is an array of bytes
See Also:
  • getParameter(byte[], byte[])
@hide
/** * Get effect parameter. The parameter is an array of 1 or 2 integers and * the value is an array of bytes * * @see #getParameter(byte[], byte[]) * @hide */
public int getParameter(int[] param, byte[] value) throws IllegalStateException { if (param.length > 2) { return ERROR_BAD_VALUE; } byte[] p = intToByteArray(param[0]); if (param.length > 1) { byte[] p2 = intToByteArray(param[1]); p = concatArrays(p, p2); } return getParameter(p, value); }
Send a command to the effect engine. This method is intended to send proprietary commands to a particular effect implementation. In case of success, returns the number of meaningful bytes in reply array. In case of failure, the returned value is negative and implementation specific.
@hide
/** * Send a command to the effect engine. This method is intended to send * proprietary commands to a particular effect implementation. * In case of success, returns the number of meaningful bytes in reply array. * In case of failure, the returned value is negative and implementation specific. * @hide */
public int command(int cmdCode, byte[] command, byte[] reply) throws IllegalStateException { checkState("command()"); return native_command(cmdCode, command.length, command, reply.length, reply); } // -------------------------------------------------------------------------- // Getters // --------------------
Returns effect unique identifier. This system wide unique identifier can be used to attach this effect to a MediaPlayer or an AudioTrack when the effect is an auxiliary effect (Reverb)
Throws:
Returns:the effect identifier.
/** * Returns effect unique identifier. This system wide unique identifier can * be used to attach this effect to a MediaPlayer or an AudioTrack when the * effect is an auxiliary effect (Reverb) * * @return the effect identifier. * @throws IllegalStateException */
public int getId() throws IllegalStateException { checkState("getId()"); return mId; }
Returns effect enabled state
Throws:
Returns:true if the effect is enabled, false otherwise.
/** * Returns effect enabled state * * @return true if the effect is enabled, false otherwise. * @throws IllegalStateException */
public boolean getEnabled() throws IllegalStateException { checkState("getEnabled()"); return native_getEnabled(); }
Checks if this AudioEffect object is controlling the effect engine.
Throws:
Returns:true if this instance has control of effect engine, false otherwise.
/** * Checks if this AudioEffect object is controlling the effect engine. * * @return true if this instance has control of effect engine, false * otherwise. * @throws IllegalStateException */
public boolean hasControl() throws IllegalStateException { checkState("hasControl()"); return native_hasControl(); } // -------------------------------------------------------------------------- // Initialization / configuration // --------------------
Sets the listener AudioEffect notifies when the effect engine is enabled or disabled.
Params:
  • listener –
/** * Sets the listener AudioEffect notifies when the effect engine is enabled * or disabled. * * @param listener */
public void setEnableStatusListener(OnEnableStatusChangeListener listener) { synchronized (mListenerLock) { mEnableStatusChangeListener = listener; } if ((listener != null) && (mNativeEventHandler == null)) { createNativeEventHandler(); } }
Sets the listener AudioEffect notifies when the effect engine control is taken or returned.
Params:
  • listener –
/** * Sets the listener AudioEffect notifies when the effect engine control is * taken or returned. * * @param listener */
public void setControlStatusListener(OnControlStatusChangeListener listener) { synchronized (mListenerLock) { mControlChangeStatusListener = listener; } if ((listener != null) && (mNativeEventHandler == null)) { createNativeEventHandler(); } }
Sets the listener AudioEffect notifies when a parameter is changed.
Params:
  • listener –
@hide
/** * Sets the listener AudioEffect notifies when a parameter is changed. * * @param listener * @hide */
@TestApi public void setParameterListener(OnParameterChangeListener listener) { synchronized (mListenerLock) { mParameterChangeListener = listener; } if ((listener != null) && (mNativeEventHandler == null)) { createNativeEventHandler(); } } // Convenience method for the creation of the native event handler // It is called only when a non-null event listener is set. // precondition: // mNativeEventHandler is null private void createNativeEventHandler() { Looper looper; if ((looper = Looper.myLooper()) != null) { mNativeEventHandler = new NativeEventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mNativeEventHandler = new NativeEventHandler(this, looper); } else { mNativeEventHandler = null; } } // --------------------------------------------------------- // Interface definitions // --------------------
The OnEnableStatusChangeListener interface defines a method called by the AudioEffect when a the enabled state of the effect engine was changed by the controlling application.
/** * The OnEnableStatusChangeListener interface defines a method called by the AudioEffect * when a the enabled state of the effect engine was changed by the controlling application. */
public interface OnEnableStatusChangeListener {
Called on the listener to notify it that the effect engine has been enabled or disabled.
Params:
  • effect – the effect on which the interface is registered.
  • enabled – new effect state.
/** * Called on the listener to notify it that the effect engine has been * enabled or disabled. * @param effect the effect on which the interface is registered. * @param enabled new effect state. */
void onEnableStatusChange(AudioEffect effect, boolean enabled); }
The OnControlStatusChangeListener interface defines a method called by the AudioEffect when a the control of the effect engine is gained or lost by the application
/** * The OnControlStatusChangeListener interface defines a method called by the AudioEffect * when a the control of the effect engine is gained or lost by the application */
public interface OnControlStatusChangeListener {
Called on the listener to notify it that the effect engine control has been taken or returned.
Params:
  • effect – the effect on which the interface is registered.
  • controlGranted – true if the application has been granted control of the effect engine, false otherwise.
/** * Called on the listener to notify it that the effect engine control * has been taken or returned. * @param effect the effect on which the interface is registered. * @param controlGranted true if the application has been granted control of the effect * engine, false otherwise. */
void onControlStatusChange(AudioEffect effect, boolean controlGranted); }
The OnParameterChangeListener interface defines a method called by the AudioEffect when a parameter is changed in the effect engine by the controlling application.
@hide
/** * The OnParameterChangeListener interface defines a method called by the AudioEffect * when a parameter is changed in the effect engine by the controlling application. * @hide */
@TestApi public interface OnParameterChangeListener {
Called on the listener to notify it that a parameter value has changed.
Params:
  • effect – the effect on which the interface is registered.
  • status – status of the set parameter operation.
  • param – ID of the modified parameter.
  • value – the new parameter value.
/** * Called on the listener to notify it that a parameter value has changed. * @param effect the effect on which the interface is registered. * @param status status of the set parameter operation. * @param param ID of the modified parameter. * @param value the new parameter value. */
void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value); } // ------------------------------------------------------------------------- // Audio Effect Control panel intents // -------------------------------------------------------------------------
Intent to launch an audio effect control panel UI.

The goal of this intent is to enable separate implementations of music/media player applications and audio effect control application or services. This will allow platform vendors to offer more advanced control options for standard effects or control for platform specific effects.

The intent carries a number of extras used by the player application to communicate necessary pieces of information to the control panel application.

The calling application must use the Activity.startActivityForResult(Intent, int) method to launch the control panel so that its package name is indicated and used by the control panel application to keep track of changes for this particular application.

The EXTRA_AUDIO_SESSION extra will indicate an audio session to which the audio effects should be applied. If no audio session is specified, either one of the follownig will happen:

- If an audio session was previously opened by the calling application with ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION intent, the effect changes will be applied to that session.

- If no audio session is opened, the changes will be stored in the package specific storage area and applied whenever a new audio session is opened by this application.

The EXTRA_CONTENT_TYPE extra will help the control panel application customize both the UI layout and the default audio effect settings if none are already stored for the calling application.

/** * Intent to launch an audio effect control panel UI. * <p>The goal of this intent is to enable separate implementations of music/media player * applications and audio effect control application or services. * This will allow platform vendors to offer more advanced control options for standard effects * or control for platform specific effects. * <p>The intent carries a number of extras used by the player application to communicate * necessary pieces of information to the control panel application. * <p>The calling application must use the * {@link android.app.Activity#startActivityForResult(Intent, int)} method to launch the * control panel so that its package name is indicated and used by the control panel * application to keep track of changes for this particular application. * <p>The {@link #EXTRA_AUDIO_SESSION} extra will indicate an audio session to which the * audio effects should be applied. If no audio session is specified, either one of the * follownig will happen: * <p>- If an audio session was previously opened by the calling application with * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intent, the effect changes will * be applied to that session. * <p>- If no audio session is opened, the changes will be stored in the package specific * storage area and applied whenever a new audio session is opened by this application. * <p>The {@link #EXTRA_CONTENT_TYPE} extra will help the control panel application * customize both the UI layout and the default audio effect settings if none are already * stored for the calling application. */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL = "android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL";
Intent to signal to the effect control application or service that a new audio session is opened and requires audio effects to be applied.

This is different from ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL in that no UI should be displayed in this case. Music player applications can broadcast this intent before starting playback to make sure that any audio effect settings previously selected by the user are applied.

The effect control application receiving this intent will look for previously stored settings for the calling application, create all required audio effects and apply the effect settings to the specified audio session.

The calling package name is indicated by the EXTRA_PACKAGE_NAME extra and the audio session ID by the EXTRA_AUDIO_SESSION extra. Both extras are mandatory.

If no stored settings are found for the calling application, default settings for the content type indicated by EXTRA_CONTENT_TYPE will be applied. The default settings for a given content type are platform specific.

/** * Intent to signal to the effect control application or service that a new audio session * is opened and requires audio effects to be applied. * <p>This is different from {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no * UI should be displayed in this case. Music player applications can broadcast this intent * before starting playback to make sure that any audio effect settings previously selected * by the user are applied. * <p>The effect control application receiving this intent will look for previously stored * settings for the calling application, create all required audio effects and apply the * effect settings to the specified audio session. * <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the * audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory. * <p>If no stored settings are found for the calling application, default settings for the * content type indicated by {@link #EXTRA_CONTENT_TYPE} will be applied. The default settings * for a given content type are platform specific. */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION = "android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";
Intent to signal to the effect control application or service that an audio session is closed and that effects should not be applied anymore.

The effect control application receiving this intent will delete all effects on this session and store current settings in package specific storage.

The calling package name is indicated by the EXTRA_PACKAGE_NAME extra and the audio session ID by the EXTRA_AUDIO_SESSION extra. Both extras are mandatory.

It is good practice for applications to broadcast this intent when music playback stops and/or when exiting to free system resources consumed by audio effect engines.

/** * Intent to signal to the effect control application or service that an audio session * is closed and that effects should not be applied anymore. * <p>The effect control application receiving this intent will delete all effects on * this session and store current settings in package specific storage. * <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the * audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory. * <p>It is good practice for applications to broadcast this intent when music playback stops * and/or when exiting to free system resources consumed by audio effect engines. */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION = "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";
Contains the ID of the audio session the effects should be applied to.

This extra is for use with ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL, ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION and ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION intents.

The extra value is of type int and is the audio session ID. @see android.media.MediaPlayer#getAudioSessionId() for details on audio sessions.

/** * Contains the ID of the audio session the effects should be applied to. * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL}, * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents. * <p>The extra value is of type int and is the audio session ID. * @see android.media.MediaPlayer#getAudioSessionId() for details on audio sessions. */
public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
Contains the package name of the calling application.

This extra is for use with ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION and ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION intents.

The extra value is a string containing the full package name.

/** * Contains the package name of the calling application. * <p>This extra is for use with {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents. * <p>The extra value is a string containing the full package name. */
public static final String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";
Indicates which type of content is played by the application.

This extra is for use with ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL and ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION intents.

This information is used by the effect control application to customize UI and select appropriate default effect settings. The content type is one of the following:

If omitted, the content type defaults to CONTENT_TYPE_MUSIC.
/** * Indicates which type of content is played by the application. * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} and * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intents. * <p>This information is used by the effect control application to customize UI and select * appropriate default effect settings. The content type is one of the following: * <ul> * <li>{@link #CONTENT_TYPE_MUSIC}</li> * <li>{@link #CONTENT_TYPE_MOVIE}</li> * <li>{@link #CONTENT_TYPE_GAME}</li> * <li>{@link #CONTENT_TYPE_VOICE}</li> * </ul> * If omitted, the content type defaults to {@link #CONTENT_TYPE_MUSIC}. */
public static final String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE";
Value for EXTRA_CONTENT_TYPE when the type of content played is music
/** * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is music */
public static final int CONTENT_TYPE_MUSIC = 0;
Value for EXTRA_CONTENT_TYPE when the type of content played is video or movie
/** * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video or movie */
public static final int CONTENT_TYPE_MOVIE = 1;
Value for EXTRA_CONTENT_TYPE when the type of content played is game audio
/** * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is game audio */
public static final int CONTENT_TYPE_GAME = 2;
Value for EXTRA_CONTENT_TYPE when the type of content played is voice audio
/** * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is voice audio */
public static final int CONTENT_TYPE_VOICE = 3; // --------------------------------------------------------- // Inner classes // --------------------
Helper class to handle the forwarding of native events to the appropriate listeners
/** * Helper class to handle the forwarding of native events to the appropriate * listeners */
private class NativeEventHandler extends Handler { private AudioEffect mAudioEffect; public NativeEventHandler(AudioEffect ae, Looper looper) { super(looper); mAudioEffect = ae; } @Override public void handleMessage(Message msg) { if (mAudioEffect == null) { return; } switch (msg.what) { case NATIVE_EVENT_ENABLED_STATUS: OnEnableStatusChangeListener enableStatusChangeListener = null; synchronized (mListenerLock) { enableStatusChangeListener = mAudioEffect.mEnableStatusChangeListener; } if (enableStatusChangeListener != null) { enableStatusChangeListener.onEnableStatusChange( mAudioEffect, (boolean) (msg.arg1 != 0)); } break; case NATIVE_EVENT_CONTROL_STATUS: OnControlStatusChangeListener controlStatusChangeListener = null; synchronized (mListenerLock) { controlStatusChangeListener = mAudioEffect.mControlChangeStatusListener; } if (controlStatusChangeListener != null) { controlStatusChangeListener.onControlStatusChange( mAudioEffect, (boolean) (msg.arg1 != 0)); } break; case NATIVE_EVENT_PARAMETER_CHANGED: OnParameterChangeListener parameterChangeListener = null; synchronized (mListenerLock) { parameterChangeListener = mAudioEffect.mParameterChangeListener; } if (parameterChangeListener != null) { // arg1 contains offset of parameter value from start of // byte array int vOffset = msg.arg1; byte[] p = (byte[]) msg.obj; // See effect_param_t in EffectApi.h for psize and vsize // fields offsets int status = byteArrayToInt(p, 0); int psize = byteArrayToInt(p, 4); int vsize = byteArrayToInt(p, 8); byte[] param = new byte[psize]; byte[] value = new byte[vsize]; System.arraycopy(p, 12, param, 0, psize); System.arraycopy(p, vOffset, value, 0, vsize); parameterChangeListener.onParameterChange(mAudioEffect, status, param, value); } break; default: Log.e(TAG, "handleMessage() Unknown event type: " + msg.what); break; } } } // --------------------------------------------------------- // Java methods called from the native side // -------------------- @SuppressWarnings("unused") private static void postEventFromNative(Object effect_ref, int what, int arg1, int arg2, Object obj) { AudioEffect effect = (AudioEffect) ((WeakReference) effect_ref).get(); if (effect == null) { return; } if (effect.mNativeEventHandler != null) { Message m = effect.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj); effect.mNativeEventHandler.sendMessage(m); } } // --------------------------------------------------------- // Native methods called from the Java side // -------------------- private static native final void native_init(); private native final int native_setup(Object audioeffect_this, String type, String uuid, int priority, int audioSession, int[] id, Object[] desc, String opPackageName); private native final void native_finalize(); private native final void native_release(); private native final int native_setEnabled(boolean enabled); private native final boolean native_getEnabled(); private native final boolean native_hasControl(); private native final int native_setParameter(int psize, byte[] param, int vsize, byte[] value); private native final int native_getParameter(int psize, byte[] param, int vsize, byte[] value); private native final int native_command(int cmdCode, int cmdSize, byte[] cmdData, int repSize, byte[] repData); private static native Object[] native_query_effects(); private static native Object[] native_query_pre_processing(int audioSession); // --------------------------------------------------------- // Utility methods // ------------------
@hide
/** * @hide */
public void checkState(String methodName) throws IllegalStateException { synchronized (mStateLock) { if (mState != STATE_INITIALIZED) { throw (new IllegalStateException(methodName + " called on uninitialized AudioEffect.")); } } }
@hide
/** * @hide */
public void checkStatus(int status) { if (isError(status)) { switch (status) { case AudioEffect.ERROR_BAD_VALUE: throw (new IllegalArgumentException( "AudioEffect: bad parameter value")); case AudioEffect.ERROR_INVALID_OPERATION: throw (new UnsupportedOperationException( "AudioEffect: invalid parameter operation")); default: throw (new RuntimeException("AudioEffect: set/get parameter error")); } } }
@hide
/** * @hide */
@TestApi public static boolean isError(int status) { return (status < 0); }
@hide
/** * @hide */
@TestApi public static int byteArrayToInt(byte[] valueBuf) { return byteArrayToInt(valueBuf, 0); }
@hide
/** * @hide */
public static int byteArrayToInt(byte[] valueBuf, int offset) { ByteBuffer converter = ByteBuffer.wrap(valueBuf); converter.order(ByteOrder.nativeOrder()); return converter.getInt(offset); }
@hide
/** * @hide */
@TestApi public static byte[] intToByteArray(int value) { ByteBuffer converter = ByteBuffer.allocate(4); converter.order(ByteOrder.nativeOrder()); converter.putInt(value); return converter.array(); }
@hide
/** * @hide */
@TestApi public static short byteArrayToShort(byte[] valueBuf) { return byteArrayToShort(valueBuf, 0); }
@hide
/** * @hide */
public static short byteArrayToShort(byte[] valueBuf, int offset) { ByteBuffer converter = ByteBuffer.wrap(valueBuf); converter.order(ByteOrder.nativeOrder()); return converter.getShort(offset); }
@hide
/** * @hide */
@TestApi public static byte[] shortToByteArray(short value) { ByteBuffer converter = ByteBuffer.allocate(2); converter.order(ByteOrder.nativeOrder()); short sValue = (short) value; converter.putShort(sValue); return converter.array(); }
@hide
/** * @hide */
public static float byteArrayToFloat(byte[] valueBuf) { return byteArrayToFloat(valueBuf, 0); }
@hide
/** * @hide */
public static float byteArrayToFloat(byte[] valueBuf, int offset) { ByteBuffer converter = ByteBuffer.wrap(valueBuf); converter.order(ByteOrder.nativeOrder()); return converter.getFloat(offset); }
@hide
/** * @hide */
public static byte[] floatToByteArray(float value) { ByteBuffer converter = ByteBuffer.allocate(4); converter.order(ByteOrder.nativeOrder()); converter.putFloat(value); return converter.array(); }
@hide
/** * @hide */
public static byte[] concatArrays(byte[]... arrays) { int len = 0; for (byte[] a : arrays) { len += a.length; } byte[] b = new byte[len]; int offs = 0; for (byte[] a : arrays) { System.arraycopy(a, 0, b, offs, a.length); offs += a.length; } return b; } }