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