前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >播放器基础--OpenSL ES音频播放

播放器基础--OpenSL ES音频播放

作者头像
小蚂蚁与大象
发布2020-06-22 15:44:06
3.7K0
发布2020-06-22 15:44:06
举报

介绍

官网

OpenSL ES (Open Sound Library for Embedded Systems)是针对嵌入式系统的一套无授权费,跨平台, 硬件加速的音频API。它提供了一套标准化,高性能,低延时的方法, 本地应用(C/C++)的开发者可以通过这套方对音频进行操作, 实现软/硬件音频性能的直接跨平台部署,降低执行难度,促进高级音频市场的发展

NDK 软件包中包括 Khronos Group 开发的 OpenSL ES™ 1.0.1 API 规范的 Android 专用实现。利用这个库,可以使用 C 或 C++ 实现高性能、低延迟的音频应用。

标准 OpenSL ES 头文件 <SLES/OpenSLES.h> 和 <SLES/OpenSLES_Platform.h> 允许音频输入和输出。<SLES/OpenSLES_Android.h> 和 <SLES/OpenSLES_AndroidConfiguration.h> 中提供了其他 Android 专用功能。

如何在Android中使用OpenSL ES

  • 在CMakeList.txt中添加OpenSL ES的引用
代码语言:javascript
复制
target_link_libraries( # Specifies the target library.
   
        OpenSLES

        )
  • 添加必要的头文件 添加核心 OpenSL ES 功能集 OpenSLES.h 添加 OpenSL ES [Android 扩展] OpenSLES_Android.h

代码示例

GitHub 页面提供了以下示例应用:

  • audio-echo 创建从输入到输出的往返循环。
  • native-audio 是一个简单的音频录制器/播放器。

Note that OpenSL ES is deprecated from Android 11, developers are recommended to use Oboe library instead.

OpenSL ES简单使用

  • 使用OpenSL相关API的通用步骤是:

1,创建对象(通过带有create的函数) 2,初始化(通过Realize函数) 3,获取接口来使用相关功能(通过GetInterface函数)

  • OpenSL使用回调机制来访问音频IO,回调方法仅仅是告诉我们:BufferQueue已经就绪,可以接受/获取数据了
  • OpenSL使用SLBufferQueueItf. Enqueue函数从(往)音频设备获取(放入)数据。

关于使用FFmpeg + opensl 实现Android播放器播放音频, 可以在回调函数里面获取解码后的音频数据,并调用Enqueue函数进行播放. 在开始播放的时候,需要手动启动回调机制,否则回调将不会被调用到。

  • 一个简单的音频播放大概需要以下的object:
代码语言:javascript
复制
   //引擎
    SLObjectItf engineObject = 0;
    //引擎接口
    SLEngineItf engineInterface = 0;
    //混音器
    SLObjectItf outputMixObject = 0;
    //播放器
    SLObjectItf bqPlayerObject = 0;
    //播放器接口
    SLPlayItf bqPlayerPlay = 0;
    //播放器队列接口
    SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue = 0;
  • 基本流程

opensles.png

代码还在整理,先简单贴一下

代码语言:javascript
复制
void AudioChannel::audio_play() {
    /**
     * 1、创建引擎并获取引擎接口
     */
    SLresult result;
    // 1.1 创建引擎对象:SLObjectItf engineObject
    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    // 1.2 初始化引擎
    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    // 1.3 获取引擎接口 SLEngineItf engineInterface
    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineInterface);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    /**
     * 2、设置混音器
     */
    // 2.1 创建混音器:SLObjectItf outputMixObject
    result = (*engineInterface)->CreateOutputMix(engineInterface, &outputMixObject, 0,
                                                 0, 0);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    // 2.2 初始化混音器
    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    /**
     * 3、创建播放器
     */
    //3.1 配置输入声音信息
    //创建buffer缓冲类型的队列 2个队列
    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
                                                       2};
    //pcm数据格式
    //SL_DATAFORMAT_PCM:数据格式为pcm格式
    //2:双声道
    //SL_SAMPLINGRATE_44_1:采样率为44100
    //SL_PCMSAMPLEFORMAT_FIXED_16:采样格式为16bit
    //SL_PCMSAMPLEFORMAT_FIXED_16:数据大小为16bit
    //SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT:左右声道(双声道)
    //SL_BYTEORDER_LITTLEENDIAN:小端模式
    SLDataFormat_PCM format_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 audioSrc = {&loc_bufq, &format_pcm};

    //3.2 配置音轨(输出)
    //设置混音器
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
    SLDataSink audioSnk = {&loc_outmix, NULL};
    //需要的接口 操作队列的接口
    const SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
    const SLboolean req[1] = {SL_BOOLEAN_TRUE};
    //3.3 创建播放器
    result = (*engineInterface)->CreateAudioPlayer(engineInterface, &bqPlayerObject, &audioSrc,
                                                   &audioSnk, 1, ids, req);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    //3.4 初始化播放器:SLObjectItf bqPlayerObject
    result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    //3.5 获取播放器接口:SLPlayItf bqPlayerPlay
    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
    if (SL_RESULT_SUCCESS != result) {
        return;
    }
    /**
     * 4、设置播放回调函数
     */
    //4.1 获取播放器队列接口:SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue
    (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);

    //4.2 设置回调 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
    (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this);

    /**
     * 5、设置播放器状态为播放状态
     */
    (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);

    /**
     * 6、手动激活回调函数
     */
    bqPlayerCallback(bqPlayerBufferQueue, this);
}
代码语言:javascript
复制
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
    AudioChannel *audioChannel = static_cast<AudioChannel *>(context);
    int pcm_size = audioChannel->getPCM();
    if (pcm_size > 0) {
        (*bq)->Enqueue(bq, audioChannel->out_buffers, pcm_size);
    }
}

代码还在整理当中https://github.com/yizhongliu/FFMediaPlayer

官网 https://www.khronos.org/opensles/ https://developer.android.google.cn/ndk/guides/audio/opensl

参考 https://www.jianshu.com/p/2b8d2de9a47b https://blog.csdn.net/Poisx/article/details/78336404

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 如何在Android中使用OpenSL ES
    • 代码示例
    • OpenSL ES简单使用
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档