一、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 <jni.h>
#include <string>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <android/log.h>
#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,,,,,);
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[*];
}
if(!fp)
{
fp = fopen("/sdcard/test.pcm","rb");
}
if(!fp)return;
if(feof(fp) == )
{
int len = fread(buf,,,fp);
if(len > )
(*bf)->Enqueue(bf,buf,len);
} } extern "C"
JNIEXPORT jstring JNICALL
Java_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 = ;
re = (*eng)->CreateOutputMix(eng,&mix,,,);
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,}; //3 配置音频信息
//缓冲队列
SLDataLocator_AndroidSimpleBufferQueue que = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,}; //以什么样的方式交互
//音频格式
SLDataFormat_PCM pcm = {
SL_DATAFORMAT_PCM,//支持PCM格式的数据
,// 声道数
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,);//断音,很快的一个操作 //设置为播放状态
(*iplayer)->SetPlayState(iplayer,SL_PLAYSTATE_PLAYING); // play状态、暂停状态、 //启动队列回调
(*pcmQue)->Enqueue(pcmQue,"",); // 先压入一点数据 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); //启动队列回调 先压入一点数据 */

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. 2019 Multi-University Training Contest 3

    B.Blow up the city solved by F0_0H 210min 题意 给一个DAG,每次询问给定u,v,求使得u或v不能与中心点联通的关键点个数 做法 按照拓扑序建树 新加节点的父 ...

  2. CodeForces 464 B Restore Cube

    Restore Cube 题解: x->yyy 其实就是把x代替成yyy这个值. 如果不好理解的话, 可以试想一下, 刚开始的话 0->0, 1->1, 2->2,...,9- ...

  3. Oracle sqlldr 在DOS窗口导入多列数据到数据库表

    sqlldr 用法详见:https://www.cnblogs.com/rootq/archive/2009/03/01/1401061.html 测试内容: 1.创建数据库表: create tab ...

  4. c语言实现名值对通过key查找value

    需求.例如: 1." key1 = value1 " 通过"key1"从该字符串中查找出"value",value去除前后空格 2.&quo ...

  5. hadoop历史服务的启动与停止

    a.配置项(在分布式环境中配置) 1.RPC访问地址 mapreduce.jobhistory.address 2.HTTP访问地址 mapreduce.jobhistory.webapp.addre ...

  6. Go从入门到放弃

    Go语言介绍 为什么你应该学习Go语言? 开发环境准备 从零开始搭建Go语言开发环境 VS Code配置Go语言开发环境 Go语言基础 Go语言基础之变量和常量 Go语言基础之基本数据类型 Go语言基 ...

  7. 024 实例5-身体质量指数BMI

    目录 一."身体质量指数BMI"问题分析 1.1 身体质量指数BMI 1.2 问题需求 二."身体质量指数BMI"实例讲解 2.1 身体质量指标BMI 2.1. ...

  8. vue-cli3.0 Typescript 项目集成环信WebIM 群组聊天

    项目背景 环信webim 官方没有vue版本的,自己就根据sdk重写了个vue版本的,只实现了基础的 登录 群组功能,其他的可以根据需要参考官方文档,添加相应的功能. 环信webim SDK相关文档: ...

  9. 各种浏览器UA值

    UA  User-Agent:用户代理,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器引擎.浏览器语言.浏览器插件等. 标准格式为: 浏览器标识 ...

  10. Elastic Stack 笔记(八)Elasticsearch5.6 Java API

    博客地址:http://www.moonxy.com 一.前言 Elasticsearch 底层依赖于 Lucene 库,而 Lucene 库完全是 Java 编写的,前面的文章都是发送的 RESTf ...