1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.audiofx; 18 19 import android.annotation.SdkConstant; 20 import android.annotation.SdkConstant.SdkConstantType; 21 import android.annotation.TestApi; 22 import android.app.ActivityThread; 23 import android.os.Handler; 24 import android.os.Looper; 25 import android.os.Message; 26 import android.util.Log; 27 import java.lang.ref.WeakReference; 28 import java.nio.ByteOrder; 29 import java.nio.ByteBuffer; 30 import java.util.UUID; 31 32 /** 33 * AudioEffect is the base class for controlling audio effects provided by the android audio 34 * framework. 35 * <p>Applications should not use the AudioEffect class directly but one of its derived classes to 36 * control specific effects: 37 * <ul> 38 * <li> {@link android.media.audiofx.Equalizer}</li> 39 * <li> {@link android.media.audiofx.Virtualizer}</li> 40 * <li> {@link android.media.audiofx.BassBoost}</li> 41 * <li> {@link android.media.audiofx.PresetReverb}</li> 42 * <li> {@link android.media.audiofx.EnvironmentalReverb}</li> 43 * <li> {@link android.media.audiofx.DynamicsProcessing}</li> 44 * </ul> 45 * <p>To apply the audio effect to a specific AudioTrack or MediaPlayer instance, 46 * the application must specify the audio session ID of that instance when creating the AudioEffect. 47 * (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions). 48 * <p>NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output 49 * mix by use of session 0 is deprecated. 50 * <p>Creating an AudioEffect object will create the corresponding effect engine in the audio 51 * framework if no instance of the same effect type exists in the specified audio session. 52 * If one exists, this instance will be used. 53 * <p>The application creating the AudioEffect object (or a derived class) will either receive 54 * control of the effect engine or not depending on the priority parameter. If priority is higher 55 * than the priority used by the current effect engine owner, the control will be transfered to the 56 * new object. Otherwise control will remain with the previous object. In this case, the new 57 * application will be notified of changes in effect engine state or control ownership by the 58 * appropriate listener. 59 */ 60 61 public class AudioEffect { 62 static { 63 System.loadLibrary("audioeffect_jni"); native_init()64 native_init(); 65 } 66 67 private final static String TAG = "AudioEffect-JAVA"; 68 69 // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h 70 71 /** 72 * The following UUIDs define effect types corresponding to standard audio 73 * effects whose implementation and interface conform to the OpenSL ES 74 * specification. The definitions match the corresponding interface IDs in 75 * OpenSLES_IID.h 76 */ 77 /** 78 * UUID for environmental reverberation effect 79 */ 80 public static final UUID EFFECT_TYPE_ENV_REVERB = UUID 81 .fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e"); 82 /** 83 * UUID for preset reverberation effect 84 */ 85 public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID 86 .fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b"); 87 /** 88 * UUID for equalizer effect 89 */ 90 public static final UUID EFFECT_TYPE_EQUALIZER = UUID 91 .fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b"); 92 /** 93 * UUID for bass boost effect 94 */ 95 public static final UUID EFFECT_TYPE_BASS_BOOST = UUID 96 .fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b"); 97 /** 98 * UUID for virtualizer effect 99 */ 100 public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID 101 .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b"); 102 103 /** 104 * UUIDs for effect types not covered by OpenSL ES. 105 */ 106 /** 107 * UUID for Automatic Gain Control (AGC) 108 */ 109 public static final UUID EFFECT_TYPE_AGC = UUID 110 .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b"); 111 112 /** 113 * UUID for Acoustic Echo Canceler (AEC) 114 */ 115 public static final UUID EFFECT_TYPE_AEC = UUID 116 .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b"); 117 118 /** 119 * UUID for Noise Suppressor (NS) 120 */ 121 public static final UUID EFFECT_TYPE_NS = UUID 122 .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b"); 123 124 /** 125 * UUID for Loudness Enhancer 126 */ 127 public static final UUID EFFECT_TYPE_LOUDNESS_ENHANCER = UUID 128 .fromString("fe3199be-aed0-413f-87bb-11260eb63cf1"); 129 130 /** 131 * UUID for Dynamics Processing 132 */ 133 public static final UUID EFFECT_TYPE_DYNAMICS_PROCESSING = UUID 134 .fromString("7261676f-6d75-7369-6364-28e2fd3ac39e"); 135 136 /** 137 * Null effect UUID. See {@link AudioEffect(UUID, UUID, int, int)} for use. 138 * @hide 139 */ 140 @TestApi 141 public static final UUID EFFECT_TYPE_NULL = UUID 142 .fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210"); 143 144 /** 145 * State of an AudioEffect object that was not successfully initialized upon 146 * creation 147 * @hide 148 */ 149 public static final int STATE_UNINITIALIZED = 0; 150 /** 151 * State of an AudioEffect object that is ready to be used. 152 * @hide 153 */ 154 public static final int STATE_INITIALIZED = 1; 155 156 // to keep in sync with 157 // frameworks/base/include/media/AudioEffect.h 158 /** 159 * Event id for engine control ownership change notification. 160 * @hide 161 */ 162 public static final int NATIVE_EVENT_CONTROL_STATUS = 0; 163 /** 164 * Event id for engine state change notification. 165 * @hide 166 */ 167 public static final int NATIVE_EVENT_ENABLED_STATUS = 1; 168 /** 169 * Event id for engine parameter change notification. 170 * @hide 171 */ 172 public static final int NATIVE_EVENT_PARAMETER_CHANGED = 2; 173 174 /** 175 * Successful operation. 176 */ 177 public static final int SUCCESS = 0; 178 /** 179 * Unspecified error. 180 */ 181 public static final int ERROR = -1; 182 /** 183 * Internal operation status. Not returned by any method. 184 */ 185 public static final int ALREADY_EXISTS = -2; 186 /** 187 * Operation failed due to bad object initialization. 188 */ 189 public static final int ERROR_NO_INIT = -3; 190 /** 191 * Operation failed due to bad parameter value. 192 */ 193 public static final int ERROR_BAD_VALUE = -4; 194 /** 195 * Operation failed because it was requested in wrong state. 196 */ 197 public static final int ERROR_INVALID_OPERATION = -5; 198 /** 199 * Operation failed due to lack of memory. 200 */ 201 public static final int ERROR_NO_MEMORY = -6; 202 /** 203 * Operation failed due to dead remote object. 204 */ 205 public static final int ERROR_DEAD_OBJECT = -7; 206 207 /** 208 * The effect descriptor contains information on a particular effect implemented in the 209 * audio framework:<br> 210 * <ul> 211 * <li>type: UUID identifying the effect type. May be one of: 212 * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC}, 213 * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, 214 * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS}, 215 * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}, {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}, 216 * {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}. 217 * </li> 218 * <li>uuid: UUID for this particular implementation</li> 219 * <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li> 220 * <li>name: human readable effect name</li> 221 * <li>implementor: human readable effect implementor name</li> 222 * </ul> 223 * The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects 224 * enumeration. 225 */ 226 public static class Descriptor { 227 Descriptor()228 public Descriptor() { 229 } 230 231 /** 232 * @param type UUID identifying the effect type. May be one of: 233 * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC}, 234 * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, 235 * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS}, 236 * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}, 237 * {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}, 238 * {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}. 239 * @param uuid UUID for this particular implementation 240 * @param connectMode {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY} 241 * @param name human readable effect name 242 * @param implementor human readable effect implementor name 243 * 244 */ Descriptor(String type, String uuid, String connectMode, String name, String implementor)245 public Descriptor(String type, String uuid, String connectMode, 246 String name, String implementor) { 247 this.type = UUID.fromString(type); 248 this.uuid = UUID.fromString(uuid); 249 this.connectMode = connectMode; 250 this.name = name; 251 this.implementor = implementor; 252 } 253 254 /** 255 * Indicates the generic type of the effect (Equalizer, Bass boost ...). 256 * One of {@link AudioEffect#EFFECT_TYPE_AEC}, 257 * {@link AudioEffect#EFFECT_TYPE_AGC}, {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, 258 * {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, 259 * {@link AudioEffect#EFFECT_TYPE_NS}, {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB} 260 * {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER} 261 * or {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}.<br> 262 * For reverberation, bass boost, EQ and virtualizer, the UUID 263 * corresponds to the OpenSL ES Interface ID. 264 */ 265 public UUID type; 266 /** 267 * Indicates the particular implementation of the effect in that type. Several effects 268 * can have the same type but this uuid is unique to a given implementation. 269 */ 270 public UUID uuid; 271 /** 272 * Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary 273 * category {@link #EFFECT_AUXILIARY}. 274 * Insert effects (typically an {@link Equalizer}) are applied 275 * to the entire audio source and usually not shared by several sources. Auxiliary effects 276 * (typically a reverberator) are applied to part of the signal (wet) and the effect output 277 * is added to the original signal (dry). 278 * Audio pre processing are applied to audio captured on a particular 279 * {@link android.media.AudioRecord}. 280 */ 281 public String connectMode; 282 /** 283 * Human readable effect name 284 */ 285 public String name; 286 /** 287 * Human readable effect implementor name 288 */ 289 public String implementor; 290 }; 291 292 /** 293 * Effect connection mode is insert. Specifying an audio session ID when creating the effect 294 * will insert this effect after all players in the same audio session. 295 */ 296 public static final String EFFECT_INSERT = "Insert"; 297 /** 298 * Effect connection mode is auxiliary. 299 * <p>Auxiliary effects must be created on session 0 (global output mix). In order for a 300 * MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to 301 * this effect and a send level must be specified. 302 * <p>Use the effect ID returned by {@link #getId()} to designate this particular effect when 303 * attaching it to the MediaPlayer or AudioTrack. 304 */ 305 public static final String EFFECT_AUXILIARY = "Auxiliary"; 306 /** 307 * Effect connection mode is pre processing. 308 * The audio pre processing effects are attached to an audio input (AudioRecord). 309 * @hide 310 */ 311 public static final String EFFECT_PRE_PROCESSING = "Pre Processing"; 312 313 // -------------------------------------------------------------------------- 314 // Member variables 315 // -------------------- 316 /** 317 * Indicates the state of the AudioEffect instance 318 */ 319 private int mState = STATE_UNINITIALIZED; 320 /** 321 * Lock to synchronize access to mState 322 */ 323 private final Object mStateLock = new Object(); 324 /** 325 * System wide unique effect ID 326 */ 327 private int mId; 328 329 // accessed by native methods 330 private long mNativeAudioEffect; 331 private long mJniData; 332 333 /** 334 * Effect descriptor 335 */ 336 private Descriptor mDescriptor; 337 338 /** 339 * Listener for effect engine state change notifications. 340 * 341 * @see #setEnableStatusListener(OnEnableStatusChangeListener) 342 */ 343 private OnEnableStatusChangeListener mEnableStatusChangeListener = null; 344 /** 345 * Listener for effect engine control ownership change notifications. 346 * 347 * @see #setControlStatusListener(OnControlStatusChangeListener) 348 */ 349 private OnControlStatusChangeListener mControlChangeStatusListener = null; 350 /** 351 * Listener for effect engine control ownership change notifications. 352 * 353 * @see #setParameterListener(OnParameterChangeListener) 354 */ 355 private OnParameterChangeListener mParameterChangeListener = null; 356 /** 357 * Lock to protect listeners updates against event notifications 358 * @hide 359 */ 360 public final Object mListenerLock = new Object(); 361 /** 362 * Handler for events coming from the native code 363 * @hide 364 */ 365 public NativeEventHandler mNativeEventHandler = null; 366 367 // -------------------------------------------------------------------------- 368 // Constructor, Finalize 369 // -------------------- 370 /** 371 * Class constructor. 372 * 373 * @param type type of effect engine created. See {@link #EFFECT_TYPE_ENV_REVERB}, 374 * {@link #EFFECT_TYPE_EQUALIZER} ... Types corresponding to 375 * built-in effects are defined by AudioEffect class. Other types 376 * can be specified provided they correspond an existing OpenSL 377 * ES interface ID and the corresponsing effect is available on 378 * the platform. If an unspecified effect type is requested, the 379 * constructor with throw the IllegalArgumentException. This 380 * parameter can be set to {@link #EFFECT_TYPE_NULL} in which 381 * case only the uuid will be used to select the effect. 382 * @param uuid unique identifier of a particular effect implementation. 383 * Must be specified if the caller wants to use a particular 384 * implementation of an effect type. This parameter can be set to 385 * {@link #EFFECT_TYPE_NULL} in which case only the type will 386 * be used to select the effect. 387 * @param priority the priority level requested by the application for 388 * controlling the effect engine. As the same effect engine can 389 * be shared by several applications, this parameter indicates 390 * how much the requesting application needs control of effect 391 * parameters. The normal priority is 0, above normal is a 392 * positive number, below normal a negative number. 393 * @param audioSession system wide unique audio session identifier. 394 * The effect will be attached to the MediaPlayer or AudioTrack in 395 * the same audio session. 396 * 397 * @throws java.lang.IllegalArgumentException 398 * @throws java.lang.UnsupportedOperationException 399 * @throws java.lang.RuntimeException 400 * @hide 401 */ 402 AudioEffect(UUID type, UUID uuid, int priority, int audioSession)403 public AudioEffect(UUID type, UUID uuid, int priority, int audioSession) 404 throws IllegalArgumentException, UnsupportedOperationException, 405 RuntimeException { 406 int[] id = new int[1]; 407 Descriptor[] desc = new Descriptor[1]; 408 // native initialization 409 int initResult = native_setup(new WeakReference<AudioEffect>(this), 410 type.toString(), uuid.toString(), priority, audioSession, id, 411 desc, ActivityThread.currentOpPackageName()); 412 if (initResult != SUCCESS && initResult != ALREADY_EXISTS) { 413 Log.e(TAG, "Error code " + initResult 414 + " when initializing AudioEffect."); 415 switch (initResult) { 416 case ERROR_BAD_VALUE: 417 throw (new IllegalArgumentException("Effect type: " + type 418 + " not supported.")); 419 case ERROR_INVALID_OPERATION: 420 throw (new UnsupportedOperationException( 421 "Effect library not loaded")); 422 default: 423 throw (new RuntimeException( 424 "Cannot initialize effect engine for type: " + type 425 + " Error: " + initResult)); 426 } 427 } 428 mId = id[0]; 429 mDescriptor = desc[0]; 430 synchronized (mStateLock) { 431 mState = STATE_INITIALIZED; 432 } 433 } 434 435 /** 436 * Releases the native AudioEffect resources. It is a good practice to 437 * release the effect engine when not in use as control can be returned to 438 * other applications or the native resources released. 439 */ release()440 public void release() { 441 synchronized (mStateLock) { 442 native_release(); 443 mState = STATE_UNINITIALIZED; 444 } 445 } 446 447 @Override finalize()448 protected void finalize() { 449 native_finalize(); 450 } 451 452 /** 453 * Get the effect descriptor. 454 * 455 * @see android.media.audiofx.AudioEffect.Descriptor 456 * @throws IllegalStateException 457 */ getDescriptor()458 public Descriptor getDescriptor() throws IllegalStateException { 459 checkState("getDescriptor()"); 460 return mDescriptor; 461 } 462 463 // -------------------------------------------------------------------------- 464 // Effects Enumeration 465 // -------------------- 466 467 /** 468 * Query all effects available on the platform. Returns an array of 469 * {@link android.media.audiofx.AudioEffect.Descriptor} objects 470 * 471 * @throws IllegalStateException 472 */ 473 queryEffects()474 static public Descriptor[] queryEffects() { 475 return (Descriptor[]) native_query_effects(); 476 } 477 478 /** 479 * Query all audio pre-processing effects applied to the AudioRecord with the supplied 480 * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor} 481 * objects. 482 * @param audioSession system wide unique audio session identifier. 483 * @throws IllegalStateException 484 * @hide 485 */ 486 queryPreProcessings(int audioSession)487 static public Descriptor[] queryPreProcessings(int audioSession) { 488 return (Descriptor[]) native_query_pre_processing(audioSession); 489 } 490 491 /** 492 * Checks if the device implements the specified effect type. 493 * @param type the requested effect type. 494 * @return true if the device implements the specified effect type, false otherwise. 495 * @hide 496 */ 497 @TestApi isEffectTypeAvailable(UUID type)498 public static boolean isEffectTypeAvailable(UUID type) { 499 AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); 500 if (desc == null) { 501 return false; 502 } 503 504 for (int i = 0; i < desc.length; i++) { 505 if (desc[i].type.equals(type)) { 506 return true; 507 } 508 } 509 return false; 510 } 511 512 // -------------------------------------------------------------------------- 513 // Control methods 514 // -------------------- 515 516 /** 517 * Enable or disable the effect. 518 * Creating an audio effect does not automatically apply this effect on the audio source. It 519 * creates the resources necessary to process this effect but the audio signal is still bypassed 520 * through the effect engine. Calling this method will make that the effect is actually applied 521 * or not to the audio content being played in the corresponding audio session. 522 * 523 * @param enabled the requested enable state 524 * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION} 525 * or {@link #ERROR_DEAD_OBJECT} in case of failure. 526 * @throws IllegalStateException 527 */ setEnabled(boolean enabled)528 public int setEnabled(boolean enabled) throws IllegalStateException { 529 checkState("setEnabled()"); 530 return native_setEnabled(enabled); 531 } 532 533 /** 534 * Set effect parameter. The setParameter method is provided in several 535 * forms addressing most common parameter formats. This form is the most 536 * generic one where the parameter and its value are both specified as an 537 * array of bytes. The parameter and value type and length are therefore 538 * totally free. For standard effect defined by OpenSL ES, the parameter 539 * format and values must match the definitions in the corresponding OpenSL 540 * ES interface. 541 * 542 * @param param the identifier of the parameter to set 543 * @param value the new value for the specified parameter 544 * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE}, 545 * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or 546 * {@link #ERROR_DEAD_OBJECT} in case of failure 547 * @throws IllegalStateException 548 * @hide 549 */ 550 @TestApi setParameter(byte[] param, byte[] value)551 public int setParameter(byte[] param, byte[] value) 552 throws IllegalStateException { 553 checkState("setParameter()"); 554 return native_setParameter(param.length, param, value.length, value); 555 } 556 557 /** 558 * Set effect parameter. The parameter and its value are integers. 559 * 560 * @see #setParameter(byte[], byte[]) 561 * @hide 562 */ 563 @TestApi setParameter(int param, int value)564 public int setParameter(int param, int value) throws IllegalStateException { 565 byte[] p = intToByteArray(param); 566 byte[] v = intToByteArray(value); 567 return setParameter(p, v); 568 } 569 570 /** 571 * Set effect parameter. The parameter is an integer and the value is a 572 * short integer. 573 * 574 * @see #setParameter(byte[], byte[]) 575 * @hide 576 */ 577 @TestApi setParameter(int param, short value)578 public int setParameter(int param, short value) 579 throws IllegalStateException { 580 byte[] p = intToByteArray(param); 581 byte[] v = shortToByteArray(value); 582 return setParameter(p, v); 583 } 584 585 /** 586 * Set effect parameter. The parameter is an integer and the value is an 587 * array of bytes. 588 * 589 * @see #setParameter(byte[], byte[]) 590 * @hide 591 */ 592 @TestApi setParameter(int param, byte[] value)593 public int setParameter(int param, byte[] value) 594 throws IllegalStateException { 595 byte[] p = intToByteArray(param); 596 return setParameter(p, value); 597 } 598 599 /** 600 * Set effect parameter. The parameter is an array of 1 or 2 integers and 601 * the value is also an array of 1 or 2 integers 602 * 603 * @see #setParameter(byte[], byte[]) 604 * @hide 605 */ 606 @TestApi setParameter(int[] param, int[] value)607 public int setParameter(int[] param, int[] value) 608 throws IllegalStateException { 609 if (param.length > 2 || value.length > 2) { 610 return ERROR_BAD_VALUE; 611 } 612 byte[] p = intToByteArray(param[0]); 613 if (param.length > 1) { 614 byte[] p2 = intToByteArray(param[1]); 615 p = concatArrays(p, p2); 616 } 617 byte[] v = intToByteArray(value[0]); 618 if (value.length > 1) { 619 byte[] v2 = intToByteArray(value[1]); 620 v = concatArrays(v, v2); 621 } 622 return setParameter(p, v); 623 } 624 625 /** 626 * Set effect parameter. The parameter is an array of 1 or 2 integers and 627 * the value is an array of 1 or 2 short integers 628 * 629 * @see #setParameter(byte[], byte[]) 630 * @hide 631 */ setParameter(int[] param, short[] value)632 public int setParameter(int[] param, short[] value) 633 throws IllegalStateException { 634 if (param.length > 2 || value.length > 2) { 635 return ERROR_BAD_VALUE; 636 } 637 byte[] p = intToByteArray(param[0]); 638 if (param.length > 1) { 639 byte[] p2 = intToByteArray(param[1]); 640 p = concatArrays(p, p2); 641 } 642 643 byte[] v = shortToByteArray(value[0]); 644 if (value.length > 1) { 645 byte[] v2 = shortToByteArray(value[1]); 646 v = concatArrays(v, v2); 647 } 648 return setParameter(p, v); 649 } 650 651 /** 652 * Set effect parameter. The parameter is an array of 1 or 2 integers and 653 * the value is an array of bytes 654 * 655 * @see #setParameter(byte[], byte[]) 656 * @hide 657 */ 658 @TestApi setParameter(int[] param, byte[] value)659 public int setParameter(int[] param, byte[] value) 660 throws IllegalStateException { 661 if (param.length > 2) { 662 return ERROR_BAD_VALUE; 663 } 664 byte[] p = intToByteArray(param[0]); 665 if (param.length > 1) { 666 byte[] p2 = intToByteArray(param[1]); 667 p = concatArrays(p, p2); 668 } 669 return setParameter(p, value); 670 } 671 672 /** 673 * Get effect parameter. The getParameter method is provided in several 674 * forms addressing most common parameter formats. This form is the most 675 * generic one where the parameter and its value are both specified as an 676 * array of bytes. The parameter and value type and length are therefore 677 * totally free. 678 * 679 * @param param the identifier of the parameter to set 680 * @param value the new value for the specified parameter 681 * @return the number of meaningful bytes in value array in case of success or 682 * {@link #ERROR_BAD_VALUE}, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} 683 * or {@link #ERROR_DEAD_OBJECT} in case of failure. 684 * @throws IllegalStateException 685 * @hide 686 */ 687 @TestApi getParameter(byte[] param, byte[] value)688 public int getParameter(byte[] param, byte[] value) 689 throws IllegalStateException { 690 checkState("getParameter()"); 691 return native_getParameter(param.length, param, value.length, value); 692 } 693 694 /** 695 * Get effect parameter. The parameter is an integer and the value is an 696 * array of bytes. 697 * 698 * @see #getParameter(byte[], byte[]) 699 * @hide 700 */ 701 @TestApi getParameter(int param, byte[] value)702 public int getParameter(int param, byte[] value) 703 throws IllegalStateException { 704 byte[] p = intToByteArray(param); 705 706 return getParameter(p, value); 707 } 708 709 /** 710 * Get effect parameter. The parameter is an integer and the value is an 711 * array of 1 or 2 integers 712 * 713 * @see #getParameter(byte[], byte[]) 714 * In case of success, returns the number of meaningful integers in value array. 715 * @hide 716 */ 717 @TestApi getParameter(int param, int[] value)718 public int getParameter(int param, int[] value) 719 throws IllegalStateException { 720 if (value.length > 2) { 721 return ERROR_BAD_VALUE; 722 } 723 byte[] p = intToByteArray(param); 724 725 byte[] v = new byte[value.length * 4]; 726 727 int status = getParameter(p, v); 728 729 if (status == 4 || status == 8) { 730 value[0] = byteArrayToInt(v); 731 if (status == 8) { 732 value[1] = byteArrayToInt(v, 4); 733 } 734 status /= 4; 735 } else { 736 status = ERROR; 737 } 738 return status; 739 } 740 741 /** 742 * Get effect parameter. The parameter is an integer and the value is an 743 * array of 1 or 2 short integers 744 * 745 * @see #getParameter(byte[], byte[]) 746 * In case of success, returns the number of meaningful short integers in value array. 747 * @hide 748 */ 749 @TestApi getParameter(int param, short[] value)750 public int getParameter(int param, short[] value) 751 throws IllegalStateException { 752 if (value.length > 2) { 753 return ERROR_BAD_VALUE; 754 } 755 byte[] p = intToByteArray(param); 756 757 byte[] v = new byte[value.length * 2]; 758 759 int status = getParameter(p, v); 760 761 if (status == 2 || status == 4) { 762 value[0] = byteArrayToShort(v); 763 if (status == 4) { 764 value[1] = byteArrayToShort(v, 2); 765 } 766 status /= 2; 767 } else { 768 status = ERROR; 769 } 770 return status; 771 } 772 773 /** 774 * Get effect parameter. The parameter is an array of 1 or 2 integers and 775 * the value is also an array of 1 or 2 integers 776 * 777 * @see #getParameter(byte[], byte[]) 778 * In case of success, the returns the number of meaningful integers in value array. 779 * @hide 780 */ getParameter(int[] param, int[] value)781 public int getParameter(int[] param, int[] value) 782 throws IllegalStateException { 783 if (param.length > 2 || value.length > 2) { 784 return ERROR_BAD_VALUE; 785 } 786 byte[] p = intToByteArray(param[0]); 787 if (param.length > 1) { 788 byte[] p2 = intToByteArray(param[1]); 789 p = concatArrays(p, p2); 790 } 791 byte[] v = new byte[value.length * 4]; 792 793 int status = getParameter(p, v); 794 795 if (status == 4 || status == 8) { 796 value[0] = byteArrayToInt(v); 797 if (status == 8) { 798 value[1] = byteArrayToInt(v, 4); 799 } 800 status /= 4; 801 } else { 802 status = ERROR; 803 } 804 return status; 805 } 806 807 /** 808 * Get effect parameter. The parameter is an array of 1 or 2 integers and 809 * the value is an array of 1 or 2 short integers 810 * 811 * @see #getParameter(byte[], byte[]) 812 * In case of success, returns the number of meaningful short integers in value array. 813 * @hide 814 */ 815 @TestApi getParameter(int[] param, short[] value)816 public int getParameter(int[] param, short[] value) 817 throws IllegalStateException { 818 if (param.length > 2 || value.length > 2) { 819 return ERROR_BAD_VALUE; 820 } 821 byte[] p = intToByteArray(param[0]); 822 if (param.length > 1) { 823 byte[] p2 = intToByteArray(param[1]); 824 p = concatArrays(p, p2); 825 } 826 byte[] v = new byte[value.length * 2]; 827 828 int status = getParameter(p, v); 829 830 if (status == 2 || status == 4) { 831 value[0] = byteArrayToShort(v); 832 if (status == 4) { 833 value[1] = byteArrayToShort(v, 2); 834 } 835 status /= 2; 836 } else { 837 status = ERROR; 838 } 839 return status; 840 } 841 842 /** 843 * Get effect parameter. The parameter is an array of 1 or 2 integers and 844 * the value is an array of bytes 845 * 846 * @see #getParameter(byte[], byte[]) 847 * @hide 848 */ getParameter(int[] param, byte[] value)849 public int getParameter(int[] param, byte[] value) 850 throws IllegalStateException { 851 if (param.length > 2) { 852 return ERROR_BAD_VALUE; 853 } 854 byte[] p = intToByteArray(param[0]); 855 if (param.length > 1) { 856 byte[] p2 = intToByteArray(param[1]); 857 p = concatArrays(p, p2); 858 } 859 860 return getParameter(p, value); 861 } 862 863 /** 864 * Send a command to the effect engine. This method is intended to send 865 * proprietary commands to a particular effect implementation. 866 * In case of success, returns the number of meaningful bytes in reply array. 867 * In case of failure, the returned value is negative and implementation specific. 868 * @hide 869 */ command(int cmdCode, byte[] command, byte[] reply)870 public int command(int cmdCode, byte[] command, byte[] reply) 871 throws IllegalStateException { 872 checkState("command()"); 873 return native_command(cmdCode, command.length, command, reply.length, reply); 874 } 875 876 // -------------------------------------------------------------------------- 877 // Getters 878 // -------------------- 879 880 /** 881 * Returns effect unique identifier. This system wide unique identifier can 882 * be used to attach this effect to a MediaPlayer or an AudioTrack when the 883 * effect is an auxiliary effect (Reverb) 884 * 885 * @return the effect identifier. 886 * @throws IllegalStateException 887 */ getId()888 public int getId() throws IllegalStateException { 889 checkState("getId()"); 890 return mId; 891 } 892 893 /** 894 * Returns effect enabled state 895 * 896 * @return true if the effect is enabled, false otherwise. 897 * @throws IllegalStateException 898 */ getEnabled()899 public boolean getEnabled() throws IllegalStateException { 900 checkState("getEnabled()"); 901 return native_getEnabled(); 902 } 903 904 /** 905 * Checks if this AudioEffect object is controlling the effect engine. 906 * 907 * @return true if this instance has control of effect engine, false 908 * otherwise. 909 * @throws IllegalStateException 910 */ hasControl()911 public boolean hasControl() throws IllegalStateException { 912 checkState("hasControl()"); 913 return native_hasControl(); 914 } 915 916 // -------------------------------------------------------------------------- 917 // Initialization / configuration 918 // -------------------- 919 /** 920 * Sets the listener AudioEffect notifies when the effect engine is enabled 921 * or disabled. 922 * 923 * @param listener 924 */ setEnableStatusListener(OnEnableStatusChangeListener listener)925 public void setEnableStatusListener(OnEnableStatusChangeListener listener) { 926 synchronized (mListenerLock) { 927 mEnableStatusChangeListener = listener; 928 } 929 if ((listener != null) && (mNativeEventHandler == null)) { 930 createNativeEventHandler(); 931 } 932 } 933 934 /** 935 * Sets the listener AudioEffect notifies when the effect engine control is 936 * taken or returned. 937 * 938 * @param listener 939 */ setControlStatusListener(OnControlStatusChangeListener listener)940 public void setControlStatusListener(OnControlStatusChangeListener listener) { 941 synchronized (mListenerLock) { 942 mControlChangeStatusListener = listener; 943 } 944 if ((listener != null) && (mNativeEventHandler == null)) { 945 createNativeEventHandler(); 946 } 947 } 948 949 /** 950 * Sets the listener AudioEffect notifies when a parameter is changed. 951 * 952 * @param listener 953 * @hide 954 */ 955 @TestApi setParameterListener(OnParameterChangeListener listener)956 public void setParameterListener(OnParameterChangeListener listener) { 957 synchronized (mListenerLock) { 958 mParameterChangeListener = listener; 959 } 960 if ((listener != null) && (mNativeEventHandler == null)) { 961 createNativeEventHandler(); 962 } 963 } 964 965 // Convenience method for the creation of the native event handler 966 // It is called only when a non-null event listener is set. 967 // precondition: 968 // mNativeEventHandler is null createNativeEventHandler()969 private void createNativeEventHandler() { 970 Looper looper; 971 if ((looper = Looper.myLooper()) != null) { 972 mNativeEventHandler = new NativeEventHandler(this, looper); 973 } else if ((looper = Looper.getMainLooper()) != null) { 974 mNativeEventHandler = new NativeEventHandler(this, looper); 975 } else { 976 mNativeEventHandler = null; 977 } 978 } 979 980 // --------------------------------------------------------- 981 // Interface definitions 982 // -------------------- 983 /** 984 * The OnEnableStatusChangeListener interface defines a method called by the AudioEffect 985 * when a the enabled state of the effect engine was changed by the controlling application. 986 */ 987 public interface OnEnableStatusChangeListener { 988 /** 989 * Called on the listener to notify it that the effect engine has been 990 * enabled or disabled. 991 * @param effect the effect on which the interface is registered. 992 * @param enabled new effect state. 993 */ onEnableStatusChange(AudioEffect effect, boolean enabled)994 void onEnableStatusChange(AudioEffect effect, boolean enabled); 995 } 996 997 /** 998 * The OnControlStatusChangeListener interface defines a method called by the AudioEffect 999 * when a the control of the effect engine is gained or lost by the application 1000 */ 1001 public interface OnControlStatusChangeListener { 1002 /** 1003 * Called on the listener to notify it that the effect engine control 1004 * has been taken or returned. 1005 * @param effect the effect on which the interface is registered. 1006 * @param controlGranted true if the application has been granted control of the effect 1007 * engine, false otherwise. 1008 */ onControlStatusChange(AudioEffect effect, boolean controlGranted)1009 void onControlStatusChange(AudioEffect effect, boolean controlGranted); 1010 } 1011 1012 /** 1013 * The OnParameterChangeListener interface defines a method called by the AudioEffect 1014 * when a parameter is changed in the effect engine by the controlling application. 1015 * @hide 1016 */ 1017 @TestApi 1018 public interface OnParameterChangeListener { 1019 /** 1020 * Called on the listener to notify it that a parameter value has changed. 1021 * @param effect the effect on which the interface is registered. 1022 * @param status status of the set parameter operation. 1023 * @param param ID of the modified parameter. 1024 * @param value the new parameter value. 1025 */ onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value)1026 void onParameterChange(AudioEffect effect, int status, byte[] param, 1027 byte[] value); 1028 } 1029 1030 1031 // ------------------------------------------------------------------------- 1032 // Audio Effect Control panel intents 1033 // ------------------------------------------------------------------------- 1034 1035 /** 1036 * Intent to launch an audio effect control panel UI. 1037 * <p>The goal of this intent is to enable separate implementations of music/media player 1038 * applications and audio effect control application or services. 1039 * This will allow platform vendors to offer more advanced control options for standard effects 1040 * or control for platform specific effects. 1041 * <p>The intent carries a number of extras used by the player application to communicate 1042 * necessary pieces of information to the control panel application. 1043 * <p>The calling application must use the 1044 * {@link android.app.Activity#startActivityForResult(Intent, int)} method to launch the 1045 * control panel so that its package name is indicated and used by the control panel 1046 * application to keep track of changes for this particular application. 1047 * <p>The {@link #EXTRA_AUDIO_SESSION} extra will indicate an audio session to which the 1048 * audio effects should be applied. If no audio session is specified, either one of the 1049 * follownig will happen: 1050 * <p>- If an audio session was previously opened by the calling application with 1051 * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intent, the effect changes will 1052 * be applied to that session. 1053 * <p>- If no audio session is opened, the changes will be stored in the package specific 1054 * storage area and applied whenever a new audio session is opened by this application. 1055 * <p>The {@link #EXTRA_CONTENT_TYPE} extra will help the control panel application 1056 * customize both the UI layout and the default audio effect settings if none are already 1057 * stored for the calling application. 1058 */ 1059 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1060 public static final String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL = 1061 "android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL"; 1062 1063 /** 1064 * Intent to signal to the effect control application or service that a new audio session 1065 * is opened and requires audio effects to be applied. 1066 * <p>This is different from {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no 1067 * UI should be displayed in this case. Music player applications can broadcast this intent 1068 * before starting playback to make sure that any audio effect settings previously selected 1069 * by the user are applied. 1070 * <p>The effect control application receiving this intent will look for previously stored 1071 * settings for the calling application, create all required audio effects and apply the 1072 * effect settings to the specified audio session. 1073 * <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the 1074 * audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory. 1075 * <p>If no stored settings are found for the calling application, default settings for the 1076 * content type indicated by {@link #EXTRA_CONTENT_TYPE} will be applied. The default settings 1077 * for a given content type are platform specific. 1078 */ 1079 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1080 public static final String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION = 1081 "android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION"; 1082 1083 /** 1084 * Intent to signal to the effect control application or service that an audio session 1085 * is closed and that effects should not be applied anymore. 1086 * <p>The effect control application receiving this intent will delete all effects on 1087 * this session and store current settings in package specific storage. 1088 * <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the 1089 * audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory. 1090 * <p>It is good practice for applications to broadcast this intent when music playback stops 1091 * and/or when exiting to free system resources consumed by audio effect engines. 1092 */ 1093 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1094 public static final String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION = 1095 "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION"; 1096 1097 /** 1098 * Contains the ID of the audio session the effects should be applied to. 1099 * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL}, 1100 * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and 1101 * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents. 1102 * <p>The extra value is of type int and is the audio session ID. 1103 * @see android.media.MediaPlayer#getAudioSessionId() for details on audio sessions. 1104 */ 1105 public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION"; 1106 1107 /** 1108 * Contains the package name of the calling application. 1109 * <p>This extra is for use with {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and 1110 * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents. 1111 * <p>The extra value is a string containing the full package name. 1112 */ 1113 public static final String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME"; 1114 1115 /** 1116 * Indicates which type of content is played by the application. 1117 * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} and 1118 * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intents. 1119 * <p>This information is used by the effect control application to customize UI and select 1120 * appropriate default effect settings. The content type is one of the following: 1121 * <ul> 1122 * <li>{@link #CONTENT_TYPE_MUSIC}</li> 1123 * <li>{@link #CONTENT_TYPE_MOVIE}</li> 1124 * <li>{@link #CONTENT_TYPE_GAME}</li> 1125 * <li>{@link #CONTENT_TYPE_VOICE}</li> 1126 * </ul> 1127 * If omitted, the content type defaults to {@link #CONTENT_TYPE_MUSIC}. 1128 */ 1129 public static final String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE"; 1130 1131 /** 1132 * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is music 1133 */ 1134 public static final int CONTENT_TYPE_MUSIC = 0; 1135 /** 1136 * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video or movie 1137 */ 1138 public static final int CONTENT_TYPE_MOVIE = 1; 1139 /** 1140 * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is game audio 1141 */ 1142 public static final int CONTENT_TYPE_GAME = 2; 1143 /** 1144 * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is voice audio 1145 */ 1146 public static final int CONTENT_TYPE_VOICE = 3; 1147 1148 1149 // --------------------------------------------------------- 1150 // Inner classes 1151 // -------------------- 1152 /** 1153 * Helper class to handle the forwarding of native events to the appropriate 1154 * listeners 1155 */ 1156 private class NativeEventHandler extends Handler { 1157 private AudioEffect mAudioEffect; 1158 NativeEventHandler(AudioEffect ae, Looper looper)1159 public NativeEventHandler(AudioEffect ae, Looper looper) { 1160 super(looper); 1161 mAudioEffect = ae; 1162 } 1163 1164 @Override handleMessage(Message msg)1165 public void handleMessage(Message msg) { 1166 if (mAudioEffect == null) { 1167 return; 1168 } 1169 switch (msg.what) { 1170 case NATIVE_EVENT_ENABLED_STATUS: 1171 OnEnableStatusChangeListener enableStatusChangeListener = null; 1172 synchronized (mListenerLock) { 1173 enableStatusChangeListener = mAudioEffect.mEnableStatusChangeListener; 1174 } 1175 if (enableStatusChangeListener != null) { 1176 enableStatusChangeListener.onEnableStatusChange( 1177 mAudioEffect, (boolean) (msg.arg1 != 0)); 1178 } 1179 break; 1180 case NATIVE_EVENT_CONTROL_STATUS: 1181 OnControlStatusChangeListener controlStatusChangeListener = null; 1182 synchronized (mListenerLock) { 1183 controlStatusChangeListener = mAudioEffect.mControlChangeStatusListener; 1184 } 1185 if (controlStatusChangeListener != null) { 1186 controlStatusChangeListener.onControlStatusChange( 1187 mAudioEffect, (boolean) (msg.arg1 != 0)); 1188 } 1189 break; 1190 case NATIVE_EVENT_PARAMETER_CHANGED: 1191 OnParameterChangeListener parameterChangeListener = null; 1192 synchronized (mListenerLock) { 1193 parameterChangeListener = mAudioEffect.mParameterChangeListener; 1194 } 1195 if (parameterChangeListener != null) { 1196 // arg1 contains offset of parameter value from start of 1197 // byte array 1198 int vOffset = msg.arg1; 1199 byte[] p = (byte[]) msg.obj; 1200 // See effect_param_t in EffectApi.h for psize and vsize 1201 // fields offsets 1202 int status = byteArrayToInt(p, 0); 1203 int psize = byteArrayToInt(p, 4); 1204 int vsize = byteArrayToInt(p, 8); 1205 byte[] param = new byte[psize]; 1206 byte[] value = new byte[vsize]; 1207 System.arraycopy(p, 12, param, 0, psize); 1208 System.arraycopy(p, vOffset, value, 0, vsize); 1209 1210 parameterChangeListener.onParameterChange(mAudioEffect, 1211 status, param, value); 1212 } 1213 break; 1214 1215 default: 1216 Log.e(TAG, "handleMessage() Unknown event type: " + msg.what); 1217 break; 1218 } 1219 } 1220 } 1221 1222 // --------------------------------------------------------- 1223 // Java methods called from the native side 1224 // -------------------- 1225 @SuppressWarnings("unused") postEventFromNative(Object effect_ref, int what, int arg1, int arg2, Object obj)1226 private static void postEventFromNative(Object effect_ref, int what, 1227 int arg1, int arg2, Object obj) { 1228 AudioEffect effect = (AudioEffect) ((WeakReference) effect_ref).get(); 1229 if (effect == null) { 1230 return; 1231 } 1232 if (effect.mNativeEventHandler != null) { 1233 Message m = effect.mNativeEventHandler.obtainMessage(what, arg1, 1234 arg2, obj); 1235 effect.mNativeEventHandler.sendMessage(m); 1236 } 1237 1238 } 1239 1240 // --------------------------------------------------------- 1241 // Native methods called from the Java side 1242 // -------------------- 1243 native_init()1244 private static native final void native_init(); 1245 native_setup(Object audioeffect_this, String type, String uuid, int priority, int audioSession, int[] id, Object[] desc, String opPackageName)1246 private native final int native_setup(Object audioeffect_this, String type, 1247 String uuid, int priority, int audioSession, int[] id, Object[] desc, 1248 String opPackageName); 1249 native_finalize()1250 private native final void native_finalize(); 1251 native_release()1252 private native final void native_release(); 1253 native_setEnabled(boolean enabled)1254 private native final int native_setEnabled(boolean enabled); 1255 native_getEnabled()1256 private native final boolean native_getEnabled(); 1257 native_hasControl()1258 private native final boolean native_hasControl(); 1259 native_setParameter(int psize, byte[] param, int vsize, byte[] value)1260 private native final int native_setParameter(int psize, byte[] param, 1261 int vsize, byte[] value); 1262 native_getParameter(int psize, byte[] param, int vsize, byte[] value)1263 private native final int native_getParameter(int psize, byte[] param, 1264 int vsize, byte[] value); 1265 native_command(int cmdCode, int cmdSize, byte[] cmdData, int repSize, byte[] repData)1266 private native final int native_command(int cmdCode, int cmdSize, 1267 byte[] cmdData, int repSize, byte[] repData); 1268 native_query_effects()1269 private static native Object[] native_query_effects(); 1270 native_query_pre_processing(int audioSession)1271 private static native Object[] native_query_pre_processing(int audioSession); 1272 1273 // --------------------------------------------------------- 1274 // Utility methods 1275 // ------------------ 1276 1277 /** 1278 * @hide 1279 */ checkState(String methodName)1280 public void checkState(String methodName) throws IllegalStateException { 1281 synchronized (mStateLock) { 1282 if (mState != STATE_INITIALIZED) { 1283 throw (new IllegalStateException(methodName 1284 + " called on uninitialized AudioEffect.")); 1285 } 1286 } 1287 } 1288 1289 /** 1290 * @hide 1291 */ checkStatus(int status)1292 public void checkStatus(int status) { 1293 if (isError(status)) { 1294 switch (status) { 1295 case AudioEffect.ERROR_BAD_VALUE: 1296 throw (new IllegalArgumentException( 1297 "AudioEffect: bad parameter value")); 1298 case AudioEffect.ERROR_INVALID_OPERATION: 1299 throw (new UnsupportedOperationException( 1300 "AudioEffect: invalid parameter operation")); 1301 default: 1302 throw (new RuntimeException("AudioEffect: set/get parameter error")); 1303 } 1304 } 1305 } 1306 1307 /** 1308 * @hide 1309 */ 1310 @TestApi isError(int status)1311 public static boolean isError(int status) { 1312 return (status < 0); 1313 } 1314 1315 /** 1316 * @hide 1317 */ 1318 @TestApi byteArrayToInt(byte[] valueBuf)1319 public static int byteArrayToInt(byte[] valueBuf) { 1320 return byteArrayToInt(valueBuf, 0); 1321 1322 } 1323 1324 /** 1325 * @hide 1326 */ byteArrayToInt(byte[] valueBuf, int offset)1327 public static int byteArrayToInt(byte[] valueBuf, int offset) { 1328 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 1329 converter.order(ByteOrder.nativeOrder()); 1330 return converter.getInt(offset); 1331 1332 } 1333 1334 /** 1335 * @hide 1336 */ 1337 @TestApi intToByteArray(int value)1338 public static byte[] intToByteArray(int value) { 1339 ByteBuffer converter = ByteBuffer.allocate(4); 1340 converter.order(ByteOrder.nativeOrder()); 1341 converter.putInt(value); 1342 return converter.array(); 1343 } 1344 1345 /** 1346 * @hide 1347 */ 1348 @TestApi byteArrayToShort(byte[] valueBuf)1349 public static short byteArrayToShort(byte[] valueBuf) { 1350 return byteArrayToShort(valueBuf, 0); 1351 } 1352 1353 /** 1354 * @hide 1355 */ byteArrayToShort(byte[] valueBuf, int offset)1356 public static short byteArrayToShort(byte[] valueBuf, int offset) { 1357 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 1358 converter.order(ByteOrder.nativeOrder()); 1359 return converter.getShort(offset); 1360 1361 } 1362 1363 /** 1364 * @hide 1365 */ 1366 @TestApi shortToByteArray(short value)1367 public static byte[] shortToByteArray(short value) { 1368 ByteBuffer converter = ByteBuffer.allocate(2); 1369 converter.order(ByteOrder.nativeOrder()); 1370 short sValue = (short) value; 1371 converter.putShort(sValue); 1372 return converter.array(); 1373 } 1374 1375 /** 1376 * @hide 1377 */ byteArrayToFloat(byte[] valueBuf)1378 public static float byteArrayToFloat(byte[] valueBuf) { 1379 return byteArrayToFloat(valueBuf, 0); 1380 1381 } 1382 1383 /** 1384 * @hide 1385 */ byteArrayToFloat(byte[] valueBuf, int offset)1386 public static float byteArrayToFloat(byte[] valueBuf, int offset) { 1387 ByteBuffer converter = ByteBuffer.wrap(valueBuf); 1388 converter.order(ByteOrder.nativeOrder()); 1389 return converter.getFloat(offset); 1390 1391 } 1392 1393 /** 1394 * @hide 1395 */ floatToByteArray(float value)1396 public static byte[] floatToByteArray(float value) { 1397 ByteBuffer converter = ByteBuffer.allocate(4); 1398 converter.order(ByteOrder.nativeOrder()); 1399 converter.putFloat(value); 1400 return converter.array(); 1401 } 1402 1403 /** 1404 * @hide 1405 */ concatArrays(byte[]... arrays)1406 public static byte[] concatArrays(byte[]... arrays) { 1407 int len = 0; 1408 for (byte[] a : arrays) { 1409 len += a.length; 1410 } 1411 byte[] b = new byte[len]; 1412 1413 int offs = 0; 1414 for (byte[] a : arrays) { 1415 System.arraycopy(a, 0, b, offs, a.length); 1416 offs += a.length; 1417 } 1418 return b; 1419 } 1420 } 1421