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