一、Open SL ES播放声音流程

  简单说明

  Open SL ES是android内部的接口,本身可以解码音频,但是我们用FFmpeg,,也可以来录音 。

  SL引擎:上下文

  混音器:两路声音的混合

  Play:控制播放 ,  有一个队列来存储播放的数据,设置一个回调的方法,播放之后调一下回调方法拿数据,

二、函数说明

  1.初始化引擎
    SLresult re; //存放引擎本身,上下文
    SLEngineItf en; //存放引擎的接口
    slCreateEngine(&engineSL,0,0,0,0,0);//创建对象
    Realize(engineSL,SL_BOOLEAN_FALSE);//实例化(内部的数据分配内存) 都是这个模式,先创建,然后实例化,在获取接口
    GetInterface(engineSL,SL_IID_ENGINE,&en);//获取接口SLEngineItf ,通过第二个参数获取对应的接口
  2.输出设备
    SLObjectItf mix = NULL;
    SLresult re = 0;
    CreateOutputMix(eng,&mix,0,0,0);//创建输出设备
    Realize(mix,SL_BOOLEAN_FALSE);//实例化
    //下面两个是存储
    SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
    SLDataSink audioSink= {&outmix,0};
  3.配置音频信息
    SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,10}; //以什么样的方式交互
    //音频格式
    SLDataFormat_PCM pcm = {
        SL_DATAFORMAT_PCM,//支持PCM格式的数据
        2,// 声道数
        SL_SAMPLINGRATE_44_1,//44100Hz的频率(采样率)
        SL_PCMSAMPLEFORMAT_FIXED_16, //位数
        SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一支即可
        SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,//立体声(前作前右)
        SL_BYTEORDER_LITTLEENDIAN //字节序,小端还是大端,默认小端 (高位还是地位在前)
    };
    SLDataSource ds = {&que,&pcm};//包装成配置信息
  4.创建播放器
    SLObjectItf player = NULL;
    SLPlayItf iplayer = NULL;
    CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建
    Realize(player,SL_BOOLEAN_FALSE);//实例化
    GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口
    GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列
    (*pcmQue)->RegisterCallback(pcmQue,PcmCall,0);//设置回调函数,播放队列空调用
    (*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); //设置为播放状态play状态、暂停状态、
    (*pcmQue)->Enqueue(pcmQue,"",1); //启动队列回调 先压入一点数据

  

