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