/*

*

*这里使用了transcode-1.1.7对wav文件进行解码。然后使用opensl es进行播放

*

*/


//用到的变量和结构体

WAV wav; //wav文件指针
SLObjectItf engineObject; //引擎对象
SLEngineItf engineInterface; //引擎接口
SLObjectItf outputMixObject; //混音器
SLObjectItf audioPlayerObject; //播放器对象
SLAndroidSimpleBufferQueueItf andioPlayerBufferQueueItf; //缓冲器队列接口
SLPlayItf audioPlayInterface; //播放接口 unsigned char *buffer; //缓冲区
size_t bufferSize; //缓冲区大小 //上下文
struct PlayerContext{
WAV wav;
unsigned char *buffer;
size_t bufferSize; PlayerContext(WAV wav,
unsigned char *buffer,
size_t bufferSize){
this->wav = wav;
this->buffer = buffer;
this->bufferSize = bufferSize;
}
};
//实现对象
void RealizeObject(SLObjectItf object){
//非异步(堵塞)
(*object)->Realize(object,SL_BOOLEAN_FALSE);
}

详细实现流程:

1.打开文件

WAV wav = OpenWaveFile(env,jFileName);
//打开文件
WAV OpenWaveFile(JNIEnv *env,jstring jFileName){
const char *cFileName = env->GetStringUTFChars(jFileName,JNI_FALSE);
WAVError err;
WAV wav = wav_open(cFileName,WAV_READ,&err); LOGI("%d",wav_get_bitrate(wav));
env->ReleaseStringUTFChars(jFileName,cFileName);
if(wav == 0){
LOGE("%s",wav_strerror(err));
}
return wav;
}

2.创建OpenSL ES引擎

//OpenSL ES在Android平台下默认是线程安全的,这样设置是为了为了兼容其它平台
SLEngineOption options[] = {
{(SLuint32)SL_ENGINEOPTION_THREADSAFE, (SLuint32)SL_BOOLEAN_TRUE}
};
slCreateEngine(&engineObject,ARRAY_LEN(engineObject),options,0,0,0); //没有接口 //实例化对象
//对象创建之后。处于未实例化状态,对象尽管存在但未分配不论什么资源,使用前先实例化(使用完之后destroy)
RealizeObject(engineObject);

3.获取引擎接口

(*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineInterface);

4.创建输出混音器

(*engineInterface)->CreateOutputMix(engineInterface,&outputMixObject,0,0,0); //没有接口
//实例化混音器
RealizeObject(outputMixObject);

5.创建缓冲区保存读取到的音频数据库

//缓冲区的大小
bufferSize = wav_get_channels(wav) * wav_get_rate(wav) * wav_get_bits(wav);
buffer = new unsigned char[bufferSize];

6.创建带有缓冲区队列的音频播放器

CreateBufferQueueAudioPlayer(wav,engineInterface,outputMixObject,audioPlayerObject);
//实例化音频播放器
RealizeObject(audioPlayerObject);

CreateBufferQueueAudioPlayer.cpp

extern "C" {
#include "wavlib.h"
}
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <android/log.h> #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
//创建音频播放对象
void CreateBufferQueueAudioPlayer(
WAV wav,
SLEngineItf engineEngine,
SLObjectItf outputMixObject,
SLObjectItf &audioPlayerObject){ // Android针对数据源的简单缓冲区队列定位器
SLDataLocator_AndroidSimpleBufferQueue dataSourceLocator = {
SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // 定位器类型
1 // 缓冲区数
}; // PCM数据源格式
SLDataFormat_PCM dataSourceFormat = {
SL_DATAFORMAT_PCM, // 格式类型
wav_get_channels(wav), // 通道数
wav_get_rate(wav) * 1000, // 毫赫兹/秒的样本数
wav_get_bits(wav), // 每一个样本的位数
wav_get_bits(wav), // 容器大小
SL_SPEAKER_FRONT_CENTER, // 通道屏蔽
SL_BYTEORDER_LITTLEENDIAN // 字节顺序
}; // 数据源是含有PCM格式的简单缓冲区队列
SLDataSource dataSource = {
&dataSourceLocator, // 数据定位器
&dataSourceFormat // 数据格式
}; // 针对数据接收器的输出混合定位器
SLDataLocator_OutputMix dataSinkLocator = {
SL_DATALOCATOR_OUTPUTMIX, // 定位器类型
outputMixObject // 输出混合
}; // 数据定位器是一个输出混合
SLDataSink dataSink = {
&dataSinkLocator, // 定位器
0 // 格式
}; // 须要的接口
SLInterfaceID interfaceIds[] = {
SL_IID_BUFFERQUEUE
}; // 须要的接口,假设所须要的接口不要用。请求将失败
SLboolean requiredInterfaces[] = {
SL_BOOLEAN_TRUE // for SL_IID_BUFFERQUEUE
}; // 创建音频播放器对象
SLresult result = (*engineEngine)->CreateAudioPlayer(
engineEngine,
&audioPlayerObject,
&dataSource,
&dataSink,
ARRAY_LEN(interfaceIds),
interfaceIds,
requiredInterfaces);
}

