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