標籤:音視頻 OpenSL ES
項目地址
https://github.com/979451341/OpenSLAudio
OpenSL ES 是基於NDK也就是c語言的底層開發音訊公開API,通過使用它能夠做到標準化, 高效能,低回應時間的音頻功能實現方法。
這次是使用OpenSL ES來做一個音樂播放器,它能夠播放m4a、mp3檔案,並能夠暫停和調整音量
播放音樂需要做一些步驟
1.建立聲音引擎
首先建立聲音引擎的對象介面
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
然後實現它
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
從聲音引擎的對象中抓取聲音引擎
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
建立"輸出混音器"
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
實現輸出混合音
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
2.建立聲音播放器
建立和實現播放器
// realize the playerresult = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);assert(SL_RESULT_SUCCESS == result);(void)result;// get the play interfaceresult = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);assert(SL_RESULT_SUCCESS == result);(void)result;
3.設定播放緩衝
資料格式配置
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_8, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
資料定位器 就是定位要播放聲音資料的存放位置,分為4種:記憶體位置,輸入/輸出裝置位置,緩衝區隊列位置,和midi緩衝區隊列位置。
資料定位器配置
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
得到了緩衝隊列介面,並註冊
// get the buffer queue interfaceresult = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);assert(SL_RESULT_SUCCESS == result);(void)result;// register callback on the buffer queueresult = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);assert(SL_RESULT_SUCCESS == result);(void)result;
4.獲得其他介面用來控制播放
得到聲音特效介面
// get the effect send interfaceresult = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend);assert(SL_RESULT_SUCCESS == result);(void)result;
得到音量介面
// get the volume interfaceresult = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);assert(SL_RESULT_SUCCESS == result);(void)result;// set the player‘s state to playingresult = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);assert(SL_RESULT_SUCCESS == result);(void)result;
5.提供播放資料
開啟音樂檔案
// convert Java string to UTF-8const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL);assert(NULL != utf8);// use asset manager to open asset by filenameAAssetManager* mgr = AAssetManager_fromJava(env, assetManager);assert(NULL != mgr);AAsset* asset = AAssetManager_open(mgr, utf8, AASSET_MODE_UNKNOWN);// release the Java string and UTF-8(*env)->ReleaseStringUTFChars(env, filename, utf8);// the asset might not be foundif (NULL == asset) { return JNI_FALSE;}// open asset as file descriptoroff_t start, length;int fd = AAsset_openFileDescriptor(asset, &start, &length);assert(0 <= fd);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 audioSrc = {&loc_fd, &format_mime};
6.播放音樂
播放音樂只需要通過播放介面改變播放狀態就可以了,暫停也是,停止也是,但是暫停必須之前的播放緩衝做了才行,否則那暫停就相當於停止了
result = (*fdPlayerPlay)->SetPlayState(fdPlayerPlay, isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
7.調解音量
SLVolumeItf getVolume()
{
if (fdPlayerVolume != NULL)
return fdPlayerVolume;
else
return bqPlayerVolume;
}
void Java_com_ywl5320_openslaudio_MainActivity_setVolumeAudioPlayer(JNIEnv env, jclass clazz,
jint millibel)
{
SLresult result;
SLVolumeItf volumeItf = getVolume();
if (NULL != volumeItf) {
result = (volumeItf)->SetVolumeLevel(volumeItf, millibel);
assert(SL_RESULT_SUCCESS == result);
(void)result;
}
}
8.釋放資源
關閉app時釋放佔用資源
void Java_com_ywl5320_openslaudio_MainActivity_shutdown(JNIEnv* env, jclass clazz)
{
// destroy buffer queue audio player object, and invalidate all associated interfacesif (bqPlayerObject != NULL) { (*bqPlayerObject)->Destroy(bqPlayerObject); bqPlayerObject = NULL; bqPlayerPlay = NULL; bqPlayerBufferQueue = NULL; bqPlayerEffectSend = NULL; bqPlayerMuteSolo = NULL; bqPlayerVolume = NULL;}// destroy file descriptor audio player object, and invalidate all associated interfacesif (fdPlayerObject != NULL) { (*fdPlayerObject)->Destroy(fdPlayerObject); fdPlayerObject = NULL; fdPlayerPlay = NULL; fdPlayerSeek = NULL; fdPlayerMuteSolo = NULL; fdPlayerVolume = NULL;}// destroy output mix object, and invalidate all associated interfacesif (outputMixObject != NULL) { (*outputMixObject)->Destroy(outputMixObject); outputMixObject = NULL; outputMixEnvironmentalReverb = NULL;}// destroy engine object, and invalidate all associated interfacesif (engineObject != NULL) { (*engineObject)->Destroy(engineObject); engineObject = NULL; engineEngine = NULL;}
}
參考文章
http://blog.csdn.net/u013898698/article/details/72822595
http://blog.csdn.net/ywl5320/article/details/78503768
Android 音視頻深入 十三 OpenSL ES 製作音樂播放器,能暫停和調整音量(附源碼下載)