posted on
2017-08-07 11:22 
lxjshuju 
阅读(...) 
评论(...) 
编辑 
收藏

Android音视频学习第7章:使用OpenSL ES进行音频解码的更多相关文章

  1. Android 音视频深入 十四 FFmpeg与OpenSL ES 播放mp3音乐,能暂停(附源码下载)

    项目地址https://github.com/979451341/FFmpegOpenslES 这次说的是FFmpeg解码mp3,数据给OpenSL ES播放,并且能够暂停. 1.创建引擎 slCre ...

  2. 堪称教科书级别的Android音视频入门进阶学习手册,开源分享!

    概述 随着整个互联网的崛起,数据传递的形式也在不断升级变化,总的流行趋势如下: 纯文本的短信,QQ -> 空间,微博,朋友圈的图片文字结合 -> 微信语音 -> 各大直播软件 -&g ...

  3. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  4. Android 音视频深入 七 学习之路的总结和资料分享

    说个实话一开始我对基于Android如何开发音视频很迷茫,甚至对音视频开发都不是很明白,我看了Android 音视频开发入门指南 http://blog.51cto.com/ticktick/1956 ...

  5. android音视频点/直播模块开发

      音视频 版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能,那么作为开发一个小白, ...

  6. Android 音视频开发(一) : 通过三种方式绘制图片

    版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7456956.html 在 Android 音视频开发学习思路 里面,我们写到了,想要逐步入门音视频开发,就 ...

  7. Android 音视频开发(六): MediaCodec API 详解

    在学习了Android 音视频的基本的相关知识,并整理了相关的API之后,我们应该对基本的音视频有一定的轮廓了. 下面开始接触一个Android音视频中相当重要的一个API: MediaCodec.通 ...

  8. Android 音视频开发(七): 音视频录制流程总结

    在前面我们学习和使用了AudioRecord.AudioTrack.Camera.MediaExtractor.MediaMuxer API.MediaCodec. 学习和使用了上述的API之后,相信 ...

  9. Android音视频点/直播模块开发实践总结-zz

    随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能.那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及 ...

随机推荐

  1. 【转帖】Sigma水平和缺陷率的对应关系:正态分布中心和1.5标准差偏移

    http://www.pinzhi.org/thread-5395-1-1.html Sigma水平和缺陷率的对应关系:正态分布中心和有1.5个标准差偏移 在过程稳定时,若给出了规范限,过程的平均与标 ...

  2. 腾讯QQ的发展与未来

    http://wenku.baidu.com/view/15166ddfc1c708a1284a447d.html 腾讯QQ的发展与未来

  3. jquery tmpl 详解(转)

    动态请求数据来更新页面是现在非常常用的方法,比如博客评论的分页动态加载,微博的滚动加载和定时请求加载等. 这些情况下,动态请求返回的数据一般不是已拼好的 HTML 就是 JSON 或 XML,总之不在 ...

  4. Android 读取<meta-data>元素中的数据

    众所周知, 每个组件都有<meta-data>元素, 用于接收一些外部数据(eg: appKey), 那其中的值应该怎么读取呢. 1> Application <applica ...

  5. HTML5 拖拽的简单实践

    坑爹点记录: 1.一定要加入 event.preventDefault(); 不然无效. 2.想测试的话,随便找到一个layui的table演示页面,插入脚本即可.不过要先在全局插入jquery. v ...

  6. vue使用vue-resource,进行网络请求

    首先使用vue-resource,需要安装 : https://blog.csdn.net/qq_36947128/article/details/72832977 下面我写的一个例子: 网络请求应该 ...

  7. WebSocket 学习--用nodejs搭建服务器

    最简单的socket服务端 var net = require("net"); server1 = net.createServer(function(client){ clien ...

  8. Angularjs $http.post

    $http.post 采用postJSON方式发送数据到后台. 如果不需要发送json格式数据,序列化成&连接的字符串,形如:"a=1&b=2",最终完整的前端解决 ...

  9. vim如何选择ESC的键位绑定

    vim除了hijk之外,按键频率最高的大概是Esc,本人已经有点Esc强迫症的兆头了.默认的Esc键远在边陲,按起来也忒麻烦了.怎么解决? 在google大神的帮助下,找到了两个方案: CapsLoc ...

  10. Linux:命令执行控制&&与||

    1.&& 方式:command1 && command2 如果command1执行成功,则执行command2 2.|| 方式:command1 || command2 ...