1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_StreamSoundPlayer.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: 22284 $
14  *---------------------------------------------------------------------------*/
15 /**
16  * :include nw/snd/snd_StreamSoundPlayer.h
17  *
18  * @file snd_StreamSoundPlayer.h
19  */
20 
21 #ifndef NW_SND_STREAM_SOUND_PLAYER_H_
22 #define NW_SND_STREAM_SOUND_PLAYER_H_
23 
24 #include <nw/io/io_FileStream.h>
25 #include <nw/snd/snd_SoundThread.h>
26 #include <nw/snd/snd_BasicSoundPlayer.h>
27 #include <nw/snd/snd_StreamSoundFileReader.h>
28 #include <nw/snd/snd_StreamTrack.h>
29 #include <nw/snd/snd_InstancePool.h>
30 #include <nw/snd/snd_Task.h>
31 #include <nw/snd/snd_Util.h>
32 
33 namespace nw {
34 namespace snd {
35 
36 //---------------------------------------------------------------------------
37 //! @brief    ストリームデータのパラメータセットです。
38 //!
39 //!           この情報は @ref StreamSoundHandle::ReadStreamDataInfo から取得できます。
40 //!
41 //! @see StreamSoundHandle::ReadStreamDataInfo
42 //!
43 //! @date 2010/03/12 誤植修正 (StearmSoundHandle → StreamSoundHandle)
44 //! @date 2010/01/22 初版
45 //---------------------------------------------------------------------------
46 struct StreamDataInfo
47 {
48     //---------------------------------------------------------------------------
49     //! @brief    ストリームデータがループするなら true、
50     //!           終端で終了するなら false となります。
51     //---------------------------------------------------------------------------
52     bool loopFlag;
53 
54     //---------------------------------------------------------------------------
55     //! @brief    ストリームデータのサンプリングレートです。
56     //---------------------------------------------------------------------------
57     int sampleRate;
58 
59     //---------------------------------------------------------------------------
60     //! @brief    ストリームデータがループする時のループ開始位置を、
61     //!           ストリームの先頭からのサンプル数で表します。
62     //---------------------------------------------------------------------------
63     u32 loopStart;
64 
65     //---------------------------------------------------------------------------
66     //! @brief    ストリームデータがループする時のループ終了位置を、
67     //!           ストリームの先頭からのサンプル数で表します。
68     //!           ループしない時は、データの終端をサンプル数で表します。
69     //!           (再生される最後のサンプルの次のサンプルを指します)
70     //---------------------------------------------------------------------------
71     u32 loopEnd;
72 };
73 
74 namespace internal {
75 namespace driver {
76 
77 class StreamBufferPool;
78 
79 class StreamSoundPlayer : public BasicSoundPlayer, public SoundThread::PlayerCallback
80 {
81     /* ------------------------------------------------------------------------
82             constant definition
83        ------------------------------------------------------------------------ */
84   public:
85     // 再生できる最大ブロックサイズ
86     static const u32 DATA_BLOCK_SIZE_MAX = 8 * 1024;
87     static const u32 STRM_TRACK_NUM = 4;
88 
89     enum SetupResult
90     {
91         SETUP_SUCCESS = 0,
92         SETUP_ERR_CANNOT_ALLOCATE_BUFFER,
93         SETUP_ERR_UNKNOWN
94     };
95 
96     enum StartOffsetType
97     {
98         START_OFFSET_TYPE_SAMPLE,
99         START_OFFSET_TYPE_MILLISEC
100     };
101 
102     /* ------------------------------------------------------------------------
103             class member
104        ------------------------------------------------------------------------ */
105     StreamSoundPlayer();
106     virtual ~StreamSoundPlayer();
107 
108     virtual void Initialize();
109     SetupResult Setup(
110         StreamBufferPool* pBufferPool,
111         u32 allocChannelCount,
112         u16 allocTrackFlag
113     );
114     virtual void Finalize();
115 
116     bool Prepare(
117         io::FileStream* pFileStream,
118         StartOffsetType startOffsetType,
119         int startOffset
120     );
121 
122     virtual void Start();
123     virtual void Stop();
124     virtual void Pause( bool flag );
125 
IsSuspendByLoadingDelay()126     bool IsSuspendByLoadingDelay() const { return m_LoadWaitFlag; }
127 
IsPrepared()128     bool IsPrepared() const { return m_IsPrepared; }
129 
130     //------------------------------------------------------------------
131     // プレイヤーパラメータ
132 
133     //------------------------------------------------------------------
134     // トラックパラメータ
135     void SetTrackVolume( u32 trackBitFlag, float volume );
136     void SetTrackPan( u32 trackBitFlag, float pan );
137     void SetTrackSurroundPan( u32 trackBitFlag, float span );
138 
139     //------------------------------------------------------------------
140     // 情報取得
141     bool ReadStreamDataInfo( StreamDataInfo* info ) const;
GetPlayLoopCount()142     long GetPlayLoopCount() const { return m_ActiveFlag ? m_LoopCounter : -1; }
143     long GetPlaySamplePosition() const;
144     float GetFilledBufferPercentage() const;
145 
146     //------------------------------------------------------------------
147     StreamTrack* GetPlayerTrack( int trackNo );
148     const StreamTrack* GetPlayerTrack( int trackNo ) const;
149 
150     bool LoadHeader(
151         const StreamSoundFile::StreamSoundInfo& streamInfo,
152         const StreamSoundFileReader::TrackInfo trackInfos[],
153         const DspAdpcmParam dspAdpcmParam[],
154         const DspAdpcmLoopParam dspAdpcmLoopParam[],
155         u32 dataBlockOffset,
156         u32 trackCount,
157         u32 channelCount
158     );
159     bool LoadStreamData(
160         int bufferBlockIndex,
161         int dataBlockIndex,
162         u32 blockSamples,
163         bool isDataLoopBlock,
164         bool lastBlockFlag
165     );
166 
167     //------------------------------------------------------------------
168   protected:
OnUpdateFrameSoundThread()169     virtual void OnUpdateFrameSoundThread() { Update(); }
OnUpdateVoiceSoundThread()170     virtual void OnUpdateVoiceSoundThread() { UpdateBuffer(); }
OnShutdownSoundThread()171     virtual void OnShutdownSoundThread() { Stop(); }
172 
173 
174     //------------------------------------------------------------------
175   private:
176     static const u32 STRM_CHANNEL_NUM = 8;
177     static const u32 STRM_CHANNEL_NUM_PER_TRACK = 2;
178 
179     static const u32 BUFFER_BLOCK_COUNT_MAX = 32; // 扱えるバッファブロックの最大数
180     static const u32 LOAD_BUFFER_CHANNEL_NUM = 2; // 同時にロードを行うチャンネルの数
181     static const u32 LOAD_BUFFER_SIZE = DATA_BLOCK_SIZE_MAX * LOAD_BUFFER_CHANNEL_NUM;
182 
183     /* ------------------------------------------------------------------------
184             StreamHeaderLoadTask class
185        ------------------------------------------------------------------------ */
186     class StreamHeaderLoadTask : public Task
187     {
188       public:
189         StreamHeaderLoadTask();
190         virtual void Execute();
191 
192       public:
193         StreamSoundPlayer* m_PlayerHandle;
194         io::FileStream* m_pFileStream;
195         StreamSoundPlayer::StartOffsetType m_StartOffsetType;
196         s32 m_StartOffset;
197 
198       private:
199         bool LoadHeader();
200     };
201     friend class StreamHeaderLoadTask;
202 
203     /* ------------------------------------------------------------------------
204             StreamDataLoadTask class
205        ------------------------------------------------------------------------ */
206     class StreamDataLoadTask : public Task
207     {
208       public:
209         StreamDataLoadTask();
210         virtual void Execute();
211 
212       public:
213         StreamSoundPlayer* m_PlayerHandle;
214         io::FileStream* m_pFileStream;
215 
216         void*   m_BufferAddress[ STRM_CHANNEL_NUM ];
217         u32     m_ChannelCount;
218         s32     m_Offset;
219         size_t  m_BlockBytes;
220         s32     m_BufferBlockIndex;
221         u32     m_BlockSamples;
222         u32     m_DataBlockSize;
223         u32     m_LoadingDataBlockIndex;
224         bool    m_IsDataLoopBlock;
225         bool    m_LastBlockFlag;
226 
227         ut::LinkListNode m_Link;
228 
229       private:
230         bool LoadStreamData();
231     };
232     friend class StreamDataLoadTask;
233 
234     typedef ut::LinkList<StreamDataLoadTask, offsetof(StreamDataLoadTask,m_Link)>
235         StreamDataLoadTaskList;
236 
237     bool SetupPlayer();
238 
239     void Update();
240     void UpdateTask();
241     void UpdateBuffer();
242     void UpdateVoiceParams( StreamTrack* track );
243 
244     bool AllocVoices();
245     void FreeVoices();
246     bool AllocStreamBuffers();
247     void FreeStreamBuffers();
248 
249     void UpdatePlayingBlockIndex();
250     void UpdateLoadingBlockIndex();
251     void UpdatePauseStatus();
252 #ifdef NW_PLATFORM_CTRWIN
253     void UpdateLoopAddress(
254         unsigned long loopStartSamples,
255         unsigned long loopEndSamples
256     );
257     void UpdateDataLoopAddress( s32 endBufferBlockIndex );
258     void SetLoopEndToZeroBuffer( int endBufferBlockIndex );
259 #endif
260     void SetAdpcmLoopContext( int channelNum, u16 predScale[] );
261 
262     void* GetBuffer( int channelNum );
263 
SetTaskErrorFlag()264     void SetTaskErrorFlag() { m_IsTaskError = true; }
265 
266 
267     bool CheckDiskDriveError() const;
268 
269     int CalcLoadingBufferBlockCount() const;
270     bool CalcStartOffset(
271         s32* pStartBlockIndex,
272         u32* pStartBlockOffset,
273         s32* pLoopCount
274     );
275 
276     static void VoiceCallbackFunc(
277         Voice* voice,
278         Voice::VoiceCallbackStatus status,
279         void* arg
280     );
281 
282     StreamChannel* GetTrackChannel( const StreamTrack& track, int channelIndex );
283 
284     s32 CalcLoadOffset() const;
285 
286     bool IsDspAdpcm() const;
287 
288     StreamSoundFile::StreamSoundInfo m_StreamInfo;
289 
290     bool m_IsInitialized;       // Initialize が呼ばれた
291     bool m_IsPrepared;          // 準備完了フラグ
292     bool m_IsTaskError;         // タスク実行中、エラー発生
293     bool m_IsLoadingDelay;      // ロード遅延メッセージ
294     bool m_PauseStatus;
295     bool m_LoadWaitFlag;        // バッファが溜まるまで、一時停止解除を遅延させる
296     bool m_IsNoRealtimeLoad;    // ストリームデータがバッファサイズより小さい時のモード
297     bool m_SkipUpdateAdpcmLoop;
298     bool m_ValidAdpcmLoop;
299 
300     bool m_PlayFinishFlag;
301     bool m_LoadFinishFlag;
302 
303     s32 m_LoopCounter;
304 
305     int m_PrepareCounter;
306     int m_ChangeNumBlocks;
307 
308     int m_DataBlockSize;
309 
310     u32 m_BufferBlockCount;
311     int m_BufferBlockCountBase;
312 
313     int m_LoadingBufferBlockCount;
314     int m_LoadingBufferBlockIndex;
315     int m_LoadingDataBlockIndex;
316 
317     int m_PlayingBufferBlockCount;
318     int m_PlayingBufferBlockIndex;
319     int m_PlayingDataBlockIndex;
320     int m_LoopStartBlockIndex;
321     int m_LastBlockIndex;
322 
323     u32 m_DataOffsetFromFileHead;   // ストリームファイル先頭を起点とした、
324                                     // サンプル実データまでのオフセット
325 
326     volatile int m_LoadWaitCount;
327 
328     StartOffsetType m_StartOffsetType;
329     int m_StartOffset;
330 
331     StreamHeaderLoadTask m_StreamHeaderLoadTask;
332     StreamDataLoadTaskList m_StreamDataLoadTaskList;
333     InstancePool<StreamDataLoadTask> m_StreamDataLoadTaskPool;
334     StreamDataLoadTask m_StreamDataLoadTaskArea[BUFFER_BLOCK_COUNT_MAX];
335 
336     StreamBufferPool* m_pBufferPool;
337     io::FileStream* m_pFileStream;
338 
339     s32 m_TrackCount;
340     s32 m_ChannelCount;
341     StreamChannel m_Channels[ STRM_CHANNEL_NUM ];
342     StreamTrack m_Tracks[ STRM_TRACK_NUM ];
343 
344     static u8 s_LoadBuffer[ LOAD_BUFFER_SIZE ];
345 };
346 
347 } // namespace nw::snd::internal::driver
348 } // namespace nw::snd::internal
349 } // namespace nw::snd
350 } // namespace nw
351 
352 
353 #endif /* NW_SND_STREAM_SOUND_PLAYER_H_ */
354 
355