1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: snd_SoundArchivePlayer.h 4 5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Revision: 29700 $ 14 *---------------------------------------------------------------------------*/ 15 16 /** 17 * :include nw/snd/snd_SoundArchivePlayer.h 18 * 19 * @file snd_SoundArchivePlayer.h 20 */ 21 22 #ifndef NW_SND_SOUND_ARCHIVE_PLAYER_H_ 23 #define NW_SND_SOUND_ARCHIVE_PLAYER_H_ 24 25 #include <nw/snd/snd_SoundStartable.h> 26 #include <nw/snd/snd_NoteOnCallback.h> 27 #include <nw/snd/snd_SoundArchive.h> 28 #include <nw/snd/snd_BasicSound.h> 29 #include <nw/snd/snd_SequenceSoundPlayer.h> // SequenceUserprocCallback 30 #include <nw/snd/snd_SequenceSound.h> // SequenceSoundInstanceManager 31 #include <nw/snd/snd_WaveSound.h> // WaveSoundInstanceManager 32 #include <nw/snd/snd_StreamSound.h> // StreamSoundInstanceManager 33 #include <nw/snd/snd_Util.h> 34 #include <nw/snd/snd_SoundInstanceManager.h> 35 #include <nw/snd/snd_MmlSequenceTrackAllocator.h> 36 #include <nw/snd/snd_MmlParser.h> 37 38 namespace nw { 39 namespace snd { 40 41 class SoundHandle; 42 class SoundHeap; 43 class SoundActor; 44 class SoundPlayer; 45 class SoundDataManager; 46 47 namespace internal { 48 49 class ExternalSoundPlayer; 50 class Channel; 51 class StreamSound; 52 class WaveSound; 53 class PlayerHeap; 54 55 } 56 57 //--------------------------------------------------------------------------- 58 //! @brief サウンドアーカイブ中のサウンドを再生するクラスです。 59 //! 60 //! SoundArchivePlayer で再生したサウンドは、 61 //! ハンドルクラスを用いて操作することができます。 62 //! 63 //! @see SoundHandle クラス 64 //! @see SoundStartable インターフェイス 65 //! 66 //! @date 2010/01/15 初版 67 //--------------------------------------------------------------------------- 68 class SoundArchivePlayer : public SoundStartable 69 { 70 private: 71 static const int DEFAULT_STREAM_BLOCK_COUNT = 5; 72 73 /* ------------------------------------------------------------------------ 74 SeqCallback class 75 ------------------------------------------------------------------------ */ 76 class SequenceNoteOnCallback : public internal::driver::NoteOnCallback 77 { 78 public: SequenceNoteOnCallback(const SoundArchivePlayer & player)79 SequenceNoteOnCallback( const SoundArchivePlayer& player ) : m_pSoundArchivePlayer( player ) { } 80 81 virtual internal::driver::Channel* NoteOn( 82 internal::driver::SequenceSoundPlayer* seqPlayer, 83 u8 bankIndex, 84 const internal::driver::NoteOnInfo& noteOnInfo 85 ); 86 87 private: 88 const SoundArchivePlayer& m_pSoundArchivePlayer; 89 }; 90 friend class SoundArchivePlayer::SequenceNoteOnCallback; 91 92 /* ------------------------------------------------------------------------ 93 WaveSoundCallback class 94 ------------------------------------------------------------------------ */ 95 private: 96 class WaveSoundCallback : public internal::driver::WaveSoundPlayer::WaveSoundCallback 97 { 98 public: WaveSoundCallback(const SoundArchivePlayer & player)99 WaveSoundCallback( const SoundArchivePlayer& player ) : m_pSoundArchivePlayer( player ) { } 100 101 virtual bool GetWaveSoundData( 102 internal::WaveSoundInfo* info, 103 internal::WaveSoundNoteInfo* noteInfo, 104 internal::WaveInfo* waveData, 105 const internal::driver::WaveSoundPlayer::WaveSoundCallbackArg& arg 106 ) const; 107 108 private: 109 const SoundArchivePlayer& m_pSoundArchivePlayer; 110 }; 111 112 /* ------------------------------------------------------------------------ 113 class member 114 ------------------------------------------------------------------------ */ 115 public: 116 //---------------------------------------- 117 //! @name コンストラクタ/デストラクタ 118 //@{ 119 //--------------------------------------------------------------------------- 120 //! @brief コンストラクタです。 121 //! 122 //! @date 2010/01/15 初版 123 //--------------------------------------------------------------------------- 124 SoundArchivePlayer(); 125 126 //--------------------------------------------------------------------------- 127 //! @brief デストラクタです。 128 //! 129 //! @date 2010/01/15 初版 130 //--------------------------------------------------------------------------- 131 virtual ~SoundArchivePlayer(); 132 //@} 133 134 //---------------------------------------- 135 //! @name 初期化 136 //@{ 137 //--------------------------------------------------------------------------- 138 //! @brief 初期化に必要なメモリのサイズを取得します。 139 //! 140 //! @param[in] arc プレイヤーで使用するサウンドアーカイブです。 141 //! 142 //! @return 初期化に必要なメモリサイズを返します。 143 //! 144 //! @see Initialize 145 //! 146 //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 147 //! @date 2010/01/15 初版 148 //--------------------------------------------------------------------------- 149 size_t GetRequiredMemSize( const SoundArchive* arc ); 150 151 //--------------------------------------------------------------------------- 152 //! @brief 初期化に必要なストリームバッファのサイズを取得します。 153 //! 154 //! @ref Initialize に渡すストリームバッファの最小サイズを取得します。 155 //! この関数で取得した値より大きいサイズのバッファを渡す必要があります。 156 //! 157 //! @param[in] arc プレイヤーで使用するサウンドアーカイブです。 158 //! 159 //! @return 初期化に必要なストリームバッファサイズを返します。 160 //! 161 //! @see Initialize 162 //! 163 //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 164 //! @date 2010/01/15 初版 165 //--------------------------------------------------------------------------- 166 size_t GetRequiredStreamBufferSize( const SoundArchive* arc ); 167 168 //--------------------------------------------------------------------------- 169 //! @brief サウンドアーカイブプレイヤーを初期化します。 170 //! 171 //! サウンドアーカイブプレイヤーを使用する前に、 172 //! 初期化を行う必要があります。 173 //! 初期化を行うことにより、 174 //! サウンドアーカイブプレイヤーがサウンドアーカイブと 175 //! サウンドデータマネージャ関連付けられ、 176 //! そのサウンドアーカイブ中のデータを再生できるようになります。 177 //! 178 //! サウンドアーカイブプレイヤーが必要とするメモリのサイズは 179 //! @ref GetRequiredMemSize 及び @ref GetRequiredStreamBufferSize 180 //! で取得することができます。 181 //! 182 //! 必要なストリームバッファサイズが 0 の場合、 183 //! ストリームバッファへのポインタ strmBuffer に NULL を渡すことができます。 184 //! 185 //! ストリームバッファを @ref GetRequiredStreamBufferSize 186 //! で取得したサイズより大きく設定すると、 187 //! ストリームサウンドの音途切れが発生しにくくなりますが、 188 //! データをロードしてから実際に再生するまでの遅延時間が大きくなります。 189 //! 190 //! ストリームバッファはデバイスメモリのアドレスを指定する必要があります。 191 //! strmBuffer および strmBuffer + strmBufferSize のアドレスが、 192 //! デバイスメモリに無い場合は、アサートで停止、あるいは、 193 //! false を返します (ビルドターゲットによって挙動が変わります)。 194 //! 195 //! @param[in] arc プレイヤーで使用するサウンドアーカイブです。 196 //! @param[in] manager プレイヤーで使用するサウンドデータマネージャです。 197 //! @param[in] buffer バッファへのポインタです。 198 //! 32 バイトアライメントされている必要があります。 199 //! @param[in] size バッファサイズです。 200 //! @param[in] strmBuffer ストリームバッファへのポインタです。 201 //! 32 バイトアライメントされているデバイスメモリを 202 //! 指定する必要があります。 203 //! @param[in] strmBufferSize ストリームバッファのサイズです。 204 //! 205 //! @return 初期化に成功したら true を、失敗したら false を返します。 206 //! 207 //! @see GetRequiredMemSize 208 //! @see GetRequiredStreamBufferSize 209 //! @see Finalize 210 //! @see IsAvailable 211 //! 212 //! @date 2010/03/05 ストリームバッファがデバイスメモリに無い場合の挙動を追記。 213 //! @date 2010/02/03 buffer のアライメントサイズを変更 (4 → 32) 214 //! @date 2010/02/01 関数名変更 (Setup → Initialize) 215 //! @date 2010/01/15 初版 216 //--------------------------------------------------------------------------- 217 bool Initialize( 218 const SoundArchive* arc, 219 const SoundDataManager* manager, 220 void* buffer, 221 u32 size, 222 void* strmBuffer, 223 u32 strmBufferSize 224 ); 225 226 //--------------------------------------------------------------------------- 227 //! @brief サウンドアーカイブプレイヤーを破棄します。 228 //! 229 //! 破棄は以下のとおり行われます。 230 //! 231 //! ・このサウンドアーカイブプレイヤーを使って再生中のサウンドを停止します。@n 232 //! ・初期化で割り当てたメモリ領域を開放します。@n 233 //! ・初期化されたサウンドアーカイブとの関連が外れます。 234 //! 235 //! @see Initialize 236 //! @see IsAvailable 237 //! 238 //! @date 2010/02/01 関数名変更 (Shutdown → Finalize) 239 //! @date 2010/01/15 初版 240 //--------------------------------------------------------------------------- 241 void Finalize(); 242 243 //--------------------------------------------------------------------------- 244 //! @brief 利用可能な状態かどうかを調べます。 245 //! 246 //! サウンドアーカイブプレイヤーを利用するためには 247 //! @ref Initialize を呼び出して初期化を完了させる必要があります。 248 //! また、@ref Finalize を呼び出すと、 249 //! サウンドアーカイブプレイヤーの終了処理が行われ、 250 //! 利用できない状態になります。 251 //! 252 //! @return サウンドアーカイブプレイヤーが利用可能な状態なら true を、 253 //! そうでなければ false を返します。 254 //! 255 //! @see Initialize 256 //! @see Finalize 257 //! 258 //! @date 2010/02/01 関数名変更 (Setup → Initialize, Shutdown → Finalize) 259 //! にともなう文言の調整 260 //! @date 2010/01/15 初版 261 //--------------------------------------------------------------------------- 262 bool IsAvailable() const; 263 //@} 264 265 //---------------------------------------- 266 //! @name 更新 267 //--------------------------------------------------------------------------- 268 //! @brief サウンドアーカイブプレイヤーの更新処理を行います。 269 //! 270 //! この関数は 1 ゲームフレームに 1 回呼び出してください。 271 //! 272 //! 内部の処理はサウンドスレッドで行われるため、 273 //! 更新処理を 1 ゲームフレームに 1 回呼び出すことができなくても 274 //! 発音が途切れることはありません。 275 //! この関数では、プレイヤーやサウンドに対するパラメータ設定や、 276 //! フェイドイン・フェイドアウトなどの連続的なパラメータ変更を 277 //! 反映するための処理が行われます。 278 //! 279 //! @date 2010/01/15 初版 280 //--------------------------------------------------------------------------- 281 void Update(); 282 //@} 283 284 //---------------------------------------- 285 //! @name その他 286 287 //--------------------------------------------------------------------------- 288 //! @brief プレイヤーに関連付けられているサウンドアーカイブを取得します。 289 //! 290 //! @return プレイヤーに関連付けられているサウンドアーカイブを返します。 291 //! 292 //! @see SoundArchive クラス 293 //! 294 //! @date 2010/01/15 初版 295 //--------------------------------------------------------------------------- 296 const SoundArchive& GetSoundArchive() const; 297 298 //--------------------------------------------------------------------------- 299 //! @brief 指定した ID のサウンドプレイヤーを取得します。 300 //! 301 //! @param[in] playerId プレイヤーの ID です。 302 //! 303 //! @return 指定した ID のサウンドプレイヤーを返します。 304 //! 305 //! @see SoundPlayer クラス 306 //! 307 //! @date 2010/01/15 初版 308 //--------------------------------------------------------------------------- 309 SoundPlayer& GetSoundPlayer( SoundArchive::ItemId playerId ); 310 311 //--------------------------------------------------------------------------- 312 //! @brief 指定した ID のサウンドプレイヤーを取得します。 313 //! 314 //! @param[in] pPlayerName プレイヤーのラベル文字列です。 315 //! 316 //! @return 指定した ID のサウンドプレイヤーを返します。 317 //! 318 //! @see SoundPlayer クラス 319 //! 320 //! @date 2010/01/15 初版 321 //--------------------------------------------------------------------------- 322 SoundPlayer& GetSoundPlayer( const char* pPlayerName ); 323 324 //--------------------------------------------------------------------------- 325 //! @brief サウンドプレイヤーの個数を取得します。 326 //! 327 //! @return サウンドプレイヤーの個数を返します。 328 //! 329 //! @see SoundPlayer クラス 330 //! 331 //! @date 2010/02/01 返り値の型を変更 (unsigned long → u32) 332 //! @date 2010/01/15 初版 333 //--------------------------------------------------------------------------- GetSoundPlayerCount()334 u32 GetSoundPlayerCount() const { return m_SoundPlayerCount; } 335 336 //--------------------------------------------------------------------------- 337 //! @brief 再生可能なシーケンスサウンドの残数を取得します。 338 //! 339 //! 残数が 0 のときに新たにシーケンスサウンドを再生すると、 340 //! 既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。 341 //! ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、 342 //! 再生に失敗します。 343 //! 344 //! 再生可能なシーケンスサウンドの総数は、 345 //! サウンドアーカイブに記述されていて、 346 //! @ref Initialize でサウンドアーカイブプレイヤーに設定されます。 347 //! 348 //! @return 再生可能なシーケンスサウンドの残数を返します。 349 //! 350 //! @see Initialize 351 //! 352 //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 353 //! @date 2010/01/15 初版 354 //--------------------------------------------------------------------------- GetFreeSequenceSoundCount()355 int GetFreeSequenceSoundCount() const 356 { 357 return m_SequenceSoundInstanceManager.GetFreeCount(); 358 } 359 360 //--------------------------------------------------------------------------- 361 //! @brief 再生可能なウェーブサウンドの残数を取得します。 362 //! 363 //! 残数が 0 のときに新たにウェーブサウンドを再生すると、 364 //! 既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。 365 //! ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、 366 //! 再生に失敗します。 367 //! 368 //! 再生可能なウェーブサウンドの総数は、 369 //! サウンドアーカイブに記述されていて、 370 //! @ref Initialize でサウンドアーカイブプレイヤーに設定されます。 371 //! 372 //! @return 再生可能なウェーブサウンドの残数を返します。 373 //! 374 //! @see Initialize 375 //! 376 //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 377 //! @date 2010/01/15 初版 378 //--------------------------------------------------------------------------- GetFreeWaveSoundCount()379 int GetFreeWaveSoundCount() const 380 { 381 return m_WaveSoundInstanceManager.GetFreeCount(); 382 } 383 384 //--------------------------------------------------------------------------- 385 //! @brief 再生可能なストリームサウンドの残数を取得します。 386 //! 387 //! 残数が 0 のときに新たにストリームサウンドを再生すると、 388 //! 既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。 389 //! ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、 390 //! 再生に失敗します。 391 //! 392 //! 再生可能なストリームサウンドの総数は、 393 //! サウンドアーカイブに記述されていて、 394 //! @ref Initialize でサウンドアーカイブプレイヤーに設定されます。 395 //! 396 //! @return 再生可能なストリームサウンドの残数を返します。 397 //! 398 //! @see Initialize 399 //! 400 //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 401 //! @date 2010/01/15 初版 402 //--------------------------------------------------------------------------- GetFreeStreamSoundCount()403 int GetFreeStreamSoundCount() const 404 { 405 return m_StreamSoundInstanceManager.GetFreeCount(); 406 } 407 408 //--------------------------------------------------------------------------- 409 //! @brief シーケンスコマンド 'userproc' で呼び出される 410 //! コールバック関数を登録します。 411 //! 412 //! ここで登録したコールバックは、シーケンスデータ側のシーケンスコマンド 413 //! 'userproc' が処理されたフレームで呼び出されます。 414 //! コールバック関数はサウンドスレッド呼び出されます。 415 //! 416 //! 'userproc' コマンドの詳細については、 417 //! シーケンスデータマニュアルを参照してください。 418 //! 419 //! ここで設定したコールバック関数はサウンドスレッドから呼び出されます。 420 //! 排他制御が必要な場合は、 421 //! @ref SoundThreadScopedLock クラスあるいは、 422 //! @ref LockSoundThread / @ref UnlockSoundThread 関数を利用する必要があります。 423 //! 424 //! コールバック関数はすみやかに処理を終える必要があります。 425 //! 処理が長引くと、ノイズが発生する可能性が高くなります。 426 //! たとえば、コールバック関数内でブロックする可能性のある API 427 //! (クリティカルセクションなど) を呼び出すと、 428 //! 処理を終えるのに時間がかかる可能性があります。 429 //! 430 //! @param[in] callback 登録するコールバック関数です。 431 //! @param[in] callbackArg コールバック関数に渡されるユーザー引数です。 432 //! 433 //! @ref SequenceUserprocCallback 434 //! 435 //! @date 2011/01/11 コールバック関数がサウンドスレッドから呼び出される旨、追記 436 //! @date 2010/01/15 初版 437 //--------------------------------------------------------------------------- 438 void SetSequenceUserprocCallback( 439 SequenceUserprocCallback callback, void* callbackArg ); 440 //@} 441 442 443 // StartSound実装 444 //! @details :private 445 StartResult detail_SetupSoundImpl( 446 SoundHandle* handle, 447 u32 soundId, 448 internal::BasicSound::AmbientInfo* ambientArgInfo, 449 SoundActor* actor, 450 bool holdFlag, 451 const StartInfo* startInfo 452 ); 453 //! @details :private detail_GetItemId(const char * pString)454 virtual SoundArchive::ItemId detail_GetItemId( const char* pString ) 455 { 456 NW_NULL_ASSERT( m_pSoundArchive ); 457 return m_pSoundArchive->GetItemId( pString ); 458 } 459 460 461 // 非公開関数 462 //! @details :private detail_SetMmlParser(internal::driver::MmlParser * parser)463 void detail_SetMmlParser( internal::driver::MmlParser* parser ) 464 { 465 if ( parser == NULL ) m_MmlSequenceTrackAllocator.SetMmlParser( &m_MmlParser ); 466 else m_MmlSequenceTrackAllocator.SetMmlParser( parser ); 467 } 468 //! @details :private 469 const void* detail_GetFileAddress( SoundArchive::FileId fileId ) const; 470 471 protected: 472 virtual StartResult detail_SetupSound( 473 SoundHandle* handle, 474 u32 soundId, 475 bool holdFlag, 476 const StartInfo* startInfo 477 ); 478 479 private: 480 481 template< typename Sound, typename Player > 482 Sound* AllocSound( 483 internal::SoundInstanceManager< Sound, Player >* manager, 484 SoundArchive::ItemId soundId, 485 int priority, 486 int ambientPriority, 487 internal::BasicSound::AmbientInfo* ambientArgInfo 488 ); 489 490 StartResult PrepareSequenceSoundImpl( 491 internal::SequenceSound* sound, 492 const SoundArchive::SoundInfo* commonInfo, 493 const SoundArchive::SequenceSoundInfo* info, 494 SoundStartable::StartInfo::StartOffsetType startOffsetType, 495 int startOffset, 496 const StartInfo::SeqSoundInfo* externalSeqInfo 497 ); 498 499 StartResult PrepareStreamSoundImpl( 500 internal::StreamSound* sound, 501 const SoundArchive::SoundInfo* commonInfo, 502 const SoundArchive::StreamSoundInfo* info, 503 SoundStartable::StartInfo::StartOffsetType startOffsetType, 504 int startOffset 505 ); 506 507 StartResult PrepareWaveSoundImpl( 508 internal::WaveSound* sound, 509 const SoundArchive::SoundInfo* commonInfo, 510 const SoundArchive::WaveSoundInfo* info, 511 SoundStartable::StartInfo::StartOffsetType startOffsetType, 512 int startOffset 513 ); 514 515 516 internal::PlayerHeap* CreatePlayerHeap( 517 void** ppBuffer, void* pEndAddress, size_t heapSize ); 518 519 // Setup 520 bool SetupMram( const SoundArchive* arc, void* buffer, unsigned long size ); 521 bool SetupSoundPlayer( const SoundArchive* arc, void** buffer, void* endp ); 522 bool SetupSequenceSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp ); 523 bool SetupSequenceTrack( const SoundArchive* arc, int numTracks, void** buffer, void* endp ); 524 bool SetupWaveSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp ); 525 bool SetupStreamSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp ); 526 bool SetupStreamBuffer( const SoundArchive* arc, void* buffer, unsigned long size ); 527 528 void UpdateCommonSoundParam( 529 internal::BasicSound* sound, const SoundArchive::SoundInfo* commonInfo ); 530 531 bool IsLoadWaveArchive( const void* bankFile, internal::LoadItemInfo* info ) const; 532 533 const SoundArchive* m_pSoundArchive; 534 535 // コールバック 536 SequenceNoteOnCallback m_SequenceCallback; 537 WaveSoundCallback m_WaveSoundCallback; 538 SequenceUserprocCallback m_SequenceUserprocCallback; 539 void* m_pSequenceUserprocCallbackArg; 540 541 // サウンドプレイヤー 542 u32 m_SoundPlayerCount; 543 SoundPlayer* m_pSoundPlayers; 544 545 // マネージャー・アロケータ 546 internal::SequenceSoundInstanceManager m_SequenceSoundInstanceManager; 547 internal::WaveSoundInstanceManager m_WaveSoundInstanceManager; 548 internal::StreamSoundInstanceManager m_StreamSoundInstanceManager; 549 550 internal::driver::SequenceTrackAllocator* m_pSequenceTrackAllocator; 551 internal::driver::MmlSequenceTrackAllocator m_MmlSequenceTrackAllocator; // デフォルトのシーケンストラックアロケータ 552 553 internal::driver::StreamBufferPool m_StreamBufferPool; 554 555 // デフォルトのシーケンスパーサ 556 internal::driver::MmlParser m_MmlParser; 557 558 // バッファ情報記憶 559 void* m_pSetupBufferAddress; 560 u32 m_SetupBufferSize; 561 562 // データマネージャ 563 const SoundDataManager* m_pSoundDataManager; 564 }; 565 566 } // namespace nw::snd 567 } // namespace nw 568 569 570 #endif /* NW_SND_SOUND_ARCHIVE_PLAYER_H_ */ 571 572