サウンドプレイヤーにに以下の機能を追加してみます。
・連続再生
・assetsファイル指定再生
連続再生
1つのサウンドデータを鳴らし終わった後に、続けて別のサウンドデータを鳴らす機能です。アプリ側で再生終了を監視して次のデータを再生するという手もありますが、ラグがあったり面倒だったりしますのでサウンドプレイヤーで処理するようにします。
BGMをイントロ部分と、メインのループ部分に分けて鳴らすようなときに使います。
ファイル指定再生
メモリに常駐するまでもない一時的なサウンドを、ファイルから読み込んで再生します。
ファイル上のサウンドデータを鳴らすだけならば、アプリ側でメモリに読み込んで再生すれば良いのですが、再生終了時にメモリを解放する必要があります。アプリ側で終了を監視するのはこれまた面倒なので、プレイヤーで処理します。
Sound.h
/********************
サウンドデータ
********************/
struct SoundData
{
char* data; // データ
u32 size; // データサイズ
int loop; // ループカウンタ
void* file_data; // 終了時に解放するデータ
SoundData* next; // 次のデータ
SoundData(char* _data, u32 _size, int _loop, void* _file = NULL) // コンストラクタ
{
data = _data;
size = _size;
loop = _loop;
file_data = _file;
next = NULL;
}
~SoundData() // デストラクタ
{
if ( file_data ) {
free(file_data);
}
if ( next ) {
delete next;
}
}
void set_next(SoundData* _next) // 次のデータを設定
{
if ( next ) {
next->set_next(_next);
}
else {
next = _next;
}
}
};
連続再生の予約で複数のサウンドデータを持つ必要があるため、サウンドデータを構造体 SoundDataで管理します。
再生終了時に解放するデータは、再生用データとは別に指定します。
Sound.cpp
void* _file_data;
switch ( _size ) {
case FILE_ASSET : // assetファイル
_file_data = load_asset((char*)_data, &_size);
_data = _file_data;
break;
default : // メモリ
_file_data = NULL;
break;
}
WaveFormat* _info = (WaveFormat*)_data;
format_pcm.formatType = SL_DATAFORMAT_PCM;
format_pcm.numChannels = (SLuint32)_info->channel;
format_pcm.samplesPerSec = (SLuint32)_info->rate*1000;
format_pcm.bitsPerSample = (SLuint32)_info->bit;
format_pcm.containerSize = (SLuint32)_info->bit;
format_pcm.channelMask = (_info->channel == 1) ? SL_SPEAKER_FRONT_CENTER : (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
sound_data = new SoundData((char*)((u32)_data + sizeof(WaveFormat)), _info->data_size, _loop, _file_data);
再生準備関数 prepare内です。
assetsファイルを再生する場合は、_dataにファイル名文字列、_sizeに定数 sys::SoundPlayer::FILE_ASSETを指定します。
セコメントをする