代码展示:

  1. #include <jni.h>
  2. #include <string>
  3. #include <SLES/OpenSLES.h>
  4. #include <SLES/OpenSLES_Android.h>
  5. #include <android/log.h>
  6. #define LOGD(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"ywl5320",FORMAT,##__VA_ARGS__);
  7.  
  8. //1 创建引擎
  9. static SLObjectItf engineSL = NULL;
  10. SLEngineItf CreateSL()
  11. {
  12. SLresult re;
  13. SLEngineItf en;
  14. re = slCreateEngine(&engineSL,,,,,);
  15. if(re != SL_RESULT_SUCCESS) return NULL;
  16. re = (*engineSL)->Realize(engineSL,SL_BOOLEAN_FALSE);
  17. if(re != SL_RESULT_SUCCESS) return NULL;
  18. re = (*engineSL)->GetInterface(engineSL,SL_IID_ENGINE,&en);
  19. if(re != SL_RESULT_SUCCESS) return NULL;
  20. return en;
  21. }
  22.  
  23. void PcmCall(SLAndroidSimpleBufferQueueItf bf,void *contex)
  24. {
  25. LOGD("PcmCall");
  26. static FILE *fp = NULL;
  27. static char *buf = NULL;
  28. if(!buf)
  29. {
  30. buf = new char[*];
  31. }
  32. if(!fp)
  33. {
  34. fp = fopen("/sdcard/test.pcm","rb");
  35. }
  36. if(!fp)return;
  37. if(feof(fp) == )
  38. {
  39. int len = fread(buf,,,fp);
  40. if(len > )
  41. (*bf)->Enqueue(bf,buf,len);
  42. }
  43.  
  44. }
  45.  
  46. extern "C"
  47. JNIEXPORT jstring
  48.  
  49. JNICALL
  50. Java_aplay_testopensl_MainActivity_stringFromJNI(
  51. JNIEnv *env,
  52. jobject /* this */) {
  53. std::string hello = "Hello from C++";
  54.  
  55. //1 创建引擎
  56. SLEngineItf eng = CreateSL();
  57. if(eng){
  58. LOGD("CreateSL success! ");
  59. }else{
  60. LOGD("CreateSL failed! ");
  61. }
  62.  
  63. //2 创建混音器
  64. SLObjectItf mix = NULL;
  65. SLresult re = ;
  66. re = (*eng)->CreateOutputMix(eng,&mix,,,);
  67. if(re !=SL_RESULT_SUCCESS )
  68. {
  69. LOGD("SL_RESULT_SUCCESS failed!");
  70. }
  71. re = (*mix)->Realize(mix,SL_BOOLEAN_FALSE);
  72. if(re !=SL_RESULT_SUCCESS )
  73. {
  74. LOGD("(*mix)->Realize failed!");
  75. }
  76. SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
  77. SLDataSink audioSink= {&outmix,};
  78.  
  79. //3 配置音频信息
  80. //缓冲队列
  81. SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,}; //以什么样的方式交互
  82. //音频格式
  83. SLDataFormat_PCM pcm = {
  84. SL_DATAFORMAT_PCM,//支持PCM格式的数据
  85. ,// 声道数
  86. SL_SAMPLINGRATE_44_1,//44100Hz的频率(采样率)
  87. SL_PCMSAMPLEFORMAT_FIXED_16, //位数
  88. SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一支即可
  89. SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,//立体声(前作前右)
  90. SL_BYTEORDER_LITTLEENDIAN //字节序,小端还是大端,默认小端 (高位还是地位在前)
  91. };
  92. SLDataSource ds = {&que,&pcm};//包装成配置信息
  93.  
  94. //4 创建播放器
  95. SLObjectItf player = NULL;
  96. SLPlayItf iplayer = NULL;
  97. SLAndroidSimpleBufferQueueItf pcmQue = NULL;
  98. const SLInterfaceID ids[] = {SL_IID_BUFFERQUEUE};
  99. const SLboolean req[] = {SL_BOOLEAN_TRUE};
  100. re = (*eng)->CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建
  101. if(re !=SL_RESULT_SUCCESS )
  102. {
  103. LOGD("CreateAudioPlayer failed!");
  104. } else{
  105. LOGD("CreateAudioPlayer success!");
  106. }
  107. (*player)->Realize(player,SL_BOOLEAN_FALSE);//实例化
  108. //获取player接口
  109. re = (*player)->GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口
  110. if(re !=SL_RESULT_SUCCESS )
  111. {
  112. LOGD("GetInterface SL_IID_PLAY failed!");
  113. }
  114. re = (*player)->GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列
  115. if(re !=SL_RESULT_SUCCESS )
  116. {
  117. LOGD("GetInterface SL_IID_BUFFERQUEUE failed!");
  118. }
  119.  
  120. //设置回调函数,播放队列空调用
  121. (*pcmQue)->RegisterCallback(pcmQue,PcmCall,);//断音,很快的一个操作
  122.  
  123. //设置为播放状态
  124. (*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); // play状态、暂停状态、
  125.  
  126. //启动队列回调
  127. (*pcmQue)->Enqueue(pcmQue,"",); // 先压入一点数据
  128.  
  129. return env->NewStringUTF(hello.c_str());
  130. }
  131. /**
  132.  
  133. 1.初始化引擎
  134. SLresult re; //存放引擎本身,上下文
  135. SLEngineItf en; //存放引擎的接口
  136. slCreateEngine(&engineSL,0,0,0,0,0);//创建对象
  137. Realize(engineSL,SL_BOOLEAN_FALSE);//实例化(内部的数据分配内存) 都是这个模式,先创建,然后实例化,在获取接口
  138. GetInterface(engineSL,SL_IID_ENGINE,&en);//获取接口SLEngineItf ,通过第二个参数获取对应的接口
  139. 2.输出设备
  140. SLObjectItf mix = NULL;
  141. SLresult re = 0;
  142. CreateOutputMix(eng,&mix,0,0,0);//创建输出设备
  143. Realize(mix,SL_BOOLEAN_FALSE);//实例化
  144. //下面两个是存储
  145. SLDataLocator_OutputMix outmix = {SL_DATALOCATOR_OUTPUTMIX,mix};
  146. SLDataSink audioSink= {&outmix,0};
  147. 3.配置音频信息
  148. SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,10}; //以什么样的方式交互
  149. //音频格式
  150. SLDataFormat_PCM pcm = {
  151. SL_DATAFORMAT_PCM,//支持PCM格式的数据
  152. 2,// 声道数
  153. SL_SAMPLINGRATE_44_1,//44100Hz的频率(采样率)
  154. SL_PCMSAMPLEFORMAT_FIXED_16, //位数
  155. SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一支即可
  156. SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,//立体声(前作前右)
  157. SL_BYTEORDER_LITTLEENDIAN //字节序,小端还是大端,默认小端 (高位还是地位在前)
  158. };
  159. SLDataSource ds = {&que,&pcm};//包装成配置信息
  160. 4.创建播放器
  161. SLObjectItf player = NULL;
  162. SLPlayItf iplayer = NULL;
  163. CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建
  164. Realize(player,SL_BOOLEAN_FALSE);//实例化
  165. GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口
  166. GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列
  167. (*pcmQue)->RegisterCallback(pcmQue,PcmCall,0);//设置回调函数,播放队列空调用
  168. (*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); //设置为播放状态play状态、暂停状态、
  169. (*pcmQue)->Enqueue(pcmQue,"",1); //启动队列回调 先压入一点数据
  170.  
  171. */

