Android OpenSL介绍 并实现播放PCM功能
目录
- Android 万能音频播放器 一 C++多线程解码音频数据
- Android 万能音频播放器 二 C++队列存放AvPacket
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等等创建三部曲
如:创建引擎接口对象( createrealizeget )
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功能相关推荐
- Android编程中利用AudioTrack播放PCM数据在音频的最后出现重复回声现象的解决方案
1 问题描述 今天在进行Android编程时遇到一个很奇怪的问题 重点说一下 这里我的测试机用的是"小米Note" 的确不怎么样 我在"华为P8"上面测试就 ...
- 2. android 直接使用hal库播放pcm demo
目录 一:概述 二:实现 环境 原理说明: 注意问题: 上源代码: 编译执行: 一:概述 这是一个c语言demo程序,android源码环境,编译得到 bin文件,push到设备上在shell环境运行 ...
- 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 ...
- Android音乐播放器-- 功能介绍
目前,市面上的播放器功能越来越强大,相对的,操作也越来越复杂,所以就萌发了做一个操作简单的音乐播放器的想法,目前实现的功能包括如下几点 : 1. 音乐列表 2. 专辑分类列表 3. 歌手分类列表 ...
- FFmpeg从入门到入魔(4):OpenSL ES播放PCM音频
1. OpenSL ES原理 OpenSL ES(Open Sound Library for Embedded Systems),即嵌入式音频加速标准,是一个无授权费.跨平台.针对嵌入式系统精心优 ...
- 【Android 高性能音频】Oboe 播放器开发 ( 为 OpenSL ES 配置参数以获得最佳延迟 | Oboe 音频流 | Oboe 音频设备 )
文章目录 一.获得最佳延迟 二.Oboe 音频流 三.Oboe 音频设备 Oboe GitHub 主页 : GitHub/Oboe ① 简单使用 : Getting Started ② Oboe 全指 ...
- Android音视频【十二】使用opensles和audiotrack进行播放pcm
人间观察 年龄到了,有些事就妥协了,这个世界上没有人可以随心所欲,生活会逼着你选择答案--最困难的是你什么都改变不了-- 介绍 播放pcm的两种方式 本节我们学习下如何播放pcm数据,在Android ...
- Android OpenSL ES 开发:Android OpenSL 录制 PCM 音频数据
一.实现说明 OpenSL ES的录音要比播放简单一些,在创建好引擎后,再创建好录音接口基本就可以录音了.在这里我们做的是流式录音,所以需要用至少2个buffer来缓存录制好的PCM数据,这里我们可以 ...
- Android开发之PCM录音实时播放的实现方法 | 边录音边播放 |PCM录音播放无延迟 | 录音无杂音 | 录音无噪音
先说下录音得开启录音权限 <uses-permission android:name="android.permission.RECORD_AUDIO" /> 然后录音 ...
最新文章
- C++阶段01笔记07【指针(基本概念、变量定义和使用、内存空间、空指针和野指针、const修饰指针、指针和数组、指针和函数)】
- 【292天】跃迁之路——程序员高效学习方法论探索系列(实验阶段50-2017.11.24)...
- 正则匹配减号_2020年这些正则应该被收藏(64条)
- cocos2d-x中CCEditbox导出到lua
- 如何安装Exchange2010上安装更新汇总(Update Rollup)
- mysql的txid是什么_mysql-存储引擎
- java 单个session过期_session过期的三种方法
- Scikit-learn_回归算法_支持向量机回归
- SnakeYAML配置文件解析器
- 在埋头写程序学技术的同时,有没有想到你们的老板和上司在搞什么?
- Zabbix实现短信报警
- H3C S5560-EI系列交换机配置Web管理
- 基于Spring Cloud Gateway 和 注册中心实现灰度发布
- 第50周收录98起融资,国内低靡,国外智能硬件火热 | 潜在周报
- 03-Python正则表达式
- 推荐几款基于 Markdown 语法在线制作简历的平台
- oracle的快捷方式,键盘快捷方式
- elasticsearch 8.3版本安装和集群部署
- 解决Module build failed: Error: no such file or directory, scandir ‘...node_modules\node-sass\vendor‘
- 分类:决策树——树的生长