Android OpenSL ES オーディオ プレーヤー

1. OpenSL ES の紹介

OpenSL ES (Open Sound Library for Embedded Systems) は、モバイル マルチメディア デバイスのアプリケーション開発者向けに、標準化された高性能で低応答のオーディオ機能の実装方法と統合 API を提供する、クロスプラットフォームでライセンス不要のオーディオ処理ライブラリです。これにより、OpenSL ES によって開発されたオーディオ処理プログラムが複数のプラットフォームで適切に実行されます。

2. OpenSL プログラミング手順

OpenSL ES オブジェクトは、Java プログラミング言語のオブジェクトの概念に似ています. OpenSL ES のオブジェクト タイプは SLObjectItf です. オブジェクトで特定のメソッドを使用する必要がある場合は、GetInterfaces を介して特定のインターフェイス オブジェクトを取得する必要があります。特定のパーソナリティ機能を使用するには. Interface オブジェクト タイプは、作成時に表示インターフェイスとして指定する必要があります. そうしないと、デフォルトで非表示になります. さらに、OpenSL ES のオブジェクトが作成された後、すぐには初期化されません. . 作成は、オブジェクトの割り当てを構築するための基本的なメモリ空間のみであり、Realize を通じて実現する必要があります。このオブジェクトは初期化されます。

3. Android プラットフォームでの OpenSL ES 開発の準備

CMakeList は基本ライブラリを導入します

target_link_libraries(
${PROJECT_NAME}
​
OpenSLES
)

ベース ライブラリ ヘッダー ファイル

#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>

4. OpenSL 再生処理の概要

OpenSL のエンジンは非常に重要なオブジェクトです。 1. Engine EngineItf を使用して、オーディオ プレーヤーやオーディオ コレクターなどのさまざまな主要オブジェクトを作成します。 2. Engine SLEngineCapabilitiesItf を使用して、関連するプラットフォームでのさまざまな機能の互換性を照会します。

DataSource と DataSink: DataSource はオーディオ プレーヤーのデータ入力ソース、DataSink はオーディオ プレーヤー (通常はシステム内のオーディオ デバイス) のデータ出力オブジェクトです。

【学習アドレス】:FFmpeg/WebRTC/RTMP/NDK/Androidの音声・動画ストリーミングメディアの高度な開発

[記事の特典]: より多くのオーディオおよびビデオ学習パッケージ、Dachang インタビューの質問、テクニカル ビデオ、学習ロードマップを無料で受け取ることができます (C/C++、Linux、FFmpeg webRTC rtmp hls rtsp ffplay srs など) 1079654574 をクリックして参加ます受け取るグループ〜

5.コード戦闘

5.1 Engine の作成と Engine インターフェイス オブジェクトの取得

// 创建并初始化Engine对象
SLObjectItf engineObj;
SLresult result = slCreateEngine(&engineObj, 0, NULL, 0, NULL, NULL);
if (result != SL_RESULT_SUCCESS) {
  // 创建Engine失败
  return;
}
result = (*engineObj)->Realize(engineObj, SL_BOOLEAN_FALSE); // TRU表示异步初始化,这里同步初始化即可
if (result != SL_RESULT_SUCCESS) {
  // Engine初始化失败
  return;
}
​
// 获取Engine接口对象
SLEngineItf engineItf;
result = (*engineObj)->GetInterfaces(engine, SL_IID_ENGINE, &engine);
if (result != SL_RESULT_TRUE) {
  // Engine接口对象获取失败
  return;
}

5.2 SLEngineItf を介してオーディオ出力オブジェクト SLDataSink (つまり、デフォルト デバイス) を作成する

// 创建混音器(它默认与系统音频设备绑定)
SLObjectItf outputMix;
SLInterfaceID outputMixItfIds[1] = {SL_IID_ENVIRONMENTALREVERB}; // 导出混音效果设置接口
SLboolean outputMixItfReq[1] = {SL_BOOLEAN_FALSE}; // FALSE:该接口不支持,也不影响对象的初始化流程;TRUE:接口不支持,会导致初始化失败
result = (*engineItf)->CreateOutputMix(engineItf, &outputMix, 1, outputMixItfIds, outputMixItfReq);
if (result != SL_RESULT_SUCCESS) {
  // 混音器对象创建失败
  return;
}
​
result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE); // 同步初始化
if (result != SL_RESULT_SUCCESS) {
  // 混音器对象初始化失败
  return;
}
​
// 混音效果设置接口对象
SLEnvironmentalReverbItf envReverbItf;
result = (*outputMix)->GetInterface(outputMix, SL_IID_ENVIRONMENTREVERB, &envRevertbItf);
if (result == SL_RESULT_SUCCESS) {
  // 接口对象获取成功,设置混音效果
  SLEnvironmentalReverbSettings stonecorridor = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR; // 走廊效果
  (*envReverbItf)->SetEnvironmentReverbProperties(envReverbItf, &stonecorridor);
  return;
}
​
// 音频数据输出对象
SLDataLocator_OutputMix locaterOutputMix;
locaterOutputMix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
locaterOutputMix.outputMix = output_mix_itf;
​
SLDataSink dataSink;
dataSink.pLocater = &locaterOutputMix;
dataSink.pFormat = NULL; // 不需要限制格式,音频输入源会指定好格式

5.3 オーディオ データ ソース SLDataSource の作成

// 指定数据送入形式,AndroidSimpleBufferQueue
SLDataLocater_AndroidSimpleBufferQueue locaterAndroidBufferQueue;
locaterAndroidBufferQueue.locaterType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
locaterAndroidBufferQueue.numBuffers = 2; // 越多播放越流畅、同时内存占用也越多
​
// 指定PCM数据格式限制
SLDataFormat_PCM formatPcm;
formatPcm.formatType = SL_DATAFORMAT_PCM;
formatPcm.numChannels = 2;                                    // 声道数 2
formatPcm.samplesPerSec = SL_SAMPLINGRATE_44_1;               // 采样率 44100HZ
formatPcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;        // 采样位深 16(2字节)
formatPcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;        // 与位深一样即可
formatPcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; // 立体声: 左前 | 右前
formatPcm.endianness = SL_BYTEORDER_LITTLEENDIAN;  // 小端
​
// 音频数据输入对象
SLDataSource dataSource;
dataSource.pLocater = &locaterAndroidBufferQueue;
dataSource.pFormat = &formatPcm;

5.4 SLEngineItf を使用してオーディオ プレーヤーを作成する

// 创建播放器对象
SLObjectItf playerObj;
SLInterfaceID playerItfIds[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};// 导出AndroidSimpleBufferQueue接口,需要此接口送入PCM原始数据进行播放
SLboolean playerItfReq[] = {SL_BOOLEAN_TRUE}; // 强依赖此接口,因此接口检查为TRUE,创建时如果发现不支持此接口,创建流程会返回失败
result = (*engineItf)->CreateAudioPlayer(engineItf, &playerObj, &dataSource, &dataSink, 1, playerItfIds, playerItfReq);
if (result != SL_RESULT_SUCCESS) {
  // 创建Player对象失败
  return;
}
​
result = (*playerObj)->Realize(playerObj, SL_BOOLEAN_FALSE); // 同步初始化
if (result != SL_RESULT_SUCCESS) {
  // Player初始化失败
  return;
}
​
// 导出播放控制接口对象
SLPlayerItf playerItf;
result = (*playerObj)->GetInterface(playerObj, SL_IID_PLAYER, &playerItf);
if (result != SL_RESULT_SUCCESS) {
  // 导出播放控制接口对象失败
  return;
}
​
// 导出BufferQueue接口对象
SLAndroidSimpleBufferQueueItf androidBufferQueueItf;
result = (*playerObj)->GetInterface(playerObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &androidBufferQueueItf);
if (result != SL_RESULT_SUCCESS) {
  // 导出BufferQueue对象接口失败
  return;
}
​
// BufferQueue 注册回调,OpenSL播放时通过回调主动要数据的形式进行播放的,开发者无法直接塞入数据
void AndroidSimpleBufferQueueCallback(const SLAndroidSimpleBufferQueueItf queue, void *data) {
  // 输入pcm原始数据,此原始数据需要与前面规范的格式一一对应上,否则播放异常
  (*queue)->Enqueue(queue, uint8_t* data, int dataSize);
}
​
result = (*androidBufferQueueItf)->RegisterCallback(androidBufferQueueItf, AndroidSimpleBufferQueueCallback, this);
if (result != SL_RESULT_SUCCESS) {
  // BufferQueue回调注册失败
  return;
}

5.5 再生制御

// 播放
(*playerItf)->SetPlayState(playerItf, SL_PLAYSTATE_PLAYING); 
// 激活回调,此后会循环回调获取PCM数据进行播放
(*androidBufferQueueItf)->Enqueue(androidBufferQueueItf, "", 1);
​
// 暂停
(*playerItf)->SetPlayState(playerItf, SL_PLAYSTATE_PAUSED);

5.6 リソースの解放

// 释放播放器
if (playerObj) {
  (*playerObj)->Destroy(playerObj);
  playerObj = NULL;
}
​
// 释放混音器 
if (outputMix) {
  (*outputMix)->Destroy(outputMix);
  outputMix = NULL;
}
​
// 释放Engine
if (engineObj) {
  (*engineObj)->Destroy(engineObj);
  engineObj = NULL;
}

上記の方法により、OpenSL ES オーディオ プレーヤーの作成は Android プラットフォーム上で完了できます.次のセクションでは、FFmpeg を組み合わせてオーディオ ファイルの再生機能を完成させます。

元のリンク: Android OpenSL ES オーディオ プレーヤー - ナゲット

おすすめ

転載: blog.csdn.net/irainsa/article/details/130031510