博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FFmpeg(七)音频的播放
阅读量:6236 次
发布时间:2019-06-22

本文共 7166 字,大约阅读时间需要 23 分钟。

一、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); //启动队列回调 先压入一点数据

  

代码展示:

#include 
#include
#include
#include
#include
#define LOGD(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"ywl5320",FORMAT,##__VA_ARGS__);//1 创建引擎static SLObjectItf engineSL = NULL;SLEngineItf CreateSL(){ SLresult re; SLEngineItf en; re = slCreateEngine(&engineSL,0,0,0,0,0); if(re != SL_RESULT_SUCCESS) return NULL; re = (*engineSL)->Realize(engineSL,SL_BOOLEAN_FALSE); if(re != SL_RESULT_SUCCESS) return NULL; re = (*engineSL)->GetInterface(engineSL,SL_IID_ENGINE,&en); if(re != SL_RESULT_SUCCESS) return NULL; return en;}void PcmCall(SLAndroidSimpleBufferQueueItf bf,void *contex){ LOGD("PcmCall"); static FILE *fp = NULL; static char *buf = NULL; if(!buf) { buf = new char[1024*1024]; } if(!fp) { fp = fopen("/sdcard/test.pcm","rb"); } if(!fp)return; if(feof(fp) == 0) { int len = fread(buf,1,1024,fp); if(len > 0) (*bf)->Enqueue(bf,buf,len); }}extern "C"JNIEXPORT jstringJNICALLJava_aplay_testopensl_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; //1 创建引擎 SLEngineItf eng = CreateSL(); if(eng){ LOGD("CreateSL success! "); }else{ LOGD("CreateSL failed! "); } //2 创建混音器 SLObjectItf mix = NULL; SLresult re = 0; re = (*eng)->CreateOutputMix(eng,&mix,0,0,0); if(re !=SL_RESULT_SUCCESS ) { LOGD("SL_RESULT_SUCCESS failed!"); } re = (*mix)->Realize(mix,SL_BOOLEAN_FALSE); if(re !=SL_RESULT_SUCCESS ) { LOGD("(*mix)->Realize failed!"); } 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; SLAndroidSimpleBufferQueueItf pcmQue = NULL; const SLInterfaceID ids[] = {SL_IID_BUFFERQUEUE}; const SLboolean req[] = {SL_BOOLEAN_TRUE}; re = (*eng)->CreateAudioPlayer(eng,&player,&ds,&audioSink,sizeof(ids)/sizeof(SLInterfaceID),ids,req);//利用前面的配置来创建 if(re !=SL_RESULT_SUCCESS ) { LOGD("CreateAudioPlayer failed!"); } else{ LOGD("CreateAudioPlayer success!"); } (*player)->Realize(player,SL_BOOLEAN_FALSE);//实例化 //获取player接口 re = (*player)->GetInterface(player,SL_IID_PLAY,&iplayer); // 获取接口 if(re !=SL_RESULT_SUCCESS ) { LOGD("GetInterface SL_IID_PLAY failed!"); } re = (*player)->GetInterface(player,SL_IID_BUFFERQUEUE,&pcmQue);//缓冲队列 if(re !=SL_RESULT_SUCCESS ) { LOGD("GetInterface SL_IID_BUFFERQUEUE failed!"); } //设置回调函数,播放队列空调用 (*pcmQue)->RegisterCallback(pcmQue,PcmCall,0);//断音,很快的一个操作 //设置为播放状态 (*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); // play状态、暂停状态、 //启动队列回调 (*pcmQue)->Enqueue(pcmQue,"",1); // 先压入一点数据 return env->NewStringUTF(hello.c_str());}/** 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); //启动队列回调 先压入一点数据 */
View Code

 

转载于:https://www.cnblogs.com/ZeGod/p/10010475.html

你可能感兴趣的文章
自定义UISlider
查看>>
构建方法
查看>>
“.NET研究”构建高性能ASP.NET站点之优化HTTP请求
查看>>
攻击法国海军病毒Conficker在中国网络同步蔓延
查看>>
软件测试——Junit的使用
查看>>
py10-函数-可变长参数
查看>>
Java并发编程:synchronized
查看>>
广告数据线性回归分析
查看>>
初识hadoop
查看>>
SQL优化技巧--远程连接对象引起的CTE性能问题
查看>>
【转】 利用.dSYM和.app文件准确定位Crash位置
查看>>
python中type dtype astype 的用法
查看>>
centos6.8/6.9 升级openssh的升级openssh-7.5p1.tar.gz
查看>>
使用ngnix做服务器的负载均衡
查看>>
盒子传值
查看>>
使用NSStream来实现Socket
查看>>
iPhone开发之调用系统提示音教程
查看>>
OAuth认证协议原理分析及使用方法
查看>>
二叉树
查看>>
linux 文件搜索命令
查看>>