• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.media.audiofx;
18 
19 import android.media.audiofx.AudioEffect;
20 import java.util.StringTokenizer;
21 
22 
23 /**
24  * A sound generated within a room travels in many directions. The listener first hears the
25  * direct sound from the source itself. Later, he or she hears discrete echoes caused by sound
26  * bouncing off nearby walls, the ceiling and the floor. As sound waves arrive after
27  * undergoing more and more reflections, individual reflections become indistinguishable and
28  * the listener hears continuous reverberation that decays over time.
29  * Reverb is vital for modeling a listener's environment. It can be used in music applications
30  * to simulate music being played back in various environments, or in games to immerse the
31  * listener within the game's environment.
32  * The PresetReverb class allows an application to configure the global reverb using a reverb preset.
33  * This is primarily used for adding some reverb in a music playback context. Applications
34  * requiring control over a more advanced environmental reverb are advised to use the
35  * {@link android.media.audiofx.EnvironmentalReverb} class.
36  * <p>An application creates a PresetReverb object to instantiate and control a reverb engine in the
37  * audio framework.
38  * <p>The methods, parameter types and units exposed by the PresetReverb implementation are
39  * directly mapping those defined by the OpenSL ES 1.0.1 Specification
40  * (http://www.khronos.org/opensles/) for the SLPresetReverbItf interface.
41  * Please refer to this specification for more details.
42  * <p>The PresetReverb is an output mix auxiliary effect and should be created on
43  * Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect,
44  * they must be explicitely attached to it and a send level must be specified. Use the effect ID
45  * returned by getId() method to designate this particular effect when attaching it to the
46  * MediaPlayer or AudioTrack.
47  * <p>Creating a reverb on the output mix (audio session 0) requires permission
48  * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
49  * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling
50  * audio effects.
51  */
52 
53 public class PresetReverb extends AudioEffect {
54 
55     private final static String TAG = "PresetReverb";
56 
57     // These constants must be synchronized with those in
58     // frameworks/base/include/media/EffectPresetReverbApi.h
59 
60     /**
61      * Preset. Parameter ID for
62      * {@link android.media.audiofx.PresetReverb.OnParameterChangeListener}
63      */
64     public static final int PARAM_PRESET = 0;
65 
66     /**
67      * No reverb or reflections
68      */
69     public static final short PRESET_NONE        = 0;
70     /**
71      * Reverb preset representing a small room less than five meters in length
72      */
73     public static final short PRESET_SMALLROOM   = 1;
74     /**
75      * Reverb preset representing a medium room with a length of ten meters or less
76      */
77     public static final short PRESET_MEDIUMROOM  = 2;
78     /**
79      * Reverb preset representing a large-sized room suitable for live performances
80      */
81     public static final short PRESET_LARGEROOM   = 3;
82     /**
83      * Reverb preset representing a medium-sized hall
84      */
85     public static final short PRESET_MEDIUMHALL  = 4;
86     /**
87      * Reverb preset representing a large-sized hall suitable for a full orchestra
88      */
89     public static final short PRESET_LARGEHALL   = 5;
90     /**
91      * Reverb preset representing a synthesis of the traditional plate reverb
92      */
93     public static final short PRESET_PLATE       = 6;
94 
95     /**
96      * Registered listener for parameter changes.
97      */
98     private OnParameterChangeListener mParamListener = null;
99 
100     /**
101      * Listener used internally to to receive raw parameter change event from AudioEffect super class
102      */
103     private BaseParameterListener mBaseParamListener = null;
104 
105     /**
106      * Lock for access to mParamListener
107      */
108     private final Object mParamListenerLock = new Object();
109 
110     /**
111      * Class constructor.
112      * @param priority the priority level requested by the application for controlling the
113      * PresetReverb engine. As the same engine can be shared by several applications, this
114      * parameter indicates how much the requesting application needs control of effect parameters.
115      * The normal priority is 0, above normal is a positive number, below normal a negative number.
116      * @param audioSession  system wide unique audio session identifier. If audioSession
117      *  is not 0, the PresetReverb will be attached to the MediaPlayer or AudioTrack in the
118      *  same audio session. Otherwise, the PresetReverb will apply to the output mix.
119      *  As the PresetReverb is an auxiliary effect it is recommended to instantiate it on
120      *  audio session 0 and to attach it to the MediaPLayer auxiliary output.
121      *
122      * @throws java.lang.IllegalArgumentException
123      * @throws java.lang.UnsupportedOperationException
124      * @throws java.lang.RuntimeException
125      */
PresetReverb(int priority, int audioSession)126     public PresetReverb(int priority, int audioSession)
127     throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
128         super(EFFECT_TYPE_PRESET_REVERB, EFFECT_TYPE_NULL, priority, audioSession);
129     }
130 
131     /**
132      *  Enables a preset on the reverb.
133      *  <p>The reverb PRESET_NONE disables any reverb from the current output but does not free the
134      *  resources associated with the reverb. For an application to signal to the implementation
135      *  to free the resources, it must call the release() method.
136      * @param preset this must be one of the the preset constants defined in this class.
137      * e.g. {@link #PRESET_SMALLROOM}
138      * @throws IllegalStateException
139      * @throws IllegalArgumentException
140      * @throws UnsupportedOperationException
141      */
setPreset(short preset)142     public void setPreset(short preset)
143     throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
144         checkStatus(setParameter(PARAM_PRESET, preset));
145     }
146 
147     /**
148      * Gets current reverb preset.
149      * @return the preset that is set at the moment.
150      * @throws IllegalStateException
151      * @throws IllegalArgumentException
152      * @throws UnsupportedOperationException
153      */
getPreset()154     public short getPreset()
155     throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
156         short[] value = new short[1];
157         checkStatus(getParameter(PARAM_PRESET, value));
158         return value[0];
159     }
160 
161     /**
162      * The OnParameterChangeListener interface defines a method called by the PresetReverb
163      * when a parameter value has changed.
164      */
165     public interface OnParameterChangeListener  {
166         /**
167          * Method called when a parameter value has changed. The method is called only if the
168          * parameter was changed by another application having the control of the same
169          * PresetReverb engine.
170          * @param effect the PresetReverb on which the interface is registered.
171          * @param status status of the set parameter operation.
172          * @param param ID of the modified parameter. See {@link #PARAM_PRESET} ...
173          * @param value the new parameter value.
174          */
onParameterChange(PresetReverb effect, int status, int param, short value)175         void onParameterChange(PresetReverb effect, int status, int param, short value);
176     }
177 
178     /**
179      * Listener used internally to receive unformatted parameter change events from AudioEffect
180      * super class.
181      */
182     private class BaseParameterListener implements AudioEffect.OnParameterChangeListener {
BaseParameterListener()183         private BaseParameterListener() {
184 
185         }
onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value)186         public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) {
187             OnParameterChangeListener l = null;
188 
189             synchronized (mParamListenerLock) {
190                 if (mParamListener != null) {
191                     l = mParamListener;
192                 }
193             }
194             if (l != null) {
195                 int p = -1;
196                 short v = -1;
197 
198                 if (param.length == 4) {
199                     p = byteArrayToInt(param, 0);
200                 }
201                 if (value.length == 2) {
202                     v = byteArrayToShort(value, 0);
203                 }
204                 if (p != -1 && v != -1) {
205                     l.onParameterChange(PresetReverb.this, status, p, v);
206                 }
207             }
208         }
209     }
210 
211     /**
212      * Registers an OnParameterChangeListener interface.
213      * @param listener OnParameterChangeListener interface registered
214      */
setParameterListener(OnParameterChangeListener listener)215     public void setParameterListener(OnParameterChangeListener listener) {
216         synchronized (mParamListenerLock) {
217             if (mParamListener == null) {
218                 mParamListener = listener;
219                 mBaseParamListener = new BaseParameterListener();
220                 super.setParameterListener(mBaseParamListener);
221             }
222         }
223     }
224 
225     /**
226      * The Settings class regroups all preset reverb parameters. It is used in
227      * conjuntion with getProperties() and setProperties() methods to backup and restore
228      * all parameters in a single call.
229      */
230     public static class Settings {
231         public short preset;
232 
Settings()233         public Settings() {
234         }
235 
236         /**
237          * Settings class constructor from a key=value; pairs formatted string. The string is
238          * typically returned by Settings.toString() method.
239          * @throws IllegalArgumentException if the string is not correctly formatted.
240          */
Settings(String settings)241         public Settings(String settings) {
242             StringTokenizer st = new StringTokenizer(settings, "=;");
243             int tokens = st.countTokens();
244             if (st.countTokens() != 3) {
245                 throw new IllegalArgumentException("settings: " + settings);
246             }
247             String key = st.nextToken();
248             if (!key.equals("PresetReverb")) {
249                 throw new IllegalArgumentException(
250                         "invalid settings for PresetReverb: " + key);
251             }
252             try {
253                 key = st.nextToken();
254                 if (!key.equals("preset")) {
255                     throw new IllegalArgumentException("invalid key name: " + key);
256                 }
257                 preset = Short.parseShort(st.nextToken());
258              } catch (NumberFormatException nfe) {
259                 throw new IllegalArgumentException("invalid value for key: " + key);
260             }
261         }
262 
263         @Override
toString()264         public String toString() {
265             String str = new String (
266                     "PresetReverb"+
267                     ";preset="+Short.toString(preset)
268                     );
269             return str;
270         }
271     };
272 
273 
274     /**
275      * Gets the preset reverb properties. This method is useful when a snapshot of current
276      * preset reverb settings must be saved by the application.
277      * @return a PresetReverb.Settings object containing all current parameters values
278      * @throws IllegalStateException
279      * @throws IllegalArgumentException
280      * @throws UnsupportedOperationException
281      */
getProperties()282     public PresetReverb.Settings getProperties()
283     throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
284         Settings settings = new Settings();
285         short[] value = new short[1];
286         checkStatus(getParameter(PARAM_PRESET, value));
287         settings.preset = value[0];
288         return settings;
289     }
290 
291     /**
292      * Sets the preset reverb properties. This method is useful when preset reverb settings have to
293      * be applied from a previous backup.
294      * @param settings a PresetReverb.Settings object containing the properties to apply
295      * @throws IllegalStateException
296      * @throws IllegalArgumentException
297      * @throws UnsupportedOperationException
298      */
setProperties(PresetReverb.Settings settings)299     public void setProperties(PresetReverb.Settings settings)
300     throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
301         checkStatus(setParameter(PARAM_PRESET, settings.preset));
302     }
303 }
304