/*************************************
OGG展開PCMデータ取得
引数 _buf = バッファ
戻り値 データサイズ
*************************************/
SLuint32 SoundPlayer::get_pcm_data(char* _buf)
{
long read_size;
SLuint32 total = 0;
while ( total < 0x400 ) {
read_size = ::ov_read(&ov_file, _buf + total, 0x400 - total, NULL);
if ( bqPlayerObject == NULL ) {
return 0;
}
else if ( read_size > 0 ) {
total += read_size;
}
else if ( sound_data->loop != 1 ) {
::ov_pcm_seek(&ov_file, 0); // ループ
if ( sound_data->loop > 1 ) {
sound_data->loop--;
}
}
else {
if ( sound_data->next == NULL ) { // 終了
break;
}
SoundData* _next = sound_data->next; // 連続再生
sound_data->next = NULL;
delete sound_data;
sound_data = _next;
::ov_clear(&ov_file);
ov_pos = 0;
if ( ::ov_open_callbacks(this, &ov_file, NULL, 0, callbacks) ) {
LOGE("ov_open_callbacks ERROR!");
::ov_clear(&ov_file);
delete sound_data;
return 0;
}
}
}
return total;
}
デコードデータ取得関数です。
基本的には ov_readを呼んでバッファにデータをデコードしているだけです。
戻り値が0の場合は終端までデコードしてしまったということなので、ループのため先頭に戻す・連続再生のため次のデータを設定するといった処理を行っています。
void SoundPlayer::callback_ogg(void)
{
if ( pcm_size > 0 ) {
(*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, &pcm_buffer[buf_cnt][0], pcm_size);
buf_cnt = ++buf_cnt % 2;
pcm_size = get_pcm_data(&pcm_buffer[buf_cnt][0]);
}
else { // 終了
(*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
::ov_clear(&ov_file);
if ( sound_data ) {
delete sound_data;
sound_data = NULL;
}
state = STOPPED;
}
}
再生コールバック関数です。
データが残っている場合は、再生準備の時と同様にデータをキューに送り次のデータをデコードしています。
ループや連続再生の処理は get_pcm_dataの方で行っているので、WAVのコールバックより簡単になっています。
セコメントをする