/*
* 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;
import android.content.Context;
import android.media.AudioManager;
import android.util.Log;
import com.h6ah4i.android.media.IReleasable;
import com.h6ah4i.android.media.utils.AudioSystemUtils;
import com.h6ah4i.android.media.utils.AudioSystemUtils.AudioSystemProperties;
public class OpenSLMediaPlayerContext implements IReleasable {
private static final String TAG = "OpenSLMediaPlayerCtx";
// options
public static final int OPTION_USE_BASSBOOST = (1 << 0);
public static final int OPTION_USE_VIRTUALIZER = (1 << 1);
public static final int OPTION_USE_EQUALIZER = (1 << 2);
public static final int OPTION_USE_ENVIRONMENAL_REVERB = (1 << 8);
public static final int OPTION_USE_PRESET_REVERB = (1 << 9);
public static final int OPTION_USE_VISUALIZER = (1 << 16);
public static final int OPTION_USE_HQ_EQUALIZER = (1 << 17);
public static final int OPTION_USE_PREAMP = (1 << 18);
public static final int OPTION_USE_HQ_VISUALIZER = (1 << 19);
// resampler quality specifiler
public static final int RESAMPLER_QUALITY_LOW = 0;
public static final int RESAMPLER_QUALITY_MIDDLE = 1;
public static final int RESAMPLER_QUALITY_HIGH = 2;
// HQEqualizer implementation type specifier
public static final int HQ_EQUALIZER_IMPL_BASIC_PEAKING_FILTER = 0;
public static final int HQ_EQUALIZER_IMPL_FLAT_GAIN_RESPONSE = 1;
// Sink back-end implementation type specifier
public static final int SINK_BACKEND_TYPE_OPENSL = 0;
public static final int SINK_BACKEND_TYPE_AUDIO_TRACK = 1;
private long mNativeHandle;
private static final boolean HAS_NATIVE;
private boolean mHasNative;
private AudioSystemUtils.AudioSystemProperties mProperties;
static {
// load native library
HAS_NATIVE = OpenSLMediaPlayerNativeLibraryLoader.loadLibraries();
}
public static class Parameters {
public int options = 0;
public int streamType = AudioManager.STREAM_MUSIC;
public int shortFadeDuration = 25; // [milli seconds]
public int longFadeDuration = 1500; // [milli seconds]
public int resamplerQuality = RESAMPLER_QUALITY_MIDDLE;
public int hqEqualizerImplType = HQ_EQUALIZER_IMPL_BASIC_PEAKING_FILTER;
public int sinkBackEndType = SINK_BACKEND_TYPE_OPENSL;
public boolean useLowLatencyIfAvailable = false;
public boolean useFloatingPointIfAvailable = true;
}
public OpenSLMediaPlayerContext(Context context, Parameters params) {
final AudioSystemProperties props = AudioSystemUtils.getProperties(context);
if (params == null) {
params = new Parameters();
}
boolean hasNative = false;
if (HAS_NATIVE) {
try {
final int[] iparams = new int[13];
iparams[0] = props.outputSampleRate * 1000; // [Hz] -> [milli hertz]
iparams[1] = props.outputFramesPerBuffer;
iparams[2] = props.supportLowLatency ? 1 : 0;
iparams[3] = props.supportFloatingPoint ? 1 : 0;
iparams[4] = params.options;
iparams[5] = params.streamType;
iparams[6] = params.shortFadeDuration;
iparams[7] = params.longFadeDuration;
iparams[8] = params.resamplerQuality;
iparams[9] = params.hqEqualizerImplType;
iparams[10] = params.sinkBackEndType;
iparams[11] = params.useLowLatencyIfAvailable ? 1 : 0;
iparams[12] = params.useFloatingPointIfAvailable ? 1 : 0;
mNativeHandle = createNativeImplHandle(iparams);
if (mNativeHandle != 0) {
hasNative = true;
}
} catch (Throwable e) {
}
}
mHasNative = hasNative;
mProperties = props;
}
@Override
protected void finalize() throws Throwable {
release();
super.finalize();
}
@Override
public void release() {
try {
if (mHasNative && mNativeHandle != 0) {
deleteNativeImplHandle(mNativeHandle);
mNativeHandle = 0;
}
} catch (Exception e) {
Log.e(TAG, "release()", e);
}
}
//
// Internal methods
//
/** @hide */
/* package */long getNativeHandle() {
return mNativeHandle;
}
/** @hide */
/* package */
int getAudioSessionId() {
return getAudioSessionIdImplNative(mNativeHandle);
}
//
// Native methods
//
private static native long createNativeImplHandle(int[] params);
private static native void deleteNativeImplHandle(long handle);
private static native int getAudioSessionIdImplNative(long handle);
}