/* * 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.opensl.audiofx; import java.nio.charset.Charset; import android.util.Log; import com.h6ah4i.android.media.audiofx.IEqualizer; import com.h6ah4i.android.media.opensl.OpenSLMediaPlayer; import com.h6ah4i.android.media.opensl.OpenSLMediaPlayerContext; import com.h6ah4i.android.media.opensl.OpenSLMediaPlayerNativeLibraryLoader; public class OpenSLEqualizer extends OpenSLAudioEffect implements IEqualizer { private static final String TAG = "Equalizer"; private long mNativeHandle; private static final boolean HAS_NATIVE; private int[] mParamIntBuff = new int[32]; private short[] mParamShortBuff = new short[1]; private boolean[] mParamBoolBuff = new boolean[1]; static { // load native library HAS_NATIVE = OpenSLMediaPlayerNativeLibraryLoader.loadLibraries(); } public OpenSLEqualizer(OpenSLMediaPlayerContext context) throws RuntimeException, IllegalStateException, IllegalArgumentException, UnsupportedOperationException { if (context == null) throw new IllegalArgumentException("The argument 'context' cannot be null"); if (HAS_NATIVE) { mNativeHandle = createNativeImplHandle( OpenSLMediaPlayer.Internal.getNativeHandle(context)); } if (mNativeHandle == 0) { throw new UnsupportedOperationException("Failed to initialize native layer"); } } @Override protected void finalize() throws Throwable { release(); super.finalize(); } @Override public void release() { try { if (HAS_NATIVE && mNativeHandle != 0) { deleteNativeImplHandle(mNativeHandle); mNativeHandle = 0; } } catch (Exception e) { Log.e(TAG, "release()", e); } } @Override public int setEnabled(boolean enabled) throws IllegalStateException { try { checkNativeImplIsAvailable(); final int result = setEnabledImplNative(mNativeHandle, enabled); parseResultAndThrowExceptForIOExceptions(result); return SUCCESS; } catch (UnsupportedOperationException e) { return ERROR_INVALID_OPERATION; } } @Override public boolean getEnabled() throws IllegalStateException { checkNativeImplIsAvailable(); final boolean[] enabled = mParamBoolBuff; final int result = getEnabledImplNative(mNativeHandle, enabled); if (result == OpenSLMediaPlayer.Internal.RESULT_CONTROL_LOST) return false; parseResultAndThrowExceptForIOExceptions(result); return enabled[0]; } @Override public int getId() throws IllegalStateException { checkNativeImplIsAvailable(); final int[] id = mParamIntBuff; final int result = getIdImplNative(mNativeHandle, id); parseResultAndThrowExceptForIOExceptions(result); return id[0]; } @Override public boolean hasControl() throws IllegalStateException { checkNativeImplIsAvailable(); final boolean[] hasControl = mParamBoolBuff; final int result = hasControlImplNative(mNativeHandle, hasControl); if (result == OpenSLMediaPlayer.Internal.RESULT_CONTROL_LOST) return false; parseResultAndThrowExceptForIOExceptions(result); return hasControl[0]; } @Override public short getBand(int frequency) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final short[] band = mParamShortBuff; final int result = getBandImplNative(mNativeHandle, frequency, band); parseResultAndThrowExceptForIOExceptions(result); return band[0]; } @Override public int[] getBandFreqRange(short band) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final int[] range = new int[2]; final int result = getBandFreqRangeImplNative(mNativeHandle, band, range); parseResultAndThrowExceptForIOExceptions(result); return range; } @Override public short getBandLevel(short band) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final short[] level = mParamShortBuff; final int result = getBandLevelImplNative(mNativeHandle, band, level); parseResultAndThrowExceptForIOExceptions(result); return level[0]; } @Override public short[] getBandLevelRange() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final short[] range = new short[2]; final int result = getBandLevelRangeImplNative(mNativeHandle, range); parseResultAndThrowExceptForIOExceptions(result); return range; } @Override public int getCenterFreq(short band) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final int[] freq = mParamIntBuff; final int result = getCenterFreqImplNative(mNativeHandle, band, freq); parseResultAndThrowExceptForIOExceptions(result); return freq[0]; } @Override public short getCurrentPreset() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final short[] preset = mParamShortBuff; final int result = getCurrentPresetImplNative(mNativeHandle, preset); parseResultAndThrowExceptForIOExceptions(result); return preset[0]; } @Override public short getNumberOfBands() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final short[] num_bands = mParamShortBuff; final int result = getNumberOfBandsImplNative(mNativeHandle, num_bands); parseResultAndThrowExceptForIOExceptions(result); return num_bands[0]; } @Override public short getNumberOfPresets() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final short[] num_presets = mParamShortBuff; final int result = getNumberOfPresetsImplNative(mNativeHandle, num_presets); parseResultAndThrowExceptForIOExceptions(result); return num_presets[0]; } @Override public String getPresetName(short preset) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); try { final byte[] buff = new byte[128]; final int result = getPresetNameImplNative(mNativeHandle, preset, buff); parseResultAndThrowExceptForIOExceptions(result); int len; for (len = 0; len < buff.length && buff[len] != 0; len++) ; return new String(buff, 0, len, Charset.forName("UTF-8")); } catch (IllegalArgumentException e) { return ""; } catch (IllegalStateException e) { return ""; } } @Override public void setBandLevel(short band, short level) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final int result = setBandLevelImplNative(mNativeHandle, band, level); parseResultAndThrowExceptForIOExceptions(result); } @Override public void usePreset(short preset) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final int result = usePresetImplNative(mNativeHandle, preset); parseResultAndThrowExceptForIOExceptions(result); } @Override public IEqualizer.Settings getProperties() throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); final int[] values = mParamIntBuff; final int result = getPropertiesImplNative(mNativeHandle, values); parseResultAndThrowExceptForIOExceptions(result); final IEqualizer.Settings settings = new Settings(); settings.curPreset = (short) (values[0] & 0xffff); settings.numBands = (short) (values[1] & 0xffff); settings.bandLevels = new short[settings.numBands]; for (int i = 0; i < settings.numBands; i++) { settings.bandLevels[i] = (short) (values[2 + i] & 0xffff); } return settings; } @Override public void setProperties(IEqualizer.Settings settings) throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException { checkNativeImplIsAvailable(); if (settings == null) throw new IllegalArgumentException("The argument 'settings' cannot be null"); if (settings.bandLevels == null) throw new IllegalArgumentException("settings invalid property: bandLevels is null"); if (settings.numBands != settings.bandLevels.length) throw new IllegalArgumentException("settings invalid band count: " + settings.numBands); final int[] values = mParamIntBuff; values[0] = settings.curPreset & 0xffff; values[1] = settings.numBands & 0xffff; for (int i = 0; i < settings.numBands; i++) { values[i + 2] = settings.bandLevels[i] & 0xffff; } final int result = setPropertiesImplNative(mNativeHandle, values); parseResultAndThrowExceptForIOExceptions(result); } @Override public void setParameterListener(IEqualizer.OnParameterChangeListener listener) { // this method is not supported. } // // Utilities // private void checkNativeImplIsAvailable() throws IllegalStateException { if (mNativeHandle == 0) { throw new IllegalStateException("Native implemenation handle is not present"); } } // // Native methods // private static native long createNativeImplHandle(long context_handle); private static native void deleteNativeImplHandle(long handle); private static native int setEnabledImplNative(long handle, boolean enabled); private static native int getEnabledImplNative(long handle, boolean[] enabled); private static native int getIdImplNative(long handle, int[] id); private static native int hasControlImplNative(long handle, boolean[] hasControl); private static native int getBandImplNative(long handle, int frequency, short[] band); private static native int getBandFreqRangeImplNative(long handle, short band, int[] range); private static native int getBandLevelImplNative(long handle, short band, short[] level); private static native int getBandLevelRangeImplNative(long handle, short[] range); private static native int getCenterFreqImplNative(long handle, short band, int[] freq); private static native int getCurrentPresetImplNative(long handle, short[] preset); private static native int getNumberOfBandsImplNative(long handle, short[] num_bands); private static native int getNumberOfPresetsImplNative(long handle, short[] num_presets); private static native int getPresetNameImplNative(long handle, short preset, byte[] buffer); private static native int getPropertiesImplNative(long handle, int[] settings); private static native int setBandLevelImplNative(long handle, short band, short level); private static native int usePresetImplNative(long handle, short preset); private static native int setPropertiesImplNative(long handle, int[] settings); }