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