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