OpenSL ES 实现音频的录制与播放

前言网上关于 OpenSL ES 的资料似乎相当少,最好的学习办法似乎是抄写 googlesamples/android-ndk 里的代码示例。这里打算使用 OpenSL ES 实现三个功能: 1) 播放 MP3 文件 2) 播放 PCM 文件 3) 录制 PCM 文件其中第 2 个功能和第 1 个雷同,这篇博客里不会给出代码示例,需要的可以看 GitHub。OpenSL E...
摘要由CSDN通过智能技术生成

前言

网上关于 OpenSL ES 的资料相当少,最好的学习办法似乎是抄写 googlesamples/android-ndk 里的代码示例。这里打算使用 OpenSL ES 实现三个功能:
1) 播放 MP3 文件
2) 播放 PCM 文件
3) 录制 PCM 文件

其中第 2 个功能和第 1 个雷同,这篇博客里不会给出代码示例,需要的可以看 GitHub

备注:CSDN 的样式太难看了,需要的可以到简书阅读本文:https://www.jianshu.com/p/5513a181580f

OpenSL ES 概述

OpenSL ES(Open Sound Library for Embedded Systems),是一种针对嵌入式系统特别优化过的硬件音频加速 API,免费并且可以跨平台使用。OpenSL ES 使用缓冲区队列机制,可以提供比系统 API 更高的性能。

在 OpenSL ES 中,所有的操作都是通过接口来完成的,尽管它使用了 C 语言来编写,但它的接口采用的是面向对象的,重要的几个接口是:
1) SLObjectItf :对象接口
2) SLEngineItf :引擎接口
3) SLPlayItf:播放接口
4) SLRecordItf:录制接口
5) SLBufferQueueItf :缓冲队列接口

其中:
1) Engine 是程序的入口,用于创建各种 Object
2) 一个 Object 对应一个或多个 Interface,Object 提供 Realize、Deatory、GetInterface 等基本接口
3) 实际的功能由各个 Interface 完成,比如播放音频,实际上是通过 SLPlayItf 来完成的

OpenSL ES 在不同系统上有不同的实现,有些接口在一些平台上可能无法使用,比如 Android 平台可以参考官方文档:面向 Android 的 OpenSL ES 来查看 Android 支持/不支持哪些功能。

以播放音频为例,最简单的代码编写流程为:
1) Engine::CreateAudioPlayer
2) Object::Realize
3) Object::GetInterface
4) Play::SetPlayState

其中,Object 可能的状态有:

/* Object state definitions */
#define SL_OBJECT_STATE_UNREALIZED ((SLuint32) 0x00000001)
#define SL_OBJECT_STATE_REALIZED      ((SLuint32) 0x00000002)
#define SL_OBJECT_STATE_SUSPENDED  ((SLuint32) 0x00000003)

使用 Engine 创建了一个 Object 时,它的状态是 UNREALIZED,必须使用方法 Realize 完成初始化,进入 REALIZED 状态,才可以进行下一步操作。如果出现错误或其它问题,它就会进入 SUSPENDED 状态,需要使用 Resume 方法才可以回到 REALIZED 状态。

播放 MP3 文件

这里以播放 Android 平台上的 asset 文件为例。

上面说过,Engine 是程序的入口,因此第一件事是创建 SLEngineItf:

void createEngine() {
    SLresult result;

    result = slCreateEngine(&engineObj, 0, nullptr, 0, nullptr, nullptr);
    assert(result == SL_RESULT_SUCCESS);
    (void) result;

    result = (*engineObj)->Realize(engineObj, SL_BOOLEAN_FALSE);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;

    result = (*engineObj)->GetInterface(engineObj, SL_IID_ENGINE, &engine);
    assert(SL_RESULT_SUCCESS == result);
    (void) result;

    const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
    const SLboolean req[1] = {SL_BOOLEAN_FALSE};
    (*engine)->CreateOutputMix(engine, &outputMixObj, 1, ids, req); // outputMixObj 用于输出声音数据

    result = 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值