美文网首页
Android-OpenSL ES

Android-OpenSL ES

作者: 凌烟醉卧 | 来源:发表于2019-10-08 15:50 被阅读0次

    RGB、YUV这两个时图像原始格式
    PCM时声音的原始格式

    Android 播放 PCM 有的方式

    • Java SDK: AudioTrack(播放pcm),AudioRecord(录制pcm)
    • NDK : OpenSL ES

    AudioRecord:指定采集的声音格式

    采样率:1s 采集多少次声音 采集频率 HZ
    采样位:16bit 2字节
    声道数:单声道、双声道

    OpenSL ES 全称为Open Sound Library for Embedded Systems,即嵌入式音频加速标准。OpenSL ES是无授权费、跨平台、针对嵌入式系统精心优化的硬件音频加速API。它为嵌入式移动多媒体设备上的本地应用程序开发者提供了标准化、高性能、低响应时间的音频功能实现方法,同时还实现了软/硬件音频性能的直接跨平台部署,不仅降低了执行难度,而且促进了高级音频市场的发展。

    Android的OpenSL ES库同样位于NDK的platforms文件夹内。
    CMakeList.txt中需要引入OpenSLES:

    target_link_libraries(OpenSLES)
    

    OpenSL ES提供的是基于C语言的API,但它是基于对
    象和接口的方式提供的,会采用面向对象的思想开发API。因此这里需要先来了解一下OpenSL ES中对象和接口的概念。

    • 对象:对象是对一组资源及其状态的抽象,每个对象都有一个在
      其创建时指定的类型,类型决定了对象可以执行的任务集,对象有点类似于C++中类的概念。
    • 接口:接口是对象提供的一组特征的抽象,这些抽象会为开发者
      提供一组方法以及每个接口的类型功能,在代码中,接口的类型由接口ID来标识。

    需要重点理解的是,一个对象在代码中其实是没有实际的表示形式
    的,可以通过接口来改变对象的状态以及使用对象提供的功能。对象可以有一个或者多个接口的实例,但是接口实例肯定只属于一个对象。对象是没有实际的代码表示形式的,对象的创建也是通过接口来完成的。通过获取对象的方法来获取出对象,进而可以访问对象的其他接口方法或者改变对象的状态。

    OpenSL ES的开发流程主要有如下7个步骤:

    • 创建接口对象
    • 设置混音器
    • 创建播放器
    • 设置播放回调函数
    • 设置播放状态
    • 启动回调函数
    • 释放

    1、创建引擎与接口

        SLresult result;
        // 创建引擎 SLObjectItf engineObject
        result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
        if (SL_RESULT_SUCCESS != result) {
            return;
        }
        // 初始化引擎 
        result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
        if (SL_RESULT_SUCCESS != result) {
            return;
        }
        // 获取引擎接口SLEngineItf engineInterface
        result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE,
                                               &engineInterface);
        if (SL_RESULT_SUCCESS != result) {
            return;
        }
    

    2、设置混音器

        // 创建混音器SLObjectItf outputMixObject
        result = (*engineInterface)->CreateOutputMix(engineInterface, &outputMixObject, 0,
                                                  0, 0);
        if (SL_RESULT_SUCCESS != result) {
            return;
        }
        // 初始化混音器outputMixObject
        result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
        if (SL_RESULT_SUCCESS != result) {
            return;
        }
    
        //不启用混响可以不用获取接口
        // 获得混音器接口
        //result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
         //                                         &outputMixEnvironmentalReverb);
        //if (SL_RESULT_SUCCESS == result) {
            //设置混响 : 默认。
            //SL_I3DL2_ENVIRONMENT_PRESET_ROOM: 室内
            //SL_I3DL2_ENVIRONMENT_PRESET_AUDITORIUM : 礼堂 等
            //const SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_DEFAULT;
            //(*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
             //       outputMixEnvironmentalReverb, &settings);
        //}
    

    3、创建播放器

        /**
         * 配置输入声音信息
         */
        //创建buffer缓冲类型的队列 2个队列
        SLDataLocator_AndroidSimpleBufferQueue android_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};
        //pcm数据格式
        SLDataFormat_PCM pcm = {SL_DATAFORMAT_PCM, 2, SL_SAMPLINGRATE_44_1, SL_PCMSAMPLEFORMAT_FIXED_16,
                                SL_PCMSAMPLEFORMAT_FIXED_16,
                                SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
                                SL_BYTEORDER_LITTLEENDIAN};
    
        //数据源 将上述配置信息放到这个数据源中
        SLDataSource slDataSource = {&android_queue, &pcm};
    
    
        //设置混音器
        SLDataLocator_OutputMix outputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
        SLDataSink audioSnk = {&outputMix, NULL};
        //需要的接口
        const SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
        const SLboolean req[1] = {SL_BOOLEAN_TRUE};
        //创建播放器
        (*engineInterface)->CreateAudioPlayer(engineInterface, &bqPlayerObject, &slDataSource,
                                           &audioSnk, 1,
                                           ids, req);
        //初始化播放器
        (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
    
    //    得到接口后调用  获取Player接口
        (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerInterface);
    
    

    4、设置播放回调

    //获取播放器队列接口
    (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
                                        &bqPlayerBufferQueue);
    //设置回调
    (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this);
    

    5、设置播放状态

    // 设置播放状态
    (*bqPlayerInterface)->SetPlayState(bqPlayerInterface, SL_PLAYSTATE_PLAYING);
    

    6、启动回调函数

    bqPlayerCallback(bqPlayerBufferQueue, this);
    

    7、释放

        //设置停止状态
        if (bqPlayerInterface) {
            (*bqPlayerInterface)->SetPlayState(bqPlayerInterface, SL_PLAYSTATE_STOPPED);
            bqPlayerInterface = 0;
        }
        //销毁播放器
        if (bqPlayerObject) {
            (*bqPlayerObject)->Destroy(bqPlayerObject);
            bqPlayerObject = 0;
            bqPlayerBufferQueue = 0;
        }
        //销毁混音器
        if (outputMixObject) {
            (*outputMixObject)->Destroy(outputMixObject);
            outputMixObject = 0;
        }
        //销毁引擎
        if (engineObject) {
            (*engineObject)->Destroy(engineObject);
            engineObject = 0;
            engineInterface = 0;
        }
    

    相关文章

      网友评论

          本文标题:Android-OpenSL ES

          本文链接:https://www.haomeiwen.com/subject/pfibpctx.html