一、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. Codefroces 920F SUM and REPLACE(线段树)

    SUM and REPLACE 题意:给你n个数,进行m次操作,分别是将区间[l,r]内的所有数替换成自己的因子数 和 对区间[l,r]进行求和. 题解:可以发现2的因子个数还是2,1的因子个数还是1 ...

  2. Atcoder C - Nuske vs Phantom Thnook(递推+思维)

    题目链接:http://agc015.contest.atcoder.jp/tasks/agc015_c 题意:给一个n*m的格,蓝色的组成路径保证不成环,q个询问,计算指定矩形区域内蓝色连通块的个数 ...

  3. 洛谷 P1666 前缀单词 题解

    题意:给n个单词,如果单词a为单词b的前缀则a,b不能共存,问能共存的集合数(包括空集) 一道dp题,排序后判断,f[i][j]表示i和j是否能共存,f[i][j]=1表示能共存,初始化dp[i]=1 ...

  4. bzoj5072 小A的树 题解

    题意 给出一棵 n 个点的树,每个点有黑白两种颜色.q 次询问,每次 询问给出 x 和 y,问能否选出一个 x 个点的联通子图,使得其中 黑点数目为 y. 范围 n ≤ 5000,q ≤ 10^5 其 ...

  5. 第四篇 跟踪过程以及openvslam中的相关实现详解

    在成功初始化之后,会创建地图以及局部地图. 创建地图 在初始化正常过后,紧接着会创建地图 // src/openvslam/module/initializer.cc:67 // create new ...

  6. c语言实现去除字符串首尾空格

    字符串内存图如下: 引入头文件: 1 #include<stdlib.h> 2 #include<stdio.h> 3 #include<string.h> 函数原 ...

  7. redis.windows.conf配置详解

    redis.windows.conf配置详解 转自:https://www.cnblogs.com/kreo/p/4423362.html # redis 配置文件示例 # 当你需要为某个配置项指定内 ...

  8. Python(Head First)学习笔记:一

    目录: 1 认识Python:Python的特点.安装.开发环境搭建 2 共享代码:连接共享社区.语法.函数.技巧 3 文件与异常:调试.处理错误.迭代.改进.完善 4 持久存储:文件存储.读写 5 ...

  9. SqlServer2014怎样还原数据库

    场景 在SqlServer2014企业版上怎样进行数据库的还原,首先你得有一个其他数据 的备份文件. 实现 打开cmd,输入sql,打开SqlServer 2014 Management Studio ...

  10. Java 教程 (Java 对象和类)

    Java 对象和类 Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 本节我们重点研究对象和类的概念. 对象:对象是类的一个实例(对象不是找个女朋友 ...