/*
* 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 android.util.Log;
import com.h6ah4i.android.media.audiofx.IBassBoost;
import com.h6ah4i.android.media.opensl.OpenSLMediaPlayer;
import com.h6ah4i.android.media.opensl.OpenSLMediaPlayerContext;
import com.h6ah4i.android.media.opensl.OpenSLMediaPlayerNativeLibraryLoader;
public class OpenSLBassBoost extends OpenSLAudioEffect implements IBassBoost {
private static final String TAG = "BassBoost";
// fields
private long mNativeHandle;
private static final boolean HAS_NATIVE;
private final boolean mStrengthSupported;
private int[] mParamIntBuff = new int[1];
private short[] mParamShortBuff = new short[1];
private boolean[] mParamBoolBuff = new boolean[1];
static {
// load native library
HAS_NATIVE = OpenSLMediaPlayerNativeLibraryLoader.loadLibraries();
}
public OpenSLBassBoost(OpenSLMediaPlayerContext context) {
if (context == null)
throw new IllegalArgumentException("The argument 'contex' cannot be null");
if (HAS_NATIVE) {
mNativeHandle = createNativeImplHandle(
OpenSLMediaPlayer.Internal.getNativeHandle(context));
}
if (mNativeHandle == 0) {
throw new UnsupportedOperationException("Failed to initialize native layer");
}
// set mStrengthSupported
mStrengthSupported = getStrengthSupportedInternal();
}
private boolean getStrengthSupportedInternal() {
final boolean[] strengthSupported = mParamBoolBuff;
strengthSupported[0] = false;
if (mNativeHandle != 0) {
if (getStrengthSupportedImplNative(mNativeHandle, strengthSupported) != SUCCESS) {
strengthSupported[0] = false;
}
}
return strengthSupported[0];
}
@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 getId() {
checkNativeImplIsAvailable();
final int[] id = mParamIntBuff;
final int result = getIdImplNative(mNativeHandle, id);
parseResultAndThrowExceptForIOExceptions(result);
return id[0];
}
@Override
public int setEnabled(boolean enabled) throws IllegalStateException {
checkNativeImplIsAvailable();
try {
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 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 boolean getStrengthSupported() {
return mStrengthSupported;
}
@Override
public void setStrength(short strength) throws IllegalStateException, IllegalArgumentException,
UnsupportedOperationException {
checkNativeImplIsAvailable();
final int result = setStrengthImplNative(mNativeHandle, strength);
parseResultAndThrowExceptForIOExceptions(result);
}
@Override
public short getRoundedStrength() throws IllegalStateException, IllegalArgumentException,
UnsupportedOperationException {
checkNativeImplIsAvailable();
final short[] roundedStrength = mParamShortBuff;
final int result = getRoundedStrengthImplNative(mNativeHandle, roundedStrength);
parseResultAndThrowExceptForIOExceptions(result);
return roundedStrength[0];
}
@Override
public IBassBoost.Settings getProperties() throws
IllegalStateException,
IllegalArgumentException,
UnsupportedOperationException {
checkNativeImplIsAvailable();
final int[] values = mParamIntBuff;
final int result = getPropertiesImplNative(mNativeHandle, values);
parseResultAndThrowExceptForIOExceptions(result);
final IBassBoost.Settings settings = new Settings();
settings.strength = (short) (values[0] & 0xffff);
return settings;
}
@Override
public void setProperties(IBassBoost.Settings settings) throws
IllegalStateException,
IllegalArgumentException,
UnsupportedOperationException {
checkNativeImplIsAvailable();
if (settings == null)
throw new IllegalArgumentException("The argument 'settings' cannot be null");
final int[] values = mParamIntBuff;
values[0] = settings.strength & 0xffff;
final int result = setPropertiesImplNative(mNativeHandle, values);
parseResultAndThrowExceptForIOExceptions(result);
}
@Override
public void setParameterListener(IBassBoost.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 getStrengthSupportedImplNative(long handle,
boolean[] strengthSupported);
private static native int getRoundedStrengthImplNative(long handle, short[] roundedStrength);
private static native int getPropertiesImplNative(long handle, int[] settings);
private static native int setStrengthImplNative(long handle, short strength);
private static native int setPropertiesImplNative(long handle, int[] settings);
}