1 /* 2 * Copyright (C) 2013 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.AudioTrack; 20 import android.media.MediaPlayer; 21 import android.media.audiofx.AudioEffect; 22 import android.util.Log; 23 24 import java.util.StringTokenizer; 25 26 27 /** 28 * LoudnessEnhancer is an audio effect for increasing audio loudness. 29 * The processing is parametrized by a target gain value, which determines the maximum amount 30 * by which an audio signal will be amplified; signals amplified outside of the sample 31 * range supported by the platform are compressed. 32 * An application creates a LoudnessEnhancer object to instantiate and control a 33 * this audio effect in the audio framework. 34 * To attach the LoudnessEnhancer to a particular AudioTrack or MediaPlayer, 35 * specify the audio session ID of this AudioTrack or MediaPlayer when constructing the effect 36 * (see {@link AudioTrack#getAudioSessionId()} and {@link MediaPlayer#getAudioSessionId()}). 37 */ 38 39 public class LoudnessEnhancer extends AudioEffect { 40 41 private final static String TAG = "LoudnessEnhancer"; 42 43 // These parameter constants must be synchronized with those in 44 // /system/media/audio_effects/include/audio_effects/effect_loudnessenhancer.h 45 /** 46 * The maximum gain applied applied to the signal to process. 47 * It is expressed in millibels (100mB = 1dB) where 0mB corresponds to no amplification. 48 */ 49 public static final int PARAM_TARGET_GAIN_MB = 0; 50 51 /** 52 * Registered listener for parameter changes. 53 */ 54 private OnParameterChangeListener mParamListener = null; 55 56 /** 57 * Listener used internally to to receive raw parameter change events 58 * from AudioEffect super class 59 */ 60 private BaseParameterListener mBaseParamListener = null; 61 62 /** 63 * Lock for access to mParamListener 64 */ 65 private final Object mParamListenerLock = new Object(); 66 67 /** 68 * Class constructor. 69 * @param audioSession system-wide unique audio session identifier. The LoudnessEnhancer 70 * will be attached to the MediaPlayer or AudioTrack in the same audio session. 71 * 72 * @throws java.lang.IllegalStateException 73 * @throws java.lang.IllegalArgumentException 74 * @throws java.lang.UnsupportedOperationException 75 * @throws java.lang.RuntimeException 76 */ LoudnessEnhancer(int audioSession)77 public LoudnessEnhancer(int audioSession) 78 throws IllegalStateException, IllegalArgumentException, 79 UnsupportedOperationException, RuntimeException { 80 super(EFFECT_TYPE_LOUDNESS_ENHANCER, EFFECT_TYPE_NULL, 0, audioSession); 81 82 if (audioSession == 0) { 83 Log.w(TAG, "WARNING: attaching a LoudnessEnhancer to global output mix is deprecated!"); 84 } 85 } 86 87 /** 88 * @hide 89 * Class constructor for the LoudnessEnhancer audio effect. 90 * @param priority the priority level requested by the application for controlling the 91 * LoudnessEnhancer engine. As the same engine can be shared by several applications, 92 * this parameter indicates how much the requesting application needs control of effect 93 * parameters. The normal priority is 0, above normal is a positive number, below normal a 94 * negative number. 95 * @param audioSession system-wide unique audio session identifier. The LoudnessEnhancer 96 * will be attached to the MediaPlayer or AudioTrack in the same audio session. 97 * 98 * @throws java.lang.IllegalStateException 99 * @throws java.lang.IllegalArgumentException 100 * @throws java.lang.UnsupportedOperationException 101 * @throws java.lang.RuntimeException 102 */ LoudnessEnhancer(int priority, int audioSession)103 public LoudnessEnhancer(int priority, int audioSession) 104 throws IllegalStateException, IllegalArgumentException, 105 UnsupportedOperationException, RuntimeException { 106 super(EFFECT_TYPE_LOUDNESS_ENHANCER, EFFECT_TYPE_NULL, priority, audioSession); 107 108 if (audioSession == 0) { 109 Log.w(TAG, "WARNING: attaching a LoudnessEnhancer to global output mix is deprecated!"); 110 } 111 } 112 113 /** 114 * Set the target gain for the audio effect. 115 * The target gain is the maximum value by which a sample value will be amplified when the 116 * effect is enabled. 117 * @param gainmB the effect target gain expressed in mB. 0mB corresponds to no amplification. 118 * @throws IllegalStateException 119 * @throws IllegalArgumentException 120 * @throws UnsupportedOperationException 121 */ setTargetGain(int gainmB)122 public void setTargetGain(int gainmB) 123 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 124 checkStatus(setParameter(PARAM_TARGET_GAIN_MB, gainmB)); 125 } 126 127 /** 128 * Return the target gain. 129 * @return the effect target gain expressed in mB. 130 * @throws IllegalStateException 131 * @throws IllegalArgumentException 132 * @throws UnsupportedOperationException 133 */ getTargetGain()134 public float getTargetGain() 135 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 136 int[] value = new int[1]; 137 checkStatus(getParameter(PARAM_TARGET_GAIN_MB, value)); 138 return value[0]; 139 } 140 141 /** 142 * @hide 143 * The OnParameterChangeListener interface defines a method called by the LoudnessEnhancer 144 * when a parameter value has changed. 145 */ 146 public interface OnParameterChangeListener { 147 /** 148 * Method called when a parameter value has changed. The method is called only if the 149 * parameter was changed by another application having the control of the same 150 * LoudnessEnhancer engine. 151 * @param effect the LoudnessEnhancer on which the interface is registered. 152 * @param param ID of the modified parameter. See {@link #PARAM_GENERIC_PARAM1} ... 153 * @param value the new parameter value. 154 */ onParameterChange(LoudnessEnhancer effect, int param, int value)155 void onParameterChange(LoudnessEnhancer effect, int param, int value); 156 } 157 158 /** 159 * Listener used internally to receive unformatted parameter change events from AudioEffect 160 * super class. 161 */ 162 private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { BaseParameterListener()163 private BaseParameterListener() { 164 165 } onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value)166 public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { 167 // only notify when the parameter was successfully change 168 if (status != AudioEffect.SUCCESS) { 169 return; 170 } 171 OnParameterChangeListener l = null; 172 synchronized (mParamListenerLock) { 173 if (mParamListener != null) { 174 l = mParamListener; 175 } 176 } 177 if (l != null) { 178 int p = -1; 179 int v = Integer.MIN_VALUE; 180 181 if (param.length == 4) { 182 p = byteArrayToInt(param, 0); 183 } 184 if (value.length == 4) { 185 v = byteArrayToInt(value, 0); 186 } 187 if (p != -1 && v != Integer.MIN_VALUE) { 188 l.onParameterChange(LoudnessEnhancer.this, p, v); 189 } 190 } 191 } 192 } 193 194 /** 195 * @hide 196 * Registers an OnParameterChangeListener interface. 197 * @param listener OnParameterChangeListener interface registered 198 */ setParameterListener(OnParameterChangeListener listener)199 public void setParameterListener(OnParameterChangeListener listener) { 200 synchronized (mParamListenerLock) { 201 if (mParamListener == null) { 202 mBaseParamListener = new BaseParameterListener(); 203 super.setParameterListener(mBaseParamListener); 204 } 205 mParamListener = listener; 206 } 207 } 208 209 /** 210 * @hide 211 * The Settings class regroups the LoudnessEnhancer parameters. It is used in 212 * conjunction with the getProperties() and setProperties() methods to backup and restore 213 * all parameters in a single call. 214 */ 215 public static class Settings { 216 public int targetGainmB; 217 Settings()218 public Settings() { 219 } 220 221 /** 222 * Settings class constructor from a key=value; pairs formatted string. The string is 223 * typically returned by Settings.toString() method. 224 * @throws IllegalArgumentException if the string is not correctly formatted. 225 */ Settings(String settings)226 public Settings(String settings) { 227 StringTokenizer st = new StringTokenizer(settings, "=;"); 228 //int tokens = st.countTokens(); 229 if (st.countTokens() != 3) { 230 throw new IllegalArgumentException("settings: " + settings); 231 } 232 String key = st.nextToken(); 233 if (!key.equals("LoudnessEnhancer")) { 234 throw new IllegalArgumentException( 235 "invalid settings for LoudnessEnhancer: " + key); 236 } 237 try { 238 key = st.nextToken(); 239 if (!key.equals("targetGainmB")) { 240 throw new IllegalArgumentException("invalid key name: " + key); 241 } 242 targetGainmB = Integer.parseInt(st.nextToken()); 243 } catch (NumberFormatException nfe) { 244 throw new IllegalArgumentException("invalid value for key: " + key); 245 } 246 } 247 248 @Override toString()249 public String toString() { 250 String str = new String ( 251 "LoudnessEnhancer"+ 252 ";targetGainmB="+Integer.toString(targetGainmB) 253 ); 254 return str; 255 } 256 }; 257 258 259 /** 260 * @hide 261 * Gets the LoudnessEnhancer properties. This method is useful when a snapshot of current 262 * effect settings must be saved by the application. 263 * @return a LoudnessEnhancer.Settings object containing all current parameters values 264 * @throws IllegalStateException 265 * @throws IllegalArgumentException 266 * @throws UnsupportedOperationException 267 */ getProperties()268 public LoudnessEnhancer.Settings getProperties() 269 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 270 Settings settings = new Settings(); 271 int[] value = new int[1]; 272 checkStatus(getParameter(PARAM_TARGET_GAIN_MB, value)); 273 settings.targetGainmB = value[0]; 274 return settings; 275 } 276 277 /** 278 * @hide 279 * Sets the LoudnessEnhancer properties. This method is useful when bass boost settings 280 * have to be applied from a previous backup. 281 * @param settings a LoudnessEnhancer.Settings object containing the properties to apply 282 * @throws IllegalStateException 283 * @throws IllegalArgumentException 284 * @throws UnsupportedOperationException 285 */ setProperties(LoudnessEnhancer.Settings settings)286 public void setProperties(LoudnessEnhancer.Settings settings) 287 throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { 288 checkStatus(setParameter(PARAM_TARGET_GAIN_MB, settings.targetGainmB)); 289 } 290 } 291