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.media.audiofx.AudioEffect; 20 import java.util.StringTokenizer; 21 22 /** 23 * A sound generated within a room travels in many directions. The listener first hears the direct 24 * sound from the source itself. Later, he or she hears discrete echoes caused by sound bouncing off 25 * nearby walls, the ceiling and the floor. As sound waves arrive after undergoing more and more 26 * reflections, individual reflections become indistinguishable and the listener hears continuous 27 * reverberation that decays over time. 28 * Reverb is vital for modeling a listener's environment. It can be used in music applications 29 * to simulate music being played back in various environments, or in games to immerse the 30 * listener within the game's environment. 31 * The EnvironmentalReverb class allows an application to control each reverb engine property in a 32 * global reverb environment and is more suitable for games. For basic control, more suitable for 33 * music applications, it is recommended to use the 34 * {@link android.media.audiofx.PresetReverb} class. 35 * <p>An application creates a EnvironmentalReverb object to instantiate and control a reverb engine 36 * in the audio framework. 37 * <p>The methods, parameter types and units exposed by the EnvironmentalReverb implementation are 38 * directly mapping those defined by the OpenSL ES 1.0.1 Specification 39 * (http://www.khronos.org/opensles/) for the SLEnvironmentalReverbItf interface. 40 * Please refer to this specification for more details. 41 * <p>The EnvironmentalReverb is an output mix auxiliary effect and should be created on 42 * Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect, 43 * they must be explicitely attached to it and a send level must be specified. Use the effect ID 44 * returned by getId() method to designate this particular effect when attaching it to the 45 * MediaPlayer or AudioTrack. 46 * <p>Creating a reverb on the output mix (audio session 0) requires permission 47 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} 48 * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling 49 * audio effects. 50 */ 51 52 public class EnvironmentalReverb extends AudioEffect { 53 54 private final static String TAG = "EnvironmentalReverb"; 55 56 // These constants must be synchronized with those in 57 // frameworks/base/include/media/EffectEnvironmentalReverbApi.h 58 59 /** 60 * Room level. Parameter ID for OnParameterChangeListener 61 */ 62 public static final int PARAM_ROOM_LEVEL = 0; 63 /** 64 * Room HF level. Parameter ID for OnParameterChangeListener 65 */ 66 public static final int PARAM_ROOM_HF_LEVEL = 1; 67 /** 68 * Decay time. Parameter ID for OnParameterChangeListener 69 */ 70 public static final int PARAM_DECAY_TIME = 2; 71 /** 72 * Decay HF ratio. Parameter ID for 73 * {@link android.media.audiofx.EnvironmentalReverb.OnParameterChangeListener} 74 */ 75 public static final int PARAM_DECAY_HF_RATIO = 3; 76 /** 77 * Early reflections level. Parameter ID for OnParameterChangeListener 78 */ 79 public static final int PARAM_REFLECTIONS_LEVEL = 4; 80 /** 81 * Early reflections delay. Parameter ID for OnParameterChangeListener 82 */ 83 public static final int PARAM_REFLECTIONS_DELAY = 5; 84 /** 85 * Reverb level. Parameter ID for OnParameterChangeListener 86 */ 87 public static final int PARAM_REVERB_LEVEL = 6; 88 /** 89 * Reverb delay. Parameter ID for OnParameterChangeListener 90 */ 91 public static final int PARAM_REVERB_DELAY = 7; 92 /** 93 * Diffusion. Parameter ID for OnParameterChangeListener 94 */ 95 public static final int PARAM_DIFFUSION = 8; 96 /** 97 * Density. Parameter ID for OnParameterChangeListener 98 */ 99 public static final int PARAM_DENSITY = 9; 100 101 // used by setProperties()/getProperties 102 private static final int PARAM_PROPERTIES = 10; 103 104 /** 105 * Registered listener for parameter changes 106 */ 107 private OnParameterChangeListener mParamListener = null; 108 109 /** 110 * Listener used internally to to receive raw parameter change event from AudioEffect super 111 * class 112 */ 113 private BaseParameterListener mBaseParamListener = null; 114 115 /** 116 * Lock for access to mParamListener 117 */ 118 private final Object mParamListenerLock = new Object(); 119 120 /** 121 * Class constructor. 122 * @param priority the priority level requested by the application for controlling the 123 * EnvironmentalReverb engine. As the same engine can be shared by several applications, this 124 * parameter indicates how much the requesting application needs control of effect parameters. 125 * The normal priority is 0, above normal is a positive number, below normal a negative number. 126 * @param audioSession system wide unique audio session identifier. If audioSession 127 * is not 0, the EnvironmentalReverb will be attached to the MediaPlayer or AudioTrack in the 128 * same audio session. Otherwise, the EnvironmentalReverb will apply to the output mix. 129 * As the EnvironmentalReverb is an auxiliary effect it is recommended to instantiate it on 130 * audio session 0 and to attach it to the MediaPLayer auxiliary output. 131 * 132 * @throws java.lang.IllegalArgumentException 133 * @throws java.lang.UnsupportedOperationException 134 * @throws java.lang.RuntimeException 135 */ EnvironmentalReverb(int priority, int audioSession)136 public EnvironmentalReverb(int priority, int audioSession) 137 throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { 138 super(EFFECT_TYPE_ENV_REVERB, EFFECT_TYPE_NULL, priority, audioSession); 139 } 140 141 /** 142 * Sets the master volume level of the environmental reverb effect. 143 * @param room room level in millibels. The valid range is [-9000, 0]. 144 * @throws IllegalStateException 145 * @throws IllegalArgumentException 146 * @throws UnsupportedOperationException 147 */ setRoomLevel(short room)148 public void setRoomLevel(short room) 149 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 150 byte[] param = shortToByteArray(room); 151 checkStatus(setParameter(PARAM_ROOM_LEVEL, param)); 152 } 153 154 /** 155 * Gets the master volume level of the environmental reverb effect. 156 * @return the room level in millibels. 157 * @throws IllegalStateException 158 * @throws IllegalArgumentException 159 * @throws UnsupportedOperationException 160 */ getRoomLevel()161 public short getRoomLevel() 162 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 163 byte[] param = new byte[2]; 164 checkStatus(getParameter(PARAM_ROOM_LEVEL, param)); 165 return byteArrayToShort(param); 166 } 167 168 /** 169 * Sets the volume level at 5 kHz relative to the volume level at low frequencies of the 170 * overall reverb effect. 171 * <p>This controls a low-pass filter that will reduce the level of the high-frequency. 172 * @param roomHF high frequency attenuation level in millibels. The valid range is [-9000, 0]. 173 * @throws IllegalStateException 174 * @throws IllegalArgumentException 175 * @throws UnsupportedOperationException 176 */ setRoomHFLevel(short roomHF)177 public void setRoomHFLevel(short roomHF) 178 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 179 byte[] param = shortToByteArray(roomHF); 180 checkStatus(setParameter(PARAM_ROOM_HF_LEVEL, param)); 181 } 182 183 /** 184 * Gets the room HF level. 185 * @return the room HF level in millibels. 186 * @throws IllegalStateException 187 * @throws IllegalArgumentException 188 * @throws UnsupportedOperationException 189 */ getRoomHFLevel()190 public short getRoomHFLevel() 191 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 192 byte[] param = new byte[2]; 193 checkStatus(getParameter(PARAM_ROOM_HF_LEVEL, param)); 194 return byteArrayToShort(param); 195 } 196 197 /** 198 * Sets the time taken for the level of reverberation to decay by 60 dB. 199 * @param decayTime decay time in milliseconds. The valid range is [100, 20000]. 200 * @throws IllegalStateException 201 * @throws IllegalArgumentException 202 * @throws UnsupportedOperationException 203 */ setDecayTime(int decayTime)204 public void setDecayTime(int decayTime) 205 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 206 byte[] param = intToByteArray(decayTime); 207 checkStatus(setParameter(PARAM_DECAY_TIME, param)); 208 } 209 210 /** 211 * Gets the decay time. 212 * @return the decay time in milliseconds. 213 * @throws IllegalStateException 214 * @throws IllegalArgumentException 215 * @throws UnsupportedOperationException 216 */ getDecayTime()217 public int getDecayTime() 218 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 219 byte[] param = new byte[4]; 220 checkStatus(getParameter(PARAM_DECAY_TIME, param)); 221 return byteArrayToInt(param); 222 } 223 224 /** 225 * Sets the ratio of high frequency decay time (at 5 kHz) relative to the decay time at low 226 * frequencies. 227 * @param decayHFRatio high frequency decay ratio using a permille scale. The valid range is 228 * [100, 2000]. A ratio of 1000 indicates that all frequencies decay at the same rate. 229 * @throws IllegalStateException 230 * @throws IllegalArgumentException 231 * @throws UnsupportedOperationException 232 */ setDecayHFRatio(short decayHFRatio)233 public void setDecayHFRatio(short decayHFRatio) 234 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 235 byte[] param = shortToByteArray(decayHFRatio); 236 checkStatus(setParameter(PARAM_DECAY_HF_RATIO, param)); 237 } 238 239 /** 240 * Gets the ratio of high frequency decay time (at 5 kHz) relative to low frequencies. 241 * @return the decay HF ration. See {@link #setDecayHFRatio(short)} for units. 242 * @throws IllegalStateException 243 * @throws IllegalArgumentException 244 * @throws UnsupportedOperationException 245 */ getDecayHFRatio()246 public short getDecayHFRatio() 247 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 248 byte[] param = new byte[2]; 249 checkStatus(getParameter(PARAM_DECAY_HF_RATIO, param)); 250 return byteArrayToShort(param); 251 } 252 253 /** 254 * Sets the volume level of the early reflections. 255 * <p>This level is combined with the overall room level 256 * (set using {@link #setRoomLevel(short)}). 257 * @param reflectionsLevel reflection level in millibels. The valid range is [-9000, 1000]. 258 * @throws IllegalStateException 259 * @throws IllegalArgumentException 260 * @throws UnsupportedOperationException 261 */ setReflectionsLevel(short reflectionsLevel)262 public void setReflectionsLevel(short reflectionsLevel) 263 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 264 byte[] param = shortToByteArray(reflectionsLevel); 265 checkStatus(setParameter(PARAM_REFLECTIONS_LEVEL, param)); 266 } 267 268 /** 269 * Gets the volume level of the early reflections. 270 * @return the early reflections level in millibels. 271 * @throws IllegalStateException 272 * @throws IllegalArgumentException 273 * @throws UnsupportedOperationException 274 */ getReflectionsLevel()275 public short getReflectionsLevel() 276 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 277 byte[] param = new byte[2]; 278 checkStatus(getParameter(PARAM_REFLECTIONS_LEVEL, param)); 279 return byteArrayToShort(param); 280 } 281 282 /** 283 * Sets the delay time for the early reflections. 284 * <p>This method sets the time between when the direct path is heard and when the first 285 * reflection is heard. 286 * @param reflectionsDelay reflections delay in milliseconds. The valid range is [0, 300]. 287 * @throws IllegalStateException 288 * @throws IllegalArgumentException 289 * @throws UnsupportedOperationException 290 */ setReflectionsDelay(int reflectionsDelay)291 public void setReflectionsDelay(int reflectionsDelay) 292 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 293 byte[] param = intToByteArray(reflectionsDelay); 294 checkStatus(setParameter(PARAM_REFLECTIONS_DELAY, param)); 295 } 296 297 /** 298 * Gets the reflections delay. 299 * @return the early reflections delay in milliseconds. 300 * @throws IllegalStateException 301 * @throws IllegalArgumentException 302 * @throws UnsupportedOperationException 303 */ getReflectionsDelay()304 public int getReflectionsDelay() 305 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 306 byte[] param = new byte[4]; 307 checkStatus(getParameter(PARAM_REFLECTIONS_DELAY, param)); 308 return byteArrayToInt(param); 309 } 310 311 /** 312 * Sets the volume level of the late reverberation. 313 * <p>This level is combined with the overall room level (set using {@link #setRoomLevel(short)}). 314 * @param reverbLevel reverb level in millibels. The valid range is [-9000, 2000]. 315 * @throws IllegalStateException 316 * @throws IllegalArgumentException 317 * @throws UnsupportedOperationException 318 */ setReverbLevel(short reverbLevel)319 public void setReverbLevel(short reverbLevel) 320 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 321 byte[] param = shortToByteArray(reverbLevel); 322 checkStatus(setParameter(PARAM_REVERB_LEVEL, param)); 323 } 324 325 /** 326 * Gets the reverb level. 327 * @return the reverb level in millibels. 328 * @throws IllegalStateException 329 * @throws IllegalArgumentException 330 * @throws UnsupportedOperationException 331 */ getReverbLevel()332 public short getReverbLevel() 333 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 334 byte[] param = new byte[2]; 335 checkStatus(getParameter(PARAM_REVERB_LEVEL, param)); 336 return byteArrayToShort(param); 337 } 338 339 /** 340 * Sets the time between the first reflection and the reverberation. 341 * @param reverbDelay reverb delay in milliseconds. The valid range is [0, 100]. 342 * @throws IllegalStateException 343 * @throws IllegalArgumentException 344 * @throws UnsupportedOperationException 345 */ setReverbDelay(int reverbDelay)346 public void setReverbDelay(int reverbDelay) 347 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 348 byte[] param = intToByteArray(reverbDelay); 349 checkStatus(setParameter(PARAM_REVERB_DELAY, param)); 350 } 351 352 /** 353 * Gets the reverb delay. 354 * @return the reverb delay in milliseconds. 355 * @throws IllegalStateException 356 * @throws IllegalArgumentException 357 * @throws UnsupportedOperationException 358 */ getReverbDelay()359 public int getReverbDelay() 360 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 361 byte[] param = new byte[4]; 362 checkStatus(getParameter(PARAM_REVERB_DELAY, param)); 363 return byteArrayToInt(param); 364 } 365 366 /** 367 * Sets the echo density in the late reverberation decay. 368 * <p>The scale should approximately map linearly to the perceived change in reverberation. 369 * @param diffusion diffusion specified using a permille scale. The diffusion valid range is 370 * [0, 1000]. A value of 1000 o/oo indicates a smooth reverberation decay. 371 * Values below this level give a more <i>grainy</i> character. 372 * @throws IllegalStateException 373 * @throws IllegalArgumentException 374 * @throws UnsupportedOperationException 375 */ setDiffusion(short diffusion)376 public void setDiffusion(short diffusion) 377 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 378 byte[] param = shortToByteArray(diffusion); 379 checkStatus(setParameter(PARAM_DIFFUSION, param)); 380 } 381 382 /** 383 * Gets diffusion level. 384 * @return the diffusion level. See {@link #setDiffusion(short)} for units. 385 * @throws IllegalStateException 386 * @throws IllegalArgumentException 387 * @throws UnsupportedOperationException 388 */ getDiffusion()389 public short getDiffusion() 390 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 391 byte[] param = new byte[2]; 392 checkStatus(getParameter(PARAM_DIFFUSION, param)); 393 return byteArrayToShort(param); 394 } 395 396 397 /** 398 * Controls the modal density of the late reverberation decay. 399 * <p> The scale should approximately map linearly to the perceived change in reverberation. 400 * A lower density creates a hollow sound that is useful for simulating small reverberation 401 * spaces such as bathrooms. 402 * @param density density specified using a permille scale. The valid range is [0, 1000]. 403 * A value of 1000 o/oo indicates a natural sounding reverberation. Values below this level 404 * produce a more colored effect. 405 * @throws IllegalStateException 406 * @throws IllegalArgumentException 407 * @throws UnsupportedOperationException 408 */ setDensity(short density)409 public void setDensity(short density) 410 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 411 byte[] param = shortToByteArray(density); 412 checkStatus(setParameter(PARAM_DENSITY, param)); 413 } 414 415 /** 416 * Gets the density level. 417 * @return the density level. See {@link #setDiffusion(short)} for units. 418 * @throws IllegalStateException 419 * @throws IllegalArgumentException 420 * @throws UnsupportedOperationException 421 */ getDensity()422 public short getDensity() 423 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 424 byte[] param = new byte[2]; 425 checkStatus(getParameter(PARAM_DENSITY, param)); 426 return byteArrayToShort(param); 427 } 428 429 430 /** 431 * The OnParameterChangeListener interface defines a method called by the EnvironmentalReverb 432 * when a parameter value has changed. 433 */ 434 public interface OnParameterChangeListener { 435 /** 436 * Method called when a parameter value has changed. The method is called only if the 437 * parameter was changed by another application having the control of the same 438 * EnvironmentalReverb engine. 439 * @param effect the EnvironmentalReverb on which the interface is registered. 440 * @param status status of the set parameter operation. 441 * @param param ID of the modified parameter. See {@link #PARAM_ROOM_LEVEL} ... 442 * @param value the new parameter value. 443 */ onParameterChange(EnvironmentalReverb effect, int status, int param, int value)444 void onParameterChange(EnvironmentalReverb effect, int status, int param, int value); 445 } 446 447 /** 448 * Listener used internally to receive unformatted parameter change events from AudioEffect 449 * super class. 450 */ 451 private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { BaseParameterListener()452 private BaseParameterListener() { 453 454 } onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value)455 public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { 456 OnParameterChangeListener l = null; 457 458 synchronized (mParamListenerLock) { 459 if (mParamListener != null) { 460 l = mParamListener; 461 } 462 } 463 if (l != null) { 464 int p = -1; 465 int v = -1; 466 467 if (param.length == 4) { 468 p = byteArrayToInt(param, 0); 469 } 470 if (value.length == 2) { 471 v = (int)byteArrayToShort(value, 0); 472 } else if (value.length == 4) { 473 v = byteArrayToInt(value, 0); 474 } 475 if (p != -1 && v != -1) { 476 l.onParameterChange(EnvironmentalReverb.this, status, p, v); 477 } 478 } 479 } 480 } 481 482 /** 483 * Registers an OnParameterChangeListener interface. 484 * @param listener OnParameterChangeListener interface registered 485 */ setParameterListener(OnParameterChangeListener listener)486 public void setParameterListener(OnParameterChangeListener listener) { 487 synchronized (mParamListenerLock) { 488 if (mParamListener == null) { 489 mParamListener = listener; 490 mBaseParamListener = new BaseParameterListener(); 491 super.setParameterListener(mBaseParamListener); 492 } 493 } 494 } 495 496 /** 497 * The Settings class regroups all environmental reverb parameters. It is used in 498 * conjuntion with getProperties() and setProperties() methods to backup and restore 499 * all parameters in a single call. 500 */ 501 public static class Settings { 502 public short roomLevel; 503 public short roomHFLevel; 504 public int decayTime; 505 public short decayHFRatio; 506 public short reflectionsLevel; 507 public int reflectionsDelay; 508 public short reverbLevel; 509 public int reverbDelay; 510 public short diffusion; 511 public short density; 512 Settings()513 public Settings() { 514 } 515 516 /** 517 * Settings class constructor from a key=value; pairs formatted string. The string is 518 * typically returned by Settings.toString() method. 519 * @throws IllegalArgumentException if the string is not correctly formatted. 520 */ Settings(String settings)521 public Settings(String settings) { 522 StringTokenizer st = new StringTokenizer(settings, "=;"); 523 int tokens = st.countTokens(); 524 if (st.countTokens() != 21) { 525 throw new IllegalArgumentException("settings: " + settings); 526 } 527 String key = st.nextToken(); 528 if (!key.equals("EnvironmentalReverb")) { 529 throw new IllegalArgumentException( 530 "invalid settings for EnvironmentalReverb: " + key); 531 } 532 533 try { 534 key = st.nextToken(); 535 if (!key.equals("roomLevel")) { 536 throw new IllegalArgumentException("invalid key name: " + key); 537 } 538 roomLevel = Short.parseShort(st.nextToken()); 539 key = st.nextToken(); 540 if (!key.equals("roomHFLevel")) { 541 throw new IllegalArgumentException("invalid key name: " + key); 542 } 543 roomHFLevel = Short.parseShort(st.nextToken()); 544 key = st.nextToken(); 545 if (!key.equals("decayTime")) { 546 throw new IllegalArgumentException("invalid key name: " + key); 547 } 548 decayTime = Integer.parseInt(st.nextToken()); 549 key = st.nextToken(); 550 if (!key.equals("decayHFRatio")) { 551 throw new IllegalArgumentException("invalid key name: " + key); 552 } 553 decayHFRatio = Short.parseShort(st.nextToken()); 554 key = st.nextToken(); 555 if (!key.equals("reflectionsLevel")) { 556 throw new IllegalArgumentException("invalid key name: " + key); 557 } 558 reflectionsLevel = Short.parseShort(st.nextToken()); 559 key = st.nextToken(); 560 if (!key.equals("reflectionsDelay")) { 561 throw new IllegalArgumentException("invalid key name: " + key); 562 } 563 reflectionsDelay = Integer.parseInt(st.nextToken()); 564 key = st.nextToken(); 565 if (!key.equals("reverbLevel")) { 566 throw new IllegalArgumentException("invalid key name: " + key); 567 } 568 reverbLevel = Short.parseShort(st.nextToken()); 569 key = st.nextToken(); 570 if (!key.equals("reverbDelay")) { 571 throw new IllegalArgumentException("invalid key name: " + key); 572 } 573 reverbDelay = Integer.parseInt(st.nextToken()); 574 key = st.nextToken(); 575 if (!key.equals("diffusion")) { 576 throw new IllegalArgumentException("invalid key name: " + key); 577 } 578 diffusion = Short.parseShort(st.nextToken()); 579 key = st.nextToken(); 580 if (!key.equals("density")) { 581 throw new IllegalArgumentException("invalid key name: " + key); 582 } 583 density = Short.parseShort(st.nextToken()); 584 } catch (NumberFormatException nfe) { 585 throw new IllegalArgumentException("invalid value for key: " + key); 586 } 587 } 588 589 @Override toString()590 public String toString() { 591 return new String ( 592 "EnvironmentalReverb"+ 593 ";roomLevel="+Short.toString(roomLevel)+ 594 ";roomHFLevel="+Short.toString(roomHFLevel)+ 595 ";decayTime="+Integer.toString(decayTime)+ 596 ";decayHFRatio="+Short.toString(decayHFRatio)+ 597 ";reflectionsLevel="+Short.toString(reflectionsLevel)+ 598 ";reflectionsDelay="+Integer.toString(reflectionsDelay)+ 599 ";reverbLevel="+Short.toString(reverbLevel)+ 600 ";reverbDelay="+Integer.toString(reverbDelay)+ 601 ";diffusion="+Short.toString(diffusion)+ 602 ";density="+Short.toString(density) 603 ); 604 } 605 }; 606 607 // Keep this in sync with sizeof(s_reverb_settings) defined in 608 // frameworks/base/include/media/EffectEnvironmentalReverbApi.h 609 static private int PROPERTY_SIZE = 26; 610 611 /** 612 * Gets the environmental reverb properties. This method is useful when a snapshot of current 613 * reverb settings must be saved by the application. 614 * @return an EnvironmentalReverb.Settings object containing all current parameters values 615 * @throws IllegalStateException 616 * @throws IllegalArgumentException 617 * @throws UnsupportedOperationException 618 */ getProperties()619 public EnvironmentalReverb.Settings getProperties() 620 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 621 byte[] param = new byte[PROPERTY_SIZE]; 622 checkStatus(getParameter(PARAM_PROPERTIES, param)); 623 Settings settings = new Settings(); 624 settings.roomLevel = byteArrayToShort(param, 0); 625 settings.roomHFLevel = byteArrayToShort(param, 2); 626 settings.decayTime = byteArrayToInt(param, 4); 627 settings.decayHFRatio = byteArrayToShort(param, 8); 628 settings.reflectionsLevel = byteArrayToShort(param, 10); 629 settings.reflectionsDelay = byteArrayToInt(param, 12); 630 settings.reverbLevel = byteArrayToShort(param, 16); 631 settings.reverbDelay = byteArrayToInt(param, 18); 632 settings.diffusion = byteArrayToShort(param, 22); 633 settings.density = byteArrayToShort(param, 24); 634 return settings; 635 } 636 637 /** 638 * Sets the environmental reverb properties. This method is useful when reverb settings have to 639 * be applied from a previous backup. 640 * @param settings a EnvironmentalReverb.Settings object containing the properties to apply 641 * @throws IllegalStateException 642 * @throws IllegalArgumentException 643 * @throws UnsupportedOperationException 644 */ setProperties(EnvironmentalReverb.Settings settings)645 public void setProperties(EnvironmentalReverb.Settings settings) 646 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 647 648 byte[] param = concatArrays(shortToByteArray(settings.roomLevel), 649 shortToByteArray(settings.roomHFLevel), 650 intToByteArray(settings.decayTime), 651 shortToByteArray(settings.decayHFRatio), 652 shortToByteArray(settings.reflectionsLevel), 653 intToByteArray(settings.reflectionsDelay), 654 shortToByteArray(settings.reverbLevel), 655 intToByteArray(settings.reverbDelay), 656 shortToByteArray(settings.diffusion), 657 shortToByteArray(settings.density)); 658 659 checkStatus(setParameter(PARAM_PROPERTIES, param)); 660 } 661 } 662