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