/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_SoundArchivePlayer.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 29700 $ *---------------------------------------------------------------------------*/ /** * :include nw/snd/snd_SoundArchivePlayer.h * * @file snd_SoundArchivePlayer.h */ #ifndef NW_SND_SOUND_ARCHIVE_PLAYER_H_ #define NW_SND_SOUND_ARCHIVE_PLAYER_H_ #include #include #include #include #include // SequenceUserprocCallback #include // SequenceSoundInstanceManager #include // WaveSoundInstanceManager #include // StreamSoundInstanceManager #include #include #include #include namespace nw { namespace snd { class SoundHandle; class SoundHeap; class SoundActor; class SoundPlayer; class SoundDataManager; namespace internal { class ExternalSoundPlayer; class Channel; class StreamSound; class WaveSound; class PlayerHeap; } //--------------------------------------------------------------------------- //! @brief サウンドアーカイブ中のサウンドを再生するクラスです。 //! //! SoundArchivePlayer で再生したサウンドは、 //! ハンドルクラスを用いて操作することができます。 //! //! @see SoundHandle クラス //! @see SoundStartable インターフェイス //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- class SoundArchivePlayer : public SoundStartable { private: static const int DEFAULT_STREAM_BLOCK_COUNT = 5; /* ------------------------------------------------------------------------ SeqCallback class ------------------------------------------------------------------------ */ class SequenceNoteOnCallback : public internal::driver::NoteOnCallback { public: SequenceNoteOnCallback( const SoundArchivePlayer& player ) : m_pSoundArchivePlayer( player ) { } virtual internal::driver::Channel* NoteOn( internal::driver::SequenceSoundPlayer* seqPlayer, u8 bankIndex, const internal::driver::NoteOnInfo& noteOnInfo ); private: const SoundArchivePlayer& m_pSoundArchivePlayer; }; friend class SoundArchivePlayer::SequenceNoteOnCallback; /* ------------------------------------------------------------------------ WaveSoundCallback class ------------------------------------------------------------------------ */ private: class WaveSoundCallback : public internal::driver::WaveSoundPlayer::WaveSoundCallback { public: WaveSoundCallback( const SoundArchivePlayer& player ) : m_pSoundArchivePlayer( player ) { } virtual bool GetWaveSoundData( internal::WaveSoundInfo* info, internal::WaveSoundNoteInfo* noteInfo, internal::WaveInfo* waveData, const internal::driver::WaveSoundPlayer::WaveSoundCallbackArg& arg ) const; private: const SoundArchivePlayer& m_pSoundArchivePlayer; }; /* ------------------------------------------------------------------------ class member ------------------------------------------------------------------------ */ public: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //--------------------------------------------------------------------------- //! @brief コンストラクタです。 //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- SoundArchivePlayer(); //--------------------------------------------------------------------------- //! @brief デストラクタです。 //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- virtual ~SoundArchivePlayer(); //@} //---------------------------------------- //! @name 初期化 //@{ //--------------------------------------------------------------------------- //! @brief 初期化に必要なメモリのサイズを取得します。 //! //! @param[in] arc プレイヤーで使用するサウンドアーカイブです。 //! //! @return 初期化に必要なメモリサイズを返します。 //! //! @see Initialize //! //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- size_t GetRequiredMemSize( const SoundArchive* arc ); //--------------------------------------------------------------------------- //! @brief 初期化に必要なストリームバッファのサイズを取得します。 //! //! @ref Initialize に渡すストリームバッファの最小サイズを取得します。 //! この関数で取得した値より大きいサイズのバッファを渡す必要があります。 //! //! @param[in] arc プレイヤーで使用するサウンドアーカイブです。 //! //! @return 初期化に必要なストリームバッファサイズを返します。 //! //! @see Initialize //! //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- size_t GetRequiredStreamBufferSize( const SoundArchive* arc ); //--------------------------------------------------------------------------- //! @brief サウンドアーカイブプレイヤーを初期化します。 //! //! サウンドアーカイブプレイヤーを使用する前に、 //! 初期化を行う必要があります。 //! 初期化を行うことにより、 //! サウンドアーカイブプレイヤーがサウンドアーカイブと //! サウンドデータマネージャ関連付けられ、 //! そのサウンドアーカイブ中のデータを再生できるようになります。 //! //! サウンドアーカイブプレイヤーが必要とするメモリのサイズは //! @ref GetRequiredMemSize 及び @ref GetRequiredStreamBufferSize //! で取得することができます。 //! //! 必要なストリームバッファサイズが 0 の場合、 //! ストリームバッファへのポインタ strmBuffer に NULL を渡すことができます。 //! //! ストリームバッファを @ref GetRequiredStreamBufferSize //! で取得したサイズより大きく設定すると、 //! ストリームサウンドの音途切れが発生しにくくなりますが、 //! データをロードしてから実際に再生するまでの遅延時間が大きくなります。 //! //! ストリームバッファはデバイスメモリのアドレスを指定する必要があります。 //! strmBuffer および strmBuffer + strmBufferSize のアドレスが、 //! デバイスメモリに無い場合は、アサートで停止、あるいは、 //! false を返します (ビルドターゲットによって挙動が変わります)。 //! //! @param[in] arc プレイヤーで使用するサウンドアーカイブです。 //! @param[in] manager プレイヤーで使用するサウンドデータマネージャです。 //! @param[in] buffer バッファへのポインタです。 //! 32 バイトアライメントされている必要があります。 //! @param[in] size バッファサイズです。 //! @param[in] strmBuffer ストリームバッファへのポインタです。 //! 32 バイトアライメントされているデバイスメモリを //! 指定する必要があります。 //! @param[in] strmBufferSize ストリームバッファのサイズです。 //! //! @return 初期化に成功したら true を、失敗したら false を返します。 //! //! @see GetRequiredMemSize //! @see GetRequiredStreamBufferSize //! @see Finalize //! @see IsAvailable //! //! @date 2010/03/05 ストリームバッファがデバイスメモリに無い場合の挙動を追記。 //! @date 2010/02/03 buffer のアライメントサイズを変更 (4 → 32) //! @date 2010/02/01 関数名変更 (Setup → Initialize) //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- bool Initialize( const SoundArchive* arc, const SoundDataManager* manager, void* buffer, u32 size, void* strmBuffer, u32 strmBufferSize ); //--------------------------------------------------------------------------- //! @brief サウンドアーカイブプレイヤーを破棄します。 //! //! 破棄は以下のとおり行われます。 //! //! ・このサウンドアーカイブプレイヤーを使って再生中のサウンドを停止します。@n //! ・初期化で割り当てたメモリ領域を開放します。@n //! ・初期化されたサウンドアーカイブとの関連が外れます。 //! //! @see Initialize //! @see IsAvailable //! //! @date 2010/02/01 関数名変更 (Shutdown → Finalize) //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- void Finalize(); //--------------------------------------------------------------------------- //! @brief 利用可能な状態かどうかを調べます。 //! //! サウンドアーカイブプレイヤーを利用するためには //! @ref Initialize を呼び出して初期化を完了させる必要があります。 //! また、@ref Finalize を呼び出すと、 //! サウンドアーカイブプレイヤーの終了処理が行われ、 //! 利用できない状態になります。 //! //! @return サウンドアーカイブプレイヤーが利用可能な状態なら true を、 //! そうでなければ false を返します。 //! //! @see Initialize //! @see Finalize //! //! @date 2010/02/01 関数名変更 (Setup → Initialize, Shutdown → Finalize) //! にともなう文言の調整 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- bool IsAvailable() const; //@} //---------------------------------------- //! @name 更新 //--------------------------------------------------------------------------- //! @brief サウンドアーカイブプレイヤーの更新処理を行います。 //! //! この関数は 1 ゲームフレームに 1 回呼び出してください。 //! //! 内部の処理はサウンドスレッドで行われるため、 //! 更新処理を 1 ゲームフレームに 1 回呼び出すことができなくても //! 発音が途切れることはありません。 //! この関数では、プレイヤーやサウンドに対するパラメータ設定や、 //! フェイドイン・フェイドアウトなどの連続的なパラメータ変更を //! 反映するための処理が行われます。 //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- void Update(); //@} //---------------------------------------- //! @name その他 //--------------------------------------------------------------------------- //! @brief プレイヤーに関連付けられているサウンドアーカイブを取得します。 //! //! @return プレイヤーに関連付けられているサウンドアーカイブを返します。 //! //! @see SoundArchive クラス //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- const SoundArchive& GetSoundArchive() const; //--------------------------------------------------------------------------- //! @brief 指定した ID のサウンドプレイヤーを取得します。 //! //! @param[in] playerId プレイヤーの ID です。 //! //! @return 指定した ID のサウンドプレイヤーを返します。 //! //! @see SoundPlayer クラス //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- SoundPlayer& GetSoundPlayer( SoundArchive::ItemId playerId ); //--------------------------------------------------------------------------- //! @brief 指定した ID のサウンドプレイヤーを取得します。 //! //! @param[in] pPlayerName プレイヤーのラベル文字列です。 //! //! @return 指定した ID のサウンドプレイヤーを返します。 //! //! @see SoundPlayer クラス //! //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- SoundPlayer& GetSoundPlayer( const char* pPlayerName ); //--------------------------------------------------------------------------- //! @brief サウンドプレイヤーの個数を取得します。 //! //! @return サウンドプレイヤーの個数を返します。 //! //! @see SoundPlayer クラス //! //! @date 2010/02/01 返り値の型を変更 (unsigned long → u32) //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- u32 GetSoundPlayerCount() const { return m_SoundPlayerCount; } //--------------------------------------------------------------------------- //! @brief 再生可能なシーケンスサウンドの残数を取得します。 //! //! 残数が 0 のときに新たにシーケンスサウンドを再生すると、 //! 既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。 //! ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、 //! 再生に失敗します。 //! //! 再生可能なシーケンスサウンドの総数は、 //! サウンドアーカイブに記述されていて、 //! @ref Initialize でサウンドアーカイブプレイヤーに設定されます。 //! //! @return 再生可能なシーケンスサウンドの残数を返します。 //! //! @see Initialize //! //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- int GetFreeSequenceSoundCount() const { return m_SequenceSoundInstanceManager.GetFreeCount(); } //--------------------------------------------------------------------------- //! @brief 再生可能なウェーブサウンドの残数を取得します。 //! //! 残数が 0 のときに新たにウェーブサウンドを再生すると、 //! 既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。 //! ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、 //! 再生に失敗します。 //! //! 再生可能なウェーブサウンドの総数は、 //! サウンドアーカイブに記述されていて、 //! @ref Initialize でサウンドアーカイブプレイヤーに設定されます。 //! //! @return 再生可能なウェーブサウンドの残数を返します。 //! //! @see Initialize //! //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- int GetFreeWaveSoundCount() const { return m_WaveSoundInstanceManager.GetFreeCount(); } //--------------------------------------------------------------------------- //! @brief 再生可能なストリームサウンドの残数を取得します。 //! //! 残数が 0 のときに新たにストリームサウンドを再生すると、 //! 既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。 //! ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、 //! 再生に失敗します。 //! //! 再生可能なストリームサウンドの総数は、 //! サウンドアーカイブに記述されていて、 //! @ref Initialize でサウンドアーカイブプレイヤーに設定されます。 //! //! @return 再生可能なストリームサウンドの残数を返します。 //! //! @see Initialize //! //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- int GetFreeStreamSoundCount() const { return m_StreamSoundInstanceManager.GetFreeCount(); } //--------------------------------------------------------------------------- //! @brief シーケンスコマンド 'userproc' で呼び出される //! コールバック関数を登録します。 //! //! ここで登録したコールバックは、シーケンスデータ側のシーケンスコマンド //! 'userproc' が処理されたフレームで呼び出されます。 //! コールバック関数はサウンドスレッド呼び出されます。 //! //! 'userproc' コマンドの詳細については、 //! シーケンスデータマニュアルを参照してください。 //! //! ここで設定したコールバック関数はサウンドスレッドから呼び出されます。 //! 排他制御が必要な場合は、 //! @ref SoundThreadScopedLock クラスあるいは、 //! @ref LockSoundThread / @ref UnlockSoundThread 関数を利用する必要があります。 //! //! コールバック関数はすみやかに処理を終える必要があります。 //! 処理が長引くと、ノイズが発生する可能性が高くなります。 //! たとえば、コールバック関数内でブロックする可能性のある API //! (クリティカルセクションなど) を呼び出すと、 //! 処理を終えるのに時間がかかる可能性があります。 //! //! @param[in] callback 登録するコールバック関数です。 //! @param[in] callbackArg コールバック関数に渡されるユーザー引数です。 //! //! @ref SequenceUserprocCallback //! //! @date 2011/01/11 コールバック関数がサウンドスレッドから呼び出される旨、追記 //! @date 2010/01/15 初版 //--------------------------------------------------------------------------- void SetSequenceUserprocCallback( SequenceUserprocCallback callback, void* callbackArg ); //@} // StartSound実装 //! @details :private StartResult detail_SetupSoundImpl( SoundHandle* handle, u32 soundId, internal::BasicSound::AmbientInfo* ambientArgInfo, SoundActor* actor, bool holdFlag, const StartInfo* startInfo ); //! @details :private virtual SoundArchive::ItemId detail_GetItemId( const char* pString ) { NW_NULL_ASSERT( m_pSoundArchive ); return m_pSoundArchive->GetItemId( pString ); } // 非公開関数 //! @details :private void detail_SetMmlParser( internal::driver::MmlParser* parser ) { if ( parser == NULL ) m_MmlSequenceTrackAllocator.SetMmlParser( &m_MmlParser ); else m_MmlSequenceTrackAllocator.SetMmlParser( parser ); } //! @details :private const void* detail_GetFileAddress( SoundArchive::FileId fileId ) const; protected: virtual StartResult detail_SetupSound( SoundHandle* handle, u32 soundId, bool holdFlag, const StartInfo* startInfo ); private: template< typename Sound, typename Player > Sound* AllocSound( internal::SoundInstanceManager< Sound, Player >* manager, SoundArchive::ItemId soundId, int priority, int ambientPriority, internal::BasicSound::AmbientInfo* ambientArgInfo ); StartResult PrepareSequenceSoundImpl( internal::SequenceSound* sound, const SoundArchive::SoundInfo* commonInfo, const SoundArchive::SequenceSoundInfo* info, SoundStartable::StartInfo::StartOffsetType startOffsetType, int startOffset, const StartInfo::SeqSoundInfo* externalSeqInfo ); StartResult PrepareStreamSoundImpl( internal::StreamSound* sound, const SoundArchive::SoundInfo* commonInfo, const SoundArchive::StreamSoundInfo* info, SoundStartable::StartInfo::StartOffsetType startOffsetType, int startOffset ); StartResult PrepareWaveSoundImpl( internal::WaveSound* sound, const SoundArchive::SoundInfo* commonInfo, const SoundArchive::WaveSoundInfo* info, SoundStartable::StartInfo::StartOffsetType startOffsetType, int startOffset ); internal::PlayerHeap* CreatePlayerHeap( void** ppBuffer, void* pEndAddress, size_t heapSize ); // Setup bool SetupMram( const SoundArchive* arc, void* buffer, unsigned long size ); bool SetupSoundPlayer( const SoundArchive* arc, void** buffer, void* endp ); bool SetupSequenceSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp ); bool SetupSequenceTrack( const SoundArchive* arc, int numTracks, void** buffer, void* endp ); bool SetupWaveSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp ); bool SetupStreamSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp ); bool SetupStreamBuffer( const SoundArchive* arc, void* buffer, unsigned long size ); void UpdateCommonSoundParam( internal::BasicSound* sound, const SoundArchive::SoundInfo* commonInfo ); bool IsLoadWaveArchive( const void* bankFile, internal::LoadItemInfo* info ) const; const SoundArchive* m_pSoundArchive; // コールバック SequenceNoteOnCallback m_SequenceCallback; WaveSoundCallback m_WaveSoundCallback; SequenceUserprocCallback m_SequenceUserprocCallback; void* m_pSequenceUserprocCallbackArg; // サウンドプレイヤー u32 m_SoundPlayerCount; SoundPlayer* m_pSoundPlayers; // マネージャー・アロケータ internal::SequenceSoundInstanceManager m_SequenceSoundInstanceManager; internal::WaveSoundInstanceManager m_WaveSoundInstanceManager; internal::StreamSoundInstanceManager m_StreamSoundInstanceManager; internal::driver::SequenceTrackAllocator* m_pSequenceTrackAllocator; internal::driver::MmlSequenceTrackAllocator m_MmlSequenceTrackAllocator; // デフォルトのシーケンストラックアロケータ internal::driver::StreamBufferPool m_StreamBufferPool; // デフォルトのシーケンスパーサ internal::driver::MmlParser m_MmlParser; // バッファ情報記憶 void* m_pSetupBufferAddress; u32 m_SetupBufferSize; // データマネージャ const SoundDataManager* m_pSoundDataManager; }; } // namespace nw::snd } // namespace nw #endif /* NW_SND_SOUND_ARCHIVE_PLAYER_H_ */