1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: snd_SoundThread.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: 26148 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NW_SND_SOUND_THREAD_H_ 17 #define NW_SND_SOUND_THREAD_H_ 18 19 #include <nn/os.h> 20 #include <nw/os.h> 21 #include <nw/ut/ut_LinkList.h> 22 #include <nw/ut/ut_PreProcessor.h> 23 #include <nw/snd/snd_Config.h> 24 #include <nw/snd/snd_HardwareManager.h> 25 #include <nw/snd/snd_ThreadStack.h> 26 #include <nw/snd/snd_Global.h> 27 28 namespace nw { 29 namespace snd { 30 namespace internal { 31 namespace driver { 32 33 class SoundThread 34 { 35 /* ------------------------------------------------------------------------ 36 typename definition 37 ------------------------------------------------------------------------ */ 38 public: 39 class SoundFrameCallback 40 { 41 public: 42 ut::LinkListNode m_Link; 43 ~SoundFrameCallback()44 virtual ~SoundFrameCallback() {} OnBeginSoundFrame()45 virtual void OnBeginSoundFrame() {} OnEndSoundFrame()46 virtual void OnEndSoundFrame() {} 47 }; 48 49 class PlayerCallback 50 { 51 public: 52 ut::LinkListNode m_Link; 53 ~PlayerCallback()54 virtual ~PlayerCallback() {} OnUpdateFrameSoundThread()55 virtual void OnUpdateFrameSoundThread() {} OnUpdateVoiceSoundThread()56 virtual void OnUpdateVoiceSoundThread() {} OnShutdownSoundThread()57 virtual void OnShutdownSoundThread() {} 58 }; 59 60 /* ------------------------------------------------------------------------ 61 constant definition 62 ------------------------------------------------------------------------ */ 63 private: 64 #ifdef NW_PLATFORM_CTRWIN 65 static const int THREAD_MESSAGE_BUFSIZE = 8; 66 static const int MESSAGE_HW_CALLBACK = 1; 67 static const int MESSAGE_SHUTDOWN = 2; 68 #endif 69 70 /* ------------------------------------------------------------------------ 71 class member 72 ------------------------------------------------------------------------ */ 73 public: 74 static SoundThread& GetInstance(); 75 76 #if defined( NW_SND_AVAILABLE_NN_SND_STARTSOUNDTHREAD ) 77 78 #if defined ( NW_SND_AVAILABLE_NN_SND_STARTSOUNDTHREAD2 ) 79 bool CreateSoundThread( 80 uptr stackBufferAddress, 81 size_t stackBufferSize, 82 s32 priority, 83 uptr userThreadStackBufferAddress, 84 size_t userThreadStackBufferSize, 85 s32 userThreadPriority, 86 s32 coreNo, 87 bool isEnableGetTick 88 ); 89 #else 90 bool CreateSoundThread( 91 uptr stackBufferAddress, 92 size_t stackBufferSize, 93 s32 priority, 94 s32 coreNo, 95 bool isEnableGetTick ); 96 bool CreateUserSoundThread( // サウンドスレッドコア1動作時用、AUX 等処理スレッド 97 uptr stackBufferAddress, 98 size_t stackBufferSize, 99 s32 priority ); 100 #endif 101 102 #else 103 bool Create( 104 s32 priority, 105 ThreadStack& stack, 106 s32 coreNo, 107 bool enableGetTick ); 108 #endif 109 void Destroy(); IsCreated()110 bool IsCreated() const { return m_CreateFlag != 0; } 111 112 void Initialize(); 113 void Finalize(); 114 Pause(bool pauseFlag)115 void Pause( bool pauseFlag ) { m_PauseFlag = pauseFlag; } 116 void FrameProcess(); 117 118 // ユーザーが自前で SDK の Wait/Send を呼ぶ場合に利用する FrameProcessForExternalThread()119 void FrameProcessForExternalThread() 120 { 121 FrameProcess(); 122 } 123 RegisterSoundFrameUserCallback(SoundFrameUserCallback callback,uptr arg)124 void RegisterSoundFrameUserCallback( SoundFrameUserCallback callback, uptr arg ) 125 { 126 m_UserCallback = callback; 127 m_UserCallbackArg = arg; 128 } ClearSoundFrameUserCallback()129 void ClearSoundFrameUserCallback() 130 { 131 m_UserCallback = NULL; 132 m_UserCallbackArg = NULL; 133 } GetRegisteredSoundFrameUserCallback(SoundFrameUserCallback * pCallback,uptr * pArg)134 void GetRegisteredSoundFrameUserCallback( SoundFrameUserCallback* pCallback, uptr* pArg ) 135 { 136 *pCallback = m_UserCallback; 137 *pArg = m_UserCallbackArg; 138 } 139 140 void RegisterSoundFrameCallback( SoundFrameCallback* callback ); 141 void UnregisterSoundFrameCallback( SoundFrameCallback* callback ); 142 143 void RegisterPlayerCallback( PlayerCallback* callback ); 144 void UnregisterPlayerCallback( PlayerCallback* callback ); 145 146 #ifdef NW_PLATFORM_CTR 147 void CalcProcessCost( const nn::os::Tick& tick ); 148 void GetTickCount( nn::os::Tick& tick, int& count ) const; 149 void ClearTickCount(); GetDspCycles()150 int GetDspCycles() const 151 { 152 return m_DspCycles; 153 } ClearDspCycles()154 void ClearDspCycles() 155 { 156 m_DspCycles = 0; 157 } GetPerfHistogram()158 Util::PerfHistogram& GetPerfHistogram() { return m_PerfHistogram; } BeginCalcPerf()159 void BeginCalcPerf() { m_IsBeginCalcPerf = true; m_PerfDataCount = 0; } EndCalcPerf()160 void EndCalcPerf() { m_IsBeginCalcPerf = false; } ResetCalcPerf()161 void ResetCalcPerf() { m_PerfDataCount = 0; } 162 #endif 163 Lock()164 void Lock() { m_CriticalSection.Enter(); } Unlock()165 void Unlock() { m_CriticalSection.Leave(); } 166 167 private: 168 typedef 169 ut::LinkList< SoundFrameCallback, offsetof(SoundFrameCallback,m_Link)> 170 SoundFrameCallbackList; 171 typedef 172 ut::LinkList< PlayerCallback, offsetof(PlayerCallback,m_Link)> 173 PlayerCallbackList; 174 175 SoundThread(); 176 177 bool PrepareForCreate( bool enableGetTick ); 178 179 void SoundThreadProc(); 180 void VoiceUpdate(); 181 #ifdef NW_PLATFORM_CTRWIN 182 void HwCallbackProc(); 183 static void HwCallbackFunc(); 184 #endif 185 static void SoundThreadFunc( uptr arg ); 186 static void UserThreadCallback( uptr arg ); 187 188 #ifdef NW_SND_AVAILABLE_NN_SND_STARTSOUNDTHREAD 189 // nn::snd::StartSoundThread では、SDK 内部に nn::os::Thread を保持する 190 #else 191 nn::os::Thread m_Thread; 192 #endif 193 194 #ifdef NW_PLATFORM_CTRWIN 195 HardwareManager::CallbackListNode m_HwCallbackNode; 196 uptr m_MsgBuffer[ THREAD_MESSAGE_BUFSIZE ]; 197 nn::os::BlockingQueue m_BlockingQueue; 198 #else 199 nn::os::Tick m_SoundThreadSumTick; // サウンドスレッド累積処理時間 200 int m_SoundThreadCount; // サウンドスレッド累積処理回数 201 int m_DspCycles; // 累積 DSP サイクル 202 Util::PerfHistogram m_PerfHistogram; 203 bool m_IsBeginCalcPerf; 204 #endif 205 206 #ifdef NW_SND_CONFIG_USE_INTERCORE_CRITICALSECTION 207 typedef nn::os::InterCoreCriticalSection CriticalSection; 208 #else 209 typedef nn::os::CriticalSection CriticalSection; 210 #endif 211 mutable CriticalSection m_CriticalSection; 212 213 SoundFrameCallbackList m_SoundFrameCallbackList; 214 PlayerCallbackList m_PlayerCallbackList; 215 SoundFrameUserCallback m_UserCallback; 216 uptr m_UserCallbackArg; 217 s32 m_SoundThreadCoreNo; 218 bool m_CreateFlag; 219 bool m_PauseFlag; 220 bool m_IsEnableGetTick; 221 volatile bool m_IsFinalizing; 222 223 // デバッグ 224 public: 225 struct PerfData 226 { 227 f32 load; // 処理負荷 (整数%) 228 u8 voice; // 使用ボイス数 229 u8 noteOn; // ノート音の数 230 u8 padding[2]; 231 }; SetPerfDataBuffer(PerfData * data,int num)232 void SetPerfDataBuffer( PerfData* data, int num ) 233 { 234 m_pPerfData = data; 235 m_PerfDataNum = num; 236 } IncrNoteOnCount()237 void IncrNoteOnCount() { m_NoteOnCount += 1; } GetPerfDataCount()238 int GetPerfDataCount() const { return m_PerfDataCount; } 239 private: 240 PerfData* m_pPerfData; 241 int m_NoteOnCount; 242 int m_PerfDataNum; 243 int m_PerfDataCount; 244 }; 245 246 class SoundThreadLock 247 { 248 public: SoundThreadLock()249 SoundThreadLock() 250 { 251 SoundThread::GetInstance().Lock(); 252 } 253 ~SoundThreadLock()254 ~SoundThreadLock() 255 { 256 SoundThread::GetInstance().Unlock(); 257 } 258 259 private: 260 NW_DISALLOW_COPY_AND_ASSIGN( SoundThreadLock ); 261 }; 262 263 } // namespace nw::snd::internal::driver 264 } // namespace nw::snd::internal 265 } // namespace nw::snd 266 } // namespace nw 267 268 269 #endif /* NW_SND_SOUND_THREAD_H_ */ 270 271