/* * Copyright (C) 2014 Haruki Hasegawa * * 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 com.h6ah4i.android.media.standard.audiofx; import android.media.audiofx.EnvironmentalReverb; import com.h6ah4i.android.media.audiofx.IEnvironmentalReverb; import com.h6ah4i.android.media.utils.AudioEffectSettingsConverter; public class StandardEnvironmentalReverb extends StandardAudioEffect implements IEnvironmentalReverb { public static final String TAG = "StdEnvReverb"; private IEnvironmentalReverb.OnParameterChangeListener mUserOnParameterChangeListener; private android.media.audiofx.EnvironmentalReverb.OnParameterChangeListener mOnParameterChangeListener = new android.media.audiofx.EnvironmentalReverb.OnParameterChangeListener() { @Override public void onParameterChange( android.media.audiofx.EnvironmentalReverb effect, int status, int param, int value) { StandardEnvironmentalReverb.this.onParameterChange(effect, status, param, value); } }; public StandardEnvironmentalReverb(int priority, int audioSession) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException, RuntimeException { super(new EnvironmentalReverb(priority, audioSession)); getEnvironmentalReverb().setParameterListener(mOnParameterChangeListener); } /** * Get underlying EnvironmentalReverb instance. * * @return underlying EnvironmentalReverb instance. */ public EnvironmentalReverb getEnvironmentalReverb() { return (EnvironmentalReverb) getAudioEffect(); } @Override public int setEnabled(boolean enabled) throws IllegalStateException { final int result = super.setEnabled(enabled); if (result == SUCCESS) { // workarounds workaroundAfterSetEnabled(enabled); } return result; } @Override public void release() { workaroundPrevReleaseSync(); super.release(); mOnParameterChangeListener = null; mUserOnParameterChangeListener = null; } @Override public IEnvironmentalReverb.Settings getProperties() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getProperties()"); // NOTE: EnvironmentalReverb.getProperties() method does not work properly... return AudioEffectSettingsConverter.convert(getPropertiesCompat(getEnvironmentalReverb())); } @Override public void setProperties(IEnvironmentalReverb.Settings settings) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifySettings(settings); checkIsNotReleased("setProperties()"); // NOTE: EnvironmentalReverb.getProperties() method does not work properly... setPropertiesCompat(getEnvironmentalReverb(), AudioEffectSettingsConverter.convert(settings)); } @Override public short getDiffusion() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getDiffusion()"); return getEnvironmentalReverb().getDiffusion(); } @Override public void setDiffusion(short diffusion) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyDiffusionParameterRange(diffusion); checkIsNotReleased("setDiffusion()"); getEnvironmentalReverb().setDiffusion(diffusion); } @Override public short getDensity() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getDensity()"); return getEnvironmentalReverb().getDensity(); } @Override public void setDensity(short density) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyDensityParameterRange(density); checkIsNotReleased("setDensity()"); getEnvironmentalReverb().setDensity(density); } @Override public short getDecayHFRatio() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getDecayHFRatio()"); return getEnvironmentalReverb().getDecayHFRatio(); } @Override public void setDecayHFRatio(short decayHFRatio) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyDecayHFRatioParameterRange(decayHFRatio); checkIsNotReleased("setDecayHFRatio()"); getEnvironmentalReverb().setDecayHFRatio(decayHFRatio); } @Override public int getDecayTime() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getDecayTime()"); return getEnvironmentalReverb().getDecayTime(); } @Override public void setDecayTime(int decayTime) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyDecayTimeParameterRange(decayTime); checkIsNotReleased("setDecayTime()"); getEnvironmentalReverb().setDecayTime(decayTime); } @Override public short getRoomLevel() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getRoomLevel()"); return getEnvironmentalReverb().getRoomLevel(); } @Override public void setRoomLevel(short room) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyRoomLevelParameterRange(room); checkIsNotReleased("setRoomLevel()"); getEnvironmentalReverb().setRoomLevel(room); } @Override public short getRoomHFLevel() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getRoomHFLevel()"); return getEnvironmentalReverb().getRoomHFLevel(); } @Override public void setRoomHFLevel(short roomHF) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyRoomHFLevelParameterRange(roomHF); checkIsNotReleased("setRoomHFLevel()"); getEnvironmentalReverb().setRoomHFLevel(roomHF); } @Override public short getReverbLevel() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getReverbLevel()"); return getEnvironmentalReverb().getReverbLevel(); } @Override public void setReverbLevel(short reverbLevel) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyReverbLevelParameterRange(reverbLevel); checkIsNotReleased("setReverbLevel()"); getEnvironmentalReverb().setReverbLevel(reverbLevel); } @Override public int getReverbDelay() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getReverbDelay()"); return getEnvironmentalReverb().getReverbDelay(); } @Override public void setReverbDelay(int reverbDelay) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyReverbDelayParameterRange(reverbDelay); checkIsNotReleased("setReverbDelay()"); getEnvironmentalReverb().setReverbDelay(reverbDelay); } @Override public short getReflectionsLevel() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getReflectionsLevel()"); return getEnvironmentalReverb().getReflectionsLevel(); } @Override public void setReflectionsLevel(short reflectionsLevel) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyReflectionsLevelParameterRange(reflectionsLevel); checkIsNotReleased("setReflectionsLevel()"); getEnvironmentalReverb().setReflectionsLevel(reflectionsLevel); } @Override public int getReflectionsDelay() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkIsNotReleased("getReflectionsDelay()"); return getEnvironmentalReverb().getReflectionsDelay(); } @Override public void setReflectionsDelay(int reflectionsDelay) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { verifyReflectionsDelayParameterRange(reflectionsDelay); checkIsNotReleased("setReflectionsDelay()"); getEnvironmentalReverb().setReflectionsDelay(reflectionsDelay); } @Override public void setParameterListener( IEnvironmentalReverb.OnParameterChangeListener listener) { mUserOnParameterChangeListener = listener; } /* package */void onParameterChange( android.media.audiofx.EnvironmentalReverb effect, int status, int param, int value) { IEnvironmentalReverb.OnParameterChangeListener listener = null; listener = mUserOnParameterChangeListener; if (listener != null) { listener.onParameterChange(this, status, param, value); } } // === Fix unwanted behaviors === private static final short ROOM_LEVEL_MIN = (short) -9000; private static final short ROOM_LEVEL_MAX = (short) 0; private static final short ROOM_HF_LEVEL_MIN = (short) -9000; private static final short ROOM_HF_LEVEL_MAX = (short) 0; private static final int DECAY_TIME_MIN = 100; /* Spec.: 20000, Actually(LVREV_MAX_T60): 7000 */ private static final int DECAY_TIME_MAX = 7000; private static final short DECAY_HF_RATIO_MIN = (short) 100; private static final short DECAY_HF_RATIO_MAX = (short) 2000; /* Spec.: -9000, Actually: 0 (not implemented yet) */ private static final short REFLECTIONS_LEVEL_MIN = (short) 0; /* Spec.: 1000, Actually: 0 (not implemented yet) */ private static final short REFLECTIONS_LEVEL_MAX = (short) 0; /* Spec.: 0, Actually: 0 (not implemented yet) */ private static final int REFLECTIONS_DELAY_MIN = 0; /* Spec.: 300, Actually: 0 (not implemented yet) */ private static final int REFLECTIONS_DELAY_MAX = 0; private static final short REVERB_LEVEL_MIN = (short) -9000; private static final short REVERB_LEVEL_MAX = (short) 2000; /* Spec.: 0, Actually: 0 (not implemented yet) */ private static final int REVERB_DELAY_MIN = 0; /* Spec.: 100, Actually: 0 (not implemented yet) */ private static final int REVERB_DELAY_MAX = 0; private static final short DIFFUSION_MIN = (short) 0; private static final short DIFFUSION_MAX = (short) 1000; private static final short DENSITY_MIN = (short) 0; private static final short DENSITY_MAX = (short) 1000; private static void verifyRoomLevelParameterRange(short roomLevel) { if (!(roomLevel >= ROOM_LEVEL_MIN && roomLevel <= ROOM_LEVEL_MAX)) throw new IllegalArgumentException("bad parameter value: roomLevel = " + roomLevel); } private static void verifyRoomHFLevelParameterRange(short roomHFLevel) { if (!(roomHFLevel >= ROOM_HF_LEVEL_MIN && roomHFLevel <= ROOM_HF_LEVEL_MAX)) throw new IllegalArgumentException("bad parameter value: roomHFLevel = " + roomHFLevel); } private static void verifyDecayTimeParameterRange(int decayTime) { if (!(decayTime >= DECAY_TIME_MIN && decayTime <= DECAY_TIME_MAX)) throw new IllegalArgumentException("bad parameter value: decayTime = " + decayTime); } private static void verifyDecayHFRatioParameterRange(short decayHFRatio) { if (!(decayHFRatio >= DECAY_HF_RATIO_MIN && decayHFRatio <= DECAY_HF_RATIO_MAX)) throw new IllegalArgumentException("bad parameter value: decayHFRatio = " + decayHFRatio); } private static void verifyReflectionsLevelParameterRange(short reflectionsLevel) { if (!(reflectionsLevel >= REFLECTIONS_LEVEL_MIN && reflectionsLevel <= REFLECTIONS_LEVEL_MAX)) throw new IllegalArgumentException("bad parameter value: reflectionsLevel = " + reflectionsLevel); } private static void verifyReflectionsDelayParameterRange(int reflectionsDelay) { if (!(reflectionsDelay >= REFLECTIONS_DELAY_MIN && reflectionsDelay <= REFLECTIONS_DELAY_MAX)) throw new IllegalArgumentException("bad parameter value: reflectionsDelay = " + reflectionsDelay); } private static void verifyReverbLevelParameterRange(short reverbLevel) { if (!(reverbLevel >= REVERB_LEVEL_MIN && reverbLevel <= REVERB_LEVEL_MAX)) throw new IllegalArgumentException("bad parameter value: reverbLevel = " + reverbLevel); } private static void verifyReverbDelayParameterRange(int reverbDelay) { if (!(reverbDelay >= REVERB_DELAY_MIN && reverbDelay <= REVERB_DELAY_MAX)) throw new IllegalArgumentException("bad parameter value: reverbDelay = " + reverbDelay); } private static void verifyDiffusionParameterRange(short diffusion) { if (!(diffusion >= DIFFUSION_MIN && diffusion <= DIFFUSION_MAX)) throw new IllegalArgumentException("bad parameter value: diffusion = " + diffusion); } private static void verifyDensityParameterRange(short density) { if (!(density >= DENSITY_MIN && density <= DENSITY_MAX)) throw new IllegalArgumentException("bad parameter value: density = " + density); } private static void verifySettings(IEnvironmentalReverb.Settings settings) { if (settings == null) throw new IllegalArgumentException("The parameter 'settings' is null"); verifyRoomLevelParameterRange(settings.roomLevel); verifyRoomHFLevelParameterRange(settings.roomHFLevel); verifyDecayTimeParameterRange(settings.decayTime); verifyDecayHFRatioParameterRange(settings.decayHFRatio); verifyReflectionsLevelParameterRange(settings.reflectionsLevel); verifyReflectionsDelayParameterRange(settings.reflectionsDelay); verifyReverbLevelParameterRange(settings.reverbLevel); verifyReverbDelayParameterRange(settings.reverbDelay); verifyDiffusionParameterRange(settings.diffusion); verifyDensityParameterRange(settings.density); } private static EnvironmentalReverb.Settings getPropertiesCompat(EnvironmentalReverb reverb) { EnvironmentalReverb.Settings settings = new EnvironmentalReverb.Settings(); settings.roomLevel = reverb.getRoomLevel(); settings.roomHFLevel = reverb.getRoomHFLevel(); settings.decayTime = reverb.getDecayTime(); settings.decayHFRatio = reverb.getDecayHFRatio(); settings.reflectionsLevel = reverb.getReflectionsLevel(); settings.reflectionsDelay = reverb.getReflectionsDelay(); settings.reverbLevel = reverb.getReverbLevel(); settings.reverbDelay = reverb.getReverbDelay(); settings.diffusion = reverb.getDiffusion(); settings.density = reverb.getDensity(); return settings; } private void setPropertiesCompat(EnvironmentalReverb reverb, EnvironmentalReverb.Settings settings) { reverb.setRoomLevel(settings.roomLevel); reverb.setRoomHFLevel(settings.roomHFLevel); reverb.setDecayTime(settings.decayTime); reverb.setDecayHFRatio(settings.decayHFRatio); reverb.setReflectionsLevel(settings.reflectionsLevel); reverb.setReflectionsDelay(settings.reflectionsDelay); reverb.setReverbLevel(settings.reverbLevel); reverb.setReverbDelay(settings.reverbDelay); reverb.setDiffusion(settings.diffusion); reverb.setDensity(settings.density); } private void workaroundAfterSetEnabled(boolean enabled) { if (enabled) { setProperties(getProperties()); } } // ============================== }