一、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. Codeforces 939 D Love Rescue

    Love Rescue 题意:Valya 和 Tolya 是一对情侣, 他们的T恤和头巾上都有小写字母,但是女朋友嫌弃男朋友上T恤上的字不和她的头巾上的字一样,就很生气, 然后来了一个魔法师, 它可以 ...

  2. codeforces 814 D. An overnight dance in discotheque (贪心+bfs)

    题目链接:http://codeforces.com/contest/814/problem/D 题意:给出奇数个舞者,每个舞者都有中心坐标和行动半径,而且这些点组成的园要么相互包含要么没有交集求,讲 ...

  3. 《2019面向对象程序设计(java)课程学习进度条》

    学习资源 1.教材P28-P76 2.第3章教学课件3.1-3.8 3.corejava.zip中第3章示例程序3-1—3-5 4.Eclipse简明教程.pdf 5.MOOC & 视频:浙江 ...

  4. Maven生成项目站点

    概述 Maven不仅仅是一个自动化构建工具和一个依赖工具,还能够帮助聚合项目信息.POM可以包含各种项目信息.如项目描述.版本控制系统地址.缺陷跟踪系统地址.许可证信息.开发者信息等. 另Maven社 ...

  5. 为什么有的编程规范要求用 void 0 代替 undefined

    Undefined Undefined 类型表示未定义,它的类型只有一个值,就是 undefined. 任何变量在被赋值前它的值都是 undefined,但是在 JavaScript 引擎中,unde ...

  6. kafka入门配置

    问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行“随机读写”的原因是什么? 3.kafka集群consumer和producer状态信息是如何保存的? ...

  7. ios 各个手机型号尺寸及分辨率适配

    常用宏 // 判断是否是ipad #define isPad ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdio ...

  8. Linux环境下进行分布式压测踩过的坑

    背景:公司为了满足大并发的情况,需要测试组配合,就需要分布式压测,这里我把我踩过坑都记录下来: 环境:Linux + jmeter-v.5.1.1;使用3台2核4G的压力机: Q1: Server f ...

  9. asp.net配置全局应用程序类 巧妙达到定时生成静态页面

    //在项目里添加一个"全局应用程序类(Global Application Class)",在里面写这样的代码: public class Global : System.Web. ...

  10. 30 道 Vue 面试题

    前言 本文以前端面试官的角度出发,对 Vue 框架中一些重要的特性.框架的原理以问题的形式进行整理汇总,意在帮助作者及读者自测下 Vue 掌握的程度. 本文章节结构以从易到难进行组织,建议读者按章节顺 ...