目录

  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 #include #include #include #include "androidLog.h"#include #include //引擎对象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. 调用与外部接口
  2. Android 基本属性绘制文本对象FontMetrics介绍
  3. android Activity之间传递对象
  4. android 中调用接口发送短信
  5. 【Android】Web开发之通过标准Java接口处理Http请求
  6. FregClient进程,创建一个BpFregService类型的代理对象
  7. android XMl 解析神奇xstream 三: 把复杂对象转换成 xml
  8. AIDL(android 接口描述语言)
  9. Android中一个Activity调用另一个Activity — Intent对象的使用

随机推荐

  1. Caused by: com.android.tools.r8.Compil
  2. Android中动态添加╱删除的Spinner菜单
  3. 我的Android成长之路(11)----Android之Shar
  4. android Select at least one project
  5. Android(安卓)getResources的作用和需要
  6. Android(安卓)studio 导入github工程
  7. Android网络连接判断与处理
  8. Android自动提示--AutoCompleteTextView
  9. Android之TabHost重定义
  10. android 一些网址收藏