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秒结束。
标签:NDK,NULL,SUCCESS,uriPlayerObject,result,SL,OpenSL,ES,RESULT From: https://www.cnblogs.com/kn-zheng/p/17005282.html