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