首页 > 编程知识 正文

Android OpenSL介绍 并实现播放PCM功能,实现简单音乐播放功能

时间:2023-05-06 02:05:58 阅读:276851 作者:2644

目录 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等等

创建三部曲
如:创建引擎接口对象( 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 JNICALLJava_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);}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。