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