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