/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_SoundThread.h Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. 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. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #ifndef NW_SND_SOUND_THREAD_H_ #define NW_SND_SOUND_THREAD_H_ #include #include #include #include #include #include #include #include namespace nw { namespace snd { namespace internal { namespace driver { class SoundThread { /* ------------------------------------------------------------------------ typename definition ------------------------------------------------------------------------ */ public: class SoundFrameCallback { public: ut::LinkListNode m_Link; virtual ~SoundFrameCallback() {} virtual void OnBeginSoundFrame() {} virtual void OnEndSoundFrame() {} }; class PlayerCallback { public: ut::LinkListNode m_Link; virtual ~PlayerCallback() {} virtual void OnUpdateFrameSoundThread() {} virtual void OnUpdateVoiceSoundThread() {} virtual void OnShutdownSoundThread() {} }; /* ------------------------------------------------------------------------ constant definition ------------------------------------------------------------------------ */ private: #ifdef NW_PLATFORM_CTRWIN static const int THREAD_MESSAGE_BUFSIZE = 8; static const int MESSAGE_HW_CALLBACK = 1; static const int MESSAGE_SHUTDOWN = 2; #endif /* ------------------------------------------------------------------------ class member ------------------------------------------------------------------------ */ public: static SoundThread& GetInstance(); #if defined( NW_SND_AVAILABLE_NN_SND_STARTSOUNDTHREAD ) #if defined ( NW_SND_AVAILABLE_NN_SND_STARTSOUNDTHREAD2 ) bool CreateSoundThread( uptr stackBufferAddress, size_t stackBufferSize, s32 priority, uptr userThreadStackBufferAddress, size_t userThreadStackBufferSize, s32 userThreadPriority, s32 coreNo, bool isEnableGetTick ); #else bool CreateSoundThread( uptr stackBufferAddress, size_t stackBufferSize, s32 priority, s32 coreNo, bool isEnableGetTick ); bool CreateUserSoundThread( // サウンドスレッドコア1動作時用、AUX 等処理スレッド uptr stackBufferAddress, size_t stackBufferSize, s32 priority ); #endif #else bool Create( s32 priority, ThreadStack& stack, s32 coreNo, bool enableGetTick ); #endif void Destroy(); bool IsCreated() const { return m_CreateFlag != 0; } void Initialize(); void Finalize(); void Pause( bool pauseFlag ) { m_PauseFlag = pauseFlag; } void FrameProcess(); // ユーザーが自前で SDK の Wait/Send を呼ぶ場合に利用する void FrameProcessForExternalThread() { FrameProcess(); } void RegisterSoundFrameUserCallback( SoundFrameUserCallback callback, uptr arg ) { m_UserCallback = callback; m_UserCallbackArg = arg; } void ClearSoundFrameUserCallback() { m_UserCallback = NULL; m_UserCallbackArg = NULL; } void GetRegisteredSoundFrameUserCallback( SoundFrameUserCallback* pCallback, uptr* pArg ) { *pCallback = m_UserCallback; *pArg = m_UserCallbackArg; } void RegisterSoundFrameCallback( SoundFrameCallback* callback ); void UnregisterSoundFrameCallback( SoundFrameCallback* callback ); void RegisterPlayerCallback( PlayerCallback* callback ); void UnregisterPlayerCallback( PlayerCallback* callback ); #ifdef NW_PLATFORM_CTR void CalcProcessCost( const nn::os::Tick& tick ); void GetTickCount( nn::os::Tick& tick, int& count ) const; void ClearTickCount(); int GetDspCycles() const { return m_DspCycles; } void ClearDspCycles() { m_DspCycles = 0; } Util::PerfHistogram& GetPerfHistogram() { return m_PerfHistogram; } void BeginCalcPerf() { m_IsBeginCalcPerf = true; m_PerfDataCount = 0; } void EndCalcPerf() { m_IsBeginCalcPerf = false; } void ResetCalcPerf() { m_PerfDataCount = 0; } #endif void Lock() { m_CriticalSection.Enter(); } void Unlock() { m_CriticalSection.Leave(); } private: typedef ut::LinkList< SoundFrameCallback, offsetof(SoundFrameCallback,m_Link)> SoundFrameCallbackList; typedef ut::LinkList< PlayerCallback, offsetof(PlayerCallback,m_Link)> PlayerCallbackList; SoundThread(); bool PrepareForCreate( bool enableGetTick ); void SoundThreadProc(); void VoiceUpdate(); #ifdef NW_PLATFORM_CTRWIN void HwCallbackProc(); static void HwCallbackFunc(); #endif static void SoundThreadFunc( uptr arg ); static void UserThreadCallback( uptr arg ); #ifdef NW_SND_AVAILABLE_NN_SND_STARTSOUNDTHREAD // nn::snd::StartSoundThread では、SDK 内部に nn::os::Thread を保持する #else nn::os::Thread m_Thread; #endif #ifdef NW_PLATFORM_CTRWIN HardwareManager::CallbackListNode m_HwCallbackNode; uptr m_MsgBuffer[ THREAD_MESSAGE_BUFSIZE ]; nn::os::BlockingQueue m_BlockingQueue; #else nn::os::Tick m_SoundThreadSumTick; // サウンドスレッド累積処理時間 int m_SoundThreadCount; // サウンドスレッド累積処理回数 int m_DspCycles; // 累積 DSP サイクル Util::PerfHistogram m_PerfHistogram; bool m_IsBeginCalcPerf; #endif #ifdef NW_SND_CONFIG_USE_INTERCORE_CRITICALSECTION typedef nn::os::InterCoreCriticalSection CriticalSection; #else typedef nn::os::CriticalSection CriticalSection; #endif mutable CriticalSection m_CriticalSection; SoundFrameCallbackList m_SoundFrameCallbackList; PlayerCallbackList m_PlayerCallbackList; SoundFrameUserCallback m_UserCallback; uptr m_UserCallbackArg; s32 m_SoundThreadCoreNo; bool m_CreateFlag; bool m_PauseFlag; bool m_IsEnableGetTick; volatile bool m_IsFinalizing; // デバッグ public: struct PerfData { f32 load; // 処理負荷 (整数%) u8 voice; // 使用ボイス数 u8 noteOn; // ノート音の数 u8 padding[2]; }; void SetPerfDataBuffer( PerfData* data, int num ) { m_pPerfData = data; m_PerfDataNum = num; } void IncrNoteOnCount() { m_NoteOnCount += 1; } int GetPerfDataCount() const { return m_PerfDataCount; } private: PerfData* m_pPerfData; int m_NoteOnCount; int m_PerfDataNum; int m_PerfDataCount; }; class SoundThreadLock { public: SoundThreadLock() { SoundThread::GetInstance().Lock(); } ~SoundThreadLock() { SoundThread::GetInstance().Unlock(); } private: NW_DISALLOW_COPY_AND_ASSIGN( SoundThreadLock ); }; } // namespace nw::snd::internal::driver } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw #endif /* NW_SND_SOUND_THREAD_H_ */