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