1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_SoundPlayer.cpp
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 #include "precompiled.h"
19
20 #include <nw/snd/snd_SoundPlayer.h>
21
22 #include <nw/snd/snd_SoundThread.h>
23
24 namespace nw {
25 namespace snd {
26
27 /* ========================================================================
28 public function
29 ======================================================================== */
30
31 /*---------------------------------------------------------------------------*
32 Name: SoundPlayer
33
34 Description: コンストラクタ
35
36 Arguments: None.
37
38 Returns: None.
39 *---------------------------------------------------------------------------*/
SoundPlayer()40 SoundPlayer::SoundPlayer()
41 : m_PlayableCount( 1 ),
42 m_PlayableLimit( INT_MAX ),
43 m_Volume( 1.0f ),
44 m_LpfFreq( 0.0f ),
45 m_BiquadType( BIQUAD_FILTER_TYPE_NONE ),
46 m_BiquadValue( 0.0f ),
47 m_MainSend( 0.0f )
48 {
49 for ( int i=0; i<AUX_BUS_NUM; i++ )
50 {
51 m_FxSend[i] = 0.0f;
52 }
53 }
54
55 /*---------------------------------------------------------------------------*
56 Name: ~SoundPlayer
57
58 Description: デストラクタ
59
60 Arguments: None.
61
62 Returns: None.
63 *---------------------------------------------------------------------------*/
~SoundPlayer()64 SoundPlayer::~SoundPlayer()
65 {
66 StopAllSound( 0 );
67 }
68
69 /*---------------------------------------------------------------------------*
70 Name: Update
71
72 Description: プレイヤーのフレーム処理を更新する
73
74 Arguments: None.
75
76 Returns: None.
77 *---------------------------------------------------------------------------*/
Update()78 void SoundPlayer::Update()
79 {
80 for ( SoundList::Iterator itr = m_SoundList.GetBeginIter();
81 itr != m_SoundList.GetEndIter();
82 )
83 {
84 SoundList::Iterator curItr = itr++;
85 curItr->Update();
86 }
87
88 // プライオリティリストを整列しなおす
89 detail_SortPriorityList();
90 }
91
92 /*---------------------------------------------------------------------------*
93 Name: StopAllSound
94
95 Description: 全てのサウンドを停止する
96
97 Arguments: fadeFrames - フェードアウトフレーム数
98
99 Returns: None.
100 *---------------------------------------------------------------------------*/
StopAllSound(int fadeFrames)101 void SoundPlayer::StopAllSound( int fadeFrames )
102 {
103 for ( SoundList::Iterator itr = m_SoundList.GetBeginIter();
104 itr != m_SoundList.GetEndIter();
105 )
106 {
107 SoundList::Iterator curItr = itr++;
108 curItr->Stop( fadeFrames );
109 }
110 }
111
112 /*---------------------------------------------------------------------------*
113 Name: PauseAllSound
114
115 Description: 全てのサウンドを一時停止または再開する
116
117 Arguments: flag - 一時停止か再開か
118 fadeFrames - フェードフレーム数
119
120 Returns: None.
121 *---------------------------------------------------------------------------*/
PauseAllSound(bool flag,int fadeFrames)122 void SoundPlayer::PauseAllSound( bool flag, int fadeFrames )
123 {
124 for ( SoundList::Iterator itr = m_SoundList.GetBeginIter();
125 itr != m_SoundList.GetEndIter();
126 )
127 {
128 SoundList::Iterator curItr = itr++;
129 curItr->Pause( flag, fadeFrames );
130 }
131 }
132
133 /*---------------------------------------------------------------------------*
134 Name: SetVolume
135
136 Description: 音量を変更
137
138 Arguments: volume - 音量
139
140 Returns: None.
141 *---------------------------------------------------------------------------*/
SetVolume(float volume)142 void SoundPlayer::SetVolume( float volume )
143 {
144 NW_ASSERT( volume >= 0.0f );
145 if ( volume < 0.0f ) volume = 0.0f;
146 m_Volume = volume;
147 }
148
149 /*---------------------------------------------------------------------------*
150 Name: SetLpfFreq
151
152 Description: ローパスフィルタの周波数変更
153
154 Arguments: lpfFreq - ローパスフィルタの周波数値
155
156 Returns: なし
157 *---------------------------------------------------------------------------*/
SetLpfFreq(float lpfFreq)158 void SoundPlayer::SetLpfFreq( float lpfFreq )
159 {
160 m_LpfFreq = lpfFreq;
161 }
162
163 /*---------------------------------------------------------------------------*
164 Name: SetBiquadFilter
165
166 Description: Biquadフィルタの設定
167
168 Arguments: type - フィルタの種類 (0 - 127)
169 value - フィルタの値 (0.0f - 1.0f)
170
171 Returns: なし
172 *---------------------------------------------------------------------------*/
SetBiquadFilter(int type,float value)173 void SoundPlayer::SetBiquadFilter( int type, float value )
174 {
175 m_BiquadType = type;
176 m_BiquadValue = value;
177 }
178
179 /*---------------------------------------------------------------------------*
180 Name: SetMainSend
181
182 Description: メインセンドバスに送る音量を変更する
183
184 Arguments: send - 音量
185
186 Returns: None.
187 *---------------------------------------------------------------------------*/
SetMainSend(float send)188 void SoundPlayer::SetMainSend( float send )
189 {
190 m_MainSend = send;
191 }
192
193 /*---------------------------------------------------------------------------*
194 Name: SetFxSend
195
196 Description: エフェクトセンドバスに送る音量を変更する
197
198 Arguments: bus - センドバス
199 send - 音量
200
201 Returns: None.
202 *---------------------------------------------------------------------------*/
SetFxSend(AuxBus bus,float send)203 void SoundPlayer::SetFxSend( AuxBus bus, float send )
204 {
205 NW_MINMAXLT_ASSERT( bus, 0, AUX_BUS_NUM );
206 m_FxSend[bus] = send;
207 }
208 /*---------------------------------------------------------------------------*
209 Name: RemoveSoundList
210
211 Description: サウンドをプレイヤーリストから削除する
212
213 Arguments: pSound - シーケンスサウンド
214
215 Returns: None.
216 *---------------------------------------------------------------------------*/
RemoveSoundList(internal::BasicSound * pSound)217 void SoundPlayer::RemoveSoundList( internal::BasicSound* pSound )
218 {
219 // 再生リストから削除する
220 m_SoundList.Erase( pSound );
221 pSound->DetachSoundPlayer( this );
222 }
223
224 /*---------------------------------------------------------------------------*
225 Name: InsertPriorityList
226
227 Description: サウンドをプライオリティリストへ追加
228
229 Arguments: pSound - 追加するサウンド
230
231 Returns: None.
232 *---------------------------------------------------------------------------*/
InsertPriorityList(internal::BasicSound * pSound)233 void SoundPlayer::InsertPriorityList( internal::BasicSound* pSound )
234 {
235 PriorityList::Iterator itr = m_PriorityList.GetBeginIter();
236 while ( itr != m_PriorityList.GetEndIter() )
237 {
238 if ( pSound->CalcCurrentPlayerPriority() < itr->CalcCurrentPlayerPriority() ) break;
239 (void)++itr;
240 }
241 m_PriorityList.Insert( itr, pSound );
242 }
243
244 /*---------------------------------------------------------------------------*
245 Name: RemovePriorityList
246
247 Description: サウンドをプライオリティリストから削除
248
249 Arguments: pSound - 削除するサウンド
250
251 Returns: None.
252 *---------------------------------------------------------------------------*/
RemovePriorityList(internal::BasicSound * pSound)253 void SoundPlayer::RemovePriorityList( internal::BasicSound* pSound )
254 {
255 m_PriorityList.Erase( pSound );
256 }
257
258 /*---------------------------------------------------------------------------*
259 Name: detail_SortPriorityList
260
261 Description: 指定したサウンドのプライオリティ順序を並び替える
262
263 Arguments: pSound - 並び替えるサウンド
264
265 Returns: None.
266 *---------------------------------------------------------------------------*/
detail_SortPriorityList(internal::BasicSound * pSound)267 void SoundPlayer::detail_SortPriorityList( internal::BasicSound* pSound )
268 {
269 RemovePriorityList( pSound );
270 InsertPriorityList( pSound );
271 }
272
273 /*---------------------------------------------------------------------------*
274 Name: detail_SortPriorityList
275
276 Description: 全サウンドのプライオリティ順序を並び替える
277
278 Arguments: None.
279
280 Returns: None.
281 *---------------------------------------------------------------------------*/
detail_SortPriorityList()282 void SoundPlayer::detail_SortPriorityList()
283 {
284 if ( m_PriorityList.GetSize() < 2 ) return;
285
286 static const int TMP_NUM = internal::BasicSound::PRIORITY_MAX - internal::BasicSound::PRIORITY_MIN + 1;
287 static PriorityList tmplist[ TMP_NUM ]; // notice: large stack
288 #ifdef NW_DEBUG
289 for ( int i=0; i<TMP_NUM; i++ ) NW_ASSERT( tmplist[i].IsEmpty() );
290 #endif
291
292 while ( !m_PriorityList.IsEmpty() )
293 {
294 internal::BasicSound& front = m_PriorityList.GetFront();
295 m_PriorityList.PopFront();
296 tmplist[ front.CalcCurrentPlayerPriority() ].PushBack( &front );
297 }
298 for ( int i=0; i<TMP_NUM; i++ )
299 {
300 while ( !tmplist[i].IsEmpty() )
301 {
302 internal::BasicSound& front = tmplist[i].GetFront();
303 tmplist[i].PopFront();
304 m_PriorityList.PushBack( &front );
305 }
306 }
307 }
308
309 /*---------------------------------------------------------------------------*
310 Name: detail_AppendSound
311
312 Description: サウンドをサウンドプレイヤーに登録する
313
314 Arguments: pSound - サウンド
315
316 Returns: 登録できたらtrue
317 *---------------------------------------------------------------------------*/
detail_AppendSound(internal::BasicSound * pSound)318 bool SoundPlayer::detail_AppendSound( internal::BasicSound* pSound )
319 {
320 NW_NULL_ASSERT( pSound );
321
322 int allocPriority = pSound->CalcCurrentPlayerPriority();
323
324 // 最大同時再生数のチェック
325 if ( GetPlayableSoundCount() == 0 ) return false;
326 while ( GetPlayingSoundCount() >= GetPlayableSoundCount() )
327 {
328 internal::BasicSound* dropSound = GetLowestPrioritySound();
329 if ( dropSound == NULL ) return false;
330 if ( allocPriority < dropSound->CalcCurrentPlayerPriority() ) return false;
331 dropSound->Finalize();
332 }
333
334 // リストへ登録
335 m_SoundList.PushBack( pSound );
336 InsertPriorityList( pSound );
337
338 pSound->AttachSoundPlayer( this );
339
340 return true;
341 }
342
343 /*---------------------------------------------------------------------------*
344 Name: detail_RemoveSound
345
346 Description: サウンドをサウンドプレイヤーから削除する
347
348 Arguments: pSound - 削除するサウンド
349
350 Returns: None.
351 *---------------------------------------------------------------------------*/
detail_RemoveSound(internal::BasicSound * pSound)352 void SoundPlayer::detail_RemoveSound( internal::BasicSound* pSound )
353 {
354 RemovePriorityList( pSound );
355 RemoveSoundList( pSound );
356 }
357
358 /*---------------------------------------------------------------------------*
359 Name: SetPlayableSoundCount
360
361 Description: 同時再生数を設定
362
363 Arguments: count - 同時再生数
364
365 Returns: None.
366 *---------------------------------------------------------------------------*/
SetPlayableSoundCount(int count)367 void SoundPlayer::SetPlayableSoundCount( int count )
368 {
369 NW_ASSERT( count >= 0 );
370
371 // プレイヤーヒープ使用時の上限
372 NW_WARNING( count <= m_PlayableLimit, "playable sound count is over limit." );
373 count = ut::Clamp( count, 0, m_PlayableLimit );
374
375 m_PlayableCount = count;
376
377 // 新しく設定された同時再生数を越えるサウンドを終了する
378 while ( GetPlayingSoundCount() > GetPlayableSoundCount() )
379 {
380 internal::BasicSound* dropSound = GetLowestPrioritySound();
381 NW_NULL_ASSERT( dropSound );
382 dropSound->Finalize();
383 }
384 }
385
386 /*---------------------------------------------------------------------------*
387 Name: detail_SetPlayableSoundLimit
388
389 Description:
390
391 Arguments: None.
392
393 Returns: None.
394 *---------------------------------------------------------------------------*/
detail_SetPlayableSoundLimit(int limit)395 void SoundPlayer::detail_SetPlayableSoundLimit( int limit )
396 {
397 NW_ASSERT( limit >= 0 );
398
399 m_PlayableLimit = limit;
400 }
401
402 /*---------------------------------------------------------------------------*
403 Name: detail_CanPlaySound
404
405 Description: 指定したプライオリティのサウンドを再生できるかどうかを調べる
406
407 Arguments: startPriority - プライオリティ
408
409 Returns: 再生可能ならtrue
410 *---------------------------------------------------------------------------*/
detail_CanPlaySound(int startPriority)411 bool SoundPlayer::detail_CanPlaySound( int startPriority )
412 {
413 // プレイヤー毎の最大同時再生数のチェック
414 if ( GetPlayableSoundCount() == 0 ) return false;
415 if ( GetPlayingSoundCount() >= GetPlayableSoundCount() )
416 {
417 internal::BasicSound* dropSound = GetLowestPrioritySound();
418 if ( dropSound == NULL ) return false;
419 if ( startPriority < dropSound->CalcCurrentPlayerPriority() ) return false;
420 }
421
422 return true;
423 }
424
425 /*---------------------------------------------------------------------------*
426 Name: detail_AppendPlayerHeap
427
428 Description: プレイヤーヒープを追加
429
430 Arguments: heap - 追加するプレイヤーヒープ
431
432 Returns: None.
433 *---------------------------------------------------------------------------*/
detail_AppendPlayerHeap(internal::PlayerHeap * pHeap)434 void SoundPlayer::detail_AppendPlayerHeap( internal::PlayerHeap* pHeap )
435 {
436 NW_NULL_ASSERT( pHeap );
437
438 pHeap->AttachSoundPlayer( this );
439 m_PlayerHeapList.PushBack( pHeap );
440 }
441
442 /*---------------------------------------------------------------------------*
443 Name: detail_RemovePlayerHeap
444
445 Description: プレイヤーヒープの削除
446
447 Arguments: heap - 削除するプレイヤーヒープ
448
449 Returns: None.
450 *---------------------------------------------------------------------------*/
detail_RemovePlayerHeap(internal::PlayerHeap * pHeap)451 void SoundPlayer::detail_RemovePlayerHeap( internal::PlayerHeap* pHeap )
452 {
453 m_PlayerHeapList.Erase( pHeap );
454 }
455
456 /*---------------------------------------------------------------------------*
457 Name: detail_AllocPlayerHeap
458
459 Description: プレイヤーヒープの確保
460
461 Arguments: sound - プレイヤーヒープを使用するサウンド
462
463 Returns: 確保したヒープ
464 *---------------------------------------------------------------------------*/
465 internal::PlayerHeap*
detail_AllocPlayerHeap(internal::BasicSound * pSound)466 SoundPlayer::detail_AllocPlayerHeap( internal::BasicSound* pSound )
467 {
468 NW_NULL_ASSERT( pSound );
469
470 // プレイヤーヒープの確保
471 if ( m_PlayerHeapList.IsEmpty() ) return NULL;
472 internal::PlayerHeap& playerHeap = m_PlayerHeapList.GetFront();
473 m_PlayerHeapList.PopFront();
474
475 // プレイヤーヒープとサウンドの結合
476 playerHeap.AttachSound( pSound );
477 pSound->AttachPlayerHeap( &playerHeap );
478
479 // NOTE: プレイヤーヒープ初期化 playerHeap.Clear() は、
480 // 各データロードタスクの Execute あたまで呼び出す
481
482 return &playerHeap;
483 }
484
485 /*---------------------------------------------------------------------------*
486 Name: detail_FreePlayerHeap
487
488 Description: プレイヤーヒープの解放
489
490 Arguments: sound - プレイヤーヒープを解放するサウンド
491
492 Returns: None.
493 *---------------------------------------------------------------------------*/
detail_FreePlayerHeap(internal::BasicSound * pSound)494 void SoundPlayer::detail_FreePlayerHeap( internal::BasicSound* pSound )
495 {
496 NW_NULL_ASSERT( pSound );
497
498 internal::PlayerHeap* pHeap = pSound->GetPlayerHeap();
499 if ( pHeap == NULL ) return;
500
501 // プレイヤーヒープとサウンドの切断
502 pHeap->DetachSound( pSound );
503 pSound->DetachPlayerHeap( pHeap );
504
505 // プレイヤーヒープの解放
506 m_PlayerHeapList.PushBack( pHeap );
507 }
508
509 } // namespace nw::snd
510 } // namespace nw
511
512