1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SoundPlayer.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: 27551 $
14  *---------------------------------------------------------------------------*/
15 
16 /**
17  * :include nw/snd/snd_SoundPlayer.h
18  *
19  * @file snd_SoundPlayer.h
20  */
21 
22 #ifndef NW_SND_SOUND_PLAYER_H_
23 #define NW_SND_SOUND_PLAYER_H_
24 
25 #include <nw/ut/ut_LinkList.h>
26 #include <nw/snd/snd_BasicSound.h>
27 #include <nw/snd/snd_PlayerHeap.h>
28 
29 namespace nw {
30 namespace snd {
31 
32 
33 //---------------------------------------------------------------------------
34 //! @brief    サウンドを再生するためのプレイヤークラスです。
35 //!
36 //!           SoundPlayer クラスのインスタンスは
37 //!           @ref SoundArchivePlayer::GetSoundPlayer を呼び出して取得してください。
38 //!
39 //!           一つの SoundPlayer で複数のサウンドを再生することができます。
40 //!           同時に再生できるサウンド数を設定することができ、
41 //!           そのサウンド数を超えた場合には、
42 //!           各サウンドに設定されたプレイヤープライオリティを比較して、
43 //!           もっとも優先度が低いサウンドが停止します。
44 //!
45 //! @see SoundArchivePlayer クラス
46 //! @see SoundArchivePlayer::GetSoundPlayer
47 //!
48 //! @date 2010/01/15 初版
49 //---------------------------------------------------------------------------
50 class SoundPlayer
51 {
52   public:
53     //! @details :private
54     typedef ut::LinkList<
55         internal::PlayerHeap,
56         offsetof(internal::PlayerHeap,m_Link)
57     > PlayerHeapList;
58 
59     //! @details :private
60     typedef ut::LinkList<
61         internal::BasicSound,
62         offsetof(internal::BasicSound,m_SoundPlayerPlayLink)
63     > SoundList;
64 
65     //! @details :private
66     typedef ut::LinkList<
67         internal::BasicSound,
68         offsetof(internal::BasicSound,m_SoundPlayerPriorityLink)
69     > PriorityList;
70 
71   public:
72 
73     //----------------------------------------
74     //! @name コンストラクタ/デストラクタ
75     //@{
76     //---------------------------------------------------------------------------
77     //! @brief        コンストラクタです。
78     //
79     //! @date 2010/01/15 初版
80     //---------------------------------------------------------------------------
81     SoundPlayer();
82 
83     //---------------------------------------------------------------------------
84     //! @brief        デストラクタです。
85     //
86     //! @date 2010/01/15 初版
87     //---------------------------------------------------------------------------
88     ~SoundPlayer();
89     //@}
90 
91     //----------------------------------------
92     //! @name 更新
93     //@{
94     //---------------------------------------------------------------------------
95     //! @brief        サウンドプレイヤーの更新処理を行います。
96     //!
97     //!               @ref SoundArchivePlayer クラスを使用している場合は、
98     //!               この関数は @ref SoundArchivePlayer::Update から呼び出されます。
99     //!
100     //! @see SoundArchivePlayer クラス
101     //! @see SoundArchivePlayer::Update
102     //
103     //! @date 2010/01/15 初版
104     //---------------------------------------------------------------------------
105     void Update();
106     //@}
107 
108     //----------------------------------------
109     //! @name 再生制御
110     //@{
111     //---------------------------------------------------------------------------
112     //! @brief        全てのサウンドを停止します。
113     //!
114     //!               プレイヤーで再生中の全てのサウンドを停止します。
115     //!               各サウンドに対して、
116     //!               ハンドルクラスを通して停止させたときと同様の処理を行います。
117     //!
118     //!               fadeFrames で指定したフレーム数をかけて、
119     //!               フェードアウトさせることができます。
120     //!               0 を指定した場合は、フェードアウトを行いません。
121     //!               ただし、シーケンスサウンドで発音中の音は、
122     //!               エンベロープのリリースを発音し全ての減衰が完了した後に
123     //!               サウンドが停止します。
124     //!
125     //!               フェードアウトの音量制御は、フェードインと共有されます。
126     //!               フェードアウトにかかるフレーム数は、
127     //!               最大音量から音が消えるまでにかかる変化速度を表しますので、
128     //!               フェードイン中にフェードアウトを指定した時などは、
129     //!               指定したフレーム数よりも短い時間で
130     //!               フェードアウトが完了する可能性があります。
131     //!
132     //! @param[in]    fadeFrames  フェードアウトにかけるフレーム数です。
133     //
134     //! @date 2010/01/15 初版
135     //---------------------------------------------------------------------------
136     void StopAllSound( int fadeFrames );
137 
138     //---------------------------------------------------------------------------
139     //! @brief        全てのサウンドを一時停止・再開します。
140     //!
141     //!               プレイヤーで再生中の全てのサウンドを一時停止または再開します。
142     //!               各サウンドに対して、
143     //!               ハンドルクラスを通して一時停止・再開させたときと同様の処理を行います。
144     //!
145     //!               一時停止・再開時のフェードは、再生開始時のフェードイン、
146     //!               停止時のフェードアウトとは独立してはたらきます。
147     //!
148     //! @param[in]    flag        true なら一時停止、false なら再開。
149     //! @param[in]    fadeFrames  フェードイン・フェードアウトにかけるフレーム数。
150     //
151     //! @date 2010/01/15 初版
152     //---------------------------------------------------------------------------
153     void PauseAllSound( bool flag, int fadeFrames );
154     //@}
155 
156     //----------------------------------------
157     //! @name パラメータ設定・取得
158     //@{
159     //---------------------------------------------------------------------------
160     //! @brief    プレイヤーの音量を変更します。
161     //!
162     //!           プレイヤーの音量は、
163     //!           プレイヤーで再生中の全てのサウンドに対して効果があります。
164     //!
165     //!           この関数で指定する値は、
166     //!           サウンドに設定される他のどの音量パラメータとも独立して動作し、
167     //!           それらは全て重ね合わされます。
168     //!
169     //!           音量 volume は、0.0 以上の倍率で指定します。
170     //!           すなわち、1.0 を指定すると音量に影響を与えません。
171     //!           0.0 を指定すると発音されなくなります。
172     //!           デフォルト値は 1.0 です。
173     //!
174     //!           他の音量パラメータと重ね合わされたあと、
175     //!           最終的な音量は 0.0 ~ 2.0 の範囲でクランプされます。
176     //!           この関数で 2.0 を設定したとしても、
177     //!           元の音量の 2 倍にならない可能性があることに注意してください。
178     //!
179     //! @param[in]    volume    プレイヤーの音量の倍率( 0.0 ~ )です。
180     //!
181     //! @see GetVolume
182     //
183     //! @date 2010/01/15 初版
184     //---------------------------------------------------------------------------
185     void SetVolume( float volume );
186     //---------------------------------------------------------------------------
187     //! @brief    プレイヤーの音量を取得します。
188     //!
189     //! @return   プレイヤーに設定されている現在の音量を返します。
190     //!
191     //! @see SetVolume
192     //
193     //! @date 2010/01/15 初版
194     //---------------------------------------------------------------------------
GetVolume()195     float GetVolume() const { return m_Volume; }
196 
197     // ローパスフィルタのカットオフ周波数を変化させる
198     //! @details :private
199     void SetLpfFreq( float lpfFreq );
200     //! @details :private
GetLpfFreq()201     float GetLpfFreq() const { return m_LpfFreq; }
202 
203     // Biquadフィルタを設定する
204     //! @details :private
205     void SetBiquadFilter( int type, float value );
206     //! @details :private
GetBiquadFilterType()207     int GetBiquadFilterType() const { return m_BiquadType; }
208     //! @details :private
GetBiquadFilterValue()209     float GetBiquadFilterValue() const { return m_BiquadValue; }
210 
211     //---------------------------------------------------------------------------
212     //! @brief  プレイヤーのメイン出力へのセンド量を変更します。
213     //!
214     //!         プレイヤーのメイン出力へのセンド量は、
215     //!         プレイヤーで再生中の全てのサウンドに対して効果があります。
216     //!
217     //!         この関数で指定する値は、
218     //!         サウンドに設定される他のどの音量パラメータとも独立して動作し、
219     //!         それらはすべて重ね合わされます。
220     //!
221     //!         メインセンドは、メイン出力に送るサウンドの音量を調節するパラメータです。
222     //!         主に、エフェクトのドライ・ウェット成分のバランスを調整するために使用されます。
223     //!
224     //!         センド量 send は、相対変化の値を指定します。
225     //!         すなわち、0.0 を指定するとセンド量を変更しません。
226     //!         -1.0 を指定するとメインバスに最大のセンド量で送られていたサウンドが
227     //!         メインバスに送られないようになります。 デフォルト値は 0.0 です。
228     //!
229     //! @param[in] send     0.0 を基準としたセンド量の相対変化の値です。
230     //!
231     //! @see GetMainSend
232     //! @see SetFxSend
233     //!
234     //! @date 2010/06/30 初版
235     //---------------------------------------------------------------------------
236     void SetMainSend( float send );
237 
238     //---------------------------------------------------------------------------
239     //! @brief  プレイヤーに設定されているメイン出力へのセンド量を取得します。
240     //!
241     //! @return 現在のメイン出力へのセンド量を返します。
242     //!
243     //! @see SetMainSend
244     //!
245     //! @date 2010/06/30 初版
246     //---------------------------------------------------------------------------
GetMainSend()247     float GetMainSend() const { return m_MainSend; }
248 
249     //---------------------------------------------------------------------------
250     //! @brief  プレイヤーのエフェクトへのセンド量を変更します。
251     //!
252     //!         プレイヤーのエフェクトへのセンド量は、
253     //!         プレイヤーで再生中の全てのサウンドに対して効果があります。
254     //!
255     //!         この関数で指定する値は、
256     //!         サウンドに設定される他のどの音量パラメータとも独立して動作し、
257     //!         それらはすべて重ね合わされます。
258     //!
259     //!         センド量 send は、相対変化の値を指定します。
260     //!         すなわち、0.0 を指定するとセンド量を変更しません。
261     //!         1.0 を指定すると AUX バスに送られていなかったサウンドが
262     //!         最大のセンド量で送られるようになります。 デフォルト値は 0.0 です。
263     //!
264     //! @param[in] bus      センド量を設定する AUX バスです。
265     //! @param[in] send     0.0 を基準としたセンド量の相対変化の値です。
266     //!
267     //! @see AuxBus
268     //! @see GetFxSend
269     //! @see SetMainSend
270     //!
271     //! @date 2010/06/30 初版
272     //---------------------------------------------------------------------------
273     void SetFxSend( AuxBus bus, float send );
274 
275     //---------------------------------------------------------------------------
276     //! @brief  プレイヤーに設定されているエフェクトへのセンド量を取得します。
277     //!
278     //! @return 現在のエフェクトへのセンド量を返します。
279     //!
280     //! @param[in] bus      センド量を設定する AUX バスです。
281     //!
282     //! @see AuxBus
283     //! @see SetFxSend
284     //!
285     //! @date 2010/06/30 初版
286     //---------------------------------------------------------------------------
GetFxSend(AuxBus bus)287     float GetFxSend( AuxBus bus ) const { return m_FxSend[ bus ]; }
288 
289 
290     //---------------------------------------------------------------------------
291     //! @brief  プレイヤーで現在再生中のサウンドの個数を取得します。
292     //!
293     //! @return プレイヤーで再生中のサウンド数を返します。
294     //!
295     //! @date 2010/06/30 初版
296     //---------------------------------------------------------------------------
GetPlayingSoundCount()297     int GetPlayingSoundCount() const { return static_cast<int>( m_SoundList.GetSize()); }
298 
299     //---------------------------------------------------------------------------
300     //! @brief  同時に再生可能なサウンド数を設定します。
301     //!
302     //!         設定したサウンド数を超えるサウンドを再生しようとすると、
303     //!         各サウンドに設定されたプレイヤープライオリティを比較して、
304     //!         もっとも優先度が低いサウンドが停止します。
305     //!
306     //!         @ref SoundArchivePlayer クラスを使用する場合は、
307     //!         サウンドアーカイブ中で指定されている同時再生数が初期化時に自動的に設定されます。
308     //!
309     //!         プレイヤーヒープを使用している場合、
310     //!         この関数で指定できる同時再生数の上限値は、
311     //!         セットアップ時に設定された同時再生数の値に制限されます。
312     //!         上限値を超える値を指定しても上限値に丸め込まれます。
313     //!
314     //! @param[in] count     	同時に再生可能なサウンド数です。
315     //!
316     //! @see SoundArchivePlayer クラス
317     //! @see GetPlayableSoundCount
318     //!
319     //! @date 2010/11/19 誤植修正 (desu→です)
320     //! @date 2010/06/30 初版
321     //---------------------------------------------------------------------------
322     void SetPlayableSoundCount( int count );
323 
324     //---------------------------------------------------------------------------
325     //! @brief  プレイヤーで同時に再生可能なサウンド数を取得します。
326     //!
327     //! @return プレイヤーで同時に再生可能なサウンド数を返します。
328     //!
329     //! @see SetPlayableSoundCount
330     //!
331     //! @date 2010/06/30 初版
332     //---------------------------------------------------------------------------
GetPlayableSoundCount()333     int GetPlayableSoundCount() const { return m_PlayableCount; }
334     //@}
335 
336     //----------------------------------------
337     //! @name その他
338     //@{
339     //---------------------------------------------------------------------------
340     //! @brief  プレイヤーで再生中の全てのサウンドに対して処理を行います。
341     //!
342     //!         プレイヤーで再生中の全てのサウンドに対して、
343     //!
344     //!         function( nw::snd::SoundHandle& handle )
345     //!
346     //!         を呼び出します。 function には、
347     //!         再生中のサウンドに関連付けられたサウンドハンドル handle が渡されます。
348     //!         これは一時的なハンドルですので、ハンドルを後で使用することはできません。
349     //!
350     //!         関数 function は、サウンドの再生が古い順に呼び出されます。
351     //!         reverse に true を指定すると、サウンドの再生が新しい順に呼び出されます。
352     //!
353     //!         function には関数ポインタ、または関数オブジェクトを渡します。
354     //!         関数ポインタを渡す例を以下に示します。
355     //!
356     //!         void ReportSoundId( nw::snd::SoundHandle& handle ) {
357     //!             NN_LOG( "%d\n", handle.GetId() );
358     //!         } @n
359     //!         soundPlayer.ForEachSound( ReportSoundId );
360     //!
361     //! @param[in] function 関数ポインタ、または関数オブジェクトです。
362     //! @param[in] reverse  処理順を逆にする場合は true を指定します。
363     //!
364     //! @return 引数に指定された関数ポインタ、または関数オブジェクトを返します。
365     //!
366     //! @see SoundHandle クラス
367     //! @see ForEachSoundPriorityOrder
368     //!
369     //! @date 2010/10/15 誤植修正 (nw4r → nw, OSReport → NN_LOG)
370     //! @date 2010/06/30 初版
371     //---------------------------------------------------------------------------
372     template< class Function >
373     Function ForEachSound( Function function, bool reverse = false );
374 
375     //---------------------------------------------------------------------------
376     //! @brief  プレイヤーで再生中の全てのサウンドに対してプライオリティ順で処理を行います。
377     //!
378     //!         その他の動作仕様は @ref ForEachSound と同じです。
379     //!
380     //! @param[in] function 関数ポインタ、または関数オブジェクトです。
381     //! @param[in] reverse  処理順を逆にする場合は true を指定します。
382     //!
383     //! @return 引数に指定された関数ポインタ、または関数オブジェクトを返します。
384     //!
385     //! @see SoundHandle クラス
386     //! @see ForEachSound
387     //!
388     //! @date 2010/06/30 初版
389     //---------------------------------------------------------------------------
390     template< class Function >
391     Function ForEachSoundPriorityOrder( Function function, bool reverse = false );
392     //@}
393 
394     //-----------------------------------------------------------------------------
395     //  internal functions
396 
397     //! @details :private
398     void detail_SetPlayableSoundLimit( int limit );
399 
400     // サウンドの登録
401     //! @details :private
402     bool detail_CanPlaySound( int startPriority );
403     //! @details :private
404     bool detail_AppendSound( internal::BasicSound* pSound );
405     //! @details :private
406     void detail_RemoveSound( internal::BasicSound* pSound );
407 
408     // プライオリティリスト
409     //! @details :private
410     void detail_SortPriorityList();
411     //! @details :private
412     void detail_SortPriorityList( internal::BasicSound* pSound );
413 
414     // プレイヤーヒープ
415     //! @details :private
416     void detail_AppendPlayerHeap( internal::PlayerHeap* pHeap );
417     //! @details :private
418     void detail_RemovePlayerHeap( internal::PlayerHeap* pHeap );
419 
420     //! @details :private
421     internal::PlayerHeap* detail_AllocPlayerHeap( internal::BasicSound* pSound );
422     //! @details :private
423     void detail_FreePlayerHeap( internal::BasicSound* pSound );
424 
425   private:
426     //-----------------------------------------------------------------------------
427     //  private functions
428 
GetLowestPrioritySound()429     internal::BasicSound* GetLowestPrioritySound() { return &m_PriorityList.GetFront(); }
430     void InsertPriorityList( internal::BasicSound* pSound );
431     void RemovePriorityList( internal::BasicSound* pSound );
432     void RemoveSoundList( internal::BasicSound* pSound );
433 
434     //-----------------------------------------------------------------------------
435     //  private variables
436 
437     SoundList       m_SoundList;
438     PriorityList    m_PriorityList;
439     PlayerHeapList  m_PlayerHeapList;
440 
441     int m_PlayableCount;
442     int m_PlayableLimit;
443 
444     float m_Volume;
445     float m_LpfFreq;
446     int m_BiquadType;
447     float m_BiquadValue;
448     float m_MainSend;
449     float m_FxSend[ AUX_BUS_NUM ];
450 };
451 
452 
453 template< class Function >
ForEachSound(Function function,bool reverse)454 inline Function SoundPlayer::ForEachSound( Function function, bool reverse )
455 {
456     if ( reverse )
457     {
458         // 再生の新しい順
459         for ( SoundList::ReverseIterator itr = m_SoundList.GetBeginReverseIter();
460               itr != m_SoundList.GetEndReverseIter();
461             )
462         {
463             SoundList::ReverseIterator curItr = itr;
464             SoundHandle handle;
465             handle.detail_AttachSoundAsTempHandle( &( *curItr ) );
466             function( handle );
467             if ( handle.IsAttachedSound() ) itr++;
468         }
469     }
470     else
471     {
472         // 再生の古い順
473         for ( SoundList::Iterator itr = m_SoundList.GetBeginIter();
474               itr != m_SoundList.GetEndIter();
475             )
476         {
477             SoundList::Iterator curItr = itr++;
478             SoundHandle handle;
479             handle.detail_AttachSoundAsTempHandle( &( *curItr ) );
480             function( handle );
481         }
482     }
483     return function;
484 }
485 
486 template< class Function >
ForEachSoundPriorityOrder(Function function,bool reverse)487 Function SoundPlayer::ForEachSoundPriorityOrder( Function function, bool reverse )
488 {
489     if ( reverse )
490     {
491         // プライオリティの低い順
492         for ( PriorityList::Iterator itr = m_PriorityList.GetBeginIter();
493               itr != m_PriorityList.GetEndIter();
494             )
495         {
496             PriorityList::Iterator curItr = itr++;
497             SoundHandle handle;
498             handle.detail_AttachSoundAsTempHandle( &( *curItr ) );
499             function( handle );
500         }
501     }
502     else
503     {
504         // プライオリティの高い順
505         for ( PriorityList::ReverseIterator itr = m_PriorityList.GetBeginReverseIter();
506               itr != m_PriorityList.GetEndReverseIter();
507             )
508         {
509             PriorityList::ReverseIterator curItr = itr;
510             SoundHandle handle;
511             handle.detail_AttachSoundAsTempHandle( &( *curItr ) );
512             function( handle );
513             if ( handle.IsAttachedSound() ) itr++;
514         }
515     }
516     return function;
517 }
518 
519 } // namespace nw::snd
520 } // namespace nw
521 
522 
523 #endif /* NW_SND_SOUND_PLAYER_H_ */
524 
525