免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 14817 | 回复: 11
打印 上一主题 下一主题

音频处理高手来-----各位谁熟悉opensles 音频播放...... [复制链接]

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-17 15:52 |只看该作者 |倒序浏览
本帖最后由 hanzhenlll 于 2011-12-19 12:29 编辑

目前正准备,在android ndk环境实现音频播放,,,,这是我在网上搜寻到的一段 C的 opensles的代码。。。验证过 可行...
  1.    
  2.      #include <stdio.h>
  3.     #include <SLES/OpenSLES.h>
  4.     #include <android/log.h>
  5.     #include <assert.h>

  6.     enum _bool {
  7.       false = 0,
  8.       true
  9.     };

  10.     typedef enum _bool bool;

  11.     /* engine interface */
  12.     static SLObjectItf engineObject = NULL;
  13.     static SLEngineItf engineEngine;

  14.     /* output mix interfaces */
  15.     static SLObjectItf outputMixObject = NULL;
  16.     static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;

  17.     /* aux effect on the output mix */
  18.     static const SLEnvironmentalReverbSettings reverbSettings =
  19.       SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;

  20.     /* uri player interfaces */
  21.     static SLObjectItf uriPlayerObject = NULL;
  22.     static SLPlayItf uriPlayerPlay;
  23.     static SLSeekItf uriPlayerSeek;

  24.     void createEngine()
  25.     {
  26.       SLresult result;

  27.       // create engine
  28.       result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
  29.       assert(SL_RESULT_SUCCESS == result);

  30.       // realize the engine
  31.       result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
  32.       assert(SL_RESULT_SUCCESS == result);

  33.       // get the engine interface
  34.       result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
  35.       assert(SL_RESULT_SUCCESS === result);

  36.       // create output mix
  37.       const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
  38.       const SLboolean req[1] = {SL_BOOLEAN_FALSE};
  39.       result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
  40.       assert(SL_RESULT_SUCCESS == result);

  41.       // realize the output mix
  42.       result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
  43.       assert(SL_RESULT_SUCCESS == result);

  44.     #if 0  
  45.       // get the environmental reverb interface
  46.       result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
  47.             &outputMixEnvironmentalReverb);
  48.       if (SL_RESULT_SUCCESS == result) {
  49.         result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &reverbSettings);
  50.       }
  51.     #endif
  52.       // ignore unsuccessful result codes for env reverb
  53.     }

  54.     bool createUriAudioPlayer(char* uri)
  55.     {
  56.       SLresult result;

  57.       // config audio source
  58.       SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) uri};
  59.       SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
  60.       SLDataSource audioSrc = {&loc_uri, &format_mime};

  61.       // config audio sink
  62.       SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
  63.       SLDataSink audioSnk = {&loc_outmix, NULL};

  64.       // create audio player
  65.       const SLInterfaceID ids[1] = {SL_IID_SEEK};
  66.       const SLboolean req[1] = {SL_BOOLEAN_TRUE};
  67.       result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc, &audioSnk, 1, ids, req);
  68.       assert(SL_RESULT_SUCCESS == result);

  69.       // realize the player
  70.       result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE);
  71.       if (SL_RESULT_SUCCESS != result) {
  72.         (*uriPlayerObject)->Destroy(uriPlayerObject);
  73.         uriPlayerObject = NULL;
  74.         return false;
  75.       }

  76.       // get the play interface
  77.       result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
  78.       assert(SL_RESULT_SUCCESS == result);

  79.       // get the seek interface
  80.       result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek);
  81.       assert(SL_RESULT_SUCCESS == result);

  82.       // enable whole file looping
  83.       result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
  84.       assert(SL_RESULT_SUCCESS == result);

  85.       return true;
  86.     }

  87.     setPlayingUriAudioPlayer(bool played)
  88.     {
  89.       SLresult result;
  90.       if (uriPlayerPlay != NULL) {
  91.         result = (*uriPlayerPlay)->SetPlayState(uriPlayerPlay, played ?
  92.                             SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
  93.         assert(SL_RESULT_SUCCESS == result);
  94.       }
  95.     }


  96.     int main(int argc, char** argv)
  97.     {
  98.       // Create the OpenSL engine
  99.       createEngine();

  100.       // Create the audio player with everything ready.
  101.       createUriAudioPlayer(argv[1]);

  102.       printf("Playing...");
  103.       setPlayingUriAudioPlayer(true);      // play the music
  104.       sleep(20);

  105.       printf("Pause...");  
  106.       setPlayingUriAudioPlayer(false);    // pause the player
  107.       sleep(20);
  108.       
  109.       printf("Playing...");   
  110.       setPlayingUriAudioPlayer(true);
  111.       
  112.       sleep(1000);  // Just wait for the playing threads
  113.     }
复制代码
我目前遇到的问题是:
1.该代码采用的是sleep 方式,很二的等待结束....我寻找获取结束标志的方法全都失败了....
不知道用的朋友,有什么好办法 可以获得这个状态...  让他播完就结束.....
该程序的内部我不知道是怎么实现的,播放模块好像是用分离线程...  相关文档我也没找到,E文太烂 愁死我了.....

2.该代码采用输入路径的方式,播放音频...这种方式对于本地文件来说是可行的, 而我的音频文件是 4KB的网络传送来的PCM文件 ,我不知道如何将这个BUFFER传入给播放单元.......

如果各位谁有播放PCM格式的NDK C代码 欢迎贴上来啊,多谢多谢...
我知道论坛里,高手多,在这里谢谢各位了......

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
2 [报告]
发表于 2011-12-19 12:21 |只看该作者
我很难过....米有人用过NDK的么.......

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
3 [报告]
发表于 2011-12-20 14:05 |只看该作者
........

论坛徽章:
0
4 [报告]
发表于 2011-12-23 14:56 |只看该作者
我用NDK编程。他是有回调函数的,在回调函数里面处理。

论坛徽章:
0
5 [报告]
发表于 2011-12-23 15:04 |只看该作者
不过这组API要android2.3或者以上才有用。

论坛徽章:
2
技术图书徽章
日期:2015-12-16 09:12:1619周年集字徽章-庆
日期:2019-09-12 16:09:19
6 [报告]
发表于 2011-12-26 11:23 |只看该作者

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
7 [报告]
发表于 2011-12-27 11:42 |只看该作者
sunway9916 发表于 2011-12-23 14:56
我用NDK编程。他是有回调函数的,在回调函数里面处理。


能具体说一下么...

论坛徽章:
0
8 [报告]
发表于 2011-12-30 09:35 |只看该作者

您上述的問題
其實在code 106行只要加上

result = (*uriPlayerPlay)->RegisterCallback(uriPlayerPlay,playOverEvent,NULL);
result = (*uriPlayerPlay)->SetCallbackEventsMask(uriPlayerPlay, SL_PLAYEVENT_HEADATEND);

然後撰寫名字為playOverEvent的回呼函數(callback)
例如:
void playOverEvent(SLPlayItf caller,void *pContext,SLuint32 playevent) {
       if (playevent & SL_PLAYEVENT_HEADATEND) {
          ..................................您要做的事......................................
       }
}

還有把reference document 的phone profile ,game profile,musice profile
看懂對你幫助很大~少走很多彎路

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
9 [报告]
发表于 2011-12-30 13:59 |只看该作者
回复 8# TerranceHsieh


    回复 8# TerranceHsieh


    首先多谢您,帮我回答问题,我看了下 好像这个回调是负责播放结束的吧..... 我找到了文件结束的标志位state,所以循环的问题已经解决了.....

目前的问题就是 4KB的pcm buffer 传入播放函数的问题, 因为现在采用的播放方式都是 打开本地文件, 然后根据FD来读取内容,这与我期盼的传入buffer 直接播放
不符,但是我又不知道该如何解决.....很惆怅
   doc文档本来是想好好看一下,但是E文实在太烂了.... 磨的很费劲啊.....

再次感谢您的回答......

论坛徽章:
0
10 [报告]
发表于 2011-12-30 14:46 |只看该作者
本帖最后由 TerranceHsieh 于 2011-12-30 14:50 编辑

4KB?不懂~是指檔案大小還是說bitsPerSample
不過wav也是有許多格式~
一般opensles只能播放pcm 16bit / pcm 8bit 未壓縮過的格式
遇到4bit已壓縮的一定播不出來(adpcm imapcm ......)很多~
你有看到文件中關於android只支援的格式嗎
所以我有在加其他的 library 來解決這問題

傳入buffer是可以的我是採用這方式在播放音樂的
只是你想問什麼?

你沒把問提說出來~只說弄不出來
難道要我幫你寫

我以為你要問播放結束要做的動作才回答~誤會大了

而且我要跟你說喔~

如果是4kb大小的音訊
也要看立體聲還是1/2聲道還有要看samplerrte去控制播放速率等等
所以放進buffer裡的絕不是你看到的文件大小
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP