OpenSLによるサウンドの再生です。
今回は最低限の処理として、PCMデータの再生を行います。
NDKにあるサンプル native-audioを参考にしていますが、データはWAVファイルから読み込むようにしています。
サウンドプレイヤークラス sys::SoundPlayer
Sound.h
#ifndef ___SOUND_H___
#define ___SOUND_H___
#include "common.h"
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
namespace sys
{
/************************
サウンドプレイヤー
************************/
class SoundPlayer
{
public :
static SLObjectItf engineObject; // エンジンオブジェクト
static SLEngineItf engineEngine; // インタフェース
static void init_engine(void); // 初期化
static void quit_engine(void); // 終了
private :
SLObjectItf outputMixObject; // 出力オブジェクト
SLObjectItf bqPlayerObject; // プレイヤーオブジェクト
SLPlayItf bqPlayerPlay; // インタフェース
SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; // バッファキューインタフェース
SLVolumeItf bqPlayerVolume; // 音量インタフェース
char* sound_data; // サウンドデータ
u32 sound_size; // サウンドデータサイズ
int sound_loop; // ループカウンタ
public :
SoundPlayer(void); // コンストラクタ
~SoundPlayer(); // デストラクタ
void play(const void*, u32, int _loop = 1); // 再生
void play(void);
void prepare(const void*, u32, int _loop = 1); // 再生準備
void stop(void); // 停止
void callback_wav(void); // 再生コールバック
};
}
#endif
/********************* End of File ********************************/
静的メンバが、サウンドシステム全体として必要な共通部分です。
native-audioを見ると outputMixオブジェクトは Engineオブジェクトを作成するとき一緒に作成していますが、プレイヤー毎に作成しなければいけないようです。
Sound.cpp
/********************
エンジン初期化
********************/
void SoundPlayer::init_engine(void)
{
SLresult result;
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); // エンジンオブジェクト作成
assert(SL_RESULT_SUCCESS == result);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); // リアライズ
assert(SL_RESULT_SUCCESS == result);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
assert(SL_RESULT_SUCCESS == result); // インタフェース取得
}
/******************
エンジン終了
******************/
void SoundPlayer::quit_engine(void)
{
if ( engineObject ) {
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
}
}
サウンドシステム全体で必要なエンジン(Engine)オブジェクトとインタフェースを作成・初期化しています。
セコメントをする