Android audio and video goes deep into thirteen OpenSL ES to create a music player, which can pause and adjust the volume (with source code download), androidopensl
Project address
Https://github.com/979451341/OpenSLAudio
OpenSL ES is a public audio API developed based on NDK, that is, the underlying C language. It can be used to achieve standardized, high-performance, and low-response-time audio functions.
This is a music player using OpenSL ES. It can play m4a and mp3 files, pause and adjust the volume.
Some steps are required to play music.
1. Create a sound engine
First, create an object interface for the sound engine.
Result = slCreateEngine (& engineObject, 0, NULL, 0, NULL, NULL );
Then implement it
Result = (* engineObject)-> Realize (engineObject, SL_BOOLEAN_FALSE );
Capture sound engine objects
Result = (* engineObject)-> GetInterface (engineObject, SL_IID_ENGINE, & engineEngine );
Create "output mixer"
Result = (* engineEngine)-> CreateOutputMix (engineEngine, & outputMixObject, 1, ids, req );
Achieve output of mixed audio
Result = (* outputMixObject)-> Realize (outputMixObject, SL_BOOLEAN_FALSE );
2. Create a sound player
Create and implement a player
// realize the player result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); assert(SL_RESULT_SUCCESS == result); (void)result; // get the play interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); assert(SL_RESULT_SUCCESS == result); (void)result;
3. Set the playback buffer.
Data format Configuration
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};
The data locator is used to locate the storage location of audio data to be played. It can be divided into four types: memory location, input/output device location, Buffer Queue location, and midi Buffer Queue location.
Data locator Configuration
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
Get the cache queue interface and register
// get the buffer queue interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue); assert(SL_RESULT_SUCCESS == result); (void)result; // register callback on the buffer queue result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); assert(SL_RESULT_SUCCESS == result); (void)result;
4. obtain other interfaces to control playback.
Interface for obtaining sound effects
// get the effect send interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend); assert(SL_RESULT_SUCCESS == result); (void)result;
Obtain the volume Interface
// get the volume interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); assert(SL_RESULT_SUCCESS == result); (void)result; // set the player's state to playing result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); assert(SL_RESULT_SUCCESS == result); (void)result;
5. Provide playback data
Open a music file
// convert Java string to UTF-8 const char *utf8 = (*env)->GetStringUTFChars(env, filename, NULL); assert(NULL != utf8); // use asset manager to open asset by filename AAssetManager* 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 found if (NULL == asset) { return JNI_FALSE; } // open asset as file descriptor off_t start, length; int fd = AAsset_openFileDescriptor(asset, &start, &length); assert(0 <= fd); AAsset_close(asset);
Set playback data
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. Play Music
You only need to change the playing status of a music player through the playing interface. Pause is also done, and stop is also done, but the pause must be done by the previous playing cache; otherwise, the pause is equivalent to stopping.
result = (*fdPlayerPlay)->SetPlayState(fdPlayerPlay, isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
7. Mediation volume
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. release resources
When the app is disabled, the occupied resources are released.
void Java_com_ywl5320_openslaudio_MainActivity_shutdown(JNIEnv* env, jclass clazz){ // destroy buffer queue audio player object, and invalidate all associated interfaces if (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 interfaces 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; }}
References
Http://blog.csdn.net/u013898698/article/details/72822595
Http://blog.csdn.net/ywl5320/article/details/78503768