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;
20fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurentimport android.util.Log;
21ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
22ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurentimport java.util.StringTokenizer;
23fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
24fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
25fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent/**
26fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent * Bass boost is an audio effect to boost or amplify low frequencies of the sound. It is comparable
27ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent * to a simple equalizer but limited to one band amplification in the low frequency range.
281a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * <p>An application creates a BassBoost object to instantiate and control a bass boost engine in
291a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * the audio framework.
30fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent * <p>The methods, parameter types and units exposed by the BassBoost implementation are directly
31fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent * mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/)
32fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent * for the SLBassBoostItf interface. Please refer to this specification for more details.
33fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent * <p>To attach the BassBoost to a particular AudioTrack or MediaPlayer, specify the audio session
341a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * ID of this AudioTrack or MediaPlayer when constructing the BassBoost.
3562f3617f2f4016ad2f59635d5156d64872989880Eric Laurent * <p>NOTE: attaching a BassBoost to the global audio output mix by use of session 0 is deprecated.
361a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
371a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
381a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * controlling audio effects.
39fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent */
40fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
41fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurentpublic class BassBoost extends AudioEffect {
42fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
43fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    private final static String TAG = "BassBoost";
44fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
45fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    // These constants must be synchronized with those in
46fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    // frameworks/base/include/media/EffectBassBoostApi.h
47fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
48fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Is strength parameter supported by bass boost engine. Parameter ID for getParameter().
49fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
50fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public static final int PARAM_STRENGTH_SUPPORTED = 0;
51fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
52fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Bass boost effect strength. Parameter ID for
531a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * {@link android.media.audiofx.BassBoost.OnParameterChangeListener}
54fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
55fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public static final int PARAM_STRENGTH = 1;
56fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
57fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
58fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Indicates if strength parameter is supported by the bass boost engine
59fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
60fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    private boolean mStrengthSupported = false;
61fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
62fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
63fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Registered listener for parameter changes.
64fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
65fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    private OnParameterChangeListener mParamListener = null;
66fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
67fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
68fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Listener used internally to to receive raw parameter change event from AudioEffect super class
69fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
70fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    private BaseParameterListener mBaseParamListener = null;
71fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
72fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
73fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Lock for access to mParamListener
74fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
75fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    private final Object mParamListenerLock = new Object();
76fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
77fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
78fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Class constructor.
79fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @param priority the priority level requested by the application for controlling the BassBoost
80fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * engine. As the same engine can be shared by several applications, this parameter indicates
81fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * how much the requesting application needs control of effect parameters. The normal priority
82fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * is 0, above normal is a positive number, below normal a negative number.
8362f3617f2f4016ad2f59635d5156d64872989880Eric Laurent     * @param audioSession system wide unique audio session identifier. The BassBoost will be
8462f3617f2f4016ad2f59635d5156d64872989880Eric Laurent     * attached to the MediaPlayer or AudioTrack in the same audio session.
85fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     *
86fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws java.lang.IllegalStateException
87fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws java.lang.IllegalArgumentException
88fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws java.lang.UnsupportedOperationException
89fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws java.lang.RuntimeException
90fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
91fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public BassBoost(int priority, int audioSession)
92fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    throws IllegalStateException, IllegalArgumentException,
93fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent           UnsupportedOperationException, RuntimeException {
94fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        super(EFFECT_TYPE_BASS_BOOST, EFFECT_TYPE_NULL, priority, audioSession);
95fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
9662f3617f2f4016ad2f59635d5156d64872989880Eric Laurent        if (audioSession == 0) {
9762f3617f2f4016ad2f59635d5156d64872989880Eric Laurent            Log.w(TAG, "WARNING: attaching a BassBoost to global output mix is deprecated!");
9862f3617f2f4016ad2f59635d5156d64872989880Eric Laurent        }
9962f3617f2f4016ad2f59635d5156d64872989880Eric Laurent
100ba8da2e61b1d9ebb7a4758f1f7849ff8440bd20cEric Laurent        int[] value = new int[1];
101fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value));
102fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        mStrengthSupported = (value[0] != 0);
103fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
104fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
105fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
106fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Indicates whether setting strength is supported. If this method returns false, only one
107fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * strength is supported and the setStrength() method always rounds to that value.
108fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @return true is strength parameter is supported, false otherwise
109fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
110fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public boolean getStrengthSupported() {
111fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent       return mStrengthSupported;
112fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
113fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
114fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
115fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Sets the strength of the bass boost effect. If the implementation does not support per mille
116fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * accuracy for setting the strength, it is allowed to round the given strength to the nearest
117fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * supported value. You can use the {@link #getRoundedStrength()} method to query the
118fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * (possibly rounded) value that was actually set.
11917cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent     * @param strength strength of the effect. The valid range for strength strength is [0, 1000],
120fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * where 0 per mille designates the mildest effect and 1000 per mille designates the strongest.
121fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws IllegalStateException
122fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws IllegalArgumentException
123fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws UnsupportedOperationException
124fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
125fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public void setStrength(short strength)
126fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
127fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        checkStatus(setParameter(PARAM_STRENGTH, strength));
128fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
129fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
130fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
131fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Gets the current strength of the effect.
13217cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent     * @return the strength of the effect. The valid range for strength is [0, 1000], where 0 per
133fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * mille designates the mildest effect and 1000 per mille the strongest
134fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws IllegalStateException
135fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws IllegalArgumentException
136fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @throws UnsupportedOperationException
137fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
138fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public short getRoundedStrength()
139fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
140fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        short[] value = new short[1];
141fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        checkStatus(getParameter(PARAM_STRENGTH, value));
142fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        return value[0];
143fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
144fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
145fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
146fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * The OnParameterChangeListener interface defines a method called by the BassBoost when a
147fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * parameter value has changed.
148fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
149fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public interface OnParameterChangeListener  {
150fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        /**
151fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * Method called when a parameter value has changed. The method is called only if the
152fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * parameter was changed by another application having the control of the same
153fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * BassBoost engine.
154fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * @param effect the BassBoost on which the interface is registered.
155fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * @param status status of the set parameter operation.
156fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * @param param ID of the modified parameter. See {@link #PARAM_STRENGTH} ...
157fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         * @param value the new parameter value.
158fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent         */
159fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        void onParameterChange(BassBoost effect, int status, int param, short value);
160fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
161fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
162fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
163fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Listener used internally to receive unformatted parameter change events from AudioEffect
164fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * super class.
165fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
166fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener {
167fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        private BaseParameterListener() {
168fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
169fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        }
170fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) {
171fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            OnParameterChangeListener l = null;
172fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
173fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            synchronized (mParamListenerLock) {
174fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                if (mParamListener != null) {
175fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                    l = mParamListener;
176fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                }
177fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            }
178fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            if (l != null) {
179fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                int p = -1;
180fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                short v = -1;
181fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
182fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                if (param.length == 4) {
183fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                    p = byteArrayToInt(param, 0);
184fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                }
185fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                if (value.length == 2) {
186fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                    v = byteArrayToShort(value, 0);
187fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                }
188fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                if (p != -1 && v != -1) {
189fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                    l.onParameterChange(BassBoost.this, status, p, v);
190fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                }
191fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            }
192fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        }
193fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
194fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent
195fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    /**
196fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * Registers an OnParameterChangeListener interface.
197fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     * @param listener OnParameterChangeListener interface registered
198fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent     */
199fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    public void setParameterListener(OnParameterChangeListener listener) {
200fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        synchronized (mParamListenerLock) {
201fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            if (mParamListener == null) {
202fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                mParamListener = listener;
203fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                mBaseParamListener = new BaseParameterListener();
204fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent                super.setParameterListener(mBaseParamListener);
205fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent            }
206fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent        }
207fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent    }
208ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
209ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    /**
210ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * The Settings class regroups all bass boost parameters. It is used in
211ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * conjuntion with getProperties() and setProperties() methods to backup and restore
212ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * all parameters in a single call.
213ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     */
214ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    public static class Settings {
215ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        public short strength;
216ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
217ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        public Settings() {
218ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        }
219ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
220ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        /**
221ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent         * Settings class constructor from a key=value; pairs formatted string. The string is
222ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent         * typically returned by Settings.toString() method.
223ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent         * @throws IllegalArgumentException if the string is not correctly formatted.
224ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent         */
225ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        public Settings(String settings) {
226ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            StringTokenizer st = new StringTokenizer(settings, "=;");
227ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            int tokens = st.countTokens();
228ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            if (st.countTokens() != 3) {
229ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                throw new IllegalArgumentException("settings: " + settings);
230ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            }
231ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            String key = st.nextToken();
232ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            if (!key.equals("BassBoost")) {
233ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                throw new IllegalArgumentException(
234ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                        "invalid settings for BassBoost: " + key);
235ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            }
236ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            try {
237ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                key = st.nextToken();
238ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                if (!key.equals("strength")) {
239ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                    throw new IllegalArgumentException("invalid key name: " + key);
240ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                }
241ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                strength = Short.parseShort(st.nextToken());
242ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent             } catch (NumberFormatException nfe) {
243ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                throw new IllegalArgumentException("invalid value for key: " + key);
244ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            }
245ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        }
246ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
247ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        @Override
248ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        public String toString() {
249ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            String str = new String (
250ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                    "BassBoost"+
251ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                    ";strength="+Short.toString(strength)
252ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent                    );
253ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent            return str;
254ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        }
255ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    };
256ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
257ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
258ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    /**
259ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * Gets the bass boost properties. This method is useful when a snapshot of current
260ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * bass boost settings must be saved by the application.
261ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @return a BassBoost.Settings object containing all current parameters values
262ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @throws IllegalStateException
263ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @throws IllegalArgumentException
264ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @throws UnsupportedOperationException
265ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     */
266ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    public BassBoost.Settings getProperties()
267ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
268ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        Settings settings = new Settings();
269ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        short[] value = new short[1];
270ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        checkStatus(getParameter(PARAM_STRENGTH, value));
271ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        settings.strength = value[0];
272ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        return settings;
273ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    }
274ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent
275ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    /**
276ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * Sets the bass boost properties. This method is useful when bass boost settings have to
277ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * be applied from a previous backup.
27817cb280e7f1ac3556eac90ab08263712e0348cb9Eric Laurent     * @param settings a BassBoost.Settings object containing the properties to apply
279ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @throws IllegalStateException
280ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @throws IllegalArgumentException
281ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     * @throws UnsupportedOperationException
282ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent     */
283ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    public void setProperties(BassBoost.Settings settings)
284ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
285ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent        checkStatus(setParameter(PARAM_STRENGTH, settings.strength));
286ca57d1cc89d65dfbd59c749c5736574cd08c7bd3Eric Laurent    }
287fd84f97af4b44d54bba53bb85b31a6dbce07f6e2Eric Laurent}
288