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