目录

  1. Android 万能音频播放器 一 C++多线程解码音频数据
  2. Android 万能音频播放器 二 C++队列存放AvPacket
  3. OpenSL介绍 并实现播放PCM功能

    前言

    简单来说OpenSL ES是一个嵌入式、跨平台、免费的、音频 处理库,本文旨在介绍OpenSL的使用方法和参数设置,绝大部分内容参考Android官方NDKdemo,地址为android NDK demo,想学NDK开发的伙伴可以去参考一下,受益良多。

    使用流程

    1、创建接口对象
    2、设置混音器
    3、创建播放器(录音器)
    4、设置缓冲队列和回调函数
    5、设置播放状态
    6、启动回调函数

    接口说明

    1、类接口:SLObjectItf
    通过SLObjectItf接口类我们可以创建所需要的各种类型的类接口,比如:
    创建引擎接口对象:SLObjectItf engineObject
    创建混音器接口对象:SLObjectItf outputMixObject
    创建播放器接口对象:SLObjectItf playerObject
    2、具体的接口类
    引擎:SLEngineItf
    播放器:SLPlayItf
    声音控制器:SLVolumeItf等等

    创建三部曲
    如:创建引擎接口对象( createrealizeget )

SLObjectItf engineObject = NULL;//用SLObjectItf声明引擎接口对象
SLEngineItf engineEngine = NULL;//声明具体的引擎对象实例
void createEngine()
{  SLresult result;//返回结果  //第一步:创建引擎 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);//第二步:实现(Realize)engineObject接口对象result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); //第三部:通过engineObject的GetInterface方法初始化engineEngine result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);

代码实现

#include <jni.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "androidLog.h"
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>//引擎对象
SLObjectItf enginObject = NULL;
//引擎接口
SLEngineItf engineItf = NULL;//混音器对象(混音器作用是做声音处理)
SLObjectItf outputmixObject = NULL;
//混音器环境接口
SLEnvironmentalReverbItf outputEnvironmentalReverbItf = NULL;
const SLEnvironmentalReverbSettings reverbSettings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;//播放器对象
SLObjectItf pcmPlayerObject = NULL;
//播放接口
SLPlayItf playItf = NULL;
//播放队列
SLAndroidSimpleBufferQueueItf simpleBufferQueueItf = NULL;FILE *pcmFile = NULL;
uint8_t *outbuffer;
void* buffer;//从pcm文件中读取数据
int getPCMbuffer(void** pcm){//读取到的字节数int size = 0;while (!feof(pcmFile)){size = fread(outbuffer,1,44100 * 2 * 2 / 2,pcmFile);if (outbuffer==NULL){LOGI("pcm文件读取完毕");break;} else{LOGI("pcm文件读取中");}*pcm = outbuffer;break;}return size;
}void pcmBufferCallBack(SLAndroidSimpleBufferQueueItf simpleBufferQueueItf1,void* data){int size = getPCMbuffer(&buffer);LOGI("pcm读取大小为:%d",size);if (buffer!=NULL){LOGI("放入播放队列");//放入播放队列(*simpleBufferQueueItf1)->Enqueue(simpleBufferQueueItf1,buffer,size);}
}extern "C"
JNIEXPORT void JNICALL
Java_com_zhongcheng_opensl_MainActivity_playPCM(JNIEnv *env, jobject instance, jstring url_) {const char *url = env->GetStringUTFChars(url_, 0);SLresult result;pcmFile = fopen(url,"r");if (pcmFile==NULL){LOGI("文件不存在");return;}LOGI("文件存在");outbuffer = (uint8_t *) malloc(44100 * 2 * 2 / 2);//初始化引擎对象并由对象得到接口slCreateEngine(&enginObject, 0, 0, 0, 0, 0);(*enginObject)->Realize(enginObject, SL_BOOLEAN_FALSE);result = (*enginObject)->GetInterface(enginObject, SL_IID_ENGINE, &engineItf);if (SL_RESULT_SUCCESS!=result){LOGI("引擎接口创建失败!");return;}//需要做的声音处理功能数组const SLInterfaceID mid[1] = {SL_IID_ENVIRONMENTALREVERB};const SLboolean mird[1] = {SL_BOOLEAN_FALSE};result = (*engineItf)->CreateOutputMix(engineItf, &outputmixObject,1,mid,mird);if (SL_RESULT_SUCCESS!=result){LOGI("混音器对象创建失败!");return;}//得到上面声明的处理功能的接口(*outputmixObject)->Realize(outputmixObject,SL_BOOLEAN_FALSE);result = (*outputmixObject)->GetInterface(outputmixObject,SL_IID_ENVIRONMENTALREVERB,&outputEnvironmentalReverbItf);if (SL_RESULT_SUCCESS!=result){LOGI("混音器接口创建失败!");return;}//混音器环境属性设置result = (*outputEnvironmentalReverbItf)->SetEnvironmentalReverbProperties(outputEnvironmentalReverbItf,&reverbSettings);if (SL_RESULT_SUCCESS!=result){LOGI("混音器参数设置失败!");}//播放队列SLDataLocator_AndroidBufferQueue android_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, //格式2,//声道数SL_SAMPLINGRATE_44_1,//采样率SL_PCMSAMPLEFORMAT_FIXED_16,//采样位数 一定要与播放的pcm的一样 要不然可能快也可能会慢SL_PCMSAMPLEFORMAT_FIXED_16,SL_SPEAKER_FRONT_RIGHT|SL_SPEAKER_FRONT_LEFT,//声道布局 前右|前左SL_BYTEORDER_LITTLEENDIAN};//播放源SLDataSource dataSource = {&android_queue,&format_pcm};//混音器SLDataLocator_OutputMix outputMix = {SL_DATALOCATOR_OUTPUTMIX,outputmixObject};//关联混音器SLDataSink audiosnk = {&outputMix,NULL};//要实现的功能const SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};//队列播放const SLboolean irds[1] = {SL_BOOLEAN_FALSE};(*engineItf)->CreateAudioPlayer(engineItf,&pcmPlayerObject,&dataSource,&audiosnk,1,ids,irds);(*pcmPlayerObject)->Realize(pcmPlayerObject,SL_BOOLEAN_FALSE);//创建播放接口result = (*pcmPlayerObject)->GetInterface(pcmPlayerObject,SL_IID_PLAY,&playItf);if (SL_RESULT_SUCCESS!=result){LOGI("播放器接口创建失败!");return;}//得到Androidbufferqueue接口(*pcmPlayerObject)->GetInterface(pcmPlayerObject,SL_IID_BUFFERQUEUE,&simpleBufferQueueItf);//注册回掉函数(*simpleBufferQueueItf)->RegisterCallback(simpleBufferQueueItf,pcmBufferCallBack,NULL);//设置播放状态(*playItf)->SetPlayState(playItf,SL_PLAYSTATE_PLAYING);//第一次手动调用回掉函数 开始播放pcmBufferCallBack(simpleBufferQueueItf,NULL);env->ReleaseStringUTFChars(url_, url);
}

Android OpenSL介绍 并实现播放PCM功能相关推荐

  1. Android编程中利用AudioTrack播放PCM数据在音频的最后出现重复回声现象的解决方案

    1 问题描述 今天在进行Android编程时遇到一个很奇怪的问题  重点说一下 这里我的测试机用的是"小米Note"  的确不怎么样 我在"华为P8"上面测试就 ...

  2. 2. android 直接使用hal库播放pcm demo

    目录 一:概述 二:实现 环境 原理说明: 注意问题: 上源代码: 编译执行: 一:概述 这是一个c语言demo程序,android源码环境,编译得到 bin文件,push到设备上在shell环境运行 ...

  3. Android直播开发之旅(13):使用FFmpeg+OpenSL ES播放PCM音频

    文章目录 1. OpenSL ES原理 1.1 OpenSL ES核心API讲解 1.1.1 对象(Object)与接口(Interface) 1.1.2 [OpenSL ES的状态机制](https ...

  4. Android音乐播放器-- 功能介绍

    目前,市面上的播放器功能越来越强大,相对的,操作也越来越复杂,所以就萌发了做一个操作简单的音乐播放器的想法,目前实现的功能包括如下几点 : 1.  音乐列表 2.  专辑分类列表 3.  歌手分类列表 ...

  5. FFmpeg从入门到入魔(4):OpenSL ES播放PCM音频

    1. OpenSL ES原理  OpenSL ES(Open Sound Library for Embedded Systems),即嵌入式音频加速标准,是一个无授权费.跨平台.针对嵌入式系统精心优 ...

  6. 【Android 高性能音频】Oboe 播放器开发 ( 为 OpenSL ES 配置参数以获得最佳延迟 | Oboe 音频流 | Oboe 音频设备 )

    文章目录 一.获得最佳延迟 二.Oboe 音频流 三.Oboe 音频设备 Oboe GitHub 主页 : GitHub/Oboe ① 简单使用 : Getting Started ② Oboe 全指 ...

  7. Android音视频【十二】使用opensles和audiotrack进行播放pcm

    人间观察 年龄到了,有些事就妥协了,这个世界上没有人可以随心所欲,生活会逼着你选择答案--最困难的是你什么都改变不了-- 介绍 播放pcm的两种方式 本节我们学习下如何播放pcm数据,在Android ...

  8. Android OpenSL ES 开发:Android OpenSL 录制 PCM 音频数据

    一.实现说明 OpenSL ES的录音要比播放简单一些,在创建好引擎后,再创建好录音接口基本就可以录音了.在这里我们做的是流式录音,所以需要用至少2个buffer来缓存录制好的PCM数据,这里我们可以 ...

  9. Android开发之PCM录音实时播放的实现方法 | 边录音边播放 |PCM录音播放无延迟 | 录音无杂音 | 录音无噪音

    先说下录音得开启录音权限 <uses-permission android:name="android.permission.RECORD_AUDIO" /> 然后录音 ...

最新文章

  1. Element UI级联选择器(Cascader)获取级联对象
  2. 转载:python3 安装pycrypto
  3. 工具_好(zhuang)用(bi)的chrome插件
  4. python123第七章_Python入门第7/10页
  5. Fastjson批量检查及一键利用工具
  6. linux一键安装node+npm
  7. 《JavaScript权威指南》——JavaScript核心
  8. 项目展示-新浪微博客户端
  9. Spring依赖注入DI
  10. 英文课程名称 c语言程序设计,课程名称C语言程序设计I.doc
  11. ffmpeg学习之路·番外篇之音视频分析常用软件介绍与分享
  12. Hash冲突的四种解决办法
  13. 已知圆上三点坐标求圆心
  14. CTE6备考与考试感悟
  15. 基于 SpringBoot 和 webSocket 的匿名聊天室
  16. 动态规划Dynamic programming笔记自用
  17. 中国运营商考虑用WiFi亭代替公共电话亭
  18. GitHub 官方代码扫描工具上线!
  19. 物联网服务商店 - Nebula浅谈
  20. 【Python】python 程序示例

热门文章

  1. 【ceph】CEPH 单活MDS主从切换流程|REPLAY
  2. android分屏后布局变化问题,Android分屏多窗口实践
  3. ajax 滚动加载 缓存,Ajax实现加载缓存的loding效果
  4. 捕获Chrome浏览器全屏退出事件
  5. matlab rho是什么意思,什么是Rho值
  6. 新版白话空间统计(25):方向分布(标准差椭圆)
  7. 定制婚礼小程序开发功能
  8. [学习笔记]导数与定积分简单入门
  9. java do po dto_彻底搞懂DAO,PO,BO,DTO,VO,DO
  10. java组合算法应用:购物满减(任意数字组合相加在某个范围内)