1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_SequenceSoundPlayer.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: 27883 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/snd/snd_SequenceSoundPlayer.h>
19 
20 #include <nw/snd/snd_SequenceTrack.h>
21 #include <nw/snd/snd_SequenceTrackAllocator.h>
22 #include <nw/snd/snd_DisposeCallbackManager.h>
23 #include <nw/snd/snd_HardwareManager.h>
24 #include <nw/snd/snd_NoteOnCallback.h>
25 #include <nw/snd/snd_SoundThread.h>
26 
27 namespace
28 {
29 // DSP プロセスの割り込み間隔の分母・分子。
30 // NUMERATOR / DENOMINATOR [msec] (約 4.888 ...) が実際の割り込み間隔。
31 const u32 INTERVAL_MSEC_NUMERATOR   = NN_SND_SAMPLES_PER_FRAME * 1000 * (32 * 256);
32 const u32 INTERVAL_MSEC_DENOMINATOR = NN_SND_HW_SYSTEM_CLOCK;
33 }
34 
35 namespace nw {
36 namespace snd {
37 namespace internal {
38 namespace driver {
39 
40 /* ========================================================================
41         static variable
42    ======================================================================== */
43 
44 vs16 SequenceSoundPlayer::m_GlobalVariable[ GLOBAL_VARIABLE_NUM ];
45 
46 /* ========================================================================
47         public function
48    ======================================================================== */
49 
InitSequenceSoundPlayer()50 void SequenceSoundPlayer::InitSequenceSoundPlayer()
51 {
52     for( int variableNo = 0 ; variableNo < GLOBAL_VARIABLE_NUM ; variableNo++ )
53     {
54         m_GlobalVariable[ variableNo ] = VARIABLE_DEFAULT_VALUE;
55     }
56 }
57 
58 /*---------------------------------------------------------------------------*
59   Name:         SequenceSoundPlayer
60 
61   Description:  コンストラクタ
62 
63   Arguments:    None.
64 
65   Returns:      None.
66  *---------------------------------------------------------------------------*/
SequenceSoundPlayer()67 SequenceSoundPlayer::SequenceSoundPlayer()
68 {
69     for ( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
70     {
71         m_pTracks[trackNo] = NULL;
72     }
73 }
74 
75 /*---------------------------------------------------------------------------*
76   Name:         ~SequenceSoundPlayer
77 
78   Description:  デストラクタ
79 
80   Arguments:    None.
81 
82   Returns:      None.
83  *---------------------------------------------------------------------------*/
~SequenceSoundPlayer()84 SequenceSoundPlayer::~SequenceSoundPlayer()
85 {
86     Finalize();
87 }
88 
89 /*---------------------------------------------------------------------------*
90   Name:         Initialize
91 
92   Description:  パラメータを初期化します
93 
94   Arguments:    None.
95 
96   Returns:      None.
97  *---------------------------------------------------------------------------*/
Initialize()98 void SequenceSoundPlayer::Initialize()
99 {
100     BasicSoundPlayer::Initialize();
101 
102     m_StartedFlag                  = false;
103     m_PauseFlag                    = false;
104     m_ReleasePriorityFixFlag       = false;
105 
106     m_TempoRatio                   = 1.0f;
107     m_TickFraction                 = 0.0f;
108     m_SkipTickCounter              = 0;
109     m_SkipTimeCounter              = 0.0f;
110     m_PanRange                     = 1.0f;
111     m_TickCounter                  = 0;
112     m_TickFraction                 = 0.0f;
113 
114     m_SequenceUserprocCallback     = NULL;
115     m_pSequenceUserprocCallbackArg = NULL;
116 
117     m_ParserParam.tempo            = DEFAULT_TEMPO;
118     m_ParserParam.timebase         = DEFAULT_TIMEBASE;
119     m_ParserParam.volume           = 127;
120     m_ParserParam.priority         = 64;
121     m_ParserParam.callback         = NULL;
122 
123     for ( int varNo = 0; varNo < PLAYER_VARIABLE_NUM ; varNo++ )
124     {
125         m_LocalVariable[ varNo ] = VARIABLE_DEFAULT_VALUE;
126     }
127 
128     for ( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
129     {
130         m_pTracks[trackNo] = NULL;
131     }
132 
133     for ( int bankIdx = 0; bankIdx < SoundArchive::SEQ_BANK_MAX; bankIdx++ )
134     {
135         m_pBankFiles[ bankIdx ] = NULL;
136     }
137 }
138 
139 /*---------------------------------------------------------------------------*
140   Name:         Finalize
141 
142   Description:  シーケンスプレイヤーのシャットダウン
143 
144   Arguments:    None.
145 
146   Returns:      None.
147   *---------------------------------------------------------------------------*/
Finalize()148 void SequenceSoundPlayer::Finalize()
149 {
150     m_FinishFlag = true;
151 
152     FinishPlayer();
153 
154     // 無効化リストから削除
155     if ( m_ActiveFlag )
156     {
157         DisposeCallbackManager::GetInstance().UnregisterDisposeCallback( this );
158         m_ActiveFlag = false;
159     }
160 
161     // NN_LOG( "track rest %d\n",m_pSequenceTrackAllocator->GetAllocatableTrackCount());
162     BasicSoundPlayer::Finalize();
163 }
164 
165 /*---------------------------------------------------------------------------*
166   Name:         Setup
167 
168   Description:  シーケンスの初期化を行います
169 
170   Arguments:
171 
172   Returns:      None.
173  *---------------------------------------------------------------------------*/
Setup(SequenceTrackAllocator * trackAllocator,u32 allocTracks,NoteOnCallback * callback)174 void SequenceSoundPlayer::Setup(
175     SequenceTrackAllocator* trackAllocator,
176     u32 allocTracks,
177     NoteOnCallback* callback
178 )
179 {
180     //-----------------------------------------------------------------------------
181     // プレイヤー初期化
182     m_ParserParam.callback = callback;
183 
184     {
185         //-----------------------------------------------------------------------------
186         // 全トラックを確保することができるかどうか
187         {
188             int trackCount = 0;
189             for( u32 trackBitMask = allocTracks; trackBitMask != 0; trackBitMask >>= 1 )
190             {
191                 if ( trackBitMask & 0x01 ) trackCount++;
192             }
193             if ( trackCount > trackAllocator->GetAllocatableTrackCount() )
194             {
195             #if 0
196                 return SETUP_ERR_CANNOT_ALLOCATE_TRACK;
197             #else
198                 NW_WARNING(false, "Failed to start sequence sound for not enough sequence track instance." );
199                 Finalize();
200                 return;
201             #endif
202             }
203         }
204 
205         //-----------------------------------------------------------------------------
206         // トラック確保
207         {
208             u32 trackBitMask = allocTracks;
209             for( int trackNo = 0; trackBitMask != 0; trackNo++, trackBitMask >>= 1 )
210             {
211                 if ( ( trackBitMask & 0x01 ) == 0 ) continue;
212 
213                 SequenceTrack* track = trackAllocator->AllocTrack( this );
214                 NW_NULL_ASSERT( track );
215                 SetPlayerTrack( trackNo, track );
216                 // NN_LOG("AllocTrack %08x\n",track);
217             }
218         }
219     }
220 
221     // NN_LOG( "track rest %d\n",trackAllocator->GetAllocatableTrackCount());
222 
223     // 無効化リストに追加
224     DisposeCallbackManager::GetInstance().RegisterDisposeCallback( this );
225 
226     m_pSequenceTrackAllocator = trackAllocator;
227     m_ActiveFlag = true;
228 
229 #ifdef NW_PLATFORM_CTR
230   #if 0   // TODO: perf
231     for ( int i = 0; i < PERF_NUM; i++ )
232     {
233         s_PerfParam[ i ].Reset();
234         s_PerfParam[ i ].isCalcTick = true;
235     }
236   #endif
237 #endif
238     // SoundThread::GetInstance().SetSoundPlay( true );
239 
240 //    return SETUP_SUCCESS;
241 }
242 
243 /*---------------------------------------------------------------------------*
244   Name:         SetSeqData
245 
246   Description:  シーケンスの再生準備を行います
247 
248   Arguments:    seqBase  - シーケンスデータベースアドレス
249                 seqOffset - シーケンスデータオフセット
250 
251   Returns:      None.
252  *---------------------------------------------------------------------------*/
SetSeqData(const void * seqBase,s32 seqOffset)253 void SequenceSoundPlayer::SetSeqData( const void* seqBase, s32 seqOffset )
254 {
255     SequenceTrack* seqTrack = GetPlayerTrack( 0 );
256     if ( seqTrack == NULL )
257     {
258         return;
259     }
260 
261     if ( seqBase != NULL )
262     {
263         seqTrack->SetSeqData( seqBase, seqOffset );
264         seqTrack->Open();
265     }
266 }
267 
SetBankData(const void * bankFiles[],u32 bankFileCount)268 void SequenceSoundPlayer::SetBankData( const void* bankFiles[], u32 bankFileCount )
269 {
270     NW_ASSERT( bankFileCount <= SoundArchive::SEQ_BANK_MAX );
271 
272     if ( bankFiles != NULL )
273     {
274         for ( int i = 0; i < bankFileCount; i++ )
275         {
276             m_pBankFiles[ i ] = bankFiles[ i ];
277         }
278     }
279 }
280 
281 /*---------------------------------------------------------------------------*
282   Name:         Start
283 
284   Description:  準備完了したシーケンスの再生を開始します
285 
286   Arguments:    playerNo - プレイヤー番号
287 
288   Returns:      None.
289  *---------------------------------------------------------------------------*/
Start()290 void SequenceSoundPlayer::Start()
291 {
292     // プレイヤーリストに追加
293     SoundThread::GetInstance().RegisterPlayerCallback( this );
294     m_StartedFlag = true;
295 }
296 
297 /*---------------------------------------------------------------------------*
298   Name:         Stop
299 
300   Description:  シーケンスを止めます
301 
302   Arguments:    playerNo - プレイヤー番号
303 
304   Returns:      None.
305  *---------------------------------------------------------------------------*/
Stop()306 void SequenceSoundPlayer::Stop()
307 {
308     FinishPlayer();
309 }
310 
311 /*---------------------------------------------------------------------------*
312   Name:         Pause
313 
314   Description:  シーケンスを一時停止または再開します
315 
316   Arguments:    playerNo - プレイヤー番号
317                 flag - trueで一時停止、falseで再開します
318 
319   Returns:      None.
320  *---------------------------------------------------------------------------*/
Pause(bool flag)321 void SequenceSoundPlayer::Pause( bool flag )
322 {
323     m_PauseFlag = flag;
324 
325     // 全トラックのチャンネルを停止
326     SequenceTrack* track;
327     for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
328     {
329         track = GetPlayerTrack( trackNo );
330         if ( track == NULL ) continue;
331 
332         track->PauseAllChannel( flag );
333     }
334 }
335 
336 /*---------------------------------------------------------------------------*
337   Name:         Skip
338 
339   Description:  シーケンスをスキップします
340                 注意:サウンドフレームを生成するタイマーを一時的に止めています
341 
342   Arguments:    playerNo - プレイヤー番号
343                 tick - スキップ量をティックで指定します
344 
345   Returns:      None.
346  *---------------------------------------------------------------------------*/
Skip(OffsetType offsetType,int offset)347 void SequenceSoundPlayer::Skip( OffsetType offsetType, int offset )
348 {
349     if ( !m_ActiveFlag )
350     {
351         return;
352     }
353 
354     switch ( offsetType )
355     {
356     case OFFSET_TYPE_TICK:
357         m_SkipTickCounter += offset;
358         break;
359     case OFFSET_TYPE_MILLISEC:
360         m_SkipTimeCounter += static_cast<f32>( offset );
361         break;
362     }
363 }
364 
SetTempoRatio(float tempoRatio)365 void SequenceSoundPlayer::SetTempoRatio( float tempoRatio )
366 {
367     NW_ASSERT( tempoRatio >= 0.0f );
368     m_TempoRatio = tempoRatio;
369 }
370 
SetPanRange(float panRange)371 void SequenceSoundPlayer::SetPanRange( float panRange )
372 {
373     m_PanRange = panRange;
374 }
375 
SetChannelPriority(int priority)376 void SequenceSoundPlayer::SetChannelPriority( int priority )
377 {
378     NW_MINMAX_ASSERT( priority, 0, 127 );
379     m_ParserParam.priority = static_cast<u8>( priority );
380 }
381 
SetReleasePriorityFix(bool fix)382 void SequenceSoundPlayer::SetReleasePriorityFix( bool fix )
383 {
384     m_ReleasePriorityFixFlag = fix;
385 }
386 
SetSequenceUserprocCallback(SequenceUserprocCallback callback,void * arg)387 void SequenceSoundPlayer::SetSequenceUserprocCallback( SequenceUserprocCallback callback, void* arg )
388 {
389     m_SequenceUserprocCallback = callback;
390     m_pSequenceUserprocCallbackArg = arg;
391 }
392 
CallSequenceUserprocCallback(u16 procId,SequenceTrack * track)393 void SequenceSoundPlayer::CallSequenceUserprocCallback( u16 procId, SequenceTrack* track )
394 {
395     if ( m_SequenceUserprocCallback == NULL )
396     {
397         return;
398     }
399 
400     NW_NULL_ASSERT( track );
401 
402     SequenceTrack::ParserTrackParam& trackParam = track->GetParserTrackParam();
403 
404     SequenceUserprocCallbackParam param;
405     param.localVariable  = GetVariablePtr( 0 );
406     param.globalVariable = GetVariablePtr( 16 );
407     param.trackVariable  = track->GetVariablePtr( 0 );
408     param.cmpFlag = trackParam.cmpFlag;
409 
410     m_SequenceUserprocCallback(
411         procId,
412         &param,
413         m_pSequenceUserprocCallbackArg
414     );
415 
416     trackParam.cmpFlag = param.cmpFlag;
417 }
418 
419 
420 /*---------------------------------------------------------------------------*
421   Name:         GetLocalVariable
422 
423   Description:  シーケンスローカル変数を取得します。
424 
425   Arguments:    player - プレイヤー
426                 varNo - 変数番号
427 
428   Returns:      変数の値
429  *---------------------------------------------------------------------------*/
GetLocalVariable(int varNo) const430 s16 SequenceSoundPlayer::GetLocalVariable( int varNo ) const
431 {
432     NW_MINMAXLT_ASSERT( varNo, 0, PLAYER_VARIABLE_NUM );
433 
434     return m_LocalVariable[ varNo ];
435 }
436 
437 /*---------------------------------------------------------------------------*
438   Name:         GetGlobalVariable
439 
440   Description:  シーケンスグローバル変数を取得します。
441 
442   Arguments:    varNo - 変数番号
443 
444   Returns:      変数の値
445  *---------------------------------------------------------------------------*/
GetGlobalVariable(int varNo)446 s16 SequenceSoundPlayer::GetGlobalVariable( int varNo )
447 {
448     NW_MINMAXLT_ASSERT( varNo, 0, GLOBAL_VARIABLE_NUM );
449 
450     return m_GlobalVariable[ varNo ];
451 }
452 
453 /*---------------------------------------------------------------------------*
454   Name:         SetLocalVariable
455 
456   Description:  シーケンスローカル変数を設定します。
457 
458   Arguments:    player - プレイヤー
459                 varNo - 変数番号
460                 var - 変数値
461 
462   Returns:      変数の値
463  *---------------------------------------------------------------------------*/
SetLocalVariable(int varNo,s16 var)464 void SequenceSoundPlayer::SetLocalVariable( int varNo, s16 var )
465 {
466     NW_MINMAXLT_ASSERT( varNo, 0, PLAYER_VARIABLE_NUM );
467 
468     m_LocalVariable[ varNo ] = var;
469 }
470 
471 /*---------------------------------------------------------------------------*
472   Name:         SetGlobalVariable
473 
474   Description:  シーケンスグローバル変数を設定します。
475 
476   Arguments:    varNo - 変数番号
477                 var - 変数値
478 
479   Returns:      変数の値
480  *---------------------------------------------------------------------------*/
SetGlobalVariable(int varNo,s16 var)481 void SequenceSoundPlayer::SetGlobalVariable( int varNo, s16 var )
482 {
483     NW_MINMAXLT_ASSERT( varNo, 0, GLOBAL_VARIABLE_NUM );
484 
485     m_GlobalVariable[ varNo ] = var;
486 }
487 
488 /*---------------------------------------------------------------------------*
489   Name:         SetTrackMute
490 
491   Description:  トラックをミュートまたはミュート解除します
492 
493   Arguments:    trackBitFlag - ミュート設定するトラックのビットマスク
494                 flag         - trueでミュート、falseでミュート解除します
495 
496   Returns:      None.
497  *---------------------------------------------------------------------------*/
SetTrackMute(u32 trackBitFlag,SeqMute mute)498 void SequenceSoundPlayer::SetTrackMute( u32 trackBitFlag, SeqMute mute )
499 {
500     SetTrackParam( trackBitFlag, &SequenceTrack::SetMute, mute );
501 }
502 
SetTrackSilence(unsigned long trackBitFlag,bool silenceFlag,int fadeTimes)503 void SequenceSoundPlayer::SetTrackSilence( unsigned long trackBitFlag, bool silenceFlag, int fadeTimes )
504 {
505     SetTrackParam( trackBitFlag, &SequenceTrack::SetSilence, silenceFlag, fadeTimes );
506 }
507 
SetTrackVolume(u32 trackBitFlag,float volume)508 void SequenceSoundPlayer::SetTrackVolume( u32 trackBitFlag, float volume )
509 {
510     NW_ASSERT( volume >= 0.0f );
511     SetTrackParam( trackBitFlag, &SequenceTrack::SetVolume, volume );
512 }
513 
SetTrackPitch(u32 trackBitFlag,float pitch)514 void SequenceSoundPlayer::SetTrackPitch( u32 trackBitFlag, float pitch )
515 {
516     NW_ASSERT( pitch >= 0.0f );
517     SetTrackParam( trackBitFlag, &SequenceTrack::SetPitch, pitch );
518 }
519 
SetTrackPan(u32 trackBitFlag,float pan)520 void SequenceSoundPlayer::SetTrackPan( u32 trackBitFlag, float pan )
521 {
522     SetTrackParam( trackBitFlag, &SequenceTrack::SetPan, pan );
523 }
524 
SetTrackSurroundPan(u32 trackBitFlag,float surroundPan)525 void SequenceSoundPlayer::SetTrackSurroundPan( u32 trackBitFlag, float surroundPan )
526 {
527     SetTrackParam( trackBitFlag, &SequenceTrack::SetSurroundPan, surroundPan );
528 }
529 
SetTrackLpfFreq(u32 trackBitFlag,float lpfFreq)530 void SequenceSoundPlayer::SetTrackLpfFreq( u32 trackBitFlag, float lpfFreq )
531 {
532     SetTrackParam( trackBitFlag, &SequenceTrack::SetLpfFreq, lpfFreq );
533 }
534 
SetTrackBiquadFilter(u32 trackBitFlag,int type,float value)535 void SequenceSoundPlayer::SetTrackBiquadFilter( u32 trackBitFlag, int type, float value )
536 {
537     SetTrackParam( trackBitFlag, &SequenceTrack::SetBiquadFilter, type, value );
538 }
539 
SetTrackPanRange(u32 trackBitFlag,float panRange)540 void SequenceSoundPlayer::SetTrackPanRange( u32 trackBitFlag, float panRange )
541 {
542     SetTrackParam( trackBitFlag, &SequenceTrack::SetPanRange, panRange );
543 }
544 
SetTrackModDepth(u32 trackBitFlag,float depth)545 void SequenceSoundPlayer::SetTrackModDepth( u32 trackBitFlag, float depth )
546 {
547     SetTrackParam( trackBitFlag, &SequenceTrack::SetModDepth, depth );
548 }
549 
SetTrackModSpeed(u32 trackBitFlag,float speed)550 void SequenceSoundPlayer::SetTrackModSpeed( u32 trackBitFlag, float speed )
551 {
552     SetTrackParam( trackBitFlag, &SequenceTrack::SetModSpeed, speed );
553 }
554 
SetTrackBankIndex(u32 trackBitFlag,int bankIndex)555 bool SequenceSoundPlayer::SetTrackBankIndex( u32 trackBitFlag, int bankIndex )
556 {
557     // SequenceSoundHandle::SetTrackBankIndex でも範囲チェックしているが、念のため。
558     NW_MINMAXLT_ASSERT( bankIndex, 0, SoundArchive::SEQ_BANK_MAX );
559     if ( m_pBankFiles[ bankIndex ] == NULL )
560     {
561         return false;
562     }
563 
564     SetTrackParam( trackBitFlag, &SequenceTrack::SetBankIndex, bankIndex );
565     return true;
566 }
567 
568 /*---------------------------------------------------------------------------*
569   Name:         InvalidateData
570 
571   Description:  指定シーケンスデータを使用しているシーケンスを無効化します
572 
573   Arguments:    start - シーケンスデータ開始アドレス
574                 end   - シーケンスデータ終了アドレス
575 
576   Returns:      None.
577  *---------------------------------------------------------------------------*/
InvalidateData(const void * start,const void * end)578 void SequenceSoundPlayer::InvalidateData( const void* start, const void* end )
579 {
580     if ( m_ActiveFlag )
581     {
582         for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
583         {
584             SequenceTrack* track = GetPlayerTrack( trackNo );
585             if ( track == NULL ) continue;
586 
587             const u8* cur = track->GetParserTrackParam().baseAddr;
588             if ( start <= cur && cur <= end )
589             {
590                 Finalize();
591                 break;
592             }
593         }
594         for ( int i = 0; i < SoundArchive::SEQ_BANK_MAX; i++ )
595         {
596             const void* cur = m_pBankFiles[ i ];
597             if ( start <= cur && cur <= end )
598             {
599                 m_pBankFiles[ i ] = NULL;
600             }
601         }
602     }
603 }
604 
605 /*---------------------------------------------------------------------------*
606   Name:         GetPlayerTrack
607 
608   Description:  プレイヤーが保持しているトラックを取得します
609 
610   Arguments:    trackNo  - トラック番号
611 
612   Returns:      トラックポインタ
613  *---------------------------------------------------------------------------*/
GetPlayerTrack(int trackNo)614 SequenceTrack* SequenceSoundPlayer::GetPlayerTrack( int trackNo )
615 {
616     if ( trackNo > TRACK_NUM_PER_PLAYER - 1 )
617     {
618         return NULL;
619     }
620 
621     return m_pTracks[ trackNo ];
622 }
623 
624 /*---------------------------------------------------------------------------*
625   Name:         GetPlayerTrack
626 
627   Description:  プレイヤーが保持しているトラックを取得します
628 
629   Arguments:    trackNo  - トラック番号
630 
631   Returns:      トラックポインタ
632  *---------------------------------------------------------------------------*/
GetPlayerTrack(int trackNo) const633 const SequenceTrack* SequenceSoundPlayer::GetPlayerTrack( int trackNo ) const
634 {
635     if ( trackNo > TRACK_NUM_PER_PLAYER - 1 )
636     {
637         return NULL;
638     }
639 
640     return m_pTracks[ trackNo ];
641 }
642 
643 /*---------------------------------------------------------------------------*
644   Name:         CloseTrack
645 
646   Description:  プレイヤーのトラックを閉じます。
647                 トラックシーケンス完了時、シーケンス2重オープン時、
648                 プレイヤーの完了時に呼びだされます。
649 
650   Arguments:    player : プレイヤー
651 
652   Returns:      None
653  *---------------------------------------------------------------------------*/
CloseTrack(int trackNo)654 void SequenceSoundPlayer::CloseTrack( int trackNo )
655 {
656     NW_MINMAXLT_ASSERT( trackNo, 0, TRACK_NUM_PER_PLAYER );
657 
658     SequenceTrack* track = GetPlayerTrack( trackNo );
659     if ( track == NULL )
660     {
661         return;
662     }
663 
664     track->Close();
665 
666     m_pSequenceTrackAllocator->FreeTrack( m_pTracks[ trackNo ] );
667 //    NN_LOG("FreeTrack %08x\n",m_pTracks[trackNo]);
668 
669     m_pTracks[ trackNo ] = NULL;
670 }
671 
672 /*---------------------------------------------------------------------------*
673   Name:         SetPlayerTrack
674 
675   Description:  プレイヤーが管理するトラックを追加します
676 
677   Arguments:    trackNo  - トラック番号
678                 trackID  - トラックID
679 
680   Returns:      なし
681  *---------------------------------------------------------------------------*/
SetPlayerTrack(int trackNo,SequenceTrack * track)682 void SequenceSoundPlayer::SetPlayerTrack( int trackNo, SequenceTrack* track )
683 {
684     if ( trackNo > TRACK_NUM_PER_PLAYER - 1 )
685     {
686         return;
687     }
688     m_pTracks[ trackNo ] = track;
689     track->SetPlayerTrackNo( trackNo );
690 
691     // トラックパラメータのフロントバイパスフラグに「サウンド」のフロントバイパスフラグを反映
692     // (その後、frontbypass_on/_off コマンドで上書きされ得ます)
693     track->GetParserTrackParam().frontBypassFlag = IsFrontBypass();
694 }
695 
696 
697 /*---------------------------------------------------------------------------*
698   Name:         FinishPlayer
699 
700   Description:  プレイヤーの完了処理を行います。
701 
702   Arguments:    player : プレイヤーポインタ
703 
704   Returns:      None
705  *---------------------------------------------------------------------------*/
FinishPlayer()706 void SequenceSoundPlayer::FinishPlayer()
707 {
708     // プレイヤーリストから削除
709     if ( m_StartedFlag )
710     {
711         SoundThread::GetInstance().UnregisterPlayerCallback( this );
712         m_StartedFlag = false;
713     }
714 
715     // 全トラック解放
716     for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
717     {
718         CloseTrack( trackNo );
719     }
720 }
721 
722 /*---------------------------------------------------------------------------*
723   Name:         UpdateChannelParam
724 
725   Description:  プレイヤーの全トラックのチャンネルパラメータを更新します
726 
727   Arguments:    player - プレイヤーポインタ
728 
729   Returns:      None.
730  *---------------------------------------------------------------------------*/
UpdateChannelParam()731 void SequenceSoundPlayer::UpdateChannelParam()
732 {
733     SequenceTrack* track;
734     for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
735     {
736         track = GetPlayerTrack( trackNo );
737         if ( track == NULL ) continue;
738         track->UpdateChannelParam();
739     }
740 }
741 
742 /*---------------------------------------------------------------------------*
743   Name:         ParseNextTick
744 
745   Description:  プレイヤーのシーケンス処理を行います
746 
747   Arguments:    player - プレイヤーポインタ
748                 doNoteOn - ノートオンするかどうか
749 
750   Returns:      継続時には0を、完了時には1を返します
751  *---------------------------------------------------------------------------*/
ParseNextTick(bool doNoteOn)752 int SequenceSoundPlayer::ParseNextTick( bool doNoteOn )
753 {
754     bool activeFlag = false;
755 
756     for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
757     {
758         SequenceTrack* track = GetPlayerTrack( trackNo );
759         if ( track == NULL )
760         {
761             continue;
762         }
763 
764         track->UpdateChannelLength();
765 
766         if ( track->ParseNextTick( doNoteOn ) < 0 )
767         {
768             // トラックのシーケンス終了
769             CloseTrack( trackNo );
770         }
771 
772         if ( track->IsOpened() )
773         {
774             activeFlag = true;
775         }
776     }
777 
778     if ( ! activeFlag )
779     {
780         return 1;
781     }
782 
783     return 0;
784 }
785 
786 /*---------------------------------------------------------------------------*
787   Name:         GetVariablePtr
788 
789   Description:  変数のポインタを取得します
790 
791   Arguments:    player - プレイヤーポインタ
792                 varNo    - 変数番号
793 
794   Returns:      変数のポインタ
795  *---------------------------------------------------------------------------*/
GetVariablePtr(int varNo)796 vs16* SequenceSoundPlayer::GetVariablePtr( int varNo )
797 {
798     NW_MINMAX_ASSERT( varNo, 0, PLAYER_VARIABLE_NUM + GLOBAL_VARIABLE_NUM );
799 
800     if ( varNo < PLAYER_VARIABLE_NUM )
801     {
802         return & m_LocalVariable[ varNo ] ;
803     }
804     else if ( varNo < PLAYER_VARIABLE_NUM + GLOBAL_VARIABLE_NUM )
805     {
806         return & m_GlobalVariable[ varNo - PLAYER_VARIABLE_NUM ];
807     }
808     else
809     {
810         return NULL;
811     }
812 }
813 
814 /*---------------------------------------------------------------------------*
815   Name:         Update
816 
817   Description:  プレイヤーのフレーム処理を行います
818 
819   Arguments:    None.
820 
821   Returns:      None.
822  *---------------------------------------------------------------------------*/
Update()823 void SequenceSoundPlayer::Update()
824 {
825     if ( ! m_ActiveFlag )
826     {
827         return;
828     }
829     if ( ! m_StartedFlag )
830     {
831         return;
832     }
833 
834     if ( ( m_SkipTickCounter > 0 ) || ( m_SkipTimeCounter > 0.0f ) )
835     {
836         SkipTick();
837     }
838     else if ( ! m_PauseFlag )
839     {
840         UpdateTick();
841     }
842 
843     UpdateChannelParam();
844 }
845 
846 /*---------------------------------------------------------------------------*
847   Name:         UpdateTick
848 
849   Description:  プレイヤーのティック処理を行います
850 
851   Returns:      None.
852   *---------------------------------------------------------------------------*/
UpdateTick()853 void SequenceSoundPlayer::UpdateTick()
854 {
855     f32 tickPerMsec = CalcTickPerMsec();
856     if ( tickPerMsec == 0.0f )
857     {
858         return;
859     }
860 
861     u64 restMsec = INTERVAL_MSEC_NUMERATOR;
862     u64 nextMsec = static_cast<u64>(INTERVAL_MSEC_DENOMINATOR * m_TickFraction / tickPerMsec);
863 
864     while ( nextMsec < restMsec )
865     {
866         restMsec -= nextMsec;
867 
868         bool result = ( ParseNextTick( true ) != 0 );
869 
870         if ( result )
871         {
872             FinishPlayer();
873             m_FinishFlag = true;
874             return;
875         }
876         ++m_TickCounter;
877 
878         tickPerMsec = CalcTickPerMsec();
879         if ( tickPerMsec == 0.0f )
880         {
881             return;
882         }
883         nextMsec = static_cast<u64>(INTERVAL_MSEC_DENOMINATOR / tickPerMsec);
884     }
885     nextMsec -= restMsec;
886     m_TickFraction = nextMsec * tickPerMsec / INTERVAL_MSEC_DENOMINATOR;
887 }
888 
889 /*---------------------------------------------------------------------------*
890   Name:         SkipTick
891 
892   Description:  ティックのスキップ処理を行います
893 
894   Arguments:    None.
895 
896   Returns:      None.
897   *---------------------------------------------------------------------------*/
SkipTick()898 void SequenceSoundPlayer::SkipTick()
899 {
900     // 全トラックの全チャンネルをリリース
901     for( int trackNo = 0; trackNo < TRACK_NUM_PER_PLAYER ; trackNo++ )
902     {
903         SequenceTrack* track = GetPlayerTrack( trackNo );
904         if ( track == NULL ) continue;
905 
906         track->ReleaseAllChannel( SequenceTrack::PAUSE_RELEASE_VALUE );
907         track->FreeAllChannel();
908     }
909 
910     // スキップ処理
911     int skipCount = 0;
912     while ( m_SkipTickCounter > 0 || m_SkipTimeCounter * CalcTickPerMsec() >= 1.0f )
913     {
914         if ( skipCount >= MAX_SKIP_TICK_PER_FRAME )
915         {
916             return;
917         }
918 
919         if ( m_SkipTickCounter > 0 )
920         {
921             --m_SkipTickCounter;
922         }
923         else
924         {
925             f32 tickPerMsec = CalcTickPerMsec();
926             NW_ASSERT( tickPerMsec > 0.0f ); // 0.0fの時、スキップは行われない
927             f32 msecPerTick = 1.0f / tickPerMsec;
928             m_SkipTimeCounter -= msecPerTick;
929         }
930 
931         if ( ParseNextTick( false ) != 0 )
932         {
933             FinishPlayer();
934             m_FinishFlag = true;
935             return;
936         }
937         ++skipCount;
938         ++m_TickCounter;
939     }
940 
941     m_SkipTimeCounter = 0.0f;
942 }
943 
NoteOn(u8 bankIndex,const NoteOnInfo & noteOnInfo)944 Channel* SequenceSoundPlayer::NoteOn(
945     u8 bankIndex,
946     const NoteOnInfo& noteOnInfo
947 )
948 {
949     Channel* channel = m_ParserParam.callback->NoteOn(
950         this,
951         bankIndex,
952         noteOnInfo
953     );
954 
955     return channel;
956 }
957 
958 } // namespace nw::snd::internal::driver
959 } // namespace nw::snd::internal
960 } // namespace nw::snd
961 } // namespace nw
962 
963