OpenSL ES 全称是:Open Sound Library for Embedded Systems,是一套无授权费、跨平台、针对嵌入式系统精心优化的硬件音频加速API。它为嵌入式移动多媒体设备上的本地应用程序开发者提供标准化, 高性能, 低响应时间的音频功能实现方法,并实现软硬件音频性能的直接跨平台部署,降低android执行难度,促进高级音频市场的发展。
在android系统中是自带了opensl es的so库的,所以我们只需要在CMakeLists中链接以下就可以了,在引入头文件
#include
#include
声明native方法
//设置播放状态
public native void setPlayingAssetAudioPlayer(boolean isPlaying);
//释放资源
public native void shutdown();
//创建引擎
public native void createEngine();
//播放 assets对象,文件名
public native boolean player(AssetManager assetManager, String filename);
extern "C"
JNIEXPORT void JNICALL
Java_com_xiukun_lxkaudio_MainActivity_createEngine(JNIEnv *env, jobject instance) {
// TODO
SLresult result;
//初始化引擎
slCreateEngine(&engineObject,0,NULL,0,NULL,NULL);
(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);
//获取引擎接口
(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
//创建音频输出,配置相关参数
const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
(*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
(*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
//环境混响
result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
&outputMixEnvironmentalReverb);
if (SL_RESULT_SUCCESS == result) {
(*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
outputMixEnvironmentalReverb, &reverbSettings);
}
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_xiukun_lxkaudio_MainActivity_player(JNIEnv *env, jobject instance, jobject assetManager,
jstring filename_) {
const char *filename = env->GetStringUTFChars(filename_, 0);
// TODO
// 读取assets文件
AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_UNKNOWN);
if (NULL == asset) {
LOGE("读取失败。。。");
return JNI_FALSE;
}
// open asset as file descriptor
off_t start, length;
int fd = AAsset_openFileDescriptor(asset, &start, &length);
AAsset_close(asset);
// 配置信息
SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
SLDataSource audioSrc1 = {&loc_fd, &format_mime};
// configure audio sink
SLDataLocator_OutputMix loc_outmix1 = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk1 = {&loc_outmix1, NULL};
// 创建播放器
const SLInterfaceID audio_ids1[3] = {SL_IID_SEEK, SL_IID_MUTESOLO, SL_IID_VOLUME};
const SLboolean audio_req1[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
(*engineEngine)->CreateAudioPlayer(engineEngine, &fdPlayerObject, &audioSrc1, &audioSnk1,
3, audio_ids1, audio_req1);
(*fdPlayerObject)->Realize(fdPlayerObject, SL_BOOLEAN_FALSE);
// 获取播放器接口
(*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_PLAY, &fdPlayerPlay);
// 定位
(*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_SEEK, &fdPlayerSeek);
// 静音独奏
(*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_MUTESOLO, &fdPlayerMuteSolo);
// 音量
(*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_VOLUME, &fdPlayerVolume);
// 开启重复播放
(*fdPlayerSeek)->SetLoop(fdPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
env->ReleaseStringUTFChars(filename_, filename);
return JNI_TRUE;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_xiukun_lxkaudio_MainActivity_setPlayingAssetAudioPlayer(JNIEnv *env, jobject instance,
jboolean isPlaying) {
//设置播放状态
if (NULL != fdPlayerPlay) {
(*fdPlayerPlay)->SetPlayState(fdPlayerPlay, isPlaying ?
SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_xiukun_lxkaudio_MainActivity_shutdown(JNIEnv *env, jobject instance) {
if (fdPlayerObject != NULL) {
(*fdPlayerObject)->Destroy(fdPlayerObject);
fdPlayerObject = NULL;
fdPlayerPlay = NULL;
fdPlayerSeek = NULL;
fdPlayerMuteSolo = NULL;
fdPlayerVolume = NULL;
}
// destroy output mix object, and invalidate all associated interfaces
if (outputMixObject != NULL) {
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL;
outputMixEnvironmentalReverb = NULL;
}
// destroy engine object, and invalidate all associated interfaces
if (engineObject != NULL) {
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
engineEngine = NULL;
}
pthread_mutex_destroy(&audioEngineLock);
}
在c中读取assets中的文件,还需引入两个头文件,这两个头文件需要链接android这个库
cmakelists文件:
target_link_libraries( # Specifies the target library.
native-lib
OpenSLES
android
${log-lib} )
c文件:
#include
#include
这样就可以进行播放了,后面会进行音频录制、分割等方面的研究。
源码地址:https://github.com/luXiuKun/LxkAudio