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