调用OpenSL ES NDK播放声音

调用OpenSL ES NDK播放声音

Android NDK 给出了native-audio的例子,这个例子结合java代码,讲解了如何使用OpenSL播放声音。
我把此例子进行了精简,完全使用c,可以让我们更好的体会到OpenSL的用法,不多说,上代码

main.c:
 

01.#include <stdio.h>
 02.#include <SLES/OpenSLES.h>
 03.#include <android/log.h>
 04.#include <assert.h>
 05.enum _bool {
 06.  false = 0,
 07.  true
 08.};
 09.typedef enum _bool bool;
 10./* engine interface */
 11.static SLObjectItf engineObject = NULL;
 12.static SLEngineItf engineEngine;
 13./* output mix interfaces */
 14.static SLObjectItf outputMixObject = NULL;
 15.static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
 16./* aux effect on the output mix */
 17.static const SLEnvironmentalReverbSettings reverbSettings =
 18.  SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
 19./* uri player interfaces */
 20.static SLObjectItf uriPlayerObject = NULL;
 21.static SLPlayItf uriPlayerPlay;
 22.static SLSeekItf uriPlayerSeek;
 23.void createEngine()
 24.{
 25.  SLresult result;
 26.  // create engine
 27.  result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
 28.  assert(SL_RESULT_SUCCESS == result);
 29.  // realize the engine
 30.  result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
 31.  assert(SL_RESULT_SUCCESS == result);
 32.  // get the engine interface
 33.  result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
 34.  assert(SL_RESULT_SUCCESS === result);
 35.  // create output mix
 36.  const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
 37.  const SLboolean req[1] = {SL_BOOLEAN_FALSE};
 38.  result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
 39.  assert(SL_RESULT_SUCCESS == result);
 40.  // realize the output mix
 41.  result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
 42.  assert(SL_RESULT_SUCCESS == result);
 43.#if 0  
 44.  // get the environmental reverb interface
 45.  result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
 46.        &outputMixEnvironmentalReverb);
 47.  if (SL_RESULT_SUCCESS == result) {
 48.    result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &reverbSettings);
 49.  }
 50.#endif
 51.  // ignore unsuccessful result codes for env reverb
 52.}
 53.bool createUriAudioPlayer(char* uri)
 54.{
 55.  SLresult result;
 56.  // config audio source
 57.  SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) uri};
 58.  SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
 59.  SLDataSource audioSrc = {&loc_uri, &format_mime};
 60.  // config audio sink
 61.  SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
 62.  SLDataSink audioSnk = {&loc_outmix, NULL};
 63.  // create audio player
 64.  const SLInterfaceID ids[1] = {SL_IID_SEEK};
 65.  const SLboolean req[1] = {SL_BOOLEAN_TRUE};
 66.  result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc, &audioSnk, 1, ids, req);
 67.  assert(SL_RESULT_SUCCESS == result);
 68.  // realize the player
 69.  result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE);
 70.  if (SL_RESULT_SUCCESS != result) {
 71.    (*uriPlayerObject)->Destroy(uriPlayerObject);
 72.    uriPlayerObject = NULL;
 73.    return false;
 74.  }
 75.  // get the play interface
 76.  result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
 77.  assert(SL_RESULT_SUCCESS == result);
 78.  // get the seek interface
 79.  result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek);
 80.  assert(SL_RESULT_SUCCESS == result);
 81.  // enable whole file looping
 82.  result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
 83.  assert(SL_RESULT_SUCCESS == result);
 84.  return true;
 85.}
 86.setPlayingUriAudioPlayer(bool played)
 87.{
 88.  SLresult result;
 89.  if (uriPlayerPlay != NULL) {
 90.    result = (*uriPlayerPlay)->SetPlayState(uriPlayerPlay, played ?
 91.                        SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
 92.    assert(SL_RESULT_SUCCESS == result);
 93.  }
 94.}
 95.int main(int argc, char** argv)
 96.{
 97.  // Create the OpenSL engine
 98.  createEngine();
 99.  // Create the audio player with everything ready.
 100.  createUriAudioPlayer(argv[1]);
 101.  printf("Playing...");
 102.  setPlayingUriAudioPlayer(true);      // play the music
 103.  sleep(20);
 104.  printf("Pause...");  
 105.  setPlayingUriAudioPlayer(false);    // pause the player
 106.  sleep(20);
 107.  
 108.  printf("Playing...");    
 109.  setPlayingUriAudioPlayer(true);
 110.  
 111.  sleep(1000);  // Just wait for the playing threads
 112.}
 复制代码 

Android.mk文件内容:
 

01.LOCAL_PATH := $(call my-dir)
 02.include $(CLEAR_VARS)
 03.LOCAL_MODULE    := audio-test
 04.LOCAL_SRC_FILES := main.c
 05.LOCAL_LDLIBS    += -lOpenSLES -llog
 06.include $(BUILD_EXECUTABLE)
 复制代码 


Application.mk文件里面需要指定android平台为9
 

01.APP_PLATFORM := android-9
 复制代码 


保存这3个文件,然后ndk-build就可以生成一个名为audio-test的可执行文件,拷贝这个文件到android 2.3的模拟器或者手机,我们这里将audio-test拷贝到/data/目录下面, 然后任意拷贝一首歌曲到模拟器或者手机,比如我们拷贝一手歌曲到/data/test.mp3,然后就可以使用audio-test来播放这个音乐了
使用adb shell登录手机或者模拟器,在终端里面执行如下命令(路径如果不同,你需要做相应修改):
 

01./data/audio-test /data/test.mp3
 复制代码 

然后就可以听到音乐了,过20秒会暂停20秒,然后一直播放,直到sleep的1000秒结束。

================================

http://bbs.chinaunix.net/forum.php?mod=viewthread&action=printable&tid=3631163

http://blog.csdn.net/hgl868/article/details/7534841

http://www.dssz.com/603896.html

原文地址:https://www.cnblogs.com/wainiwann/p/2984307.html