FFmpeg(七)音频的播放的更多相关文章

  1. FFmpeg学习3:播放音频

    参考dranger tutorial,本文将介绍如何使用FFmpeg解码音频数据,并使用SDL将解码后的数据输出. 本文主要包含以下几方面的内容: 关于播放音频的需要的一些基础知识介绍 使用SDL2播 ...

  2. FFMPEG + SDL音频播放分析

    目录 [hide] 1 抽象流程: 2 关键实现: 2.1 main()函数 2.2 decode_thread()读取文件信息和音频包 2.3 stream_component_open():设置音 ...

  3. FFmpeg 入门(3):播放音频

    本文转自:FFmpeg 入门(3):播放音频 | www.samirchen.com 音频 SDL 提供了播放音频的方法.SDL_OpenAudio 函数用来让设备播放音频,它需要我们传入一个包含了所 ...

  4. [转]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  5. [总结]FFMPEG视音频编解码零基础学习方法--转

    ffmpeg编解码学习   目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ...

  6. FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  7. FFMPEG视音频编解码零基础学习方法-b

    感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...

  8. [总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  9. 【转】[总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  10. 浏览器音频兼容和ffmpeg的音频转码使用

    浏览器对各音/视频格式的支持问题 浏览器测试效果图 ffmpeg在音频格式转换,和从视频中提取音频的简单实用 1.百度搜索浏览器对于音频文件的兼容,排在前面的文章大部分是复制粘贴很久以前的文章,容易误 ...

随机推荐

  1. hdu6437 Problem L.Videos(网络流)

    Problem L.Videos Problem Description: C-bacteria takes charge of two kinds of videos: ’The Collectio ...

  2. 洛谷p2015二叉苹果树&yzoj1856多叉苹果树题解

    二叉 多叉 有一棵苹果树,如果树枝有分叉,可以是分多叉,分叉数k>=0(就是说儿子的结点数大于等于0)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1~N,树根编号一定是1.我们用一根树枝两 ...

  3. Springboot源码分析之Spring循环依赖揭秘

    摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...

  4. SVN更新失败

    一.svn更新失败 使用svn遇到的问题是,更新失败,代码被锁定. 解决办法: 在项目上右键,如图所示: 图一: ​ 图二: ​ 之后再更新,基本上都没有问题了.如果还有问题,看下面. 二.工具清理 ...

  5. html5表单与Jquery Ajax配合使用

    html5的表单控件提供了很多格式检测功能,可以省去很多烦人的javascript验证代码,例如pattern属性和require属性,但触发的条件是表单提交,如果想通过ajax提交表单,就出现了不能 ...

  6. Winform中设置ZedGraph曲线图的字体样式是避免出现边框

    场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  7. Hive bucket表

    Hive 桶 对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分.Hive也是 针对某一列进行桶的组织.Hive采用对列值哈希,然后除以桶的个数求余 ...

  8. 关于spring boot多张表建立外健的讨论

    现在有四张表:student(学生表).blogs(博客表).comment(评论表).reply(回复表) 现在说一下这四张表: student(学生表):学生的信息记录表 blogs(博客表):学 ...

  9. Stanford公开课《编译原理》学习笔记(1~4课)

    目录 一. 编译的基本流程 二. Lexical Analysis(词法分析阶段) 2.1 Lexical Specification(分词原则) 2.2 Finite Automata (典型分词算 ...

  10. Python连载39-生成器、next函数、yield返回值

    ​一.生成器 1.定义(generator):一边循环一边计算下一个元素的机制/算法 2.满三个条件 (1)每次调用都能产生出for循环需要的下一个元素 (2)如果达到最后一个后,能够爆出StopIt ...