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