目录

  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. C++阶段01笔记07【指针(基本概念、变量定义和使用、内存空间、空指针和野指针、const修饰指针、指针和数组、指针和函数)】
  2. 【292天】跃迁之路——程序员高效学习方法论探索系列(实验阶段50-2017.11.24)...
  3. 正则匹配减号_2020年这些正则应该被收藏(64条)
  4. cocos2d-x中CCEditbox导出到lua
  5. 如何安装Exchange2010上安装更新汇总(Update Rollup)
  6. mysql的txid是什么_mysql-存储引擎
  7. java 单个session过期_session过期的三种方法
  8. Scikit-learn_回归算法_支持向量机回归
  9. SnakeYAML配置文件解析器
  10. 在埋头写程序学技术的同时,有没有想到你们的老板和上司在搞什么?
  11. Zabbix实现短信报警
  12. H3C S5560-EI系列交换机配置Web管理
  13. 基于Spring Cloud Gateway 和 注册中心实现灰度发布
  14. 第50周收录98起融资,国内低靡,国外智能硬件火热 | 潜在周报
  15. 03-Python正则表达式
  16. 推荐几款基于 Markdown 语法在线制作简历的平台
  17. oracle的快捷方式,键盘快捷方式
  18. elasticsearch 8.3版本安装和集群部署
  19. 解决Module build failed: Error: no such file or directory, scandir ‘...node_modules\node-sass\vendor‘
  20. 分类:决策树——树的生长

热门文章

  1. elementUi tabs刷新后,选中的tab下划线不显示
  2. 第十三届蓝桥杯大赛软件赛决赛(Java 大学B组)
  3. pytorch编写cuda/c++ extention 方法
  4. Widget Extention开发笔记
  5. cgroup v2介绍及测试
  6. 实现调用阿里云API第一章——API请求与认证
  7. 地图上制作线路的动画_使用百度地图API制作线路轨迹播放
  8. 计算机快捷键ctrl记忆,PS篇:有效记忆快捷键
  9. Xilinx软件开发:PMU实验
  10. 黑马程序员---MYSQL数据库---01