サウンド処理は非同期で その3 ― 2013/11/30
サウンド管理でコマンドを javaに送る処理、そしてキューの中身を受け取ってサウンドプレイヤーの処理を実行する部分を作成します。これでサウンドの非同期処理の実装完了となります。
Sound.cpp
サウンド管理終了時、まだキューにコマンドが残っている可能性がありますので java側の関数を呼んでクリアしています。
再生などサウンドのコマンドを受け取る処理です。
直接サウンドプレイヤーの処理を呼んでいたのを、キューにコマンドを送るように変更しています。
javaからコマンドを受け取って実行する部分です。
コマンドの値に従ってサウンドプレイヤーの関数を呼び出しています。
再生・停止など命令がいろいろあるので処理は多いですが、どれもやっていることは同じです。
サウンドの命令自体は同じなので、サンプルに変更はありません。
プロジェクト一式は、こちらから。
Sound.cpp
/********** 終了 **********/ void SoundManager::quit(void) { { // コマンド停止 JNIEnv* env; Bool attach_flag = FALSE; if ( g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6) < 0 ) { if ( g_JavaVM->AttachCurrentThread(&env, NULL) < 0 ) { goto error; } attach_flag = TRUE; } jclass clazz = env->FindClass("sys/SoundManager"); if ( clazz ) { jmethodID mid = env->GetStaticMethodID(clazz, "stop_command", "()V"); if ( mid ) { env->CallStaticVoidMethod(clazz, mid); } } if ( attach_flag ) { g_JavaVM->DetachCurrentThread(); } } error : if ( player ) { delete[] player; player = NULL; } SoundPlayer::quit_engine(); // サウンドエンジン終了 }
サウンド管理終了時、まだキューにコマンドが残っている可能性がありますので java側の関数を呼んでクリアしています。
// サウンドコマンド enum { COMMAND_UPDATE, // 稼働 COMMAND_PREPARE, // 準備 COMMAND_PLAY, // 再生・再開 COMMAND_STOP, // 停止 COMMAND_VOLUME, // 音量設定 COMMAND_NEXT, // 連続再生設定 COMMAND_PAUSE, // 一時停止 COMMAND_PAUSE_SYS, COMMAND_RESUME, // 再開 COMMAND_RESUME_SYS, }; /********** 稼働 **********/ void SoundManager::update(void) { set_command(-1, COMMAND_UPDATE); } /******************************************************** 再生 引数 _channel = チャンネル番号 _data = サウンドデータ _size = サウンドデータサイズ _loop = ループ回数(0:無限ループ) _vol = 音量 *******************************************************/ void SoundManager::prepare(int _channel, const void* _data, u32 _size, int _loop, float _vol) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_PREPARE, _data, _size, _loop, _vol); } void SoundManager::play(int _channel) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_PLAY); } void SoundManager::play(int _channel, const void* _data, u32 _size, int _loop, float _vol) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_PLAY, _data, _size, _loop, _vol); } void SoundManager::play(void) { set_command(-1, COMMAND_PLAY); // 全て再生開始 } /******************************************* 停止 引数 _channel = チャンネル番号 _cnt = フェード時間 *******************************************/ void SoundManager::stop(int _channel, int _cnt) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_STOP, NULL, (u32)_cnt); } void SoundManager::stop(void) { set_command(-1, COMMAND_STOP); // 全て停止 } /********************************************************* 音量設定 引数 _channel = チャンネル番号 _vol = 音量(0.0:最小 ~ 1.0:最大) *********************************************************/ void SoundManager::set_volume(int _channel, float _vol) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_VOLUME, NULL, 0, 0, _vol); } /***************************************************** マスター音量設定 引数 _vol = 音量(0.0:最小 ~ 1.0:最大) *****************************************************/ void SoundManager::set_master_volume(float _vol) { set_command(-1, COMMAND_VOLUME, NULL, 0, 0, _vol); } /******************************************************* 連続再生設定 引数 _channel = チャンネル番号 _data = サウンドデータ _size = サウンドデータサイズ _loop = ループ回数(0:無限ループ) *******************************************************/ void SoundManager::set_next(int _channel, const void* _data, u32 _size, int _loop) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_NEXT, _data, _size, _loop); } /********************************************* 一時停止 引数 _channel = チャンネル番号 *********************************************/ void SoundManager::pause(int _channel) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_PAUSE); } void SoundManager::pause(void) { set_command(-1, COMMAND_PAUSE); // 全て一時停止 } void SoundManager::pause_system(void) // システムによる一時停止 { set_command(-1, COMMAND_PAUSE_SYS); } /********************************************* 再開 引数 _channel = チャンネル番号 *********************************************/ void SoundManager::resume(int _channel) { assert((0 <= _channel) && (_channel < SOUND_CHANNEL_MAX)); set_command(_channel, COMMAND_RESUME); } void SoundManager::resume(void) { set_command(-1, COMMAND_RESUME); // 全て再開 } void SoundManager::resume_system(void) // システムによる再開 { set_command(-1, COMMAND_RESUME_SYS); }
再生などサウンドのコマンドを受け取る処理です。
直接サウンドプレイヤーの処理を呼んでいたのを、キューにコマンドを送るように変更しています。
/******************************** Javaからコマンドを受け取る ********************************/ extern "C" { JNIEXPORT void JNICALL Java_sys_SoundManager_sendSoundCommand(JNIEnv*, jobject, jshort, jshort, jint, jint, jshort, jfloat); } JNIEXPORT void JNICALL Java_sys_SoundManager_sendSoundCommand(JNIEnv*, jobject, jshort _channel, jshort _command, jint _data, jint _size, jshort _loop, jfloat _volume) { SoundManager::get_command((int)_channel, (int)_command, (void*)_data, (u32)_size, (int)_loop, (float)_volume); } void SoundManager::get_command(int _channel, int _command, void* _data, u32 _size, int _loop, float _volume) { switch ( _command ) { case COMMAND_UPDATE : for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { player[i].update(); } break; case COMMAND_PREPARE : player[_channel].prepare(_data, _size, _loop, _volume); break; case COMMAND_PLAY : if ( _channel >= 0 ) { if ( _size ) { player[_channel].prepare(_data, _size, _loop, _volume); } player[_channel].play(); } else { for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { // 全て再開 player[i].play(); } } break; case COMMAND_STOP : if ( _channel >= 0 ) { player[_channel].stop((int)_size); } else { for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { // 全て停止 player[i].stop(); } } break; case COMMAND_VOLUME : if ( _channel >= 0 ) { player[_channel].set_volume(_volume); } else if ( SoundPlayer::set_master_volume(_volume) ) { // マスター音量設定 for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { player[i].set_volume(); // 音量再設定 } } break; case COMMAND_NEXT : player[_channel].set_next(_data, _size, _loop); break; case COMMAND_PAUSE : if ( _channel >= 0 ) { player[_channel].pause(TRUE); } else { for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { // 全て一時停止 player[i].pause(TRUE); } } break; case COMMAND_PAUSE_SYS : for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { // システムによる再開 player[i].pause(FALSE); } break; case COMMAND_RESUME : if ( _channel >= 0 ) { player[_channel].resume(); } else if ( _size ) { for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { // 全て再開 player[i].resume(); } } break; case COMMAND_RESUME_SYS : for (int i = 0; i < SOUND_CHANNEL_MAX; i++) { // システムによる再開 player[i].resume(SoundPlayer::PLAYING); } break; } }
javaからコマンドを受け取って実行する部分です。
コマンドの値に従ってサウンドプレイヤーの関数を呼び出しています。
再生・停止など命令がいろいろあるので処理は多いですが、どれもやっていることは同じです。
サウンドの命令自体は同じなので、サンプルに変更はありません。
プロジェクト一式は、こちらから。
最近のコメント