diff options
| -rw-r--r-- | include/media/EffectBassBoostApi.h | 42 | ||||
| -rw-r--r-- | include/media/EffectEnvironmentalReverbApi.h (renamed from include/media/EffectReverbApi.h) | 27 | ||||
| -rw-r--r-- | include/media/EffectPresetReverbApi.h | 54 | ||||
| -rw-r--r-- | include/media/EffectVirtualizerApi.h | 42 | ||||
| -rw-r--r-- | media/java/android/media/BassBoost.java | 213 | ||||
| -rw-r--r-- | media/java/android/media/EnvironmentalReverb.java | 504 | ||||
| -rw-r--r-- | media/java/android/media/Equalizer.java | 443 | ||||
| -rw-r--r-- | media/java/android/media/PresetReverb.java | 219 | ||||
| -rw-r--r-- | media/java/android/media/Virtualizer.java | 214 | ||||
| -rw-r--r-- | media/libeffects/EffectReverb.c | 1145 | ||||
| -rw-r--r-- | media/libeffects/EffectReverb.h | 7 | 
11 files changed, 2323 insertions, 587 deletions
| diff --git a/include/media/EffectBassBoostApi.h b/include/media/EffectBassBoostApi.h new file mode 100644 index 000000000000..b24a5f45abba --- /dev/null +++ b/include/media/EffectBassBoostApi.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EFFECTBASSBOOSTAPI_H_ +#define ANDROID_EFFECTBASSBOOSTAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +// TODO: include OpenSLES_IID.h instead +static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_; + +/* enumerated parameter settings for BassBoost effect */ +typedef enum +{ +    BASSBOOST_PARAM_STRENGTH_SUPPORTED, +    BASSBOOST_PARAM_STRENGTH +} t_bassboost_params; + +#if __cplusplus +}  // extern "C" +#endif + + +#endif /*ANDROID_EFFECTBASSBOOSTAPI_H_*/ diff --git a/include/media/EffectReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h index 6371adba1c26..d490f71cd2cf 100644 --- a/include/media/EffectReverbApi.h +++ b/include/media/EffectEnvironmentalReverbApi.h @@ -14,8 +14,8 @@   * limitations under the License.   */ -#ifndef ANDROID_EFFECTREVERBAPI_H_ -#define ANDROID_EFFECTREVERBAPI_H_ +#ifndef ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_ +#define ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_  #include <media/EffectApi.h> @@ -27,14 +27,9 @@ extern "C" {  static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } };  const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_; -static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; -const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_; - -/* enumerated parameter settings for Reverb effect */ +/* enumerated parameter settings for environmental reverb effect */  typedef enum  { -    REVERB_PARAM_BYPASS, -    REVERB_PARAM_PRESET,      // Parameters below are as defined in OpenSL ES specification for environmental reverb interface      REVERB_PARAM_ROOM_LEVEL,            // in millibels,    range -6000 to 0      REVERB_PARAM_ROOM_HF_LEVEL,         // in millibels,    range -4000 to 0 @@ -46,17 +41,9 @@ typedef enum      REVERB_PARAM_REVERB_DELAY,          // in milliseconds, range 0 to 65      REVERB_PARAM_DIFFUSION,             // in permilles,    range 0 to 1000      REVERB_PARAM_DENSITY,               // in permilles,    range 0 to 1000 -    REVERB_PARAM_PROPERTIES -} t_reverb_params; - - -typedef enum -{ -    REVERB_PRESET_LARGE_HALL, -    REVERB_PRESET_HALL, -    REVERB_PRESET_CHAMBER, -    REVERB_PRESET_ROOM, -} t_reverb_presets; +    REVERB_PARAM_PROPERTIES, +    REVERB_PARAM_BYPASS +} t_env_reverb_params;  //t_reverb_properties is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.  typedef struct s_reverb_properties { @@ -79,4 +66,4 @@ typedef struct s_reverb_properties {  #endif -#endif /*ANDROID_EFFECTREVERBAPI_H_*/ +#endif /*ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_*/ diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h new file mode 100644 index 000000000000..34ffffe3bbcb --- /dev/null +++ b/include/media/EffectPresetReverbApi.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EFFECTPRESETREVERBAPI_H_ +#define ANDROID_EFFECTPRESETREVERBAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +// TODO: include OpenSLES_IID.h instead + +static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_; + +/* enumerated parameter settings for preset reverb effect */ +typedef enum +{ +    REVERB_PARAM_PRESET +} t_preset_reverb_params; + + +typedef enum +{ +    REVERB_PRESET_NONE, +    REVERB_PRESET_SMALLROOM, +    REVERB_PRESET_MEDIUMROOM, +    REVERB_PRESET_LARGEROOM, +    REVERB_PRESET_MEDIUMHALL, +    REVERB_PRESET_LARGEHALL, +    REVERB_PRESET_PLATE +} t_reverb_presets; + +#if __cplusplus +}  // extern "C" +#endif + + +#endif /*ANDROID_EFFECTPRESETREVERBAPI_H_*/ diff --git a/include/media/EffectVirtualizerApi.h b/include/media/EffectVirtualizerApi.h new file mode 100644 index 000000000000..601c384d54ac --- /dev/null +++ b/include/media/EffectVirtualizerApi.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EFFECTVIRTUALIZERAPI_H_ +#define ANDROID_EFFECTVIRTUALIZERAPI_H_ + +#include <media/EffectApi.h> + +#if __cplusplus +extern "C" { +#endif + +// TODO: include OpenSLES_IID.h instead +static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; +const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_; + +/* enumerated parameter settings for virtualizer effect */ +typedef enum +{ +    VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, +    VIRTUALIZER_PARAM_STRENGTH +} t_virtualizer_params; + +#if __cplusplus +}  // extern "C" +#endif + + +#endif /*ANDROID_EFFECTVIRTUALIZERAPI_H_*/ diff --git a/media/java/android/media/BassBoost.java b/media/java/android/media/BassBoost.java new file mode 100644 index 000000000000..ef4ce059d1c7 --- /dev/null +++ b/media/java/android/media/BassBoost.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; + +import android.media.AudioEffect; + +/** + * Bass boost is an audio effect to boost or amplify low frequencies of the sound. It is comparable + * to an simple equalizer but limited to one band amplification in the low frequency range. + * <p>An application creates a BassBoost object to instantiate and control a bass boost engine + * in the audio framework. + * <p>The methods, parameter types and units exposed by the BassBoost implementation are directly + * mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/) + * for the SLBassBoostItf interface. Please refer to this specification for more details. + * <p>To attach the BassBoost to a particular AudioTrack or MediaPlayer, specify the audio session + * ID of this AudioTrack or MediaPlayer when constructing the BassBoost. If the audio session ID 0 + * is specified, the BassBoost applies to the main audio output mix. + // TODO when AudioEffect is unhidden + // <p> See {_at_link android.media.AudioEffect} class for more details on controlling audio effects. + * + * {@hide Pending API council review} + */ + +public class BassBoost extends AudioEffect { + +    private final static String TAG = "BassBoost"; + +    // These constants must be synchronized with those in +    // frameworks/base/include/media/EffectBassBoostApi.h +    /** +     * Is strength parameter supported by bass boost engine. Parameter ID for getParameter(). +     */ +    public static final int PARAM_STRENGTH_SUPPORTED = 0; +    /** +     * Bass boost effect strength. Parameter ID for +     * {@link android.media.BassBoost.OnParameterChangeListener} +     */ +    public static final int PARAM_STRENGTH = 1; + +    /** +     * Indicates if strength parameter is supported by the bass boost engine +     */ +    private boolean mStrengthSupported = false; + +    /** +     * Registered listener for parameter changes. +     */ +    private OnParameterChangeListener mParamListener = null; + +    /** +     * Listener used internally to to receive raw parameter change event from AudioEffect super class +     */ +    private BaseParameterListener mBaseParamListener = null; + +    /** +     * Lock for access to mParamListener +     */ +    private final Object mParamListenerLock = new Object(); + +    /** +     * Class constructor. +     * @param priority the priority level requested by the application for controlling the BassBoost +     * engine. As the same engine can be shared by several applications, this parameter indicates +     * how much the requesting application needs control of effect parameters. The normal priority +     * is 0, above normal is a positive number, below normal a negative number. +     * @param audioSession  System wide unique audio session identifier. If audioSession +     *  is not 0, the BassBoost will be attached to the MediaPlayer or AudioTrack in the +     *  same audio session. Otherwise, the BassBoost will apply to the output mix. +     * +     * @throws java.lang.IllegalStateException +     * @throws java.lang.IllegalArgumentException +     * @throws java.lang.UnsupportedOperationException +     * @throws java.lang.RuntimeException +     */ +    public BassBoost(int priority, int audioSession) +    throws IllegalStateException, IllegalArgumentException, +           UnsupportedOperationException, RuntimeException { +        super(EFFECT_TYPE_BASS_BOOST, EFFECT_TYPE_NULL, priority, audioSession); + +        short[] value = new short[1]; +        checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value)); +        mStrengthSupported = (value[0] != 0); +    } + +    /** +     * Indicates whether setting strength is supported. If this method returns false, only one +     * strength is supported and the setStrength() method always rounds to that value. +     * @return true is strength parameter is supported, false otherwise +     */ +    public boolean getStrengthSupported() { +       return mStrengthSupported; +    } + +    /** +     * Sets the strength of the bass boost effect. If the implementation does not support per mille +     * accuracy for setting the strength, it is allowed to round the given strength to the nearest +     * supported value. You can use the {@link #getRoundedStrength()} method to query the +     * (possibly rounded) value that was actually set. +     * @param strength Strength of the effect. The valid range for strength strength is [0, 1000], +     * where 0 per mille designates the mildest effect and 1000 per mille designates the strongest. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setStrength(short strength) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        checkStatus(setParameter(PARAM_STRENGTH, strength)); +    } + +    /** +     * Gets the current strength of the effect. +     * @return The strength of the effect. The valid range for strength is [0, 1000], where 0 per +     * mille designates the mildest effect and 1000 per mille the strongest +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getRoundedStrength() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        short[] value = new short[1]; +        checkStatus(getParameter(PARAM_STRENGTH, value)); +        return value[0]; +    } + +    /** +     * The OnParameterChangeListener interface defines a method called by the BassBoost when a +     * parameter value has changed. +     */ +    public interface OnParameterChangeListener  { +        /** +         * Method called when a parameter value has changed. The method is called only if the +         * parameter was changed by another application having the control of the same +         * BassBoost engine. +         * @param effect the BassBoost on which the interface is registered. +         * @param status status of the set parameter operation. +         // TODO when AudioEffect is unhidden +         // See {_at_link android.media.AudioEffect#setParameter(byte[], byte[])}. +         * @param param ID of the modified parameter. See {@link #PARAM_STRENGTH} ... +         * @param value the new parameter value. +         */ +        void onParameterChange(BassBoost effect, int status, int param, short value); +    } + +    /** +     * Listener used internally to receive unformatted parameter change events from AudioEffect +     * super class. +     */ +    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { +        private BaseParameterListener() { + +        } +        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { +            OnParameterChangeListener l = null; + +            synchronized (mParamListenerLock) { +                if (mParamListener != null) { +                    l = mParamListener; +                } +            } +            if (l != null) { +                int p = -1; +                short v = -1; + +                if (param.length == 4) { +                    p = byteArrayToInt(param, 0); +                } +                if (value.length == 2) { +                    v = byteArrayToShort(value, 0); +                } +                if (p != -1 && v != -1) { +                    l.onParameterChange(BassBoost.this, status, p, v); +                } +            } +        } +    } + +    /** +     * Registers an OnParameterChangeListener interface. +     * @param listener OnParameterChangeListener interface registered +     */ +    public void setParameterListener(OnParameterChangeListener listener) { +        synchronized (mParamListenerLock) { +            if (mParamListener == null) { +                mParamListener = listener; +                mBaseParamListener = new BaseParameterListener(); +                super.setParameterListener(mBaseParamListener); +            } +        } +    } +} diff --git a/media/java/android/media/EnvironmentalReverb.java b/media/java/android/media/EnvironmentalReverb.java new file mode 100644 index 000000000000..88230fc51f5d --- /dev/null +++ b/media/java/android/media/EnvironmentalReverb.java @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; + +import android.media.AudioEffect; + +/** + * A sound generated within a room travels in many directions. The listener first hears the + * direct sound from the source itself. Later, he or she hears discrete echoes caused by sound + * bouncing off nearby walls, the ceiling and the floor. As sound waves arrive after + * undergoing more and more reflections, individual reflections become indistinguishable and + * the listener hears continuous reverberation that decays over time. + * Reverb is vital for modeling a listener's environment. It can be used in music applications + * to simulate music being played back in various environments, or in games to immerse the + * listener within the game's environment. + * The EnvironmentalReverb class allows an application to control each reverb engine property in a + * global reverb environment and is more suitable for games. For basic control, more suitable for + * music applications, it is recommended to use the + // TODO when PresetReverb is unhidden + // {_at_link android.media.PresetReverb} class. + * <p>An application creates a EnvironmentalReverb object to instantiate and control a reverb engine + * in the audio framework. + * <p>The methods, parameter types and units exposed by the EnvironmentalReverb implementation are + * directly mapping those defined by the OpenSL ES 1.0.1 Specification + * (http://www.khronos.org/opensles/) for the SLEnvironmentalReverbItf interface. + * Please refer to this specification for more details. + * <p>The EnvironmentalReverb is an output mix auxiliary effect and should be created on + * Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect, + * they must be explicitely attached to it and a send level must be specified. Use the effect ID + * returned by getId() method to designate this particular effect when attaching it to the + * MediaPlayer or AudioTrack. + // TODO when AudioEffect is unhidden + // <p> See {_at_link android.media.AudioEffect} class for more details on controlling + * audio effects. + * + * {@hide Pending API council review} + */ + +public class EnvironmentalReverb extends AudioEffect { + +    private final static String TAG = "EnvironmentalReverb"; + +    // These constants must be synchronized with those in +    // frameworks/base/include/media/EffectEnvironmentalReverbApi.h + +    /** +     * Room level. Parameter ID for +     * {@link android.media.EnvironmentalReverb.OnParameterChangeListener} +     */ +    public static final int PARAM_ROOM_LEVEL = 0; +    /** +     * Room HF level. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_ROOM_HF_LEVEL = 1; +    /** +     * Decay time. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_DECAY_TIME = 2; +    /** +     * Decay HF ratio. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_DECAY_HF_RATIO = 3; +    /** +     * Early reflections level. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_REFLECTIONS_LEVEL = 4; +    /** +     * Early reflections delay. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_REFLECTIONS_DELAY = 5; +    /** +     * Reverb level. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_REVERB_LEVEL = 6; +    /** +     * Reverb delay. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_REVERB_DELAY = 7; +    /** +     * Diffusion. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_DIFFUSION = 8; +    /** +     * Density. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_DENSITY = 9; + +    /** +     * Registered listener for parameter changes +     */ +    private OnParameterChangeListener mParamListener = null; + +    /** +     * Listener used internally to to receive raw parameter change event from AudioEffect super +     * class +     */ +    private BaseParameterListener mBaseParamListener = null; + +    /** +     * Lock for access to mParamListener +     */ +    private final Object mParamListenerLock = new Object(); + +    /** +     * Class constructor. +     * @param priority the priority level requested by the application for controlling the +     * EnvironmentalReverb engine. As the same engine can be shared by several applications, this +     * parameter indicates how much the requesting application needs control of effect parameters. +     * The normal priority is 0, above normal is a positive number, below normal a negative number. +     * @param audioSession  System wide unique audio session identifier. If audioSession +     *  is not 0, the EnvironmentalReverb will be attached to the MediaPlayer or AudioTrack in the +     *  same audio session. Otherwise, the EnvironmentalReverb will apply to the output mix. +     *  As the EnvironmentalReverb is an auxiliary effect it is recommended to instantiate it on +     *  audio session 0 and to attach it to the MediaPLayer auxiliary output. +     * +     * @throws java.lang.IllegalArgumentException +     * @throws java.lang.UnsupportedOperationException +     * @throws java.lang.RuntimeException +     */ +    public EnvironmentalReverb(int priority, int audioSession) +    throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { +        super(EFFECT_TYPE_ENV_REVERB, EFFECT_TYPE_NULL, priority, audioSession); +        Log.e(TAG, "contructor"); +    } + +    /** +     * Sets the master volume level of the environmental reverb effect. +     * @param room Room level in millibels. The valid range is [-9000, 0]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setRoomLevel(short room) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(room); +        checkStatus(setParameter(PARAM_ROOM_LEVEL, param)); +    } + +    /** +     * Gets the master volume level of the environmental reverb effect. +     * @return the room level in millibels. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getRoomLevel() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_ROOM_LEVEL, param)); +        return byteArrayToShort(param); +    } + +    /** +     * Sets the volume level at 5 kHz relative to the volume level at low frequencies of the +     * overall reverb effect. +     * <p>This controls a low-pass filter that will reduce the level of the high-frequency. +     * @param roomHF High frequency attenuation level in millibels. The valid range is [-9000, 0]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setRoomHFLevel(short roomHF) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(roomHF); +        checkStatus(setParameter(PARAM_ROOM_HF_LEVEL, param)); +    } + +    /** +     * Gets the room HF level. +     * @return the room HF level in millibels. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getRoomHFLevel() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_ROOM_HF_LEVEL, param)); +        return byteArrayToShort(param); +    } + +    /** +     * Sets the time taken for the level of reverberation to decay by 60 dB. +     * @param decayTime Decay time in milliseconds. The valid range is [100, 20000]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setDecayTime(int decayTime) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = intToByteArray(decayTime); +        checkStatus(setParameter(PARAM_DECAY_TIME, param)); +    } + +    /** +     * Gets the decay time. +     * @return the decay time in milliseconds. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public int getDecayTime() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[4]; +        checkStatus(getParameter(PARAM_DECAY_TIME, param)); +        return byteArrayToInt(param); +    } + +    /** +     * Sets the ratio of high frequency decay time (at 5 kHz) relative to the decay time at low +     * frequencies. +     * @param decayHFRatio High frequency decay ratio using a permille scale. The valid range is +     * [100, 2000]. A ratio of 1000 indicates that all frequencies decay at the same rate. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setDecayHFRatio(short decayHFRatio) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(decayHFRatio); +        checkStatus(setParameter(PARAM_DECAY_HF_RATIO, param)); +    } + +    /** +     * Gets the ratio of high frequency decay time (at 5 kHz) relative to low frequencies. +     * @return the decay HF ration. See {@link #setDecayHFRatio(short)} for units. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getDecayHFRatio() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_DECAY_HF_RATIO, param)); +        return byteArrayToShort(param); +    } + +    /** +     * Sets the volume level of the early reflections. +     * <p>This level is combined with the overall room level +     * (set using {@link #setRoomLevel(short)}). +     * @param reflectionsLevel Reflection level in millibels. The valid range is [-9000, 1000]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setReflectionsLevel(short reflectionsLevel) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(reflectionsLevel); +        checkStatus(setParameter(PARAM_REFLECTIONS_LEVEL, param)); +    } + +    /** +     * Gets the volume level of the early reflections. +     * @return the early reflections level in millibels. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getReflectionsLevel() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_REFLECTIONS_LEVEL, param)); +        return byteArrayToShort(param); +    } + +    /** +     * Sets the delay time for the early reflections. +     * <p>This method sets the time between when the direct path is heard and when the first +     * reflection is heard. +     * @param reflectionsDelay Reflections delay in milliseconds. The valid range is [0, 300]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setReflectionsDelay(int reflectionsDelay) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = intToByteArray(reflectionsDelay); +        checkStatus(setParameter(PARAM_REFLECTIONS_DELAY, param)); +    } + +    /** +     * Gets the reflections delay. +     * @return the early reflections delay in milliseconds. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public int getReflectionsDelay() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[4]; +        checkStatus(getParameter(PARAM_REFLECTIONS_DELAY, param)); +        return byteArrayToInt(param); +    } + +    /** +     * Sets the volume level of the late reverberation. +     * <p>This level is combined with the overall room level (set using {@link #setRoomLevel(short)}). +     * @param reverbLevel Reverb level in millibels. The valid range is [-9000, 2000]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setReverbLevel(short reverbLevel) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(reverbLevel); +        checkStatus(setParameter(PARAM_REVERB_LEVEL, param)); +    } + +    /** +     * Gets the reverb level. +     * @return the reverb level in millibels. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getReverbLevel() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_REVERB_LEVEL, param)); +        return byteArrayToShort(param); +    } + +    /** +     * Sets the time between the first reflection and the reverberation. +     * @param reverbDelay Reverb delay in milliseconds. The valid range is [0, 100]. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setReverbDelay(int reverbDelay) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = intToByteArray(reverbDelay); +        checkStatus(setParameter(PARAM_REVERB_DELAY, param)); +    } + +    /** +     * Gets the reverb delay. +     * @return the reverb delay in milliseconds. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public int getReverbDelay() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[4]; +        checkStatus(getParameter(PARAM_REVERB_DELAY, param)); +        return byteArrayToInt(param); +    } + +    /** +     * Sets the echo density in the late reverberation decay. +     * <p>The scale should approximately map linearly to the perceived change in reverberation. +     * @param diffusion Diffusion specified using a permille scale. The diffusion valid range is +     * [0, 1000]. A value of 1000 o/oo indicates a smooth reverberation decay. +     * Values below this level give a more <i>grainy</i> character. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setDiffusion(short diffusion) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(diffusion); +        checkStatus(setParameter(PARAM_DIFFUSION, param)); +    } + +    /** +     * Gets diffusion level. +     * @return the diffusion level. See {@link #setDiffusion(short)} for units. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getDiffusion() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_DIFFUSION, param)); +        return byteArrayToShort(param); +    } + + +    /** +     * Controls the modal density of the late reverberation decay. +     * <p> The scale should approximately map linearly to the perceived change in reverberation. +     * A lower density creates a hollow sound that is useful for simulating small reverberation +     * spaces such as bathrooms. +     * @param density Density specified using a permille scale. The valid range is [0, 1000]. +     * A value of 1000 o/oo indicates a natural sounding reverberation. Values below this level +     * produce a more colored effect. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setDensity(short density) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = shortToByteArray(density); +        checkStatus(setParameter(PARAM_DENSITY, param)); +    } + +    /** +     * Gets the density level. +     * @return the density level. See {@link #setDiffusion(short)} for units. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getDensity() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        byte[] param = new byte[2]; +        checkStatus(getParameter(PARAM_DENSITY, param)); +        return byteArrayToShort(param); +    } + + +    /** +     * The OnParameterChangeListener interface defines a method called by the EnvironmentalReverb +     * when a parameter value has changed. +     */ +    public interface OnParameterChangeListener  { +        /** +         * Method called when a parameter value has changed. The method is called only if the +         * parameter was changed by another application having the control of the same +         * EnvironmentalReverb engine. +         * @param effect the EnvironmentalReverb on which the interface is registered. +         * @param status status of the set parameter operation. +         // TODO when AudioEffect is unhidden +         // See {_at_link android.media.AudioEffect#setParameter(byte[], byte[])}. +         * @param param ID of the modified parameter. See {@link #PARAM_ROOM_LEVEL} ... +         * @param value the new parameter value. +         */ +        void onParameterChange(EnvironmentalReverb effect, int status, int param, int value); +    } + +    /** +     * Listener used internally to receive unformatted parameter change events from AudioEffect +     * super class. +     */ +    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { +        private BaseParameterListener() { + +        } +        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { +            OnParameterChangeListener l = null; + +            synchronized (mParamListenerLock) { +                if (mParamListener != null) { +                    l = mParamListener; +                } +            } +            if (l != null) { +                int p = -1; +                int v = -1; + +                if (param.length == 4) { +                    p = byteArrayToInt(param, 0); +                } +                if (value.length == 2) { +                    v = (int)byteArrayToShort(value, 0); +                } else if (value.length == 4) { +                    v = byteArrayToInt(value, 0); +                } +                if (p != -1 && v != -1) { +                    l.onParameterChange(EnvironmentalReverb.this, status, p, v); +                } +            } +        } +    } + +    /** +     * Registers an OnParameterChangeListener interface. +     * @param listener OnParameterChangeListener interface registered +     */ +    public void setParameterListener(OnParameterChangeListener listener) { +        synchronized (mParamListenerLock) { +            if (mParamListener == null) { +                mParamListener = listener; +                mBaseParamListener = new BaseParameterListener(); +                super.setParameterListener(mBaseParamListener); +            } +        } +    } +} diff --git a/media/java/android/media/Equalizer.java b/media/java/android/media/Equalizer.java new file mode 100644 index 000000000000..082f69416fb4 --- /dev/null +++ b/media/java/android/media/Equalizer.java @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; + +import android.media.AudioEffect; + +/** + * An Equalizer is used to alter the frequency response of a particular music source or of the main + * output mix. + * <p>An application creates an Equalizer object to instantiate and control an Equalizer engine + * in the audio framework. The application can either simply use predefined presets or have a more + * precise control of the gain in each frequency band controlled by the equalizer. + * <p>The methods, parameter types and units exposed by the Equalizer implementation are directly + * mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/) + * for the SLEqualizerItf interface. Please refer to this specification for more details. + * <p>To attach the Equalizer to a particular AudioTrack or MediaPlayer, specify the audio session + * ID of this AudioTrack or MediaPlayer when constructing the Equalizer. If the audio session ID 0 + * is specified, the Equalizer applies to the main audio output mix. + // TODO when AudioEffect is unhidden + // <p> See {_at_link android.media.AudioEffect} class for more details on controlling audio effects. + * + * {@hide Pending API council review} + */ + +public class Equalizer extends AudioEffect { + +    private final static String TAG = "Equalizer"; + +    // These constants must be synchronized with those in +    // frameworks/base/include/media/EffectEqualizerApi.h +    /** +     * Number of bands. Parameter ID for {@link android.media.Equalizer.OnParameterChangeListener} +     */ +    public static final int PARAM_NUM_BANDS = 0; +    /** +     * Band level range. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_LEVEL_RANGE = 1; +    /** +     * Band level. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_BAND_LEVEL = 2; +    /** +     * Band center frequency. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_CENTER_FREQ = 3; +    /** +     * Band frequency range. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_BAND_FREQ_RANGE = 4; +    /** +     * Band for a given frequency. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_GET_BAND = 5; +    /** +     * Current preset. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_CURRENT_PRESET = 6; +    /** +     * Request number of presets. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_GET_NUM_OF_PRESETS = 7; +    /** +     * Request preset name. Parameter ID for OnParameterChangeListener +     */ +    public static final int PARAM_GET_PRESET_NAME = 8; +    /** +     * maximum size for perset name +     */ +    public static final int PARAM_STRING_SIZE_MAX = 32; + +    /** +     * Number of presets implemented by Equalizer engine +     */ +    private int mNumPresets; +    /** +     * Names of presets implemented by Equalizer engine +     */ +    private String[] mPresetNames; + +    /** +     * Registered listener for parameter changes. +     */ +    private OnParameterChangeListener mParamListener = null; + +    /** +     * Listener used internally to to receive raw parameter change event from AudioEffect super class +     */ +    private BaseParameterListener mBaseParamListener = null; + +    /** +     * Lock for access to mParamListener +     */ +    private final Object mParamListenerLock = new Object(); + +    /** +     * Class constructor. +     * @param priority the priority level requested by the application for controlling the Equalizer +     * engine. As the same engine can be shared by several applications, this parameter indicates +     * how much the requesting application needs control of effect parameters. The normal priority +     * is 0, above normal is a positive number, below normal a negative number. +     * @param audioSession  System wide unique audio session identifier. If audioSession +     *  is not 0, the Equalizer will be attached to the MediaPlayer or AudioTrack in the +     *  same audio session. Otherwise, the Equalizer will apply to the output mix. +     * +     * @throws java.lang.IllegalStateException +     * @throws java.lang.IllegalArgumentException +     * @throws java.lang.UnsupportedOperationException +     * @throws java.lang.RuntimeException +     */ +    public Equalizer(int priority, int audioSession) +    throws IllegalStateException, IllegalArgumentException, +           UnsupportedOperationException, RuntimeException { +        super(EFFECT_TYPE_EQUALIZER, EFFECT_TYPE_NULL, priority, audioSession); + +        mNumPresets = (int)getNumberOfPresets(); + +        if (mNumPresets != 0) { +            mPresetNames = new String[mNumPresets]; +            byte[] value = new byte[PARAM_STRING_SIZE_MAX]; +            int[] param = new int[2]; +            param[0] = PARAM_GET_PRESET_NAME; +            for (int i = 0; i < mNumPresets; i++) { +                param[1] = i; +                checkStatus(getParameter(param, value)); +                int length = 0; +                while (value[length] != 0) length++; +                try { +                    mPresetNames[i] = new String(value, 0, length, "ISO-8859-1"); +                    Log.e(TAG, "preset #: "+i+" name: "+mPresetNames[i]+" length: "+length); +                } catch (java.io.UnsupportedEncodingException e) { +                    Log.e(TAG, "preset name decode error"); +                } +            } +        } +    } + +    /** +     * Gets the number of frequency bands supported by the Equalizer engine. +     * @return the number of bands +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getNumberOfBands() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[1]; +        param[0] = PARAM_NUM_BANDS; +        short[] value = new short[1]; +        checkStatus(getParameter(param, value)); +        return value[0]; +    } + +    /** +     * Gets the level range for use by {@link #setBandLevel(int,short)}. The level is expressed in +     * milliBel. +     * @return the band level range in an array of short integers. The first element is the lower +     * limit of the range, the second element the upper limit. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short[] getBandLevelRange() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[1]; +        int[] value = new int[2]; +        param[0] = PARAM_LEVEL_RANGE; +        checkStatus(getParameter(param, value)); + +        short[] result = new short[2]; + +        result[0] = (short)value[0]; +        result[1] = (short)value[1]; + +        return result; +    } + +    /** +     * Sets the given equalizer band to the given gain value. +     * @param band Frequency band that will have the new gain. The numbering of the bands starts +     * from 0 and ends at (number of bands - 1). See @see #getNumberOfBands(). +     * @param level New gain in millibels that will be set to the given band. getBandLevelRange() +     * will define the maximum and minimum values. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setBandLevel(int band, short level) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[2]; +        int[] value = new int[1]; + +        param[0] = PARAM_BAND_LEVEL; +        param[1] = band; +        value[0] = (int)level; +        checkStatus(setParameter(param, value)); +    } + +    /** +     * Gets the gain set for the given equalizer band. +     * @param band Frequency band whose gain is requested. The numbering of the bands starts +     * from 0 and ends at (number of bands - 1). +     * @return Gain in millibels of the given band. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getBandLevel(int band) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[2]; +        int[] result = new int[1]; + +        param[0] = PARAM_BAND_LEVEL; +        param[1] = band; +        checkStatus(getParameter(param, result)); + +        return (short)result[0]; +    } + + +    /** +     * Gets the center frequency of the given band. +     * @param band Frequency band whose center frequency is requested. The numbering of the bands +     * starts from 0 and ends at (number of bands - 1). +     * @return The center frequency in milliHertz +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public int getCenterFreq(int band) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[2]; +        int[] result = new int[1]; + +        param[0] = PARAM_CENTER_FREQ; +        param[1] = band; +        checkStatus(getParameter(param, result)); + +        return result[0]; +    } + +    /** +     * Gets the frequency range of the given frequency band. +     * @param band Frequency band whose frequency range is requested. The numbering of the bands +     * starts from 0 and ends at (number of bands - 1). +     * @return The frequency range in millHertz in an array of integers. The first element is the +     * lower limit of the range, the second element the upper limit. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public int[] getBandFreqRange(int band) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[2]; +        int[] result = new int[2]; +        param[0] = PARAM_BAND_FREQ_RANGE; +        param[1] = band; +        checkStatus(getParameter(param, result)); + +        return result; +    } + +    /** +     * Gets the band that has the most effect on the given frequency. +     * @param frequency Frequency in milliHertz which is to be equalized via the returned band. +     * @return Frequency band that has most effect on the given frequency. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public int getBand(int frequency) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[2]; +        int[] result = new int[1]; + +        param[0] = PARAM_GET_BAND; +        param[1] = frequency; +        checkStatus(getParameter(param, result)); + +        return result[0]; +    } + +    /** +     * Gets current preset. +     * @return Preset that is set at the moment. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getCurrentPreset() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[1]; +        param[0] = PARAM_CURRENT_PRESET; +        short[] value = new short[1]; +        checkStatus(getParameter(param, value)); +        return value[0]; +    } + +    /** +     * Sets the equalizer according to the given preset. +     * @param preset New preset that will be taken into use. The valid range is [0, +     * number of presets-1]. See {@see #getNumberOfPresets()}. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void usePreset(short preset) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        checkStatus(setParameter(PARAM_CURRENT_PRESET, preset)); +    } + +    /** +     * Gets the total number of presets the equalizer supports. The presets will have indices +     * [0, number of presets-1]. +     * @return The number of presets the equalizer supports. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getNumberOfPresets() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[1]; +        param[0] = PARAM_GET_NUM_OF_PRESETS; +        short[] value = new short[1]; +        checkStatus(getParameter(param, value)); +        return value[0]; +    } + +    /** +     * Gets the preset name based on the index. +     * @param preset Index of the preset. The valid range is [0, number of presets-1]. +     * @return A string containing the name of the given preset. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public String getPresetName(short preset) +    { +        if (preset >= 0 && preset < mNumPresets) { +            return mPresetNames[preset]; +        } else { +            return ""; +        } +    } + +    /** +     * The OnParameterChangeListener interface defines a method called by the Equalizer when a +     * parameter value has changed. +     */ +    public interface OnParameterChangeListener  { +        /** +         * Method called when a parameter value has changed. The method is called only if the +         * parameter was changed by another application having the control of the same +         * Equalizer engine. +         * @param effect the Equalizer on which the interface is registered. +         * @param status status of the set parameter operation. +         // TODO when AudioEffect is unhidden +         // See {_at_link android.media.AudioEffect#setParameter(byte[], byte[])}. +         * @param param1 ID of the modified parameter. See {@link #PARAM_BAND_LEVEL} ... +         * @param param2 additional parameter qualifier (e.g the band for band level parameter). +         * @param value the new parameter value. +         */ +        void onParameterChange(Equalizer effect, int status, int param1, int param2, int value); +    } + +    /** +     * Listener used internally to receive unformatted parameter change events from AudioEffect +     * super class. +     */ +    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { +        private BaseParameterListener() { + +        } +        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { +            OnParameterChangeListener l = null; + +            synchronized (mParamListenerLock) { +                if (mParamListener != null) { +                    l = mParamListener; +                } +            } +            if (l != null) { +                int p1 = -1; +                int p2 = -1; +                int v = -1; + +                if (param.length >= 4) { +                    p1 = byteArrayToInt(param, 0); +                    if (param.length >= 8) { +                        p2 = byteArrayToInt(param, 4); +                    } +                } +                if (value.length == 2) { +                    v = (int)byteArrayToShort(value, 0);; +                } else if (value.length == 4) { +                    v = byteArrayToInt(value, 0); +                } + +                if (p1 != -1 && v != -1) { +                    l.onParameterChange(Equalizer.this, status, p1, p2, v); +                } +            } +        } +    } + +    /** +     * Registers an OnParameterChangeListener interface. +     * @param listener OnParameterChangeListener interface registered +     */ +    public void setParameterListener(OnParameterChangeListener listener) { +        synchronized (mParamListenerLock) { +            if (mParamListener == null) { +                mParamListener = listener; +                mBaseParamListener = new BaseParameterListener(); +                super.setParameterListener(mBaseParamListener); +            } +        } +    } + +} diff --git a/media/java/android/media/PresetReverb.java b/media/java/android/media/PresetReverb.java new file mode 100644 index 000000000000..83a01a48e46e --- /dev/null +++ b/media/java/android/media/PresetReverb.java @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; + +import android.media.AudioEffect; + +/** + * A sound generated within a room travels in many directions. The listener first hears the + * direct sound from the source itself. Later, he or she hears discrete echoes caused by sound + * bouncing off nearby walls, the ceiling and the floor. As sound waves arrive after + * undergoing more and more reflections, individual reflections become indistinguishable and + * the listener hears continuous reverberation that decays over time. + * Reverb is vital for modeling a listener's environment. It can be used in music applications + * to simulate music being played back in various environments, or in games to immerse the + * listener within the game's environment. + * The PresetReverb class allows an application to configure the global reverb using a reverb preset. + * This is primarily used for adding some reverb in a music playback context. Applications + * requiring control over a more advanced environmental reverb are advised to use the + // TODO when EnvironmentalReverb is unhidden + // {_at_link android.media.EnvironmentalReverb} class. + * <p>An application creates a PresetReverb object to instantiate and control a reverb engine in the + * audio framework. + * <p>The methods, parameter types and units exposed by the PresetReverb implementation are + * directly mapping those defined by the OpenSL ES 1.0.1 Specification + * (http://www.khronos.org/opensles/) for the SLPresetReverbItf interface. + * Please refer to this specification for more details. + * <p>The PresetReverb is an output mix auxiliary effect and should be created on + * Audio session 0. In order for a MediaPlayer or AudioTrack to be fed into this effect, + * they must be explicitely attached to it and a send level must be specified. Use the effect ID + * returned by getId() method to designate this particular effect when attaching it to the + * MediaPlayer or AudioTrack. + // TODO when AudioEffect is unhidden + // <p> See {_at_link android.media.AudioEffect} class for more details on controlling audio effects. + * + * {@hide Pending API council review} + */ + +public class PresetReverb extends AudioEffect { + +    private final static String TAG = "PresetReverb"; + +    // These constants must be synchronized with those in +    // frameworks/base/include/media/EffectPresetReverbApi.h + +    /** +     * Preset. Parameter ID for +     * {@link android.media.PresetReverb.OnParameterChangeListener} +     */ +    public static final int PARAM_PRESET = 0; + +    /** +     * Room level. Parameter ID for +     * {@link android.media.PresetReverb.OnParameterChangeListener} +     */ +    public static final int PRESET_NONE        = 0; +    public static final int PRESET_SMALLROOM   = 1; +    public static final int PRESET_MEDIUMROOM  = 2; +    public static final int PRESET_LARGEROOM   = 3; +    public static final int PRESET_MEDIUMHALL  = 4; +    public static final int PRESET_LARGEHALL   = 5; +    public static final int PRESET_PLATE       = 6; + +    /** +     * Registered listener for parameter changes. +     */ +    private OnParameterChangeListener mParamListener = null; + +    /** +     * Listener used internally to to receive raw parameter change event from AudioEffect super class +     */ +    private BaseParameterListener mBaseParamListener = null; + +    /** +     * Lock for access to mParamListener +     */ +    private final Object mParamListenerLock = new Object(); + +    /** +     * Class constructor. +     * @param priority the priority level requested by the application for controlling the +     * PresetReverb engine. As the same engine can be shared by several applications, this +     * parameter indicates how much the requesting application needs control of effect parameters. +     * The normal priority is 0, above normal is a positive number, below normal a negative number. +     * @param audioSession  System wide unique audio session identifier. If audioSession +     *  is not 0, the PresetReverb will be attached to the MediaPlayer or AudioTrack in the +     *  same audio session. Otherwise, the PresetReverb will apply to the output mix. +     *  As the PresetReverb is an auxiliary effect it is recommended to instantiate it on +     *  audio session 0 and to attach it to the MediaPLayer auxiliary output. +     * +     * @throws java.lang.IllegalArgumentException +     * @throws java.lang.UnsupportedOperationException +     * @throws java.lang.RuntimeException +     */ +    public PresetReverb(int priority, int audioSession) +    throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { +        super(EFFECT_TYPE_PRESET_REVERB, EFFECT_TYPE_NULL, priority, audioSession); +        Log.e(TAG, "contructor"); +    } + +    /** +     *  Enables a preset on the reverb. +     *  <p>The reverb PRESET_NONE disables any reverb from the current output but does not free the +     *  resources associated with the reverb. For an application to signal to the implementation +     *  to free the resources, it must call the release() method. +     * @param preset This must be one of the the preset constants defined in this class. +     * e.g. {@link #PRESET_SMALLROOM} +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setPreset(short preset) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        checkStatus(setParameter(PARAM_PRESET, preset)); +    } + +    /** +     * Gets current reverb preset. +     * @return Preset that is set at the moment. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getPreset() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        int[] param = new int[1]; +        param[0] = PARAM_PRESET; +        short[] value = new short[1]; +        checkStatus(getParameter(param, value)); +        return value[0]; +    } + +    /** +     * The OnParameterChangeListener interface defines a method called by the PresetReverb +     * when a parameter value has changed. +     */ +    public interface OnParameterChangeListener  { +        /** +         * Method called when a parameter value has changed. The method is called only if the +         * parameter was changed by another application having the control of the same +         * PresetReverb engine. +         * @param effect the PresetReverb on which the interface is registered. +         * @param status status of the set parameter operation. +         // TODO when AudioEffect is unhidden +         // See {_at_link android.media.AudioEffect#setParameter(byte[], byte[])}. +         * @param param ID of the modified parameter. See {@link #PARAM_PRESET} ... +         * @param value the new parameter value. +         */ +        void onParameterChange(PresetReverb effect, int status, int param, short value); +    } + +    /** +     * Listener used internally to receive unformatted parameter change events from AudioEffect +     * super class. +     */ +    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { +        private BaseParameterListener() { + +        } +        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { +            OnParameterChangeListener l = null; + +            synchronized (mParamListenerLock) { +                if (mParamListener != null) { +                    l = mParamListener; +                } +            } +            if (l != null) { +                int p = -1; +                short v = -1; + +                if (param.length == 4) { +                    p = byteArrayToInt(param, 0); +                } +                if (value.length == 2) { +                    v = byteArrayToShort(value, 0); +                } +                if (p != -1 && v != -1) { +                    l.onParameterChange(PresetReverb.this, status, p, v); +                } +            } +        } +    } + +    /** +     * Registers an OnParameterChangeListener interface. +     * @param listener OnParameterChangeListener interface registered +     */ +    public void setParameterListener(OnParameterChangeListener listener) { +        synchronized (mParamListenerLock) { +            if (mParamListener == null) { +                mParamListener = listener; +                mBaseParamListener = new BaseParameterListener(); +                super.setParameterListener(mBaseParamListener); +            } +        } +    } +} diff --git a/media/java/android/media/Virtualizer.java b/media/java/android/media/Virtualizer.java new file mode 100644 index 000000000000..9f7129772fae --- /dev/null +++ b/media/java/android/media/Virtualizer.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import java.nio.ByteOrder; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; + +import android.media.AudioEffect; + +/** + * An audio virtualizer is a general name for an effect to spatialize audio channels. The exact + * behavior of this effect is dependent on the number of audio input channels and the types and + * number of audio output channels of the device. For example, in the case of a stereo input and + * stereo headphone output, a stereo widening effect is used when this effect is turned on. + * <p>An application creates a Virtualizer object to instantiate and control a virtualizer engine + * in the audio framework. + * <p>The methods, parameter types and units exposed by the Virtualizer implementation are directly + * mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/) + * for the SLVirtualizerItf interface. Please refer to this specification for more details. + * <p>To attach the Virtualizer to a particular AudioTrack or MediaPlayer, specify the audio session + * ID of this AudioTrack or MediaPlayer when constructing the Virtualizer. If the audio session ID 0 + * is specified, the Virtualizer applies to the main audio output mix. + // TODO when AudioEffect is unhidden + // <p> See {_at_link android.media.AudioEffect} class for more details on controlling audio effects. + * + * {@hide Pending API council review} + */ + +public class Virtualizer extends AudioEffect { + +    private final static String TAG = "Virtualizer"; + +    // These constants must be synchronized with those in frameworks/base/include/media/EffectVirtualizerApi.h +    /** +     * Is strength parameter supported by virtualizer engine. Parameter ID for getParameter(). +     */ +    public static final int PARAM_STRENGTH_SUPPORTED = 0; +    /** +     * Virtualizer effect strength. Parameter ID for +     * {@link android.media.Virtualizer.OnParameterChangeListener} +     */ +    public static final int PARAM_STRENGTH = 1; + +    /** +     * Indicates if strength parameter is supported by the virtualizer engine +     */ +    private boolean mStrengthSupported = false; + +    /** +     * Registered listener for parameter changes. +     */ +    private OnParameterChangeListener mParamListener = null; + +    /** +     * Listener used internally to to receive raw parameter change event from AudioEffect super class +     */ +    private BaseParameterListener mBaseParamListener = null; + +    /** +     * Lock for access to mParamListener +     */ +    private final Object mParamListenerLock = new Object(); + +    /** +     * Class constructor. +     * @param priority the priority level requested by the application for controlling the Virtualizer +     * engine. As the same engine can be shared by several applications, this parameter indicates +     * how much the requesting application needs control of effect parameters. The normal priority +     * is 0, above normal is a positive number, below normal a negative number. +     * @param audioSession  System wide unique audio session identifier. If audioSession +     *  is not 0, the Virtualizer will be attached to the MediaPlayer or AudioTrack in the +     *  same audio session. Otherwise, the Virtualizer will apply to the output mix. +     * +     * @throws java.lang.IllegalStateException +     * @throws java.lang.IllegalArgumentException +     * @throws java.lang.UnsupportedOperationException +     * @throws java.lang.RuntimeException +     */ +    public Virtualizer(int priority, int audioSession) +    throws IllegalStateException, IllegalArgumentException, +           UnsupportedOperationException, RuntimeException { +        super(EFFECT_TYPE_VIRTUALIZER, EFFECT_TYPE_NULL, priority, audioSession); + +        short[] value = new short[1]; +        checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value)); +        mStrengthSupported = (value[0] != 0); +    } + +    /** +     * Indicates whether setting strength is supported. If this method returns false, only one +     * strength is supported and the setStrength() method always rounds to that value. +     * @return true is strength parameter is supported, false otherwise +     */ +    public boolean getStrengthSupported() { +       return mStrengthSupported; +    } + +    /** +     * Sets the strength of the virtualizer effect. If the implementation does not support per mille +     * accuracy for setting the strength, it is allowed to round the given strength to the nearest +     * supported value. You can use the {@link #getRoundedStrength()} method to query the +     * (possibly rounded) value that was actually set. +     * @param strength Strength of the effect. The valid range for strength strength is [0, 1000], +     * where 0 per mille designates the mildest effect and 1000 per mille designates the strongest. +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public void setStrength(short strength) +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        checkStatus(setParameter(PARAM_STRENGTH, strength)); +    } + +    /** +     * Gets the current strength of the effect. +     * @return The strength of the effect. The valid range for strength is [0, 1000], where 0 per +     * mille designates the mildest effect and 1000 per mille the strongest +     * @throws IllegalStateException +     * @throws IllegalArgumentException +     * @throws UnsupportedOperationException +     */ +    public short getRoundedStrength() +    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { +        short[] value = new short[1]; +        checkStatus(getParameter(PARAM_STRENGTH, value)); +        return value[0]; +    } + +    /** +     * The OnParameterChangeListener interface defines a method called by the Virtualizer when a +     * parameter value has changed. +     */ +    public interface OnParameterChangeListener  { +        /** +         * Method called when a parameter value has changed. The method is called only if the +         * parameter was changed by another application having the control of the same +         * Virtualizer engine. +         * @param effect the Virtualizer on which the interface is registered. +         * @param status status of the set parameter operation. +         // TODO when AudioEffect is unhidden +         // See {_at_link android.media.AudioEffect#setParameter(byte[], byte[])}. +         * @param param ID of the modified parameter. See {@link #PARAM_STRENGTH} ... +         * @param value the new parameter value. +         */ +        void onParameterChange(Virtualizer effect, int status, int param, short value); +    } + +    /** +     * Listener used internally to receive unformatted parameter change events from AudioEffect +     * super class. +     */ +    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener { +        private BaseParameterListener() { + +        } +        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) { +            OnParameterChangeListener l = null; + +            synchronized (mParamListenerLock) { +                if (mParamListener != null) { +                    l = mParamListener; +                } +            } +            if (l != null) { +                int p = -1; +                short v = -1; + +                if (param.length == 4) { +                    p = byteArrayToInt(param, 0); +                } +                if (value.length == 2) { +                    v = byteArrayToShort(value, 0); +                } +                if (p != -1 && v != -1) { +                    l.onParameterChange(Virtualizer.this, status, p, v); +                } +            } +        } +    } + +    /** +     * Registers an OnParameterChangeListener interface. +     * @param listener OnParameterChangeListener interface registered +     */ +    public void setParameterListener(OnParameterChangeListener listener) { +        synchronized (mParamListenerLock) { +            if (mParamListener == null) { +                mParamListener = listener; +                mBaseParamListener = new BaseParameterListener(); +                super.setParameterListener(mBaseParamListener); +            } +        } +    } +} diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c index ada252c917ec..5c87f23c4357 100644 --- a/media/libeffects/EffectReverb.c +++ b/media/libeffects/EffectReverb.c @@ -57,7 +57,7 @@ static const effect_descriptor_t gInsertEnvReverbDescriptor = {  // Google auxiliary preset reverb UUID: 63909320-53a6-11df-bdbd-0002a5d5c51b  static const effect_descriptor_t gAuxPresetReverbDescriptor = { -        {0x47382d60, 0xddd8, 0x4763, 0x11db, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, +        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},          {0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},          EFFECT_API_VERSION,          EFFECT_FLAG_TYPE_AUXILIARY, @@ -69,7 +69,7 @@ static const effect_descriptor_t gAuxPresetReverbDescriptor = {  // Google insert preset reverb UUID: d93dc6a0-6342-11df-b128-0002a5d5c51b  static const effect_descriptor_t gInsertPresetReverbDescriptor = { -        {0x47382d60, 0xddd8, 0x4763, 0x11db, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, +        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},          {0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},          EFFECT_API_VERSION,          EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST, @@ -196,7 +196,7 @@ static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, aud      pReverb = (reverb_object_t*) &pRvbModule->context;      //if bypassed or the preset forces the signal to be completely dry -    if (pReverb->m_bBypass) { +    if (pReverb->m_bBypass != 0) {          if (inBuffer->raw != outBuffer->raw) {              int16_t smp;              pSrc = inBuffer->s16; @@ -520,7 +520,7 @@ int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig,          pReverb->m_bUseNoise = true;          // for debugging purposes, allow bypass -        pReverb->m_bBypass = false; +        pReverb->m_bBypass = 0;          pReverb->m_nNextRoom = 1; @@ -662,248 +662,254 @@ int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,      int32_t temp2;      size_t size; -    if (pReverb->m_Preset && param != REVERB_PARAM_PRESET) { -        return -EINVAL; -    } -    if (!pReverb->m_Preset && param == REVERB_PARAM_PRESET) { -        return -EINVAL; -    } - -    switch (param) { -    case REVERB_PARAM_ROOM_LEVEL: -    case REVERB_PARAM_ROOM_HF_LEVEL: -    case REVERB_PARAM_DECAY_HF_RATIO: -    case REVERB_PARAM_REFLECTIONS_LEVEL: -    case REVERB_PARAM_REVERB_LEVEL: -    case REVERB_PARAM_DIFFUSION: -    case REVERB_PARAM_DENSITY: +    if (pReverb->m_Preset) { +        if (param != REVERB_PARAM_PRESET || *pSize < sizeof(int16_t)) { +            return -EINVAL; +        }          size = sizeof(int16_t); -        break; - -    case REVERB_PARAM_BYPASS: -    case REVERB_PARAM_PRESET: -    case REVERB_PARAM_DECAY_TIME: -    case REVERB_PARAM_REFLECTIONS_DELAY: -    case REVERB_PARAM_REVERB_DELAY: -        size = sizeof(int32_t); -        break; - -    case REVERB_PARAM_PROPERTIES: -        size = sizeof(t_reverb_properties); -        break; - -    default: -        return -EINVAL; -    } +        pValue16 = (int16_t *)pValue; +        // REVERB_PRESET_NONE is mapped to bypass +        if (pReverb->m_bBypass != 0) { +            *pValue16 = (int16_t)REVERB_PRESET_NONE; +        } else { +            *pValue16 = (int16_t)(pReverb->m_nNextRoom + 1); +        } +        LOGV("get REVERB_PARAM_PRESET, preset %d", *pValue16); +    } else { +        switch (param) { +        case REVERB_PARAM_ROOM_LEVEL: +        case REVERB_PARAM_ROOM_HF_LEVEL: +        case REVERB_PARAM_DECAY_HF_RATIO: +        case REVERB_PARAM_REFLECTIONS_LEVEL: +        case REVERB_PARAM_REVERB_LEVEL: +        case REVERB_PARAM_DIFFUSION: +        case REVERB_PARAM_DENSITY: +            size = sizeof(int16_t); +            break; -    if (*pSize < size) { -        return -EINVAL; -    } -    *pSize = size; -    pValue32 = (int32_t *) pValue; -    pValue16 = (int16_t *) pValue; -    pProperties = (t_reverb_properties *) pValue; +        case REVERB_PARAM_BYPASS: +        case REVERB_PARAM_DECAY_TIME: +        case REVERB_PARAM_REFLECTIONS_DELAY: +        case REVERB_PARAM_REVERB_DELAY: +            size = sizeof(int32_t); +            break; -    switch (param) { -    case REVERB_PARAM_BYPASS: -        *(int32_t *) pValue = (int32_t) pReverb->m_bBypass; -        break; -    case REVERB_PARAM_PRESET: -        *(int32_t *) pValue = (int8_t) pReverb->m_nCurrentRoom; -        break; +        case REVERB_PARAM_PROPERTIES: +            size = sizeof(t_reverb_properties); +            break; -    case REVERB_PARAM_PROPERTIES: -        pValue16 = &pProperties->roomLevel; -        /* FALL THROUGH */ +        default: +            return -EINVAL; +        } -    case REVERB_PARAM_ROOM_LEVEL: -        // Convert m_nRoomLpfFwd to millibels -        temp = (pReverb->m_nRoomLpfFwd << 15) -                / (32767 - pReverb->m_nRoomLpfFbk); -        *pValue16 = Effects_Linear16ToMillibels(temp); +        if (*pSize < size) { +            return -EINVAL; +        } -        LOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); +        pValue32 = (int32_t *) pValue; +        pValue16 = (int16_t *) pValue; +        pProperties = (t_reverb_properties *) pValue; -        if (param == REVERB_PARAM_ROOM_LEVEL) { -            break; -        } -        pValue16 = &pProperties->roomHFLevel; -        /* FALL THROUGH */ - -    case REVERB_PARAM_ROOM_HF_LEVEL: -        // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is: -        // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where: -        // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk -        // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz - -        temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk); -        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp); -        temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz) -                << 1; -        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2); -        temp = 32767 + temp - temp2; -        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp); -        temp = Effects_Sqrt(temp) * 181; -        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp); -        temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp; - -        LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); - -        *pValue16 = Effects_Linear16ToMillibels(temp); - -        if (param == REVERB_PARAM_ROOM_HF_LEVEL) { +        switch (param) { +        case REVERB_PARAM_BYPASS: +            *pValue32 = (int32_t) pReverb->m_bBypass;              break; -        } -        pValue32 = &pProperties->decayTime; -        /* FALL THROUGH */ -    case REVERB_PARAM_DECAY_TIME: -        // Calculate reverb feedback path gain -        temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk); -        temp = Effects_Linear16ToMillibels(temp); +        case REVERB_PARAM_PROPERTIES: +            pValue16 = &pProperties->roomLevel; +            /* FALL THROUGH */ -        // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time -        temp = (-6000 * pReverb->m_nLateDelay) / temp; +        case REVERB_PARAM_ROOM_LEVEL: +            // Convert m_nRoomLpfFwd to millibels +            temp = (pReverb->m_nRoomLpfFwd << 15) +                    / (32767 - pReverb->m_nRoomLpfFbk); +            *pValue16 = Effects_Linear16ToMillibels(temp); -        // Convert samples to ms -        *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate; +            LOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); -        LOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32); - -        if (param == REVERB_PARAM_DECAY_TIME) { -            break; -        } -        pValue16 = &pProperties->decayHFRatio; -        /* FALL THROUGH */ - -    case REVERB_PARAM_DECAY_HF_RATIO: -        // If r is the decay HF ratio  (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have: -        //       DT_5000Hz = DT_0Hz * r -        //  and  G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so : -        // r = G_0Hz/G_5000Hz in millibels -        // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where: -        // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk -        // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd -        // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz -        if (pReverb->m_nRvbLpfFbk == 0) { -            *pValue16 = 1000; -            LOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16); -        } else { -            temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk); -            temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz) +            if (param == REVERB_PARAM_ROOM_LEVEL) { +                break; +            } +            pValue16 = &pProperties->roomHFLevel; +            /* FALL THROUGH */ + +        case REVERB_PARAM_ROOM_HF_LEVEL: +            // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is: +            // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where: +            // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk +            // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz + +            temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk); +            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp); +            temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz)                      << 1; +            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2);              temp = 32767 + temp - temp2; +            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp);              temp = Effects_Sqrt(temp) * 181; -            temp = (pReverb->m_nRvbLpfFwd << 15) / temp; -            // The linear gain at 0Hz is b0 / (a1 + 1) -            temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 -                    - pReverb->m_nRvbLpfFbk); +            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp); +            temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp; + +            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); + +            *pValue16 = Effects_Linear16ToMillibels(temp); + +            if (param == REVERB_PARAM_ROOM_HF_LEVEL) { +                break; +            } +            pValue32 = &pProperties->decayTime; +            /* FALL THROUGH */ +        case REVERB_PARAM_DECAY_TIME: +            // Calculate reverb feedback path gain +            temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);              temp = Effects_Linear16ToMillibels(temp); -            temp2 = Effects_Linear16ToMillibels(temp2); -            LOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2); -            if (temp == 0) -                temp = 1; -            temp = (int16_t) ((1000 * temp2) / temp); -            if (temp > 1000) -                temp = 1000; +            // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time +            temp = (-6000 * pReverb->m_nLateDelay) / temp; -            *pValue16 = temp; -            LOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16); -        } +            // Convert samples to ms +            *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate; -        if (param == REVERB_PARAM_DECAY_HF_RATIO) { -            break; -        } -        pValue16 = &pProperties->reflectionsLevel; -        /* FALL THROUGH */ +            LOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32); -    case REVERB_PARAM_REFLECTIONS_LEVEL: -        *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain); +            if (param == REVERB_PARAM_DECAY_TIME) { +                break; +            } +            pValue16 = &pProperties->decayHFRatio; +            /* FALL THROUGH */ + +        case REVERB_PARAM_DECAY_HF_RATIO: +            // If r is the decay HF ratio  (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have: +            //       DT_5000Hz = DT_0Hz * r +            //  and  G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so : +            // r = G_0Hz/G_5000Hz in millibels +            // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where: +            // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk +            // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd +            // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz +            if (pReverb->m_nRvbLpfFbk == 0) { +                *pValue16 = 1000; +                LOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16); +            } else { +                temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk); +                temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz) +                        << 1; +                temp = 32767 + temp - temp2; +                temp = Effects_Sqrt(temp) * 181; +                temp = (pReverb->m_nRvbLpfFwd << 15) / temp; +                // The linear gain at 0Hz is b0 / (a1 + 1) +                temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 +                        - pReverb->m_nRvbLpfFbk); + +                temp = Effects_Linear16ToMillibels(temp); +                temp2 = Effects_Linear16ToMillibels(temp2); +                LOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2); + +                if (temp == 0) +                    temp = 1; +                temp = (int16_t) ((1000 * temp2) / temp); +                if (temp > 1000) +                    temp = 1000; + +                *pValue16 = temp; +                LOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16); +            } -        LOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16); -        if (param == REVERB_PARAM_REFLECTIONS_LEVEL) { -            break; -        } -        pValue32 = &pProperties->reflectionsDelay; -        /* FALL THROUGH */ +            if (param == REVERB_PARAM_DECAY_HF_RATIO) { +                break; +            } +            pValue16 = &pProperties->reflectionsLevel; +            /* FALL THROUGH */ -    case REVERB_PARAM_REFLECTIONS_DELAY: -        // convert samples to ms -        *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate; +        case REVERB_PARAM_REFLECTIONS_LEVEL: +            *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain); -        LOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32); +            LOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16); +            if (param == REVERB_PARAM_REFLECTIONS_LEVEL) { +                break; +            } +            pValue32 = &pProperties->reflectionsDelay; +            /* FALL THROUGH */ -        if (param == REVERB_PARAM_REFLECTIONS_DELAY) { -            break; -        } -        pValue16 = &pProperties->reverbLevel; -        /* FALL THROUGH */ +        case REVERB_PARAM_REFLECTIONS_DELAY: +            // convert samples to ms +            *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate; -    case REVERB_PARAM_REVERB_LEVEL: -        // Convert linear gain to millibels -        *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2); +            LOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32); -        LOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16); +            if (param == REVERB_PARAM_REFLECTIONS_DELAY) { +                break; +            } +            pValue16 = &pProperties->reverbLevel; +            /* FALL THROUGH */ -        if (param == REVERB_PARAM_REVERB_LEVEL) { -            break; -        } -        pValue32 = &pProperties->reverbDelay; -        /* FALL THROUGH */ +        case REVERB_PARAM_REVERB_LEVEL: +            // Convert linear gain to millibels +            *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2); -    case REVERB_PARAM_REVERB_DELAY: -        // convert samples to ms -        *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate; +            LOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16); -        LOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32); +            if (param == REVERB_PARAM_REVERB_LEVEL) { +                break; +            } +            pValue32 = &pProperties->reverbDelay; +            /* FALL THROUGH */ -        if (param == REVERB_PARAM_REVERB_DELAY) { -            break; -        } -        pValue16 = &pProperties->diffusion; -        /* FALL THROUGH */ +        case REVERB_PARAM_REVERB_DELAY: +            // convert samples to ms +            *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate; -    case REVERB_PARAM_DIFFUSION: -        temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE)) -                / AP0_GAIN_RANGE); +            LOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32); -        if (temp < 0) -            temp = 0; -        if (temp > 1000) -            temp = 1000; +            if (param == REVERB_PARAM_REVERB_DELAY) { +                break; +            } +            pValue16 = &pProperties->diffusion; +            /* FALL THROUGH */ -        *pValue16 = temp; -        LOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain); +        case REVERB_PARAM_DIFFUSION: +            temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE)) +                    / AP0_GAIN_RANGE); -        if (param == REVERB_PARAM_DIFFUSION) { -            break; -        } -        pValue16 = &pProperties->density; -        /* FALL THROUGH */ +            if (temp < 0) +                temp = 0; +            if (temp > 1000) +                temp = 1000; -    case REVERB_PARAM_DENSITY: -        // Calculate AP delay in time units -        temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16) -                / pReverb->m_nSamplingRate; +            *pValue16 = temp; +            LOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain); -        temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE); +            if (param == REVERB_PARAM_DIFFUSION) { +                break; +            } +            pValue16 = &pProperties->density; +            /* FALL THROUGH */ -        if (temp < 0) -            temp = 0; -        if (temp > 1000) -            temp = 1000; +        case REVERB_PARAM_DENSITY: +            // Calculate AP delay in time units +            temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16) +                    / pReverb->m_nSamplingRate; -        *pValue16 = temp; +            temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE); -        LOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn); -        break; +            if (temp < 0) +                temp = 0; +            if (temp > 1000) +                temp = 1000; -    default: -        break; +            *pValue16 = temp; + +            LOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn); +            break; + +        default: +            break; +        }      } +    *pSize = size; +      LOGV("Reverb_getParameter, context %p, param %d, value %d",              pReverb, param, *(int *)pValue); @@ -945,382 +951,386 @@ int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,      LOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d",              pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue); -    if (pReverb->m_Preset && param != REVERB_PARAM_PRESET) { -        return -EINVAL; -    } -    if (!pReverb->m_Preset && param == REVERB_PARAM_PRESET) { -        return -EINVAL; -    } - -    switch (param) { -    case REVERB_PARAM_ROOM_LEVEL: -    case REVERB_PARAM_ROOM_HF_LEVEL: -    case REVERB_PARAM_DECAY_HF_RATIO: -    case REVERB_PARAM_REFLECTIONS_LEVEL: -    case REVERB_PARAM_REVERB_LEVEL: -    case REVERB_PARAM_DIFFUSION: -    case REVERB_PARAM_DENSITY: -        paramSize = sizeof(int16_t); -        break; - -    case REVERB_PARAM_BYPASS: -    case REVERB_PARAM_PRESET: -    case REVERB_PARAM_DECAY_TIME: -    case REVERB_PARAM_REFLECTIONS_DELAY: -    case REVERB_PARAM_REVERB_DELAY: -        paramSize = sizeof(int32_t); -        break; - -    case REVERB_PARAM_PROPERTIES: -        paramSize = sizeof(t_reverb_properties); -        break; - -    default: -        return -EINVAL; -    } - -    if (size != paramSize) { -        return -EINVAL; -    } - -    if (paramSize == sizeof(int16_t)) { -        value16 = *(int16_t *) pValue; -    } else if (paramSize == sizeof(int32_t)) { -        value32 = *(int32_t *) pValue; -    } else { -        pProperties = (t_reverb_properties *) pValue; -    } - -    pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nCurrentRoom]; - -    switch (param) { -    case REVERB_PARAM_BYPASS: -        pReverb->m_bBypass = (uint16_t)value32; -        break; -    case REVERB_PARAM_PRESET: -        if (value32 != REVERB_PRESET_LARGE_HALL && value32 -                != REVERB_PRESET_HALL && value32 != REVERB_PRESET_CHAMBER -                && value32 != REVERB_PRESET_ROOM) +    if (pReverb->m_Preset) { +        if (param != REVERB_PARAM_PRESET || size != sizeof(int16_t)) {              return -EINVAL; -        pReverb->m_nNextRoom = (int16_t) value32; -        break; - -    case REVERB_PARAM_PROPERTIES: -        value16 = pProperties->roomLevel; -        /* FALL THROUGH */ - -    case REVERB_PARAM_ROOM_LEVEL: -        // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd -        if (value16 > 0) +        } +        value16 = *(int16_t *)pValue; +        LOGV("set REVERB_PARAM_PRESET, preset %d", value16); +        if (value16 < REVERB_PRESET_NONE || value16 > REVERB_PRESET_PLATE) {              return -EINVAL; +        } +        // REVERB_PRESET_NONE is mapped to bypass +        if (value16 == REVERB_PRESET_NONE) { +            pReverb->m_bBypass = 1; +        } else { +            pReverb->m_bBypass = 0; +            pReverb->m_nNextRoom = value16 - 1; +        } +    } else { +        switch (param) { +        case REVERB_PARAM_ROOM_LEVEL: +        case REVERB_PARAM_ROOM_HF_LEVEL: +        case REVERB_PARAM_DECAY_HF_RATIO: +        case REVERB_PARAM_REFLECTIONS_LEVEL: +        case REVERB_PARAM_REVERB_LEVEL: +        case REVERB_PARAM_DIFFUSION: +        case REVERB_PARAM_DENSITY: +            paramSize = sizeof(int16_t); +            break; -        temp = Effects_MillibelsToLinear16(value16); - -        pReverb->m_nRoomLpfFwd -                = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk)); - -        LOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); -        if (param == REVERB_PARAM_ROOM_LEVEL) +        case REVERB_PARAM_BYPASS: +        case REVERB_PARAM_DECAY_TIME: +        case REVERB_PARAM_REFLECTIONS_DELAY: +        case REVERB_PARAM_REVERB_DELAY: +            paramSize = sizeof(int32_t);              break; -        value16 = pProperties->roomHFLevel; -        /* FALL THROUGH */ -    case REVERB_PARAM_ROOM_HF_LEVEL: +        case REVERB_PARAM_PROPERTIES: +            paramSize = sizeof(t_reverb_properties); +            break; -        // Limit to 0 , -40dB range because of low pass implementation -        if (value16 > 0 || value16 < -4000) +        default:              return -EINVAL; -        // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk -        // m_nRoomLpfFbk is -a1 where a1 is the solution of: -        // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where: -        // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz) -        // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz) - -        // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged -        // while changing HF level -        temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767 -                - pReverb->m_nRoomLpfFbk); -        if (value16 == 0) { -            pReverb->m_nRoomLpfFbk = 0; -        } else { -            int32_t dG2, b, delta; - -            // dG^2 -            temp = Effects_MillibelsToLinear16(value16); -            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp); -            temp = (1 << 30) / temp; -            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp); -            dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15); -            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2); -            // b = 2*(C-dG^2)/(1-dG^2) -            b = (int32_t) ((((int64_t) 1 << (15 + 1)) -                    * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2)) -                    / ((int64_t) 32767 - (int64_t) dG2)); - -            // delta = b^2 - 4 -            delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15 -                    + 2))); - -            LOGV_IF(delta > (1<<30), " delta overflow %d", delta); - -            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz); -            // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2 -            pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;          } -        LOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d", -                temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd); -        pReverb->m_nRoomLpfFwd -                = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk)); -        LOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd); - -        if (param == REVERB_PARAM_ROOM_HF_LEVEL) -            break; -        value32 = pProperties->decayTime; -        /* FALL THROUGH */ - -    case REVERB_PARAM_DECAY_TIME: - -        // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk) -        // convert ms to samples -        value32 = (value32 * pReverb->m_nSamplingRate) / 1000; - -        // calculate valid decay time range as a function of current reverb delay and -        // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB -        // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels. -        // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time -        averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion; -        averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) -                + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1; - -        temp = (-6000 * averageDelay) / value32; -        LOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp); -        if (temp < -4000 || temp > -100) +        if (size != paramSize) {              return -EINVAL; +        } -        // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output -        // xfade and sum gain (max +9dB) -        temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900; -        temp = Effects_MillibelsToLinear16(temp); - -        // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk) -        pReverb->m_nRvbLpfFwd -                = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk)); +        if (paramSize == sizeof(int16_t)) { +            value16 = *(int16_t *) pValue; +        } else if (paramSize == sizeof(int32_t)) { +            value32 = *(int32_t *) pValue; +        } else { +            pProperties = (t_reverb_properties *) pValue; +        } -        LOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain)); +        pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom]; -        if (param == REVERB_PARAM_DECAY_TIME) +        switch (param) { +        case REVERB_PARAM_BYPASS: +            pReverb->m_bBypass = (uint16_t)value32;              break; -        value16 = pProperties->decayHFRatio; -        /* FALL THROUGH */ -    case REVERB_PARAM_DECAY_HF_RATIO: +        case REVERB_PARAM_PROPERTIES: +            value16 = pProperties->roomLevel; +            /* FALL THROUGH */ -        // We limit max value to 1000 because reverb filter is lowpass only -        if (value16 < 100 || value16 > 1000) -            return -EINVAL; -        // Convert per mille to => m_nLpfFwd, m_nLpfFbk - -        // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged -        // while changing HF level -        temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk); +        case REVERB_PARAM_ROOM_LEVEL: +            // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd +            if (value16 > 0) +                return -EINVAL; -        if (value16 == 1000) { -            pReverb->m_nRvbLpfFbk = 0; -        } else { -            int32_t dG2, b, delta; +            temp = Effects_MillibelsToLinear16(value16); -            temp = Effects_Linear16ToMillibels(temp2); -            // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels +            pReverb->m_nRoomLpfFwd +                    = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk)); + +            LOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk); +            if (param == REVERB_PARAM_ROOM_LEVEL) +                break; +            value16 = pProperties->roomHFLevel; +            /* FALL THROUGH */ + +        case REVERB_PARAM_ROOM_HF_LEVEL: + +            // Limit to 0 , -40dB range because of low pass implementation +            if (value16 > 0 || value16 < -4000) +                return -EINVAL; +            // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk +            // m_nRoomLpfFbk is -a1 where a1 is the solution of: +            // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where: +            // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz) +            // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz) + +            // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged +            // while changing HF level +            temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767 +                    - pReverb->m_nRoomLpfFbk); +            if (value16 == 0) { +                pReverb->m_nRoomLpfFbk = 0; +            } else { +                int32_t dG2, b, delta; + +                // dG^2 +                temp = Effects_MillibelsToLinear16(value16); +                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp); +                temp = (1 << 30) / temp; +                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp); +                dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15); +                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2); +                // b = 2*(C-dG^2)/(1-dG^2) +                b = (int32_t) ((((int64_t) 1 << (15 + 1)) +                        * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2)) +                        / ((int64_t) 32767 - (int64_t) dG2)); + +                // delta = b^2 - 4 +                delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15 +                        + 2))); + +                LOGV_IF(delta > (1<<30), " delta overflow %d", delta); + +                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz); +                // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2 +                pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1; +            } +            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d", +                    temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd); + +            pReverb->m_nRoomLpfFwd +                    = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk)); +            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd); + +            if (param == REVERB_PARAM_ROOM_HF_LEVEL) +                break; +            value32 = pProperties->decayTime; +            /* FALL THROUGH */ + +        case REVERB_PARAM_DECAY_TIME: + +            // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk) +            // convert ms to samples +            value32 = (value32 * pReverb->m_nSamplingRate) / 1000; + +            // calculate valid decay time range as a function of current reverb delay and +            // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB +            // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels. +            // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time +            averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion; +            averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) +                    + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1; + +            temp = (-6000 * averageDelay) / value32; +            LOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp); +            if (temp < -4000 || temp > -100) +                return -EINVAL; + +            // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output +            // xfade and sum gain (max +9dB) +            temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900; +            temp = Effects_MillibelsToLinear16(temp); -            value32 = ((int32_t) 1000 << 15) / (int32_t) value16; -            LOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32); +            // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk) +            pReverb->m_nRvbLpfFwd +                    = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk)); -            temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15); +            LOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain)); -            if (temp < -4000) { -                LOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp); -                temp = -4000; -            } +            if (param == REVERB_PARAM_DECAY_TIME) +                break; +            value16 = pProperties->decayHFRatio; +            /* FALL THROUGH */ -            temp = Effects_MillibelsToLinear16(temp); -            LOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp); -            // dG^2 -            temp = (temp2 << 15) / temp; -            dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15); +        case REVERB_PARAM_DECAY_HF_RATIO: -            // b = 2*(C-dG^2)/(1-dG^2) -            b = (int32_t) ((((int64_t) 1 << (15 + 1)) -                    * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2)) -                    / ((int64_t) 32767 - (int64_t) dG2)); +            // We limit max value to 1000 because reverb filter is lowpass only +            if (value16 < 100 || value16 > 1000) +                return -EINVAL; +            // Convert per mille to => m_nLpfFwd, m_nLpfFbk -            // delta = b^2 - 4 -            delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15 -                    + 2))); +            // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged +            // while changing HF level +            temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk); -            // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2 -            pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1; +            if (value16 == 1000) { +                pReverb->m_nRvbLpfFbk = 0; +            } else { +                int32_t dG2, b, delta; -            LOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta); +                temp = Effects_Linear16ToMillibels(temp2); +                // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels -        } +                value32 = ((int32_t) 1000 << 15) / (int32_t) value16; +                LOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32); -        LOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd); +                temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15); -        pReverb->m_nRvbLpfFwd -                = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk)); +                if (temp < -4000) { +                    LOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp); +                    temp = -4000; +                } -        if (param == REVERB_PARAM_DECAY_HF_RATIO) -            break; -        value16 = pProperties->reflectionsLevel; -        /* FALL THROUGH */ +                temp = Effects_MillibelsToLinear16(temp); +                LOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp); +                // dG^2 +                temp = (temp2 << 15) / temp; +                dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15); -    case REVERB_PARAM_REFLECTIONS_LEVEL: -        // We limit max value to 0 because gain is limited to 0dB -        if (value16 > 0 || value16 < -6000) -            return -EINVAL; +                // b = 2*(C-dG^2)/(1-dG^2) +                b = (int32_t) ((((int64_t) 1 << (15 + 1)) +                        * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2)) +                        / ((int64_t) 32767 - (int64_t) dG2)); -        // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i]. -        value16 = Effects_MillibelsToLinear16(value16); -        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { -            pReverb->m_sEarlyL.m_nGain[i] -                    = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16); -            pReverb->m_sEarlyR.m_nGain[i] -                    = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16); -        } -        pReverb->m_nEarlyGain = value16; -        LOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain); +                // delta = b^2 - 4 +                delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15 +                        + 2))); -        if (param == REVERB_PARAM_REFLECTIONS_LEVEL) -            break; -        value32 = pProperties->reflectionsDelay; -        /* FALL THROUGH */ - -    case REVERB_PARAM_REFLECTIONS_DELAY: -        // We limit max value MAX_EARLY_TIME -        // convert ms to time units -        temp = (value32 * 65536) / 1000; -        if (temp < 0 || temp > MAX_EARLY_TIME) -            return -EINVAL; +                // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2 +                pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1; -        maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate) -                >> 16; -        temp = (temp * pReverb->m_nSamplingRate) >> 16; -        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { -            temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i] -                    * pReverb->m_nSamplingRate) >> 16); -            if (temp2 > maxSamples) -                temp2 = maxSamples; -            pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2; -            temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i] -                    * pReverb->m_nSamplingRate) >> 16); -            if (temp2 > maxSamples) -                temp2 = maxSamples; -            pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2; -        } -        pReverb->m_nEarlyDelay = temp; +                LOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta); -        LOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples); +            } -        // Convert milliseconds to sample count => m_nEarlyDelay -        if (param == REVERB_PARAM_REFLECTIONS_DELAY) -            break; -        value16 = pProperties->reverbLevel; -        /* FALL THROUGH */ +            LOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd); -    case REVERB_PARAM_REVERB_LEVEL: -        // We limit max value to 0 because gain is limited to 0dB -        if (value16 > 0 || value16 < -6000) -            return -EINVAL; -        // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain. -        pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2; +            pReverb->m_nRvbLpfFwd +                    = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk)); -        LOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain); +            if (param == REVERB_PARAM_DECAY_HF_RATIO) +                break; +            value16 = pProperties->reflectionsLevel; +            /* FALL THROUGH */ -        if (param == REVERB_PARAM_REVERB_LEVEL) -            break; -        value32 = pProperties->reverbDelay; -        /* FALL THROUGH */ - -    case REVERB_PARAM_REVERB_DELAY: -        // We limit max value to MAX_DELAY_TIME -        // convert ms to time units -        temp = (value32 * 65536) / 1000; -        if (temp < 0 || temp > MAX_DELAY_TIME) -            return -EINVAL; +        case REVERB_PARAM_REFLECTIONS_LEVEL: +            // We limit max value to 0 because gain is limited to 0dB +            if (value16 > 0 || value16 < -6000) +                return -EINVAL; -        maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate) -                >> 16; -        temp = (temp * pReverb->m_nSamplingRate) >> 16; -        if ((temp + pReverb->m_nMaxExcursion) > maxSamples) { -            temp = maxSamples - pReverb->m_nMaxExcursion; -        } -        if (temp < pReverb->m_nMaxExcursion) { -            temp = pReverb->m_nMaxExcursion; -        } +            // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i]. +            value16 = Effects_MillibelsToLinear16(value16); +            for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { +                pReverb->m_sEarlyL.m_nGain[i] +                        = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16); +                pReverb->m_sEarlyR.m_nGain[i] +                        = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16); +            } +            pReverb->m_nEarlyGain = value16; +            LOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain); + +            if (param == REVERB_PARAM_REFLECTIONS_LEVEL) +                break; +            value32 = pProperties->reflectionsDelay; +            /* FALL THROUGH */ + +        case REVERB_PARAM_REFLECTIONS_DELAY: +            // We limit max value MAX_EARLY_TIME +            // convert ms to time units +            temp = (value32 * 65536) / 1000; +            if (temp < 0 || temp > MAX_EARLY_TIME) +                return -EINVAL; + +            maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate) +                    >> 16; +            temp = (temp * pReverb->m_nSamplingRate) >> 16; +            for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { +                temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i] +                        * pReverb->m_nSamplingRate) >> 16); +                if (temp2 > maxSamples) +                    temp2 = maxSamples; +                pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2; +                temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i] +                        * pReverb->m_nSamplingRate) >> 16); +                if (temp2 > maxSamples) +                    temp2 = maxSamples; +                pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2; +            } +            pReverb->m_nEarlyDelay = temp; + +            LOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples); + +            // Convert milliseconds to sample count => m_nEarlyDelay +            if (param == REVERB_PARAM_REFLECTIONS_DELAY) +                break; +            value16 = pProperties->reverbLevel; +            /* FALL THROUGH */ + +        case REVERB_PARAM_REVERB_LEVEL: +            // We limit max value to 0 because gain is limited to 0dB +            if (value16 > 0 || value16 < -6000) +                return -EINVAL; +            // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain. +            pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2; + +            LOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain); + +            if (param == REVERB_PARAM_REVERB_LEVEL) +                break; +            value32 = pProperties->reverbDelay; +            /* FALL THROUGH */ + +        case REVERB_PARAM_REVERB_DELAY: +            // We limit max value to MAX_DELAY_TIME +            // convert ms to time units +            temp = (value32 * 65536) / 1000; +            if (temp < 0 || temp > MAX_DELAY_TIME) +                return -EINVAL; + +            maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate) +                    >> 16; +            temp = (temp * pReverb->m_nSamplingRate) >> 16; +            if ((temp + pReverb->m_nMaxExcursion) > maxSamples) { +                temp = maxSamples - pReverb->m_nMaxExcursion; +            } +            if (temp < pReverb->m_nMaxExcursion) { +                temp = pReverb->m_nMaxExcursion; +            } -        temp -= pReverb->m_nLateDelay; -        pReverb->m_nDelay0Out += temp; -        pReverb->m_nDelay1Out += temp; -        pReverb->m_nLateDelay += temp; +            temp -= pReverb->m_nLateDelay; +            pReverb->m_nDelay0Out += temp; +            pReverb->m_nDelay1Out += temp; +            pReverb->m_nLateDelay += temp; -        LOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples); +            LOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples); -        // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion -        if (param == REVERB_PARAM_REVERB_DELAY) -            break; +            // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion +            if (param == REVERB_PARAM_REVERB_DELAY) +                break; -        value16 = pProperties->diffusion; -        /* FALL THROUGH */ +            value16 = pProperties->diffusion; +            /* FALL THROUGH */ -    case REVERB_PARAM_DIFFUSION: -        if (value16 < 0 || value16 > 1000) -            return -EINVAL; +        case REVERB_PARAM_DIFFUSION: +            if (value16 < 0 || value16 > 1000) +                return -EINVAL; -        // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain -        pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16 -                * AP0_GAIN_RANGE) / 1000; -        pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16 -                * AP1_GAIN_RANGE) / 1000; +            // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain +            pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16 +                    * AP0_GAIN_RANGE) / 1000; +            pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16 +                    * AP1_GAIN_RANGE) / 1000; -        LOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain); +            LOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain); -        if (param == REVERB_PARAM_DIFFUSION) -            break; +            if (param == REVERB_PARAM_DIFFUSION) +                break; -        value16 = pProperties->density; -        /* FALL THROUGH */ +            value16 = pProperties->density; +            /* FALL THROUGH */ -    case REVERB_PARAM_DENSITY: -        if (value16 < 0 || value16 > 1000) -            return -EINVAL; +        case REVERB_PARAM_DENSITY: +            if (value16 < 0 || value16 > 1000) +                return -EINVAL; -        // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut -        maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16; +            // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut +            maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16; -        temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000; -        /*lint -e{702} shift for performance */ -        temp = (temp * pReverb->m_nSamplingRate) >> 16; -        if (temp > maxSamples) -            temp = maxSamples; -        pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp); +            temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000; +            /*lint -e{702} shift for performance */ +            temp = (temp * pReverb->m_nSamplingRate) >> 16; +            if (temp > maxSamples) +                temp = maxSamples; +            pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp); -        LOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp); +            LOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp); -        temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000; -        /*lint -e{702} shift for performance */ -        temp = (temp * pReverb->m_nSamplingRate) >> 16; -        if (temp > maxSamples) -            temp = maxSamples; -        pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp); +            temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000; +            /*lint -e{702} shift for performance */ +            temp = (temp * pReverb->m_nSamplingRate) >> 16; +            if (temp > maxSamples) +                temp = maxSamples; +            pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp); -        LOGV("Ap1 delay smps %d", temp); +            LOGV("Ap1 delay smps %d", temp); -        break; +            break; -    default: -        break; +        default: +            break; +        }      } +      return 0;  } /* end Reverb_setParameter */ @@ -1905,24 +1915,26 @@ static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {   */  static int ReverbReadInPresets(reverb_object_t *pReverb) { -    int preset = 0; -    int defaultPreset = 0; +    int preset; -    //now init any remaining presets to defaults -    for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) { -        reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[defaultPreset]; -        if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE - 1) { -            pPreset->m_nRvbLpfFbk = 8307; -            pPreset->m_nRvbLpfFwd = 14768; +    // this is for test only. OpenSL ES presets are mapped to 4 presets. +    // REVERB_PRESET_NONE is mapped to bypass +    for (preset = 0; preset < REVERB_NUM_PRESETS; preset++) { +        reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[preset]; +        switch (preset + 1) { +        case REVERB_PRESET_PLATE: +        case REVERB_PRESET_SMALLROOM: +            pPreset->m_nRvbLpfFbk = 5077; +            pPreset->m_nRvbLpfFwd = 11076;              pPreset->m_nEarlyGain = 27690;              pPreset->m_nEarlyDelay = 1311;              pPreset->m_nLateGain = 8191;              pPreset->m_nLateDelay = 3932;              pPreset->m_nRoomLpfFbk = 3692; -            pPreset->m_nRoomLpfFwd = 24569; +            pPreset->m_nRoomLpfFwd = 20474;              pPreset->m_sEarlyL.m_zDelay[0] = 1376;              pPreset->m_sEarlyL.m_nGain[0] = 22152; -            pPreset->m_sEarlyL.m_zDelay[1] = 2163; +            pPreset->m_sEarlyL.m_zDelay[1] = 1462;              pPreset->m_sEarlyL.m_nGain[1] = 17537;              pPreset->m_sEarlyL.m_zDelay[2] = 0;              pPreset->m_sEarlyL.m_nGain[2] = 14768; @@ -1941,11 +1953,11 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_sEarlyR.m_zDelay[4] = 0;              pPreset->m_sEarlyR.m_nGain[4] = 13384;              pPreset->m_nMaxExcursion = 127; -            pPreset->m_nXfadeInterval = 6388; -            pPreset->m_nAp0_ApGain = 15691; -            pPreset->m_nAp0_ApOut = 711; -            pPreset->m_nAp1_ApGain = 16317; -            pPreset->m_nAp1_ApOut = 1029; +            pPreset->m_nXfadeInterval = 6470; //6483; +            pPreset->m_nAp0_ApGain = 14768; +            pPreset->m_nAp0_ApOut = 792; +            pPreset->m_nAp1_ApGain = 14777; +            pPreset->m_nAp1_ApOut = 1191;              pPreset->m_rfu4 = 0;              pPreset->m_rfu5 = 0;              pPreset->m_rfu6 = 0; @@ -1953,15 +1965,17 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_rfu8 = 0;              pPreset->m_rfu9 = 0;              pPreset->m_rfu10 = 0; -        } else if (defaultPreset == 1) { -            pPreset->m_nRvbLpfFbk = 6461; -            pPreset->m_nRvbLpfFwd = 14307; +            break; +        case REVERB_PRESET_MEDIUMROOM: +        case REVERB_PRESET_LARGEROOM: +            pPreset->m_nRvbLpfFbk = 5077; +            pPreset->m_nRvbLpfFwd = 12922;              pPreset->m_nEarlyGain = 27690;              pPreset->m_nEarlyDelay = 1311;              pPreset->m_nLateGain = 8191;              pPreset->m_nLateDelay = 3932;              pPreset->m_nRoomLpfFbk = 3692; -            pPreset->m_nRoomLpfFwd = 24569; +            pPreset->m_nRoomLpfFwd = 21703;              pPreset->m_sEarlyL.m_zDelay[0] = 1376;              pPreset->m_sEarlyL.m_nGain[0] = 22152;              pPreset->m_sEarlyL.m_zDelay[1] = 1462; @@ -1983,11 +1997,11 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_sEarlyR.m_zDelay[4] = 0;              pPreset->m_sEarlyR.m_nGain[4] = 13384;              pPreset->m_nMaxExcursion = 127; -            pPreset->m_nXfadeInterval = 6391; -            pPreset->m_nAp0_ApGain = 15230; -            pPreset->m_nAp0_ApOut = 708; -            pPreset->m_nAp1_ApGain = 15547; -            pPreset->m_nAp1_ApOut = 1023; +            pPreset->m_nXfadeInterval = 6449; +            pPreset->m_nAp0_ApGain = 15691; +            pPreset->m_nAp0_ApOut = 774; +            pPreset->m_nAp1_ApGain = 16317; +            pPreset->m_nAp1_ApOut = 1155;              pPreset->m_rfu4 = 0;              pPreset->m_rfu5 = 0;              pPreset->m_rfu6 = 0; @@ -1995,15 +2009,16 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_rfu8 = 0;              pPreset->m_rfu9 = 0;              pPreset->m_rfu10 = 0; -        } else if (defaultPreset == 2) { -            pPreset->m_nRvbLpfFbk = 5077; -            pPreset->m_nRvbLpfFwd = 12922; +            break; +        case REVERB_PRESET_MEDIUMHALL: +            pPreset->m_nRvbLpfFbk = 6461; +            pPreset->m_nRvbLpfFwd = 14307;              pPreset->m_nEarlyGain = 27690;              pPreset->m_nEarlyDelay = 1311;              pPreset->m_nLateGain = 8191;              pPreset->m_nLateDelay = 3932;              pPreset->m_nRoomLpfFbk = 3692; -            pPreset->m_nRoomLpfFwd = 21703; +            pPreset->m_nRoomLpfFwd = 24569;              pPreset->m_sEarlyL.m_zDelay[0] = 1376;              pPreset->m_sEarlyL.m_nGain[0] = 22152;              pPreset->m_sEarlyL.m_zDelay[1] = 1462; @@ -2025,11 +2040,11 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_sEarlyR.m_zDelay[4] = 0;              pPreset->m_sEarlyR.m_nGain[4] = 13384;              pPreset->m_nMaxExcursion = 127; -            pPreset->m_nXfadeInterval = 6449; -            pPreset->m_nAp0_ApGain = 15691; -            pPreset->m_nAp0_ApOut = 774; -            pPreset->m_nAp1_ApGain = 16317; -            pPreset->m_nAp1_ApOut = 1155; +            pPreset->m_nXfadeInterval = 6391; +            pPreset->m_nAp0_ApGain = 15230; +            pPreset->m_nAp0_ApOut = 708; +            pPreset->m_nAp1_ApGain = 15547; +            pPreset->m_nAp1_ApOut = 1023;              pPreset->m_rfu4 = 0;              pPreset->m_rfu5 = 0;              pPreset->m_rfu6 = 0; @@ -2037,18 +2052,19 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_rfu8 = 0;              pPreset->m_rfu9 = 0;              pPreset->m_rfu10 = 0; -        } else if (defaultPreset == 3) { -            pPreset->m_nRvbLpfFbk = 5077; -            pPreset->m_nRvbLpfFwd = 11076; +            break; +        case REVERB_PRESET_LARGEHALL: +            pPreset->m_nRvbLpfFbk = 8307; +            pPreset->m_nRvbLpfFwd = 14768;              pPreset->m_nEarlyGain = 27690;              pPreset->m_nEarlyDelay = 1311;              pPreset->m_nLateGain = 8191;              pPreset->m_nLateDelay = 3932;              pPreset->m_nRoomLpfFbk = 3692; -            pPreset->m_nRoomLpfFwd = 20474; +            pPreset->m_nRoomLpfFwd = 24569;              pPreset->m_sEarlyL.m_zDelay[0] = 1376;              pPreset->m_sEarlyL.m_nGain[0] = 22152; -            pPreset->m_sEarlyL.m_zDelay[1] = 1462; +            pPreset->m_sEarlyL.m_zDelay[1] = 2163;              pPreset->m_sEarlyL.m_nGain[1] = 17537;              pPreset->m_sEarlyL.m_zDelay[2] = 0;              pPreset->m_sEarlyL.m_nGain[2] = 14768; @@ -2067,11 +2083,11 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_sEarlyR.m_zDelay[4] = 0;              pPreset->m_sEarlyR.m_nGain[4] = 13384;              pPreset->m_nMaxExcursion = 127; -            pPreset->m_nXfadeInterval = 6470; //6483; -            pPreset->m_nAp0_ApGain = 14768; -            pPreset->m_nAp0_ApOut = 792; -            pPreset->m_nAp1_ApGain = 14777; -            pPreset->m_nAp1_ApOut = 1191; +            pPreset->m_nXfadeInterval = 6388; +            pPreset->m_nAp0_ApGain = 15691; +            pPreset->m_nAp0_ApOut = 711; +            pPreset->m_nAp1_ApGain = 16317; +            pPreset->m_nAp1_ApOut = 1029;              pPreset->m_rfu4 = 0;              pPreset->m_rfu5 = 0;              pPreset->m_rfu6 = 0; @@ -2079,6 +2095,7 @@ static int ReverbReadInPresets(reverb_object_t *pReverb) {              pPreset->m_rfu8 = 0;              pPreset->m_rfu9 = 0;              pPreset->m_rfu10 = 0; +            break;          }      } diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h index f5aadfa9cb08..5af316d0f0cb 100644 --- a/media/libeffects/EffectReverb.h +++ b/media/libeffects/EffectReverb.h @@ -17,7 +17,8 @@  #ifndef ANDROID_EFFECTREVERB_H_  #define ANDROID_EFFECTREVERB_H_ -#include <media/EffectReverbApi.h> +#include <media/EffectEnvironmentalReverbApi.h> +#include <media/EffectPresetReverbApi.h>  /*------------------------------------ @@ -43,7 +44,7 @@ if the buffer size is a power of two.  #define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX   16384 -#define REVERB_MAX_ROOM_TYPE            4   // any room numbers larger than this are invalid +#define REVERB_NUM_PRESETS  REVERB_PRESET_PLATE   // REVERB_PRESET_NONE is not included  #define REVERB_MAX_NUM_REFLECTIONS      5   // max num reflections per channel @@ -171,7 +172,7 @@ typedef struct  typedef struct  { -    reverb_preset_t     m_sPreset[REVERB_MAX_ROOM_TYPE];    //array of presets +    reverb_preset_t     m_sPreset[REVERB_NUM_PRESETS]; // array of presets(does not include REVERB_PRESET_NONE)  } reverb_preset_bank_t; |