1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundArchivePlayer.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 /**
17  * :include nw/snd/snd_SoundArchivePlayer.h
18  *
19  * @file snd_SoundArchivePlayer.h
20  */
21 
22 #ifndef NW_SND_SOUND_ARCHIVE_PLAYER_H_
23 #define NW_SND_SOUND_ARCHIVE_PLAYER_H_
24 
25 #include <nw/snd/snd_SoundStartable.h>
26 #include <nw/snd/snd_NoteOnCallback.h>
27 #include <nw/snd/snd_SoundArchive.h>
28 #include <nw/snd/snd_BasicSound.h>
29 #include <nw/snd/snd_SequenceSoundPlayer.h> // SequenceUserprocCallback
30 #include <nw/snd/snd_SequenceSound.h>       // SequenceSoundInstanceManager
31 #include <nw/snd/snd_WaveSound.h>           // WaveSoundInstanceManager
32 #include <nw/snd/snd_StreamSound.h>         // StreamSoundInstanceManager
33 #include <nw/snd/snd_Util.h>
34 #include <nw/snd/snd_SoundInstanceManager.h>
35 #include <nw/snd/snd_MmlSequenceTrackAllocator.h>
36 #include <nw/snd/snd_MmlParser.h>
37 
38 namespace nw {
39 namespace snd {
40 
41 class SoundHandle;
42 class SoundHeap;
43 class SoundActor;
44 class SoundPlayer;
45 class SoundDataManager;
46 
47 namespace internal {
48 
49 class ExternalSoundPlayer;
50 class Channel;
51 class StreamSound;
52 class WaveSound;
53 class PlayerHeap;
54 
55 }
56 
57 //!
58 //---------------------------------------------------------------------------
59 //! @brief    サウンドアーカイブ中のサウンドを再生するクラスです。
60 //!
61 //!           SoundArchivePlayer で再生したサウンドは、
62 //!           ハンドルクラスを用いて操作することができます。
63 //!
64 //! @see SoundHandle クラス
65 //! @see SoundStartable インターフェイス
66 //!
67 //! @date 2010/01/15 初版
68 //---------------------------------------------------------------------------
69 class SoundArchivePlayer : public SoundStartable
70 {
71   private:
72     static const int DEFAULT_STREAM_BLOCK_COUNT = 5;
73 
74     /* ------------------------------------------------------------------------
75             SeqCallback class
76        ------------------------------------------------------------------------ */
77     class SequenceNoteOnCallback : public internal::driver::NoteOnCallback
78     {
79       public:
SequenceNoteOnCallback(const SoundArchivePlayer & player)80         SequenceNoteOnCallback( const SoundArchivePlayer& player ) : m_pSoundArchivePlayer( player ) { }
81 
82         virtual internal::driver::Channel* NoteOn(
83             internal::driver::SequenceSoundPlayer* seqPlayer,
84             u8 bankIndex,
85             const internal::driver::NoteOnInfo& noteOnInfo
86         );
87 
88       private:
89         const SoundArchivePlayer& m_pSoundArchivePlayer;
90     };
91     friend class SoundArchivePlayer::SequenceNoteOnCallback;
92 
93     /* ------------------------------------------------------------------------
94             WaveSoundCallback class
95        ------------------------------------------------------------------------ */
96   private:
97     class WaveSoundCallback : public internal::driver::WaveSoundPlayer::WaveSoundCallback
98     {
99       public:
WaveSoundCallback(const SoundArchivePlayer & player)100         WaveSoundCallback( const SoundArchivePlayer& player ) : m_pSoundArchivePlayer( player ) { }
101 
102         virtual bool GetWaveSoundData(
103             internal::WaveSoundInfo* info,
104             internal::WaveSoundNoteInfo* noteInfo,
105             internal::WaveInfo* waveData,
106             const void* waveSoundData,
107             int index,
108             int noteIndex,
109             u32 userData
110         ) const;
111 
112       private:
113         const SoundArchivePlayer& m_pSoundArchivePlayer;
114     };
115 
116     /* ------------------------------------------------------------------------
117             class member
118        ------------------------------------------------------------------------ */
119   public:
120     //----------------------------------------
121     //! @name コンストラクタ/デストラクタ
122     //@{
123     //---------------------------------------------------------------------------
124     //! @brief        コンストラクタです。
125     //!
126     //! @date 2010/01/15 初版
127     //---------------------------------------------------------------------------
128     SoundArchivePlayer();
129 
130     //---------------------------------------------------------------------------
131     //! @brief        デストラクタです。
132     //!
133     //! @date 2010/01/15 初版
134     //---------------------------------------------------------------------------
135     virtual ~SoundArchivePlayer();
136     //@}
137 
138     //----------------------------------------
139     //! @name 初期化
140     //@{
141     //---------------------------------------------------------------------------
142     //! @brief        初期化に必要なメモリのサイズを取得します。
143     //!
144     //! @param[in]    arc  プレイヤーで使用するサウンドアーカイブです。
145     //!
146     //! @return       初期化に必要なメモリサイズを返します。
147     //!
148     //! @see Initialize
149     //!
150     //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整
151     //! @date 2010/01/15 初版
152     //---------------------------------------------------------------------------
153     size_t GetRequiredMemSize( const SoundArchive* arc );
154 
155     //---------------------------------------------------------------------------
156     //! @brief        初期化に必要なストリームバッファのサイズを取得します。
157     //!
158     //!               @ref Initialize に渡すストリームバッファの最小サイズを取得します。
159     //!               この関数で取得した値より大きいサイズのバッファを渡す必要があります。
160     //!
161     //! @param[in]    arc             プレイヤーで使用するサウンドアーカイブです。
162     //!
163     //! @return       初期化に必要なストリームバッファサイズを返します。
164     //!
165     //! @see Initialize
166     //!
167     //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整
168     //! @date 2010/01/15 初版
169     //---------------------------------------------------------------------------
170     size_t GetRequiredStreamBufferSize( const SoundArchive* arc );
171 
172     //---------------------------------------------------------------------------
173     //! @brief        サウンドアーカイブプレイヤーを初期化します。
174     //!
175     //!               サウンドアーカイブプレイヤーを使用する前に、
176     //!               初期化を行う必要があります。
177     //!               初期化を行うことにより、
178     //!               サウンドアーカイブプレイヤーがサウンドアーカイブと
179     //!               サウンドデータマネージャ関連付けられ、
180     //!               そのサウンドアーカイブ中のデータを再生できるようになります。
181     //!
182     //!               サウンドアーカイブプレイヤーが必要とするメモリのサイズは
183     //!               @ref GetRequiredMemSize 及び @ref GetRequiredStreamBufferSize
184     //!               で取得することができます。
185     //!
186     //!               必要なストリームバッファサイズが 0 の場合、
187     //!               ストリームバッファへのポインタ strmBuffer に NULL を渡すことができます。
188     //!
189     //!               ストリームバッファを @ref GetRequiredStreamBufferSize
190     //!               で取得したサイズより大きく設定すると、
191     //!               ストリームサウンドの音途切れが発生しにくくなりますが、
192     //!               データをロードしてから実際に再生するまでの遅延時間が大きくなります。
193     //!
194     //!               ストリームバッファはデバイスメモリのアドレスを指定する必要があります。
195     //!               strmBuffer および strmBuffer + strmBufferSize のアドレスが、
196     //!               デバイスメモリに無い場合は、アサートで停止、あるいは、
197     //!               false を返します (ビルドターゲットによって挙動が変わります)。
198     //!
199     //! @param[in]    arc             プレイヤーで使用するサウンドアーカイブです。
200     //! @param[in]    manager         プレイヤーで使用するサウンドデータマネージャです。
201     //! @param[in]    buffer          バッファへのポインタです。
202     //!                               32 バイトアライメントされている必要があります。
203     //! @param[in]    size            バッファサイズです。
204     //! @param[in]    strmBuffer      ストリームバッファへのポインタです。
205     //!                               32 バイトアライメントされているデバイスメモリを
206     //!                               指定する必要があります。
207     //! @param[in]    strmBufferSize  ストリームバッファのサイズです。
208     //!
209     //! @return       初期化に成功したら true を、失敗したら false を返します。
210     //!
211     //! @see GetRequiredMemSize
212     //! @see GetRequiredStreamBufferSize
213     //! @see Finalize
214     //! @see IsAvailable
215     //!
216     //! @date 2010/03/05 ストリームバッファがデバイスメモリに無い場合の挙動を追記。
217     //! @date 2010/02/03 buffer のアライメントサイズを変更 (4 → 32)
218     //! @date 2010/02/01 関数名変更 (Setup → Initialize)
219     //! @date 2010/01/15 初版
220     //---------------------------------------------------------------------------
221     bool Initialize(
222         const SoundArchive* arc,
223         const SoundDataManager* manager,
224         void*   buffer,
225         u32     size,
226         void*   strmBuffer,
227         u32     strmBufferSize
228     );
229 
230     //---------------------------------------------------------------------------
231     //! @brief        サウンドアーカイブプレイヤーを破棄します。
232     //!
233     //!               破棄は以下のとおり行われます。
234     //!
235     //!               ・このサウンドアーカイブプレイヤーを使って再生中のサウンドを停止します。@n
236     //!               ・初期化で割り当てたメモリ領域を開放します。@n
237     //!               ・初期化されたサウンドアーカイブとの関連が外れます。
238     //!
239     //! @see Initialize
240     //! @see IsAvailable
241     //!
242     //! @date 2010/02/01 関数名変更 (Shutdown → Finalize)
243     //! @date 2010/01/15 初版
244     //---------------------------------------------------------------------------
245     void Finalize();
246 
247     //---------------------------------------------------------------------------
248     //! @brief        利用可能な状態かどうかを調べます。
249     //!
250     //!               サウンドアーカイブプレイヤーを利用するためには
251     //!               @ref Initialize を呼び出して初期化を完了させる必要があります。
252     //!               また、@ref Finalize を呼び出すと、
253     //!               サウンドアーカイブプレイヤーの終了処理が行われ、
254     //!               利用できない状態になります。
255     //!
256     //! @return       サウンドアーカイブプレイヤーが利用可能な状態なら true を、
257     //!               そうでなければ false を返します。
258     //!
259     //! @see Initialize
260     //! @see Finalize
261     //!
262     //! @date 2010/02/01 関数名変更 (Setup → Initialize, Shutdown → Finalize)
263     //!                  にともなう文言の調整
264     //! @date 2010/01/15 初版
265     //---------------------------------------------------------------------------
266     bool IsAvailable() const;
267     //@}
268 
269     //----------------------------------------
270     //! @name 更新
271     //---------------------------------------------------------------------------
272     //! @brief    サウンドアーカイブプレイヤーの更新処理を行います。
273     //!
274     //!           この関数は 1 ゲームフレームに 1 回呼び出してください。
275     //!
276     //!           内部の処理はサウンドスレッドで行われるため、
277     //!           更新処理を 1 ゲームフレームに 1 回呼び出すことができなくても
278     //!           発音が途切れることはありません。
279     //!           この関数では、プレイヤーやサウンドに対するパラメータ設定や、
280     //!           フェイドイン・フェイドアウトなどの連続的なパラメータ変更を
281     //!           反映するための処理が行われます。
282     //!
283     //! @date 2010/01/15 初版
284     //---------------------------------------------------------------------------
285     void Update();
286     //@}
287 
288     //----------------------------------------
289     //! @name その他
290 
291     //---------------------------------------------------------------------------
292     //! @brief    プレイヤーに関連付けられているサウンドアーカイブを取得します。
293     //!
294     //! @return   プレイヤーに関連付けられているサウンドアーカイブを返します。
295     //!
296     //! @see SoundArchive クラス
297     //!
298     //! @date 2010/01/15 初版
299     //---------------------------------------------------------------------------
300     const SoundArchive& GetSoundArchive() const;
301 
302     //---------------------------------------------------------------------------
303     //! @brief    指定した ID のサウンドプレイヤーを取得します。
304     //!
305     //! @param[in]    playerId    プレイヤーの ID です。
306     //!
307     //! @return   指定した ID のサウンドプレイヤーを返します。
308     //!
309     //! @see SoundPlayer クラス
310     //!
311     //! @date 2010/01/15 初版
312     //---------------------------------------------------------------------------
313     SoundPlayer& GetSoundPlayer( SoundArchive::ItemId playerId );
314 
315     //---------------------------------------------------------------------------
316     //! @brief    指定した ID のサウンドプレイヤーを取得します。
317     //!
318     //! @param[in]    pPlayerName     プレイヤーのラベル文字列です。
319     //!
320     //! @return   指定した ID のサウンドプレイヤーを返します。
321     //!
322     //! @see SoundPlayer クラス
323     //!
324     //! @date 2010/01/15 初版
325     //---------------------------------------------------------------------------
326     SoundPlayer& GetSoundPlayer( const char* pPlayerName );
327 
328     //---------------------------------------------------------------------------
329     //! @brief    サウンドプレイヤーの個数を取得します。
330     //!
331     //! @return   サウンドプレイヤーの個数を返します。
332     //!
333     //! @see SoundPlayer クラス
334     //!
335     //! @date 2010/02/01 返り値の型を変更 (unsigned long → u32)
336     //! @date 2010/01/15 初版
337     //---------------------------------------------------------------------------
GetSoundPlayerCount()338     u32 GetSoundPlayerCount() const { return m_SoundPlayerCount; }
339 
340     //---------------------------------------------------------------------------
341     //! @brief    再生可能なシーケンスサウンドの残数を取得します。
342     //!
343     //!           残数が 0 のときに新たにシーケンスサウンドを再生すると、
344     //!           既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。
345     //!           ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、
346     //!           再生に失敗します。
347     //!
348     //!           再生可能なシーケンスサウンドの総数は、
349     //!           サウンドアーカイブに記述されていて、
350     //!           @ref Initialize でサウンドアーカイブプレイヤーに設定されます。
351     //!
352     //! @return   再生可能なシーケンスサウンドの残数を返します。
353     //!
354     //! @see Initialize
355     //!
356     //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整
357     //! @date 2010/01/15 初版
358     //---------------------------------------------------------------------------
GetFreeSequenceSoundCount()359     int GetFreeSequenceSoundCount() const
360     {
361         return m_SequenceSoundInstanceManager.GetFreeCount();
362     }
363 
364     //---------------------------------------------------------------------------
365     //! @brief    再生可能なウェーブサウンドの残数を取得します。
366     //!
367     //!           残数が 0 のときに新たにウェーブサウンドを再生すると、
368     //!           既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。
369     //!           ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、
370     //!           再生に失敗します。
371     //!
372     //!           再生可能なウェーブサウンドの総数は、
373     //!           サウンドアーカイブに記述されていて、
374     //!           @ref Initialize でサウンドアーカイブプレイヤーに設定されます。
375     //!
376     //! @return   再生可能なウェーブサウンドの残数を返します。
377     //!
378     //! @see Initialize
379     //!
380     //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整
381     //! @date 2010/01/15 初版
382     //---------------------------------------------------------------------------
GetFreeWaveSoundCount()383     int GetFreeWaveSoundCount() const
384     {
385         return m_WaveSoundInstanceManager.GetFreeCount();
386     }
387 
388     //---------------------------------------------------------------------------
389     //! @brief    再生可能なストリームサウンドの残数を取得します。
390     //!
391     //!           残数が 0 のときに新たにストリームサウンドを再生すると、
392     //!           既に再生中の最もプレイヤープライオリティの低いサウンドが停止します。
393     //!           ただし、新たに再生するサウンドのほうがプレイヤープライオリティが低い場合は、
394     //!           再生に失敗します。
395     //!
396     //!           再生可能なストリームサウンドの総数は、
397     //!           サウンドアーカイブに記述されていて、
398     //!           @ref Initialize でサウンドアーカイブプレイヤーに設定されます。
399     //!
400     //! @return   再生可能なストリームサウンドの残数を返します。
401     //!
402     //! @see Initialize
403     //!
404     //! @date 2010/02/01 関数名変更 (Setup → Initialize) にともなう文言の調整
405     //! @date 2010/01/15 初版
406     //---------------------------------------------------------------------------
GetFreeStreamSoundCount()407     int GetFreeStreamSoundCount() const
408     {
409         return m_StreamSoundInstanceManager.GetFreeCount();
410     }
411 
412     //---------------------------------------------------------------------------
413     //! @brief    シーケンスコマンド 'userproc' で呼び出される
414     //!           コールバック関数を登録します。
415     //!
416     //!           ここで登録したコールバックは、シーケンスデータ側のシーケンスコマンド
417     //!           'userproc' が処理されたフレームで呼び出されます。
418     //!           コールバック関数はサウンドスレッド呼び出されます。
419     //!
420     //!           'userproc' コマンドの詳細については、
421     //!           シーケンスデータマニュアルを参照してください。
422     //!
423     //! @param[in] callback       登録するコールバック関数です。
424     //! @param[in] callbackArg    コールバック関数に渡されるユーザー引数です。
425     //!
426     //! @ref SequenceUserprocCallback
427     //!
428     //! @date 2010/01/15 初版
429     //---------------------------------------------------------------------------
430     void SetSequenceUserprocCallback(
431             SequenceUserprocCallback callback, void* callbackArg );
432     //@}
433 
434 
435     // StartSound実装
436     //! @details :private
437     StartResult detail_SetupSoundImpl(
438         SoundHandle* handle,
439         u32 soundId,
440         internal::BasicSound::AmbientInfo* ambientArgInfo,
441         SoundActor* actor,
442         bool holdFlag,
443         const StartInfo* startInfo
444     );
445     //! @details :private
detail_GetItemId(const char * pString)446     virtual SoundArchive::ItemId detail_GetItemId( const char* pString )
447     {
448         NW_NULL_ASSERT( m_pSoundArchive );
449         return m_pSoundArchive->GetItemId( pString );
450     }
451 
452 
453     // 非公開関数
454     //! @details :private
detail_SetMmlParser(internal::driver::MmlParser * parser)455     void detail_SetMmlParser( internal::driver::MmlParser* parser )
456     {
457         if ( parser == NULL ) m_MmlSequenceTrackAllocator.SetMmlParser( &m_MmlParser );
458         else m_MmlSequenceTrackAllocator.SetMmlParser( parser );
459     }
460     //! @details :private
461     const void* detail_GetFileAddress( SoundArchive::FileId fileId ) const;
462 
463   protected:
464     virtual StartResult detail_SetupSound(
465         SoundHandle* handle,
466         u32 soundId,
467         bool holdFlag,
468         const StartInfo* startInfo
469     );
470 
471   private:
472 
473     template< typename Sound, typename Player >
474     Sound* AllocSound(
475         internal::SoundInstanceManager< Sound, Player >* manager,
476         SoundArchive::ItemId soundId,
477         int priority,
478         int ambientPriority,
479         internal::BasicSound::AmbientInfo* ambientArgInfo
480     );
481 
482     StartResult PrepareSeqImpl(
483         internal::SequenceSound* sound,
484         const SoundArchive::SoundInfo* commonInfo,
485         const SoundArchive::SequenceSoundInfo* info,
486         SoundStartable::StartInfo::StartOffsetType startOffsetType,
487         int startOffset,
488         const StartInfo::SeqSoundInfo* externalSeqInfo
489     );
490 
491     StartResult PrepareStreamImpl(
492         internal::StreamSound* sound,
493         const SoundArchive::SoundInfo* commonInfo,
494         const SoundArchive::StreamSoundInfo* info,
495         SoundStartable::StartInfo::StartOffsetType startOffsetType,
496         int startOffset
497     );
498 
499     StartResult PrepareWaveSoundImpl(
500         internal::WaveSound* sound,
501         const SoundArchive::SoundInfo* commonInfo,
502         const SoundArchive::WaveSoundInfo* info,
503         SoundStartable::StartInfo::StartOffsetType startOffsetType,
504         int startOffset
505     );
506 
507 
508     internal::PlayerHeap* CreatePlayerHeap(
509             void** ppBuffer, void* pEndAddress, size_t heapSize );
510 
511     // Setup
512     bool SetupMram( const SoundArchive* arc, void* buffer, unsigned long size );
513     bool SetupSoundPlayer( const SoundArchive* arc, void** buffer, void* endp );
514     bool SetupSequenceSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp );
515     bool SetupSequenceTrack( const SoundArchive* arc, int numTracks, void** buffer, void* endp );
516     bool SetupWaveSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp );
517     bool SetupStreamSound( const SoundArchive* arc, int numSounds, void** buffer, void* endp );
518     bool SetupStreamBuffer( const SoundArchive* arc, void* buffer, unsigned long size );
519 
520     void UpdateCommonSoundParam( internal::BasicSound* sound, const SoundArchive::SoundInfo* commonInfo );
521 
522     const SoundArchive* m_pSoundArchive;
523 
524     // コールバック
525     SequenceNoteOnCallback m_SequenceCallback;
526     WaveSoundCallback m_WaveSoundCallback;
527     SequenceUserprocCallback m_SequenceUserprocCallback;
528     void* m_pSequenceUserprocCallbackArg;
529 
530     // サウンドプレイヤー
531     u32 m_SoundPlayerCount;
532     SoundPlayer* m_pSoundPlayers;
533 
534     // マネージャー・アロケータ
535     internal::SequenceSoundInstanceManager m_SequenceSoundInstanceManager;
536     internal::WaveSoundInstanceManager m_WaveSoundInstanceManager;
537     internal::StreamSoundInstanceManager m_StreamSoundInstanceManager;
538 
539     internal::driver::SequenceTrackAllocator* m_pSequenceTrackAllocator;
540     internal::driver::MmlSequenceTrackAllocator m_MmlSequenceTrackAllocator; // デフォルトのシーケンストラックアロケータ
541 
542     internal::driver::StreamBufferPool m_StreamBufferPool;
543 
544     // デフォルトのシーケンスパーサ
545     internal::driver::MmlParser m_MmlParser;
546 
547     // バッファ情報記憶
548     void* m_pSetupBufferAddress;
549     u32 m_SetupBufferSize;
550 
551     // データマネージャ
552     const SoundDataManager* m_pSoundDataManager;
553 };
554 
555 } // namespace nw::snd
556 } // namespace nw
557 
558 
559 #endif /* NW_SND_SOUND_ARCHIVE_PLAYER_H_ */
560 
561